diff options
| -rw-r--r-- | arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h | 11 | ||||
| -rw-r--r-- | drivers/char/keyboard.c | 10 | ||||
| -rw-r--r-- | drivers/input/input.c | 10 | ||||
| -rw-r--r-- | drivers/input/keyboard/ep93xx_keypad.c | 150 | ||||
| -rw-r--r-- | drivers/input/mouse/alps.c | 265 | ||||
| -rw-r--r-- | drivers/input/mouse/alps.h | 1 | ||||
| -rw-r--r-- | drivers/input/serio/altera_ps2.c | 15 | ||||
| -rw-r--r-- | drivers/input/serio/ambakmi.c | 9 | ||||
| -rw-r--r-- | drivers/input/serio/at32psif.c | 3 | ||||
| -rw-r--r-- | drivers/input/serio/gscps2.c | 6 | ||||
| -rw-r--r-- | drivers/input/serio/hil_mlc.c | 8 | ||||
| -rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 8 | ||||
| -rw-r--r-- | drivers/input/serio/i8042.c | 88 | ||||
| -rw-r--r-- | drivers/input/serio/sa1111ps2.c | 10 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom.h | 11 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_sys.c | 231 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_wac.c | 368 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_wac.h | 29 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/mc13783_ts.c | 258 | ||||
| -rw-r--r-- | include/linux/i8042.h | 18 |
22 files changed, 1137 insertions, 385 deletions
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h index 83f31cd0a274..62d17421e48c 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h | |||
| @@ -5,9 +5,6 @@ | |||
| 5 | #ifndef __ASM_ARCH_EP93XX_KEYPAD_H | 5 | #ifndef __ASM_ARCH_EP93XX_KEYPAD_H |
| 6 | #define __ASM_ARCH_EP93XX_KEYPAD_H | 6 | #define __ASM_ARCH_EP93XX_KEYPAD_H |
| 7 | 7 | ||
| 8 | #define MAX_MATRIX_KEY_ROWS (8) | ||
| 9 | #define MAX_MATRIX_KEY_COLS (8) | ||
| 10 | |||
| 11 | /* flags for the ep93xx_keypad driver */ | 8 | /* flags for the ep93xx_keypad driver */ |
| 12 | #define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */ | 9 | #define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */ |
| 13 | #define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */ | 10 | #define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */ |
| @@ -18,8 +15,6 @@ | |||
| 18 | 15 | ||
| 19 | /** | 16 | /** |
| 20 | * struct ep93xx_keypad_platform_data - platform specific device structure | 17 | * struct ep93xx_keypad_platform_data - platform specific device structure |
| 21 | * @matrix_key_rows: number of rows in the keypad matrix | ||
| 22 | * @matrix_key_cols: number of columns in the keypad matrix | ||
| 23 | * @matrix_key_map: array of keycodes defining the keypad matrix | 18 | * @matrix_key_map: array of keycodes defining the keypad matrix |
| 24 | * @matrix_key_map_size: ARRAY_SIZE(matrix_key_map) | 19 | * @matrix_key_map_size: ARRAY_SIZE(matrix_key_map) |
| 25 | * @debounce: debounce start count; terminal count is 0xff | 20 | * @debounce: debounce start count; terminal count is 0xff |
| @@ -27,8 +22,6 @@ | |||
| 27 | * @flags: see above | 22 | * @flags: see above |
| 28 | */ | 23 | */ |
| 29 | struct ep93xx_keypad_platform_data { | 24 | struct ep93xx_keypad_platform_data { |
| 30 | unsigned int matrix_key_rows; | ||
| 31 | unsigned int matrix_key_cols; | ||
| 32 | unsigned int *matrix_key_map; | 25 | unsigned int *matrix_key_map; |
| 33 | int matrix_key_map_size; | 26 | int matrix_key_map_size; |
| 34 | unsigned int debounce; | 27 | unsigned int debounce; |
| @@ -36,7 +29,7 @@ struct ep93xx_keypad_platform_data { | |||
| 36 | unsigned int flags; | 29 | unsigned int flags; |
| 37 | }; | 30 | }; |
| 38 | 31 | ||
| 39 | /* macro for creating the matrix_key_map table */ | 32 | #define EP93XX_MATRIX_ROWS (8) |
| 40 | #define KEY(row, col, val) (((row) << 28) | ((col) << 24) | (val)) | 33 | #define EP93XX_MATRIX_COLS (8) |
| 41 | 34 | ||
| 42 | #endif /* __ASM_ARCH_EP93XX_KEYPAD_H */ | 35 | #endif /* __ASM_ARCH_EP93XX_KEYPAD_H */ |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 5619007e7e05..f706b1dffdb3 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
| @@ -233,7 +233,8 @@ int setkeycode(unsigned int scancode, unsigned int keycode) | |||
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | /* | 235 | /* |
| 236 | * Making beeps and bells. | 236 | * Making beeps and bells. Note that we prefer beeps to bells, but when |
| 237 | * shutting the sound off we do both. | ||
| 237 | */ | 238 | */ |
| 238 | 239 | ||
| 239 | static int kd_sound_helper(struct input_handle *handle, void *data) | 240 | static int kd_sound_helper(struct input_handle *handle, void *data) |
| @@ -242,9 +243,12 @@ static int kd_sound_helper(struct input_handle *handle, void *data) | |||
| 242 | struct input_dev *dev = handle->dev; | 243 | struct input_dev *dev = handle->dev; |
| 243 | 244 | ||
| 244 | if (test_bit(EV_SND, dev->evbit)) { | 245 | if (test_bit(EV_SND, dev->evbit)) { |
| 245 | if (test_bit(SND_TONE, dev->sndbit)) | 246 | if (test_bit(SND_TONE, dev->sndbit)) { |
| 246 | input_inject_event(handle, EV_SND, SND_TONE, *hz); | 247 | input_inject_event(handle, EV_SND, SND_TONE, *hz); |
| 247 | if (test_bit(SND_BELL, handle->dev->sndbit)) | 248 | if (*hz) |
| 249 | return 0; | ||
| 250 | } | ||
| 251 | if (test_bit(SND_BELL, dev->sndbit)) | ||
| 248 | input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0); | 252 | input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0); |
| 249 | } | 253 | } |
| 250 | 254 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 5c16001959cc..ab060710688f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -296,9 +296,15 @@ static void input_handle_event(struct input_dev *dev, | |||
| 296 | * @value: value of the event | 296 | * @value: value of the event |
| 297 | * | 297 | * |
| 298 | * This function should be used by drivers implementing various input | 298 | * This function should be used by drivers implementing various input |
| 299 | * devices. See also input_inject_event(). | 299 | * devices to report input events. See also input_inject_event(). |
| 300 | * | ||
| 301 | * NOTE: input_event() may be safely used right after input device was | ||
| 302 | * allocated with input_allocate_device(), even before it is registered | ||
| 303 | * with input_register_device(), but the event will not reach any of the | ||
| 304 | * input handlers. Such early invocation of input_event() may be used | ||
| 305 | * to 'seed' initial state of a switch or initial position of absolute | ||
| 306 | * axis, etc. | ||
| 300 | */ | 307 | */ |
| 301 | |||
| 302 | void input_event(struct input_dev *dev, | 308 | void input_event(struct input_dev *dev, |
| 303 | unsigned int type, unsigned int code, int value) | 309 | unsigned int type, unsigned int code, int value) |
| 304 | { | 310 | { |
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 181d30e3018e..e45740429f7e 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c | |||
| @@ -22,11 +22,11 @@ | |||
| 22 | 22 | ||
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
| 25 | #include <linux/input.h> | ||
| 26 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/input/matrix_keypad.h> | ||
| 27 | 28 | ||
| 28 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
| 29 | #include <mach/gpio.h> | ||
| 30 | #include <mach/ep93xx_keypad.h> | 30 | #include <mach/ep93xx_keypad.h> |
| 31 | 31 | ||
| 32 | /* | 32 | /* |
| @@ -60,38 +60,37 @@ | |||
| 60 | #define KEY_REG_KEY1_MASK (0x0000003f) | 60 | #define KEY_REG_KEY1_MASK (0x0000003f) |
| 61 | #define KEY_REG_KEY1_SHIFT (0) | 61 | #define KEY_REG_KEY1_SHIFT (0) |
| 62 | 62 | ||
| 63 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | 63 | #define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS) |
| 64 | #define keypad_writel(v, off) __raw_writel((v), keypad->mmio_base + (off)) | ||
| 65 | |||
| 66 | #define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) | ||
| 67 | 64 | ||
| 68 | struct ep93xx_keypad { | 65 | struct ep93xx_keypad { |
| 69 | struct ep93xx_keypad_platform_data *pdata; | 66 | struct ep93xx_keypad_platform_data *pdata; |
| 70 | |||
| 71 | struct clk *clk; | ||
| 72 | struct input_dev *input_dev; | 67 | struct input_dev *input_dev; |
| 68 | struct clk *clk; | ||
| 69 | |||
| 73 | void __iomem *mmio_base; | 70 | void __iomem *mmio_base; |
| 74 | 71 | ||
| 75 | int irq; | 72 | unsigned int matrix_keycodes[EP93XX_MATRIX_SIZE]; |
| 76 | int enabled; | ||
| 77 | 73 | ||
| 78 | int key1; | 74 | int key1; |
| 79 | int key2; | 75 | int key2; |
| 80 | 76 | ||
| 81 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 77 | int irq; |
| 78 | |||
| 79 | bool enabled; | ||
| 82 | }; | 80 | }; |
| 83 | 81 | ||
| 84 | static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad) | 82 | static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad) |
| 85 | { | 83 | { |
| 86 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; | 84 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; |
| 87 | struct input_dev *input_dev = keypad->input_dev; | 85 | struct input_dev *input_dev = keypad->input_dev; |
| 86 | unsigned int *key; | ||
| 88 | int i; | 87 | int i; |
| 89 | 88 | ||
| 90 | for (i = 0; i < pdata->matrix_key_map_size; i++) { | 89 | key = &pdata->matrix_key_map[0]; |
| 91 | unsigned int key = pdata->matrix_key_map[i]; | 90 | for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { |
| 92 | int row = (key >> 28) & 0xf; | 91 | int row = KEY_ROW(*key); |
| 93 | int col = (key >> 24) & 0xf; | 92 | int col = KEY_COL(*key); |
| 94 | int code = key & 0xffffff; | 93 | int code = KEY_VAL(*key); |
| 95 | 94 | ||
| 96 | keypad->matrix_keycodes[(row << 3) + col] = code; | 95 | keypad->matrix_keycodes[(row << 3) + col] = code; |
| 97 | __set_bit(code, input_dev->keybit); | 96 | __set_bit(code, input_dev->keybit); |
| @@ -102,9 +101,11 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) | |||
| 102 | { | 101 | { |
| 103 | struct ep93xx_keypad *keypad = dev_id; | 102 | struct ep93xx_keypad *keypad = dev_id; |
| 104 | struct input_dev *input_dev = keypad->input_dev; | 103 | struct input_dev *input_dev = keypad->input_dev; |
| 105 | unsigned int status = keypad_readl(KEY_REG); | 104 | unsigned int status; |
| 106 | int keycode, key1, key2; | 105 | int keycode, key1, key2; |
| 107 | 106 | ||
| 107 | status = __raw_readl(keypad->mmio_base + KEY_REG); | ||
| 108 | |||
| 108 | keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; | 109 | keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; |
| 109 | key1 = keypad->matrix_keycodes[keycode]; | 110 | key1 = keypad->matrix_keycodes[keycode]; |
| 110 | 111 | ||
| @@ -152,7 +153,10 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) | |||
| 152 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; | 153 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; |
| 153 | unsigned int val = 0; | 154 | unsigned int val = 0; |
| 154 | 155 | ||
| 155 | clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV); | 156 | if (pdata->flags & EP93XX_KEYPAD_KDIV) |
| 157 | clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4); | ||
| 158 | else | ||
| 159 | clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16); | ||
| 156 | 160 | ||
| 157 | if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) | 161 | if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) |
| 158 | val |= KEY_INIT_DIS3KY; | 162 | val |= KEY_INIT_DIS3KY; |
| @@ -167,7 +171,7 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) | |||
| 167 | 171 | ||
| 168 | val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); | 172 | val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); |
| 169 | 173 | ||
| 170 | keypad_writel(val, KEY_INIT); | 174 | __raw_writel(val, keypad->mmio_base + KEY_INIT); |
| 171 | } | 175 | } |
| 172 | 176 | ||
| 173 | static int ep93xx_keypad_open(struct input_dev *pdev) | 177 | static int ep93xx_keypad_open(struct input_dev *pdev) |
| @@ -177,7 +181,7 @@ static int ep93xx_keypad_open(struct input_dev *pdev) | |||
| 177 | if (!keypad->enabled) { | 181 | if (!keypad->enabled) { |
| 178 | ep93xx_keypad_config(keypad); | 182 | ep93xx_keypad_config(keypad); |
| 179 | clk_enable(keypad->clk); | 183 | clk_enable(keypad->clk); |
| 180 | keypad->enabled = 1; | 184 | keypad->enabled = true; |
| 181 | } | 185 | } |
| 182 | 186 | ||
| 183 | return 0; | 187 | return 0; |
| @@ -189,7 +193,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev) | |||
| 189 | 193 | ||
| 190 | if (keypad->enabled) { | 194 | if (keypad->enabled) { |
| 191 | clk_disable(keypad->clk); | 195 | clk_disable(keypad->clk); |
| 192 | keypad->enabled = 0; | 196 | keypad->enabled = false; |
| 193 | } | 197 | } |
| 194 | } | 198 | } |
| 195 | 199 | ||
| @@ -211,7 +215,7 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev, | |||
| 211 | 215 | ||
| 212 | if (keypad->enabled) { | 216 | if (keypad->enabled) { |
| 213 | clk_disable(keypad->clk); | 217 | clk_disable(keypad->clk); |
| 214 | keypad->enabled = 0; | 218 | keypad->enabled = false; |
| 215 | } | 219 | } |
| 216 | 220 | ||
| 217 | mutex_unlock(&input_dev->mutex); | 221 | mutex_unlock(&input_dev->mutex); |
| @@ -236,7 +240,7 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) | |||
| 236 | if (!keypad->enabled) { | 240 | if (!keypad->enabled) { |
| 237 | ep93xx_keypad_config(keypad); | 241 | ep93xx_keypad_config(keypad); |
| 238 | clk_enable(keypad->clk); | 242 | clk_enable(keypad->clk); |
| 239 | keypad->enabled = 1; | 243 | keypad->enabled = true; |
| 240 | } | 244 | } |
| 241 | } | 245 | } |
| 242 | 246 | ||
| @@ -252,88 +256,56 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) | |||
| 252 | static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | 256 | static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) |
| 253 | { | 257 | { |
| 254 | struct ep93xx_keypad *keypad; | 258 | struct ep93xx_keypad *keypad; |
| 255 | struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data; | ||
| 256 | struct input_dev *input_dev; | 259 | struct input_dev *input_dev; |
| 257 | struct resource *res; | 260 | struct resource *res; |
| 258 | int irq, err, i, gpio; | 261 | int err; |
| 259 | |||
| 260 | if (!pdata || | ||
| 261 | !pdata->matrix_key_rows || | ||
| 262 | pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS || | ||
| 263 | !pdata->matrix_key_cols || | ||
| 264 | pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) { | ||
| 265 | dev_err(&pdev->dev, "invalid or missing platform data\n"); | ||
| 266 | return -EINVAL; | ||
| 267 | } | ||
| 268 | 262 | ||
| 269 | keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); | 263 | keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); |
| 270 | if (!keypad) { | 264 | if (!keypad) |
| 271 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 272 | return -ENOMEM; | 265 | return -ENOMEM; |
| 273 | } | ||
| 274 | 266 | ||
| 275 | keypad->pdata = pdata; | 267 | keypad->pdata = pdev->dev.platform_data; |
| 268 | if (!keypad->pdata) { | ||
| 269 | err = -EINVAL; | ||
| 270 | goto failed_free; | ||
| 271 | } | ||
| 276 | 272 | ||
| 277 | irq = platform_get_irq(pdev, 0); | 273 | keypad->irq = platform_get_irq(pdev, 0); |
| 278 | if (irq < 0) { | 274 | if (!keypad->irq) { |
| 279 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
| 280 | err = -ENXIO; | 275 | err = -ENXIO; |
| 281 | goto failed_free; | 276 | goto failed_free; |
| 282 | } | 277 | } |
| 283 | 278 | ||
| 284 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 279 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 285 | if (!res) { | 280 | if (!res) { |
| 286 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
| 287 | err = -ENXIO; | 281 | err = -ENXIO; |
| 288 | goto failed_free; | 282 | goto failed_free; |
| 289 | } | 283 | } |
| 290 | 284 | ||
| 291 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 285 | res = request_mem_region(res->start, resource_size(res), pdev->name); |
| 292 | if (!res) { | 286 | if (!res) { |
| 293 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
| 294 | err = -EBUSY; | 287 | err = -EBUSY; |
| 295 | goto failed_free; | 288 | goto failed_free; |
| 296 | } | 289 | } |
| 297 | 290 | ||
| 298 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | 291 | keypad->mmio_base = ioremap(res->start, resource_size(res)); |
| 299 | if (keypad->mmio_base == NULL) { | 292 | if (keypad->mmio_base == NULL) { |
| 300 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
| 301 | err = -ENXIO; | 293 | err = -ENXIO; |
| 302 | goto failed_free_mem; | 294 | goto failed_free_mem; |
| 303 | } | 295 | } |
| 304 | 296 | ||
| 305 | /* Request the needed GPIO's */ | 297 | err = ep93xx_keypad_acquire_gpio(pdev); |
| 306 | gpio = EP93XX_GPIO_LINE_ROW0; | 298 | if (err) |
| 307 | for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) { | 299 | goto failed_free_io; |
| 308 | err = gpio_request(gpio, pdev->name); | ||
| 309 | if (err) { | ||
| 310 | dev_err(&pdev->dev, "failed to request gpio-%d\n", | ||
| 311 | gpio); | ||
| 312 | goto failed_free_rows; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | gpio = EP93XX_GPIO_LINE_COL0; | ||
| 317 | for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) { | ||
| 318 | err = gpio_request(gpio, pdev->name); | ||
| 319 | if (err) { | ||
| 320 | dev_err(&pdev->dev, "failed to request gpio-%d\n", | ||
| 321 | gpio); | ||
| 322 | goto failed_free_cols; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | 300 | ||
| 326 | keypad->clk = clk_get(&pdev->dev, "key_clk"); | 301 | keypad->clk = clk_get(&pdev->dev, NULL); |
| 327 | if (IS_ERR(keypad->clk)) { | 302 | if (IS_ERR(keypad->clk)) { |
| 328 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
| 329 | err = PTR_ERR(keypad->clk); | 303 | err = PTR_ERR(keypad->clk); |
| 330 | goto failed_free_io; | 304 | goto failed_free_gpio; |
| 331 | } | 305 | } |
| 332 | 306 | ||
| 333 | /* Create and register the input driver */ | ||
| 334 | input_dev = input_allocate_device(); | 307 | input_dev = input_allocate_device(); |
| 335 | if (!input_dev) { | 308 | if (!input_dev) { |
| 336 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
| 337 | err = -ENOMEM; | 309 | err = -ENOMEM; |
| 338 | goto failed_put_clk; | 310 | goto failed_put_clk; |
| 339 | } | 311 | } |
| @@ -358,44 +330,29 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | |||
| 358 | ep93xx_keypad_build_keycode(keypad); | 330 | ep93xx_keypad_build_keycode(keypad); |
| 359 | platform_set_drvdata(pdev, keypad); | 331 | platform_set_drvdata(pdev, keypad); |
| 360 | 332 | ||
| 361 | err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED, | 333 | err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, |
| 362 | pdev->name, keypad); | 334 | IRQF_DISABLED, pdev->name, keypad); |
| 363 | if (err) { | 335 | if (err) |
| 364 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 365 | goto failed_free_dev; | 336 | goto failed_free_dev; |
| 366 | } | ||
| 367 | |||
| 368 | keypad->irq = irq; | ||
| 369 | 337 | ||
| 370 | /* Register the input device */ | ||
| 371 | err = input_register_device(input_dev); | 338 | err = input_register_device(input_dev); |
| 372 | if (err) { | 339 | if (err) |
| 373 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
| 374 | goto failed_free_irq; | 340 | goto failed_free_irq; |
| 375 | } | ||
| 376 | 341 | ||
| 377 | device_init_wakeup(&pdev->dev, 1); | 342 | device_init_wakeup(&pdev->dev, 1); |
| 378 | 343 | ||
| 379 | return 0; | 344 | return 0; |
| 380 | 345 | ||
| 381 | failed_free_irq: | 346 | failed_free_irq: |
| 382 | free_irq(irq, pdev); | 347 | free_irq(keypad->irq, pdev); |
| 383 | platform_set_drvdata(pdev, NULL); | 348 | platform_set_drvdata(pdev, NULL); |
| 384 | failed_free_dev: | 349 | failed_free_dev: |
| 385 | input_free_device(input_dev); | 350 | input_free_device(input_dev); |
| 386 | failed_put_clk: | 351 | failed_put_clk: |
| 387 | clk_put(keypad->clk); | 352 | clk_put(keypad->clk); |
| 353 | failed_free_gpio: | ||
| 354 | ep93xx_keypad_release_gpio(pdev); | ||
| 388 | failed_free_io: | 355 | failed_free_io: |
| 389 | i = keypad->pdata->matrix_key_cols - 1; | ||
| 390 | gpio = EP93XX_GPIO_LINE_COL0 + i; | ||
| 391 | failed_free_cols: | ||
| 392 | for ( ; i >= 0; i--, gpio--) | ||
| 393 | gpio_free(gpio); | ||
| 394 | i = keypad->pdata->matrix_key_rows - 1; | ||
| 395 | gpio = EP93XX_GPIO_LINE_ROW0 + i; | ||
| 396 | failed_free_rows: | ||
| 397 | for ( ; i >= 0; i--, gpio--) | ||
| 398 | gpio_free(gpio); | ||
| 399 | iounmap(keypad->mmio_base); | 356 | iounmap(keypad->mmio_base); |
| 400 | failed_free_mem: | 357 | failed_free_mem: |
| 401 | release_mem_region(res->start, resource_size(res)); | 358 | release_mem_region(res->start, resource_size(res)); |
| @@ -408,7 +365,6 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) | |||
| 408 | { | 365 | { |
| 409 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | 366 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); |
| 410 | struct resource *res; | 367 | struct resource *res; |
| 411 | int i, gpio; | ||
| 412 | 368 | ||
| 413 | free_irq(keypad->irq, pdev); | 369 | free_irq(keypad->irq, pdev); |
| 414 | 370 | ||
| @@ -420,15 +376,7 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) | |||
| 420 | 376 | ||
| 421 | input_unregister_device(keypad->input_dev); | 377 | input_unregister_device(keypad->input_dev); |
| 422 | 378 | ||
| 423 | i = keypad->pdata->matrix_key_cols - 1; | 379 | ep93xx_keypad_release_gpio(pdev); |
| 424 | gpio = EP93XX_GPIO_LINE_COL0 + i; | ||
| 425 | for ( ; i >= 0; i--, gpio--) | ||
| 426 | gpio_free(gpio); | ||
| 427 | |||
| 428 | i = keypad->pdata->matrix_key_rows - 1; | ||
| 429 | gpio = EP93XX_GPIO_LINE_ROW0 + i; | ||
| 430 | for ( ; i >= 0; i--, gpio--) | ||
| 431 | gpio_free(gpio); | ||
| 432 | 380 | ||
| 433 | iounmap(keypad->mmio_base); | 381 | iounmap(keypad->mmio_base); |
| 434 | 382 | ||
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index a3f492a50850..f93c2c0daf1f 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> | 5 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> |
| 6 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> | 6 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> |
| 7 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> |
| 8 | * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net> | ||
| 8 | * | 9 | * |
| 9 | * ALPS detection, tap switching and status querying info is taken from | 10 | * ALPS detection, tap switching and status querying info is taken from |
| 10 | * tpconfig utility (by C. Scott Ananian and Bruce Kall). | 11 | * tpconfig utility (by C. Scott Ananian and Bruce Kall). |
| @@ -28,7 +29,6 @@ | |||
| 28 | #define dbg(format, arg...) do {} while (0) | 29 | #define dbg(format, arg...) do {} while (0) |
| 29 | #endif | 30 | #endif |
| 30 | 31 | ||
| 31 | |||
| 32 | #define ALPS_OLDPROTO 0x01 /* old style input */ | 32 | #define ALPS_OLDPROTO 0x01 /* old style input */ |
| 33 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ | 33 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ |
| 34 | #define ALPS_PASS 0x04 /* device has a pass-through port */ | 34 | #define ALPS_PASS 0x04 /* device has a pass-through port */ |
| @@ -37,7 +37,8 @@ | |||
| 37 | #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ | 37 | #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ |
| 38 | #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ | 38 | #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ |
| 39 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ | 39 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ |
| 40 | 40 | #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with | |
| 41 | 6-byte ALPS packet */ | ||
| 41 | 42 | ||
| 42 | static const struct alps_model_info alps_model_data[] = { | 43 | static const struct alps_model_info alps_model_data[] = { |
| 43 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | 44 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ |
| @@ -58,7 +59,9 @@ static const struct alps_model_info alps_model_data[] = { | |||
| 58 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 59 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
| 59 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 60 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
| 60 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 61 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
| 61 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ | 62 | /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ |
| 63 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, | ||
| 64 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, | ||
| 62 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ | 65 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ |
| 63 | }; | 66 | }; |
| 64 | 67 | ||
| @@ -69,20 +72,88 @@ static const struct alps_model_info alps_model_data[] = { | |||
| 69 | */ | 72 | */ |
| 70 | 73 | ||
| 71 | /* | 74 | /* |
| 72 | * ALPS abolute Mode - new format | 75 | * PS/2 packet format |
| 76 | * | ||
| 77 | * byte 0: 0 0 YSGN XSGN 1 M R L | ||
| 78 | * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 | ||
| 79 | * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
| 80 | * | ||
| 81 | * Note that the device never signals overflow condition. | ||
| 82 | * | ||
| 83 | * ALPS absolute Mode - new format | ||
| 73 | * | 84 | * |
| 74 | * byte 0: 1 ? ? ? 1 ? ? ? | 85 | * byte 0: 1 ? ? ? 1 ? ? ? |
| 75 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | 86 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 |
| 76 | * byte 2: 0 x10 x9 x8 x7 ? fin ges | 87 | * byte 2: 0 x10 x9 x8 x7 ? fin ges |
| 77 | * byte 3: 0 y9 y8 y7 1 M R L | 88 | * byte 3: 0 y9 y8 y7 1 M R L |
| 78 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | 89 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 |
| 79 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | 90 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 |
| 80 | * | 91 | * |
| 92 | * Dualpoint device -- interleaved packet format | ||
| 93 | * | ||
| 94 | * byte 0: 1 1 0 0 1 1 1 1 | ||
| 95 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | ||
| 96 | * byte 2: 0 x10 x9 x8 x7 0 fin ges | ||
| 97 | * byte 3: 0 0 YSGN XSGN 1 1 1 1 | ||
| 98 | * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 | ||
| 99 | * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
| 100 | * byte 6: 0 y9 y8 y7 1 m r l | ||
| 101 | * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 | ||
| 102 | * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 | ||
| 103 | * | ||
| 104 | * CAPITALS = stick, miniscules = touchpad | ||
| 105 | * | ||
| 81 | * ?'s can have different meanings on different models, | 106 | * ?'s can have different meanings on different models, |
| 82 | * such as wheel rotation, extra buttons, stick buttons | 107 | * such as wheel rotation, extra buttons, stick buttons |
| 83 | * on a dualpoint, etc. | 108 | * on a dualpoint, etc. |
| 84 | */ | 109 | */ |
| 85 | 110 | ||
| 111 | static bool alps_is_valid_first_byte(const struct alps_model_info *model, | ||
| 112 | unsigned char data) | ||
| 113 | { | ||
| 114 | return (data & model->mask0) == model->byte0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static void alps_report_buttons(struct psmouse *psmouse, | ||
| 118 | struct input_dev *dev1, struct input_dev *dev2, | ||
| 119 | int left, int right, int middle) | ||
| 120 | { | ||
| 121 | struct alps_data *priv = psmouse->private; | ||
| 122 | const struct alps_model_info *model = priv->i; | ||
| 123 | |||
| 124 | if (model->flags & ALPS_PS2_INTERLEAVED) { | ||
| 125 | struct input_dev *dev; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * If shared button has already been reported on the | ||
| 129 | * other device (dev2) then this event should be also | ||
| 130 | * sent through that device. | ||
| 131 | */ | ||
| 132 | dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; | ||
| 133 | input_report_key(dev, BTN_LEFT, left); | ||
| 134 | |||
| 135 | dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; | ||
| 136 | input_report_key(dev, BTN_RIGHT, right); | ||
| 137 | |||
| 138 | dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; | ||
| 139 | input_report_key(dev, BTN_MIDDLE, middle); | ||
| 140 | |||
| 141 | /* | ||
| 142 | * Sync the _other_ device now, we'll do the first | ||
| 143 | * device later once we report the rest of the events. | ||
| 144 | */ | ||
| 145 | input_sync(dev2); | ||
| 146 | } else { | ||
| 147 | /* | ||
| 148 | * For devices with non-interleaved packets we know what | ||
| 149 | * device buttons belong to so we can simply report them. | ||
| 150 | */ | ||
| 151 | input_report_key(dev1, BTN_LEFT, left); | ||
| 152 | input_report_key(dev1, BTN_RIGHT, right); | ||
| 153 | input_report_key(dev1, BTN_MIDDLE, middle); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 86 | static void alps_process_packet(struct psmouse *psmouse) | 157 | static void alps_process_packet(struct psmouse *psmouse) |
| 87 | { | 158 | { |
| 88 | struct alps_data *priv = psmouse->private; | 159 | struct alps_data *priv = psmouse->private; |
| @@ -93,18 +164,6 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
| 93 | int x, y, z, ges, fin, left, right, middle; | 164 | int x, y, z, ges, fin, left, right, middle; |
| 94 | int back = 0, forward = 0; | 165 | int back = 0, forward = 0; |
| 95 | 166 | ||
| 96 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ | ||
| 97 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); | ||
| 98 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); | ||
| 99 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); | ||
| 100 | input_report_rel(dev2, REL_X, | ||
| 101 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | ||
| 102 | input_report_rel(dev2, REL_Y, | ||
| 103 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | ||
| 104 | input_sync(dev2); | ||
| 105 | return; | ||
| 106 | } | ||
| 107 | |||
| 108 | if (model->flags & ALPS_OLDPROTO) { | 167 | if (model->flags & ALPS_OLDPROTO) { |
| 109 | left = packet[2] & 0x10; | 168 | left = packet[2] & 0x10; |
| 110 | right = packet[2] & 0x08; | 169 | right = packet[2] & 0x08; |
| @@ -140,18 +199,13 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
| 140 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); | 199 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); |
| 141 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); | 200 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); |
| 142 | 201 | ||
| 143 | input_report_key(dev2, BTN_LEFT, left); | 202 | alps_report_buttons(psmouse, dev2, dev, left, right, middle); |
| 144 | input_report_key(dev2, BTN_RIGHT, right); | ||
| 145 | input_report_key(dev2, BTN_MIDDLE, middle); | ||
| 146 | 203 | ||
| 147 | input_sync(dev); | ||
| 148 | input_sync(dev2); | 204 | input_sync(dev2); |
| 149 | return; | 205 | return; |
| 150 | } | 206 | } |
| 151 | 207 | ||
| 152 | input_report_key(dev, BTN_LEFT, left); | 208 | alps_report_buttons(psmouse, dev, dev2, left, right, middle); |
| 153 | input_report_key(dev, BTN_RIGHT, right); | ||
| 154 | input_report_key(dev, BTN_MIDDLE, middle); | ||
| 155 | 209 | ||
| 156 | /* Convert hardware tap to a reasonable Z value */ | 210 | /* Convert hardware tap to a reasonable Z value */ |
| 157 | if (ges && !fin) | 211 | if (ges && !fin) |
| @@ -202,25 +256,168 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
| 202 | input_sync(dev); | 256 | input_sync(dev); |
| 203 | } | 257 | } |
| 204 | 258 | ||
| 259 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, | ||
| 260 | unsigned char packet[], | ||
| 261 | bool report_buttons) | ||
| 262 | { | ||
| 263 | struct alps_data *priv = psmouse->private; | ||
| 264 | struct input_dev *dev2 = priv->dev2; | ||
| 265 | |||
| 266 | if (report_buttons) | ||
| 267 | alps_report_buttons(psmouse, dev2, psmouse->dev, | ||
| 268 | packet[0] & 1, packet[0] & 2, packet[0] & 4); | ||
| 269 | |||
| 270 | input_report_rel(dev2, REL_X, | ||
| 271 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | ||
| 272 | input_report_rel(dev2, REL_Y, | ||
| 273 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | ||
| 274 | |||
| 275 | input_sync(dev2); | ||
| 276 | } | ||
| 277 | |||
| 278 | static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | ||
| 279 | { | ||
| 280 | struct alps_data *priv = psmouse->private; | ||
| 281 | |||
| 282 | if (psmouse->pktcnt < 6) | ||
| 283 | return PSMOUSE_GOOD_DATA; | ||
| 284 | |||
| 285 | if (psmouse->pktcnt == 6) { | ||
| 286 | /* | ||
| 287 | * Start a timer to flush the packet if it ends up last | ||
| 288 | * 6-byte packet in the stream. Timer needs to fire | ||
| 289 | * psmouse core times out itself. 20 ms should be enough | ||
| 290 | * to decide if we are getting more data or not. | ||
| 291 | */ | ||
| 292 | mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); | ||
| 293 | return PSMOUSE_GOOD_DATA; | ||
| 294 | } | ||
| 295 | |||
| 296 | del_timer(&priv->timer); | ||
| 297 | |||
| 298 | if (psmouse->packet[6] & 0x80) { | ||
| 299 | |||
| 300 | /* | ||
| 301 | * Highest bit is set - that means we either had | ||
| 302 | * complete ALPS packet and this is start of the | ||
| 303 | * next packet or we got garbage. | ||
| 304 | */ | ||
| 305 | |||
| 306 | if (((psmouse->packet[3] | | ||
| 307 | psmouse->packet[4] | | ||
| 308 | psmouse->packet[5]) & 0x80) || | ||
| 309 | (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { | ||
| 310 | dbg("refusing packet %x %x %x %x " | ||
| 311 | "(suspected interleaved ps/2)\n", | ||
| 312 | psmouse->packet[3], psmouse->packet[4], | ||
| 313 | psmouse->packet[5], psmouse->packet[6]); | ||
| 314 | return PSMOUSE_BAD_DATA; | ||
| 315 | } | ||
| 316 | |||
| 317 | alps_process_packet(psmouse); | ||
| 318 | |||
| 319 | /* Continue with the next packet */ | ||
| 320 | psmouse->packet[0] = psmouse->packet[6]; | ||
| 321 | psmouse->pktcnt = 1; | ||
| 322 | |||
| 323 | } else { | ||
| 324 | |||
| 325 | /* | ||
| 326 | * High bit is 0 - that means that we indeed got a PS/2 | ||
| 327 | * packet in the middle of ALPS packet. | ||
| 328 | * | ||
| 329 | * There is also possibility that we got 6-byte ALPS | ||
| 330 | * packet followed by 3-byte packet from trackpoint. We | ||
| 331 | * can not distinguish between these 2 scenarios but | ||
| 332 | * becase the latter is unlikely to happen in course of | ||
| 333 | * normal operation (user would need to press all | ||
| 334 | * buttons on the pad and start moving trackpoint | ||
| 335 | * without touching the pad surface) we assume former. | ||
| 336 | * Even if we are wrong the wost thing that would happen | ||
| 337 | * the cursor would jump but we should not get protocol | ||
| 338 | * desynchronization. | ||
| 339 | */ | ||
| 340 | |||
| 341 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], | ||
| 342 | false); | ||
| 343 | |||
| 344 | /* | ||
| 345 | * Continue with the standard ALPS protocol handling, | ||
| 346 | * but make sure we won't process it as an interleaved | ||
| 347 | * packet again, which may happen if all buttons are | ||
| 348 | * pressed. To avoid this let's reset the 4th bit which | ||
| 349 | * is normally 1. | ||
| 350 | */ | ||
| 351 | psmouse->packet[3] = psmouse->packet[6] & 0xf7; | ||
| 352 | psmouse->pktcnt = 4; | ||
| 353 | } | ||
| 354 | |||
| 355 | return PSMOUSE_GOOD_DATA; | ||
| 356 | } | ||
| 357 | |||
| 358 | static void alps_flush_packet(unsigned long data) | ||
| 359 | { | ||
| 360 | struct psmouse *psmouse = (struct psmouse *)data; | ||
| 361 | |||
| 362 | serio_pause_rx(psmouse->ps2dev.serio); | ||
| 363 | |||
| 364 | if (psmouse->pktcnt == 6) { | ||
| 365 | |||
| 366 | /* | ||
| 367 | * We did not any more data in reasonable amount of time. | ||
| 368 | * Validate the last 3 bytes and process as a standard | ||
| 369 | * ALPS packet. | ||
| 370 | */ | ||
| 371 | if ((psmouse->packet[3] | | ||
| 372 | psmouse->packet[4] | | ||
| 373 | psmouse->packet[5]) & 0x80) { | ||
| 374 | dbg("refusing packet %x %x %x " | ||
| 375 | "(suspected interleaved ps/2)\n", | ||
| 376 | psmouse->packet[3], psmouse->packet[4], | ||
| 377 | psmouse->packet[5]); | ||
| 378 | } else { | ||
| 379 | alps_process_packet(psmouse); | ||
| 380 | } | ||
| 381 | psmouse->pktcnt = 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | serio_continue_rx(psmouse->ps2dev.serio); | ||
| 385 | } | ||
| 386 | |||
| 205 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | 387 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) |
| 206 | { | 388 | { |
| 207 | struct alps_data *priv = psmouse->private; | 389 | struct alps_data *priv = psmouse->private; |
| 390 | const struct alps_model_info *model = priv->i; | ||
| 208 | 391 | ||
| 209 | if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ | 392 | if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ |
| 210 | if (psmouse->pktcnt == 3) { | 393 | if (psmouse->pktcnt == 3) { |
| 211 | alps_process_packet(psmouse); | 394 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
| 395 | true); | ||
| 212 | return PSMOUSE_FULL_PACKET; | 396 | return PSMOUSE_FULL_PACKET; |
| 213 | } | 397 | } |
| 214 | return PSMOUSE_GOOD_DATA; | 398 | return PSMOUSE_GOOD_DATA; |
| 215 | } | 399 | } |
| 216 | 400 | ||
| 217 | if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0) | 401 | /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ |
| 402 | |||
| 403 | if ((model->flags & ALPS_PS2_INTERLEAVED) && | ||
| 404 | psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { | ||
| 405 | return alps_handle_interleaved_ps2(psmouse); | ||
| 406 | } | ||
| 407 | |||
| 408 | if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { | ||
| 409 | dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", | ||
| 410 | psmouse->packet[0], model->mask0, model->byte0); | ||
| 218 | return PSMOUSE_BAD_DATA; | 411 | return PSMOUSE_BAD_DATA; |
| 412 | } | ||
| 219 | 413 | ||
| 220 | /* Bytes 2 - 6 should have 0 in the highest bit */ | 414 | /* Bytes 2 - 6 should have 0 in the highest bit */ |
| 221 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && | 415 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && |
| 222 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) | 416 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
| 417 | dbg("refusing packet[%i] = %x\n", | ||
| 418 | psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); | ||
| 223 | return PSMOUSE_BAD_DATA; | 419 | return PSMOUSE_BAD_DATA; |
| 420 | } | ||
| 224 | 421 | ||
| 225 | if (psmouse->pktcnt == 6) { | 422 | if (psmouse->pktcnt == 6) { |
| 226 | alps_process_packet(psmouse); | 423 | alps_process_packet(psmouse); |
| @@ -459,6 +656,7 @@ static void alps_disconnect(struct psmouse *psmouse) | |||
| 459 | struct alps_data *priv = psmouse->private; | 656 | struct alps_data *priv = psmouse->private; |
| 460 | 657 | ||
| 461 | psmouse_reset(psmouse); | 658 | psmouse_reset(psmouse); |
| 659 | del_timer_sync(&priv->timer); | ||
| 462 | input_unregister_device(priv->dev2); | 660 | input_unregister_device(priv->dev2); |
| 463 | kfree(priv); | 661 | kfree(priv); |
| 464 | } | 662 | } |
| @@ -476,6 +674,8 @@ int alps_init(struct psmouse *psmouse) | |||
| 476 | goto init_fail; | 674 | goto init_fail; |
| 477 | 675 | ||
| 478 | priv->dev2 = dev2; | 676 | priv->dev2 = dev2; |
| 677 | setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); | ||
| 678 | |||
| 479 | psmouse->private = priv; | 679 | psmouse->private = priv; |
| 480 | 680 | ||
| 481 | model = alps_get_model(psmouse, &version); | 681 | model = alps_get_model(psmouse, &version); |
| @@ -487,6 +687,17 @@ int alps_init(struct psmouse *psmouse) | |||
| 487 | if (alps_hw_init(psmouse)) | 687 | if (alps_hw_init(psmouse)) |
| 488 | goto init_fail; | 688 | goto init_fail; |
| 489 | 689 | ||
| 690 | /* | ||
| 691 | * Undo part of setup done for us by psmouse core since touchpad | ||
| 692 | * is not a relative device. | ||
| 693 | */ | ||
| 694 | __clear_bit(EV_REL, dev1->evbit); | ||
| 695 | __clear_bit(REL_X, dev1->relbit); | ||
| 696 | __clear_bit(REL_Y, dev1->relbit); | ||
| 697 | |||
| 698 | /* | ||
| 699 | * Now set up our capabilities. | ||
| 700 | */ | ||
| 490 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); | 701 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); |
| 491 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); | 702 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); |
| 492 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); | 703 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index bc87936fee1a..904ed8b3c8be 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
| @@ -23,6 +23,7 @@ struct alps_data { | |||
| 23 | char phys[32]; /* Phys */ | 23 | char phys[32]; /* Phys */ |
| 24 | const struct alps_model_info *i;/* Info */ | 24 | const struct alps_model_info *i;/* Info */ |
| 25 | int prev_fin; /* Finger bit from previous packet */ | 25 | int prev_fin; /* Finger bit from previous packet */ |
| 26 | struct timer_list timer; | ||
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | #ifdef CONFIG_MOUSE_PS2_ALPS | 29 | #ifdef CONFIG_MOUSE_PS2_ALPS |
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index f479ea50919f..320b7ca48bf8 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c | |||
| @@ -79,11 +79,11 @@ static void altera_ps2_close(struct serio *io) | |||
| 79 | /* | 79 | /* |
| 80 | * Add one device to this driver. | 80 | * Add one device to this driver. |
| 81 | */ | 81 | */ |
| 82 | static int altera_ps2_probe(struct platform_device *pdev) | 82 | static int __devinit altera_ps2_probe(struct platform_device *pdev) |
| 83 | { | 83 | { |
| 84 | struct ps2if *ps2if; | 84 | struct ps2if *ps2if; |
| 85 | struct serio *serio; | 85 | struct serio *serio; |
| 86 | int error; | 86 | int error, irq; |
| 87 | 87 | ||
| 88 | ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); | 88 | ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); |
| 89 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | 89 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
| @@ -108,11 +108,13 @@ static int altera_ps2_probe(struct platform_device *pdev) | |||
| 108 | goto err_free_mem; | 108 | goto err_free_mem; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | ps2if->irq = platform_get_irq(pdev, 0); | 111 | |
| 112 | if (ps2if->irq < 0) { | 112 | irq = platform_get_irq(pdev, 0); |
| 113 | if (irq < 0) { | ||
| 113 | error = -ENXIO; | 114 | error = -ENXIO; |
| 114 | goto err_free_mem; | 115 | goto err_free_mem; |
| 115 | } | 116 | } |
| 117 | ps2if->irq = irq; | ||
| 116 | 118 | ||
| 117 | if (!request_mem_region(ps2if->iomem_res->start, | 119 | if (!request_mem_region(ps2if->iomem_res->start, |
| 118 | resource_size(ps2if->iomem_res), pdev->name)) { | 120 | resource_size(ps2if->iomem_res), pdev->name)) { |
| @@ -155,7 +157,7 @@ static int altera_ps2_probe(struct platform_device *pdev) | |||
| 155 | /* | 157 | /* |
| 156 | * Remove one device from this driver. | 158 | * Remove one device from this driver. |
| 157 | */ | 159 | */ |
| 158 | static int altera_ps2_remove(struct platform_device *pdev) | 160 | static int __devexit altera_ps2_remove(struct platform_device *pdev) |
| 159 | { | 161 | { |
| 160 | struct ps2if *ps2if = platform_get_drvdata(pdev); | 162 | struct ps2if *ps2if = platform_get_drvdata(pdev); |
| 161 | 163 | ||
| @@ -175,9 +177,10 @@ static int altera_ps2_remove(struct platform_device *pdev) | |||
| 175 | */ | 177 | */ |
| 176 | static struct platform_driver altera_ps2_driver = { | 178 | static struct platform_driver altera_ps2_driver = { |
| 177 | .probe = altera_ps2_probe, | 179 | .probe = altera_ps2_probe, |
| 178 | .remove = altera_ps2_remove, | 180 | .remove = __devexit_p(altera_ps2_remove), |
| 179 | .driver = { | 181 | .driver = { |
| 180 | .name = DRV_NAME, | 182 | .name = DRV_NAME, |
| 183 | .owner = THIS_MODULE, | ||
| 181 | }, | 184 | }, |
| 182 | }; | 185 | }; |
| 183 | 186 | ||
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 89b394183a75..92563a681d65 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
| @@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io) | |||
| 107 | clk_disable(kmi->clk); | 107 | clk_disable(kmi->clk); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | 110 | static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) |
| 111 | { | 111 | { |
| 112 | struct amba_kmi_port *kmi; | 112 | struct amba_kmi_port *kmi; |
| 113 | struct serio *io; | 113 | struct serio *io; |
| @@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | |||
| 134 | io->port_data = kmi; | 134 | io->port_data = kmi; |
| 135 | io->dev.parent = &dev->dev; | 135 | io->dev.parent = &dev->dev; |
| 136 | 136 | ||
| 137 | kmi->io = io; | 137 | kmi->io = io; |
| 138 | kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); | 138 | kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); |
| 139 | if (!kmi->base) { | 139 | if (!kmi->base) { |
| 140 | ret = -ENOMEM; | 140 | ret = -ENOMEM; |
| @@ -162,7 +162,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | |||
| 162 | return ret; | 162 | return ret; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static int amba_kmi_remove(struct amba_device *dev) | 165 | static int __devexit amba_kmi_remove(struct amba_device *dev) |
| 166 | { | 166 | { |
| 167 | struct amba_kmi_port *kmi = amba_get_drvdata(dev); | 167 | struct amba_kmi_port *kmi = amba_get_drvdata(dev); |
| 168 | 168 | ||
| @@ -197,10 +197,11 @@ static struct amba_id amba_kmi_idtable[] = { | |||
| 197 | static struct amba_driver ambakmi_driver = { | 197 | static struct amba_driver ambakmi_driver = { |
| 198 | .drv = { | 198 | .drv = { |
| 199 | .name = "kmi-pl050", | 199 | .name = "kmi-pl050", |
| 200 | .owner = THIS_MODULE, | ||
| 200 | }, | 201 | }, |
| 201 | .id_table = amba_kmi_idtable, | 202 | .id_table = amba_kmi_idtable, |
| 202 | .probe = amba_kmi_probe, | 203 | .probe = amba_kmi_probe, |
| 203 | .remove = amba_kmi_remove, | 204 | .remove = __devexit_p(amba_kmi_remove), |
| 204 | .resume = amba_kmi_resume, | 205 | .resume = amba_kmi_resume, |
| 205 | }; | 206 | }; |
| 206 | 207 | ||
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index a6fb7a3dcc46..b54452a8c771 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
| @@ -137,7 +137,7 @@ static int psif_write(struct serio *io, unsigned char val) | |||
| 137 | spin_lock_irqsave(&psif->lock, flags); | 137 | spin_lock_irqsave(&psif->lock, flags); |
| 138 | 138 | ||
| 139 | while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) | 139 | while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) |
| 140 | msleep(10); | 140 | udelay(50); |
| 141 | 141 | ||
| 142 | if (timeout >= 0) { | 142 | if (timeout >= 0) { |
| 143 | psif_writel(psif, THR, val); | 143 | psif_writel(psif, THR, val); |
| @@ -352,6 +352,7 @@ static struct platform_driver psif_driver = { | |||
| 352 | .remove = __exit_p(psif_remove), | 352 | .remove = __exit_p(psif_remove), |
| 353 | .driver = { | 353 | .driver = { |
| 354 | .name = "atmel_psif", | 354 | .name = "atmel_psif", |
| 355 | .owner = THIS_MODULE, | ||
| 355 | }, | 356 | }, |
| 356 | .suspend = psif_suspend, | 357 | .suspend = psif_suspend, |
| 357 | .resume = psif_resume, | 358 | .resume = psif_resume, |
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index bd0f92d9f40f..06addfa7cc47 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> | 6 | * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> |
| 7 | * | 7 | * |
| 8 | * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c | 8 | * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c |
| 9 | * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> | 9 | * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> |
| 10 | * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> | 10 | * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> |
| 11 | * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> | 11 | * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> |
| 12 | * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> | 12 | * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> |
| @@ -326,7 +326,7 @@ static void gscps2_close(struct serio *port) | |||
| 326 | * @return: success/error report | 326 | * @return: success/error report |
| 327 | */ | 327 | */ |
| 328 | 328 | ||
| 329 | static int __init gscps2_probe(struct parisc_device *dev) | 329 | static int __devinit gscps2_probe(struct parisc_device *dev) |
| 330 | { | 330 | { |
| 331 | struct gscps2port *ps2port; | 331 | struct gscps2port *ps2port; |
| 332 | struct serio *serio; | 332 | struct serio *serio; |
| @@ -443,7 +443,7 @@ static struct parisc_driver parisc_ps2_driver = { | |||
| 443 | .name = "gsc_ps2", | 443 | .name = "gsc_ps2", |
| 444 | .id_table = gscps2_device_tbl, | 444 | .id_table = gscps2_device_tbl, |
| 445 | .probe = gscps2_probe, | 445 | .probe = gscps2_probe, |
| 446 | .remove = gscps2_remove, | 446 | .remove = __devexit_p(gscps2_remove), |
| 447 | }; | 447 | }; |
| 448 | 448 | ||
| 449 | static int __init gscps2_init(void) | 449 | static int __init gscps2_init(void) |
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 7ba9f2b2c041..6cd03ebaf5fb 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c | |||
| @@ -993,10 +993,8 @@ int hil_mlc_unregister(hil_mlc *mlc) | |||
| 993 | 993 | ||
| 994 | static int __init hil_mlc_init(void) | 994 | static int __init hil_mlc_init(void) |
| 995 | { | 995 | { |
| 996 | init_timer(&hil_mlcs_kicker); | 996 | setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0); |
| 997 | hil_mlcs_kicker.expires = jiffies + HZ; | 997 | mod_timer(&hil_mlcs_kicker, jiffies + HZ); |
| 998 | hil_mlcs_kicker.function = &hil_mlcs_timer; | ||
| 999 | add_timer(&hil_mlcs_kicker); | ||
| 1000 | 998 | ||
| 1001 | tasklet_enable(&hil_mlcs_tasklet); | 999 | tasklet_enable(&hil_mlcs_tasklet); |
| 1002 | 1000 | ||
| @@ -1005,7 +1003,7 @@ static int __init hil_mlc_init(void) | |||
| 1005 | 1003 | ||
| 1006 | static void __exit hil_mlc_exit(void) | 1004 | static void __exit hil_mlc_exit(void) |
| 1007 | { | 1005 | { |
| 1008 | del_timer(&hil_mlcs_kicker); | 1006 | del_timer_sync(&hil_mlcs_kicker); |
| 1009 | 1007 | ||
| 1010 | tasklet_disable(&hil_mlcs_tasklet); | 1008 | tasklet_disable(&hil_mlcs_tasklet); |
| 1011 | tasklet_kill(&hil_mlcs_tasklet); | 1009 | tasklet_kill(&hil_mlcs_tasklet); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 7fbffe431bc5..64b688daf48a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
| @@ -158,6 +158,14 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { | |||
| 158 | }, | 158 | }, |
| 159 | }, | 159 | }, |
| 160 | { | 160 | { |
| 161 | /* Gigabyte M1022M netbook */ | ||
| 162 | .matches = { | ||
| 163 | DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."), | ||
| 164 | DMI_MATCH(DMI_BOARD_NAME, "M1022E"), | ||
| 165 | DMI_MATCH(DMI_BOARD_VERSION, "1.02"), | ||
| 166 | }, | ||
| 167 | }, | ||
| 168 | { | ||
| 161 | .matches = { | 169 | .matches = { |
| 162 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 170 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 163 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), | 171 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 1df02d25aca5..d84a36e545f6 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
| @@ -126,6 +126,8 @@ static unsigned char i8042_suppress_kbd_ack; | |||
| 126 | static struct platform_device *i8042_platform_device; | 126 | static struct platform_device *i8042_platform_device; |
| 127 | 127 | ||
| 128 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); | 128 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); |
| 129 | static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, | ||
| 130 | struct serio *serio); | ||
| 129 | 131 | ||
| 130 | void i8042_lock_chip(void) | 132 | void i8042_lock_chip(void) |
| 131 | { | 133 | { |
| @@ -139,6 +141,48 @@ void i8042_unlock_chip(void) | |||
| 139 | } | 141 | } |
| 140 | EXPORT_SYMBOL(i8042_unlock_chip); | 142 | EXPORT_SYMBOL(i8042_unlock_chip); |
| 141 | 143 | ||
| 144 | int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 145 | struct serio *serio)) | ||
| 146 | { | ||
| 147 | unsigned long flags; | ||
| 148 | int ret = 0; | ||
| 149 | |||
| 150 | spin_lock_irqsave(&i8042_lock, flags); | ||
| 151 | |||
| 152 | if (i8042_platform_filter) { | ||
| 153 | ret = -EBUSY; | ||
| 154 | goto out; | ||
| 155 | } | ||
| 156 | |||
| 157 | i8042_platform_filter = filter; | ||
| 158 | |||
| 159 | out: | ||
| 160 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | EXPORT_SYMBOL(i8042_install_filter); | ||
| 164 | |||
| 165 | int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 166 | struct serio *port)) | ||
| 167 | { | ||
| 168 | unsigned long flags; | ||
| 169 | int ret = 0; | ||
| 170 | |||
| 171 | spin_lock_irqsave(&i8042_lock, flags); | ||
| 172 | |||
| 173 | if (i8042_platform_filter != filter) { | ||
| 174 | ret = -EINVAL; | ||
| 175 | goto out; | ||
| 176 | } | ||
| 177 | |||
| 178 | i8042_platform_filter = NULL; | ||
| 179 | |||
| 180 | out: | ||
| 181 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
| 182 | return ret; | ||
| 183 | } | ||
| 184 | EXPORT_SYMBOL(i8042_remove_filter); | ||
| 185 | |||
| 142 | /* | 186 | /* |
| 143 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to | 187 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to |
| 144 | * be ready for reading values from it / writing values to it. | 188 | * be ready for reading values from it / writing values to it. |
| @@ -369,6 +413,31 @@ static void i8042_stop(struct serio *serio) | |||
| 369 | } | 413 | } |
| 370 | 414 | ||
| 371 | /* | 415 | /* |
| 416 | * i8042_filter() filters out unwanted bytes from the input data stream. | ||
| 417 | * It is called from i8042_interrupt and thus is running with interrupts | ||
| 418 | * off and i8042_lock held. | ||
| 419 | */ | ||
| 420 | static bool i8042_filter(unsigned char data, unsigned char str, | ||
| 421 | struct serio *serio) | ||
| 422 | { | ||
| 423 | if (unlikely(i8042_suppress_kbd_ack)) { | ||
| 424 | if ((~str & I8042_STR_AUXDATA) && | ||
| 425 | (data == 0xfa || data == 0xfe)) { | ||
| 426 | i8042_suppress_kbd_ack--; | ||
| 427 | dbg("Extra keyboard ACK - filtered out\n"); | ||
| 428 | return true; | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 432 | if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { | ||
| 433 | dbg("Filtered out by platfrom filter\n"); | ||
| 434 | return true; | ||
| 435 | } | ||
| 436 | |||
| 437 | return false; | ||
| 438 | } | ||
| 439 | |||
| 440 | /* | ||
| 372 | * i8042_interrupt() is the most important function in this driver - | 441 | * i8042_interrupt() is the most important function in this driver - |
| 373 | * it handles the interrupts from the i8042, and sends incoming bytes | 442 | * it handles the interrupts from the i8042, and sends incoming bytes |
| 374 | * to the upper layers. | 443 | * to the upper layers. |
| @@ -377,13 +446,16 @@ static void i8042_stop(struct serio *serio) | |||
| 377 | static irqreturn_t i8042_interrupt(int irq, void *dev_id) | 446 | static irqreturn_t i8042_interrupt(int irq, void *dev_id) |
| 378 | { | 447 | { |
| 379 | struct i8042_port *port; | 448 | struct i8042_port *port; |
| 449 | struct serio *serio; | ||
| 380 | unsigned long flags; | 450 | unsigned long flags; |
| 381 | unsigned char str, data; | 451 | unsigned char str, data; |
| 382 | unsigned int dfl; | 452 | unsigned int dfl; |
| 383 | unsigned int port_no; | 453 | unsigned int port_no; |
| 454 | bool filtered; | ||
| 384 | int ret = 1; | 455 | int ret = 1; |
| 385 | 456 | ||
| 386 | spin_lock_irqsave(&i8042_lock, flags); | 457 | spin_lock_irqsave(&i8042_lock, flags); |
| 458 | |||
| 387 | str = i8042_read_status(); | 459 | str = i8042_read_status(); |
| 388 | if (unlikely(~str & I8042_STR_OBF)) { | 460 | if (unlikely(~str & I8042_STR_OBF)) { |
| 389 | spin_unlock_irqrestore(&i8042_lock, flags); | 461 | spin_unlock_irqrestore(&i8042_lock, flags); |
| @@ -391,8 +463,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
| 391 | ret = 0; | 463 | ret = 0; |
| 392 | goto out; | 464 | goto out; |
| 393 | } | 465 | } |
| 466 | |||
| 394 | data = i8042_read_data(); | 467 | data = i8042_read_data(); |
| 395 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
| 396 | 468 | ||
| 397 | if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { | 469 | if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { |
| 398 | static unsigned long last_transmit; | 470 | static unsigned long last_transmit; |
| @@ -441,21 +513,19 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
| 441 | } | 513 | } |
| 442 | 514 | ||
| 443 | port = &i8042_ports[port_no]; | 515 | port = &i8042_ports[port_no]; |
| 516 | serio = port->exists ? port->serio : NULL; | ||
| 444 | 517 | ||
| 445 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", | 518 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", |
| 446 | data, port_no, irq, | 519 | data, port_no, irq, |
| 447 | dfl & SERIO_PARITY ? ", bad parity" : "", | 520 | dfl & SERIO_PARITY ? ", bad parity" : "", |
| 448 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); | 521 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); |
| 449 | 522 | ||
| 450 | if (unlikely(i8042_suppress_kbd_ack)) | 523 | filtered = i8042_filter(data, str, serio); |
| 451 | if (port_no == I8042_KBD_PORT_NO && | 524 | |
| 452 | (data == 0xfa || data == 0xfe)) { | 525 | spin_unlock_irqrestore(&i8042_lock, flags); |
| 453 | i8042_suppress_kbd_ack--; | ||
| 454 | goto out; | ||
| 455 | } | ||
| 456 | 526 | ||
| 457 | if (likely(port->exists)) | 527 | if (likely(port->exists && !filtered)) |
| 458 | serio_interrupt(port->serio, data, dfl); | 528 | serio_interrupt(serio, data, dfl); |
| 459 | 529 | ||
| 460 | out: | 530 | out: |
| 461 | return IRQ_RETVAL(ret); | 531 | return IRQ_RETVAL(ret); |
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index f412c69478a8..d55874e5d1c2 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c | |||
| @@ -180,8 +180,8 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if) | |||
| 180 | } | 180 | } |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | static inline unsigned int | 183 | static unsigned int __devinit ps2_test_one(struct ps2if *ps2if, |
| 184 | ps2_test_one(struct ps2if *ps2if, unsigned int mask) | 184 | unsigned int mask) |
| 185 | { | 185 | { |
| 186 | unsigned int val; | 186 | unsigned int val; |
| 187 | 187 | ||
| @@ -197,7 +197,7 @@ ps2_test_one(struct ps2if *ps2if, unsigned int mask) | |||
| 197 | * Test the keyboard interface. We basically check to make sure that | 197 | * Test the keyboard interface. We basically check to make sure that |
| 198 | * we can drive each line to the keyboard independently of each other. | 198 | * we can drive each line to the keyboard independently of each other. |
| 199 | */ | 199 | */ |
| 200 | static int __init ps2_test(struct ps2if *ps2if) | 200 | static int __devinit ps2_test(struct ps2if *ps2if) |
| 201 | { | 201 | { |
| 202 | unsigned int stat; | 202 | unsigned int stat; |
| 203 | int ret = 0; | 203 | int ret = 0; |
| @@ -312,7 +312,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) | |||
| 312 | /* | 312 | /* |
| 313 | * Remove one device from this driver. | 313 | * Remove one device from this driver. |
| 314 | */ | 314 | */ |
| 315 | static int ps2_remove(struct sa1111_dev *dev) | 315 | static int __devexit ps2_remove(struct sa1111_dev *dev) |
| 316 | { | 316 | { |
| 317 | struct ps2if *ps2if = sa1111_get_drvdata(dev); | 317 | struct ps2if *ps2if = sa1111_get_drvdata(dev); |
| 318 | 318 | ||
| @@ -335,7 +335,7 @@ static struct sa1111_driver ps2_driver = { | |||
| 335 | }, | 335 | }, |
| 336 | .devid = SA1111_DEVID_PS2, | 336 | .devid = SA1111_DEVID_PS2, |
| 337 | .probe = ps2_probe, | 337 | .probe = ps2_probe, |
| 338 | .remove = ps2_remove, | 338 | .remove = __devexit_p(ps2_remove), |
| 339 | }; | 339 | }; |
| 340 | 340 | ||
| 341 | static int __init ps2_init(void) | 341 | static int __init ps2_init(void) |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 9114ae1c7488..16310f368dab 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/input/tablet/wacom.h | 2 | * drivers/input/tablet/wacom.h |
| 3 | * | 3 | * |
| 4 | * USB Wacom Graphire and Wacom Intuos tablet support | 4 | * USB Wacom tablet support |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> | 6 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> |
| 7 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> | 7 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> |
| @@ -69,6 +69,9 @@ | |||
| 69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) | 69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) |
| 70 | * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 | 70 | * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 |
| 71 | * v1.51 (pc) - Added support for Intuos4 | 71 | * v1.51 (pc) - Added support for Intuos4 |
| 72 | * v1.52 (pc) - Query Wacom data upon system resume | ||
| 73 | * - add defines for features->type | ||
| 74 | * - add new devices (0x9F, 0xE2, and 0XE3) | ||
| 72 | */ | 75 | */ |
| 73 | 76 | ||
| 74 | /* | 77 | /* |
| @@ -89,9 +92,9 @@ | |||
| 89 | /* | 92 | /* |
| 90 | * Version Information | 93 | * Version Information |
| 91 | */ | 94 | */ |
| 92 | #define DRIVER_VERSION "v1.51" | 95 | #define DRIVER_VERSION "v1.52" |
| 93 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 96 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
| 94 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 97 | #define DRIVER_DESC "USB Wacom tablet driver" |
| 95 | #define DRIVER_LICENSE "GPL" | 98 | #define DRIVER_LICENSE "GPL" |
| 96 | 99 | ||
| 97 | MODULE_AUTHOR(DRIVER_AUTHOR); | 100 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| @@ -133,6 +136,8 @@ extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
| 133 | extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 136 | extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 134 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 137 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 135 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 138 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 139 | extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
| 140 | extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
| 136 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 141 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 137 | extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 142 | extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 138 | extern __u16 wacom_le16_to_cpu(unsigned char *data); | 143 | extern __u16 wacom_le16_to_cpu(unsigned char *data); |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index ea30c983a33e..072f33b3b2b0 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/input/tablet/wacom_sys.c | 2 | * drivers/input/tablet/wacom_sys.c |
| 3 | * | 3 | * |
| 4 | * USB Wacom Graphire and Wacom Intuos tablet support - system specific code | 4 | * USB Wacom tablet support - system specific code |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | /* | 7 | /* |
| @@ -209,6 +209,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 209 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | | 209 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | |
| 210 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | 210 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); |
| 211 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | | 211 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | |
| 212 | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | | ||
| 212 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); | 213 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); |
| 213 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | 214 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); |
| 214 | } | 215 | } |
| @@ -256,6 +257,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 256 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | | 257 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | |
| 257 | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); | 258 | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); |
| 258 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | | 259 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | |
| 260 | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | | ||
| 259 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | | 261 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | |
| 260 | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | | 262 | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | |
| 261 | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); | 263 | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); |
| @@ -269,7 +271,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 269 | 271 | ||
| 270 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 272 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
| 271 | { | 273 | { |
| 272 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); | 274 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | |
| 275 | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); | ||
| 273 | } | 276 | } |
| 274 | 277 | ||
| 275 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 278 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
| @@ -277,12 +280,32 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 277 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); | 280 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); |
| 278 | } | 281 | } |
| 279 | 282 | ||
| 283 | void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
| 284 | { | ||
| 285 | if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP || | ||
| 286 | wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) { | ||
| 287 | input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0); | ||
| 288 | input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0); | ||
| 289 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
| 294 | { | ||
| 295 | if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) { | ||
| 296 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); | ||
| 297 | input_dev->evbit[0] |= BIT_MASK(EV_MSC); | ||
| 298 | input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 280 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, | 302 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, |
| 281 | struct wacom_wac *wacom_wac) | 303 | struct wacom_features *features) |
| 282 | { | 304 | { |
| 283 | struct usb_device *dev = interface_to_usbdev(intf); | 305 | struct usb_device *dev = interface_to_usbdev(intf); |
| 284 | struct wacom_features *features = wacom_wac->features; | 306 | char limit = 0; |
| 285 | char limit = 0, result = 0; | 307 | /* result has to be defined as int for some devices */ |
| 308 | int result = 0; | ||
| 286 | int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; | 309 | int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; |
| 287 | unsigned char *report; | 310 | unsigned char *report; |
| 288 | 311 | ||
| @@ -328,13 +351,24 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 328 | case HID_USAGE_X: | 351 | case HID_USAGE_X: |
| 329 | if (usage == WCM_DESKTOP) { | 352 | if (usage == WCM_DESKTOP) { |
| 330 | if (finger) { | 353 | if (finger) { |
| 331 | features->touch_x_max = | 354 | features->device_type = BTN_TOOL_DOUBLETAP; |
| 332 | features->touch_y_max = | 355 | if (features->type == TABLETPC2FG) { |
| 333 | wacom_le16_to_cpu(&report[i + 3]); | 356 | /* need to reset back */ |
| 357 | features->pktlen = WACOM_PKGLEN_TPC2FG; | ||
| 358 | features->device_type = BTN_TOOL_TRIPLETAP; | ||
| 359 | } | ||
| 334 | features->x_max = | 360 | features->x_max = |
| 361 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 362 | features->x_phy = | ||
| 335 | wacom_le16_to_cpu(&report[i + 6]); | 363 | wacom_le16_to_cpu(&report[i + 6]); |
| 336 | i += 7; | 364 | features->unit = report[i + 9]; |
| 365 | features->unitExpo = report[i + 11]; | ||
| 366 | i += 12; | ||
| 337 | } else if (pen) { | 367 | } else if (pen) { |
| 368 | /* penabled only accepts exact bytes of data */ | ||
| 369 | if (features->type == TABLETPC2FG) | ||
| 370 | features->pktlen = WACOM_PKGLEN_PENABLED; | ||
| 371 | features->device_type = BTN_TOOL_PEN; | ||
| 338 | features->x_max = | 372 | features->x_max = |
| 339 | wacom_le16_to_cpu(&report[i + 3]); | 373 | wacom_le16_to_cpu(&report[i + 3]); |
| 340 | i += 4; | 374 | i += 4; |
| @@ -350,10 +384,35 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 350 | break; | 384 | break; |
| 351 | 385 | ||
| 352 | case HID_USAGE_Y: | 386 | case HID_USAGE_Y: |
| 353 | if (usage == WCM_DESKTOP) | 387 | if (usage == WCM_DESKTOP) { |
| 354 | features->y_max = | 388 | if (finger) { |
| 355 | wacom_le16_to_cpu(&report[i + 3]); | 389 | features->device_type = BTN_TOOL_DOUBLETAP; |
| 356 | i += 4; | 390 | if (features->type == TABLETPC2FG) { |
| 391 | /* need to reset back */ | ||
| 392 | features->pktlen = WACOM_PKGLEN_TPC2FG; | ||
| 393 | features->device_type = BTN_TOOL_TRIPLETAP; | ||
| 394 | features->y_max = | ||
| 395 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 396 | features->y_phy = | ||
| 397 | wacom_le16_to_cpu(&report[i + 6]); | ||
| 398 | i += 7; | ||
| 399 | } else { | ||
| 400 | features->y_max = | ||
| 401 | features->x_max; | ||
| 402 | features->y_phy = | ||
| 403 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 404 | i += 4; | ||
| 405 | } | ||
| 406 | } else if (pen) { | ||
| 407 | /* penabled only accepts exact bytes of data */ | ||
| 408 | if (features->type == TABLETPC2FG) | ||
| 409 | features->pktlen = WACOM_PKGLEN_PENABLED; | ||
| 410 | features->device_type = BTN_TOOL_PEN; | ||
| 411 | features->y_max = | ||
| 412 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 413 | i += 4; | ||
| 414 | } | ||
| 415 | } | ||
| 357 | break; | 416 | break; |
| 358 | 417 | ||
| 359 | case HID_USAGE_FINGER: | 418 | case HID_USAGE_FINGER: |
| @@ -376,7 +435,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 376 | break; | 435 | break; |
| 377 | 436 | ||
| 378 | case HID_COLLECTION: | 437 | case HID_COLLECTION: |
| 379 | /* reset UsagePage ans Finger */ | 438 | /* reset UsagePage and Finger */ |
| 380 | finger = usage = 0; | 439 | finger = usage = 0; |
| 381 | break; | 440 | break; |
| 382 | } | 441 | } |
| @@ -388,43 +447,92 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 388 | return result; | 447 | return result; |
| 389 | } | 448 | } |
| 390 | 449 | ||
| 391 | static int wacom_query_tablet_data(struct usb_interface *intf) | 450 | static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features) |
| 392 | { | 451 | { |
| 393 | unsigned char *rep_data; | 452 | unsigned char *rep_data; |
| 394 | int limit = 0; | 453 | int limit = 0, report_id = 2; |
| 395 | int error; | 454 | int error = -ENOMEM; |
| 396 | 455 | ||
| 397 | rep_data = kmalloc(2, GFP_KERNEL); | 456 | rep_data = kmalloc(2, GFP_KERNEL); |
| 398 | if (!rep_data) | 457 | if (!rep_data) |
| 399 | return -ENOMEM; | 458 | return error; |
| 400 | 459 | ||
| 401 | do { | 460 | /* ask to report tablet data if it is 2FGT or not a Tablet PC */ |
| 402 | rep_data[0] = 2; | 461 | if (features->device_type == BTN_TOOL_TRIPLETAP) { |
| 403 | rep_data[1] = 2; | 462 | do { |
| 404 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | 463 | rep_data[0] = 3; |
| 405 | 2, rep_data, 2); | 464 | rep_data[1] = 4; |
| 406 | if (error >= 0) | 465 | report_id = 3; |
| 407 | error = usb_get_report(intf, | 466 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, |
| 408 | WAC_HID_FEATURE_REPORT, 2, | 467 | report_id, rep_data, 2); |
| 409 | rep_data, 2); | 468 | if (error >= 0) |
| 410 | } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); | 469 | error = usb_get_report(intf, |
| 470 | WAC_HID_FEATURE_REPORT, report_id, | ||
| 471 | rep_data, 3); | ||
| 472 | } while ((error < 0 || rep_data[1] != 4) && limit++ < 5); | ||
| 473 | } else if (features->type != TABLETPC && features->type != TABLETPC2FG) { | ||
| 474 | do { | ||
| 475 | rep_data[0] = 2; | ||
| 476 | rep_data[1] = 2; | ||
| 477 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | ||
| 478 | report_id, rep_data, 2); | ||
| 479 | if (error >= 0) | ||
| 480 | error = usb_get_report(intf, | ||
| 481 | WAC_HID_FEATURE_REPORT, report_id, | ||
| 482 | rep_data, 2); | ||
| 483 | } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); | ||
| 484 | } | ||
| 411 | 485 | ||
| 412 | kfree(rep_data); | 486 | kfree(rep_data); |
| 413 | 487 | ||
| 414 | return error < 0 ? error : 0; | 488 | return error < 0 ? error : 0; |
| 415 | } | 489 | } |
| 416 | 490 | ||
| 491 | static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | ||
| 492 | struct wacom_features *features) | ||
| 493 | { | ||
| 494 | int error = 0; | ||
| 495 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 496 | struct hid_descriptor *hid_desc; | ||
| 497 | |||
| 498 | /* default device to penabled */ | ||
| 499 | features->device_type = BTN_TOOL_PEN; | ||
| 500 | |||
| 501 | /* only Tablet PCs need to retrieve the info */ | ||
| 502 | if ((features->type != TABLETPC) && (features->type != TABLETPC2FG)) | ||
| 503 | goto out; | ||
| 504 | |||
| 505 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { | ||
| 506 | if (usb_get_extra_descriptor(&interface->endpoint[0], | ||
| 507 | HID_DEVICET_REPORT, &hid_desc)) { | ||
| 508 | printk("wacom: can not retrieve extra class descriptor\n"); | ||
| 509 | error = 1; | ||
| 510 | goto out; | ||
| 511 | } | ||
| 512 | } | ||
| 513 | error = wacom_parse_hid(intf, hid_desc, features); | ||
| 514 | if (error) | ||
| 515 | goto out; | ||
| 516 | |||
| 517 | /* touch device found but size is not defined. use default */ | ||
| 518 | if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { | ||
| 519 | features->x_max = 1023; | ||
| 520 | features->y_max = 1023; | ||
| 521 | } | ||
| 522 | |||
| 523 | out: | ||
| 524 | return error; | ||
| 525 | } | ||
| 526 | |||
| 417 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 527 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 418 | { | 528 | { |
| 419 | struct usb_device *dev = interface_to_usbdev(intf); | 529 | struct usb_device *dev = interface_to_usbdev(intf); |
| 420 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 421 | struct usb_endpoint_descriptor *endpoint; | 530 | struct usb_endpoint_descriptor *endpoint; |
| 422 | struct wacom *wacom; | 531 | struct wacom *wacom; |
| 423 | struct wacom_wac *wacom_wac; | 532 | struct wacom_wac *wacom_wac; |
| 424 | struct wacom_features *features; | 533 | struct wacom_features *features; |
| 425 | struct input_dev *input_dev; | 534 | struct input_dev *input_dev; |
| 426 | int error = -ENOMEM; | 535 | int error = -ENOMEM; |
| 427 | struct hid_descriptor *hid_desc; | ||
| 428 | 536 | ||
| 429 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | 537 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); |
| 430 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); | 538 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); |
| @@ -432,7 +540,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 432 | if (!wacom || !input_dev || !wacom_wac) | 540 | if (!wacom || !input_dev || !wacom_wac) |
| 433 | goto fail1; | 541 | goto fail1; |
| 434 | 542 | ||
| 435 | wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); | 543 | wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, GFP_KERNEL, &wacom->data_dma); |
| 436 | if (!wacom_wac->data) | 544 | if (!wacom_wac->data) |
| 437 | goto fail1; | 545 | goto fail1; |
| 438 | 546 | ||
| @@ -448,7 +556,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 448 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | 556 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); |
| 449 | 557 | ||
| 450 | wacom_wac->features = features = get_wacom_feature(id); | 558 | wacom_wac->features = features = get_wacom_feature(id); |
| 451 | BUG_ON(features->pktlen > 10); | 559 | BUG_ON(features->pktlen > WACOM_PKGLEN_MAX); |
| 452 | 560 | ||
| 453 | input_dev->name = wacom_wac->features->name; | 561 | input_dev->name = wacom_wac->features->name; |
| 454 | wacom->wacom_wac = wacom_wac; | 562 | wacom->wacom_wac = wacom_wac; |
| @@ -463,47 +571,24 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 463 | 571 | ||
| 464 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | 572 | endpoint = &intf->cur_altsetting->endpoint[0].desc; |
| 465 | 573 | ||
| 466 | /* Initialize touch_x_max and touch_y_max in case it is not defined */ | 574 | /* Retrieve the physical and logical size for OEM devices */ |
| 467 | if (wacom_wac->features->type == TABLETPC) { | 575 | error = wacom_retrieve_hid_descriptor(intf, features); |
| 468 | features->touch_x_max = 1023; | 576 | if (error) |
| 469 | features->touch_y_max = 1023; | 577 | goto fail2; |
| 470 | } else { | ||
| 471 | features->touch_x_max = 0; | ||
| 472 | features->touch_y_max = 0; | ||
| 473 | } | ||
| 474 | |||
| 475 | /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ | ||
| 476 | if (wacom_wac->features->type == TABLETPC) { | ||
| 477 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { | ||
| 478 | if (usb_get_extra_descriptor(&interface->endpoint[0], | ||
| 479 | HID_DEVICET_REPORT, &hid_desc)) { | ||
| 480 | printk("wacom: can not retrive extra class descriptor\n"); | ||
| 481 | goto fail2; | ||
| 482 | } | ||
| 483 | } | ||
| 484 | error = wacom_parse_hid(intf, hid_desc, wacom_wac); | ||
| 485 | if (error) | ||
| 486 | goto fail2; | ||
| 487 | } | ||
| 488 | 578 | ||
| 489 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 579 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 490 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | | 580 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); |
| 491 | BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS); | 581 | |
| 492 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); | 582 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); |
| 493 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); | 583 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); |
| 494 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); | 584 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); |
| 495 | if (features->type == TABLETPC) { | ||
| 496 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); | ||
| 497 | input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0); | ||
| 498 | input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0); | ||
| 499 | } | ||
| 500 | input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); | 585 | input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); |
| 501 | 586 | ||
| 502 | wacom_init_input_dev(input_dev, wacom_wac); | 587 | wacom_init_input_dev(input_dev, wacom_wac); |
| 503 | 588 | ||
| 504 | usb_fill_int_urb(wacom->irq, dev, | 589 | usb_fill_int_urb(wacom->irq, dev, |
| 505 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | 590 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), |
| 506 | wacom_wac->data, wacom_wac->features->pktlen, | 591 | wacom_wac->data, features->pktlen, |
| 507 | wacom_sys_irq, wacom, endpoint->bInterval); | 592 | wacom_sys_irq, wacom, endpoint->bInterval); |
| 508 | wacom->irq->transfer_dma = wacom->data_dma; | 593 | wacom->irq->transfer_dma = wacom->data_dma; |
| 509 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 594 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| @@ -512,18 +597,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 512 | if (error) | 597 | if (error) |
| 513 | goto fail3; | 598 | goto fail3; |
| 514 | 599 | ||
| 515 | /* | 600 | /* Note that if query fails it is not a hard failure */ |
| 516 | * Ask the tablet to report tablet data if it is not a Tablet PC. | 601 | wacom_query_tablet_data(intf, features); |
| 517 | * Note that if query fails it is not a hard failure. | ||
| 518 | */ | ||
| 519 | if (wacom_wac->features->type != TABLETPC) | ||
| 520 | wacom_query_tablet_data(intf); | ||
| 521 | 602 | ||
| 522 | usb_set_intfdata(intf, wacom); | 603 | usb_set_intfdata(intf, wacom); |
| 523 | return 0; | 604 | return 0; |
| 524 | 605 | ||
| 525 | fail3: usb_free_urb(wacom->irq); | 606 | fail3: usb_free_urb(wacom->irq); |
| 526 | fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); | 607 | fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); |
| 527 | fail1: input_free_device(input_dev); | 608 | fail1: input_free_device(input_dev); |
| 528 | kfree(wacom); | 609 | kfree(wacom); |
| 529 | kfree(wacom_wac); | 610 | kfree(wacom_wac); |
| @@ -539,7 +620,7 @@ static void wacom_disconnect(struct usb_interface *intf) | |||
| 539 | usb_kill_urb(wacom->irq); | 620 | usb_kill_urb(wacom->irq); |
| 540 | input_unregister_device(wacom->dev); | 621 | input_unregister_device(wacom->dev); |
| 541 | usb_free_urb(wacom->irq); | 622 | usb_free_urb(wacom->irq); |
| 542 | usb_buffer_free(interface_to_usbdev(intf), 10, | 623 | usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, |
| 543 | wacom->wacom_wac->data, wacom->data_dma); | 624 | wacom->wacom_wac->data, wacom->data_dma); |
| 544 | kfree(wacom->wacom_wac); | 625 | kfree(wacom->wacom_wac); |
| 545 | kfree(wacom); | 626 | kfree(wacom); |
| @@ -559,12 +640,16 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 559 | static int wacom_resume(struct usb_interface *intf) | 640 | static int wacom_resume(struct usb_interface *intf) |
| 560 | { | 641 | { |
| 561 | struct wacom *wacom = usb_get_intfdata(intf); | 642 | struct wacom *wacom = usb_get_intfdata(intf); |
| 643 | struct wacom_features *features = wacom->wacom_wac->features; | ||
| 562 | int rv; | 644 | int rv; |
| 563 | 645 | ||
| 564 | mutex_lock(&wacom->lock); | 646 | mutex_lock(&wacom->lock); |
| 565 | if (wacom->open) | 647 | if (wacom->open) { |
| 566 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); | 648 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); |
| 567 | else | 649 | /* switch to wacom mode if needed */ |
| 650 | if (!wacom_retrieve_hid_descriptor(intf, features)) | ||
| 651 | wacom_query_tablet_data(intf, features); | ||
| 652 | } else | ||
| 568 | rv = 0; | 653 | rv = 0; |
| 569 | mutex_unlock(&wacom->lock); | 654 | mutex_unlock(&wacom->lock); |
| 570 | 655 | ||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index c896d6a21b7e..1056f149fe31 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/input/tablet/wacom_wac.c | 2 | * drivers/input/tablet/wacom_wac.c |
| 3 | * | 3 | * |
| 4 | * USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code | 4 | * USB Wacom tablet support - Wacom specific code |
| 5 | * | 5 | * |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| @@ -58,16 +58,15 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 58 | unsigned char *data = wacom->data; | 58 | unsigned char *data = wacom->data; |
| 59 | int prox, pressure; | 59 | int prox, pressure; |
| 60 | 60 | ||
| 61 | if (data[0] != 2) { | 61 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 62 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); | 62 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); |
| 63 | return 0; | 63 | return 0; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | prox = data[1] & 0x40; | 66 | prox = data[1] & 0x40; |
| 67 | 67 | ||
| 68 | wacom->id[0] = ERASER_DEVICE_ID; | ||
| 69 | if (prox) { | 68 | if (prox) { |
| 70 | 69 | wacom->id[0] = ERASER_DEVICE_ID; | |
| 71 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 70 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
| 72 | if (wacom->features->pressure_max > 255) | 71 | if (wacom->features->pressure_max > 255) |
| 73 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); | 72 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); |
| @@ -128,7 +127,7 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 128 | { | 127 | { |
| 129 | unsigned char *data = wacom->data; | 128 | unsigned char *data = wacom->data; |
| 130 | 129 | ||
| 131 | if (data[0] != 2) { | 130 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 132 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | 131 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); |
| 133 | return 0; | 132 | return 0; |
| 134 | } | 133 | } |
| @@ -155,14 +154,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 155 | { | 154 | { |
| 156 | unsigned char *data = wacom->data; | 155 | unsigned char *data = wacom->data; |
| 157 | int x, y, rw; | 156 | int x, y, rw; |
| 157 | static int penData = 0; | ||
| 158 | 158 | ||
| 159 | if (data[0] != 2) { | 159 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 160 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | 160 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); |
| 161 | return 0; | 161 | return 0; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | if (data[1] & 0x80) { | 164 | if (data[1] & 0x80) { |
| 165 | /* in prox and not a pad data */ | 165 | /* in prox and not a pad data */ |
| 166 | penData = 1; | ||
| 166 | 167 | ||
| 167 | switch ((data[1] >> 5) & 3) { | 168 | switch ((data[1] >> 5) & 3) { |
| 168 | 169 | ||
| @@ -232,7 +233,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 232 | switch (wacom->features->type) { | 233 | switch (wacom->features->type) { |
| 233 | case WACOM_G4: | 234 | case WACOM_G4: |
| 234 | if (data[7] & 0xf8) { | 235 | if (data[7] & 0xf8) { |
| 235 | wacom_input_sync(wcombo); /* sync last event */ | 236 | if (penData) { |
| 237 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 238 | if (!wacom->id[0]) | ||
| 239 | penData = 0; | ||
| 240 | } | ||
| 236 | wacom->id[1] = PAD_DEVICE_ID; | 241 | wacom->id[1] = PAD_DEVICE_ID; |
| 237 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 242 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); |
| 238 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | 243 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); |
| @@ -242,10 +247,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 242 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 247 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); |
| 243 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 248 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| 244 | } else if (wacom->id[1]) { | 249 | } else if (wacom->id[1]) { |
| 245 | wacom_input_sync(wcombo); /* sync last event */ | 250 | if (penData) { |
| 251 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 252 | if (!wacom->id[0]) | ||
| 253 | penData = 0; | ||
| 254 | } | ||
| 246 | wacom->id[1] = 0; | 255 | wacom->id[1] = 0; |
| 247 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 256 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); |
| 248 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | 257 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); |
| 258 | wacom_report_rel(wcombo, REL_WHEEL, 0); | ||
| 249 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | 259 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); |
| 250 | wacom_report_abs(wcombo, ABS_MISC, 0); | 260 | wacom_report_abs(wcombo, ABS_MISC, 0); |
| 251 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 261 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| @@ -253,7 +263,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 253 | break; | 263 | break; |
| 254 | case WACOM_MO: | 264 | case WACOM_MO: |
| 255 | if ((data[7] & 0xf8) || (data[8] & 0xff)) { | 265 | if ((data[7] & 0xf8) || (data[8] & 0xff)) { |
| 256 | wacom_input_sync(wcombo); /* sync last event */ | 266 | if (penData) { |
| 267 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 268 | if (!wacom->id[0]) | ||
| 269 | penData = 0; | ||
| 270 | } | ||
| 257 | wacom->id[1] = PAD_DEVICE_ID; | 271 | wacom->id[1] = PAD_DEVICE_ID; |
| 258 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | 272 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); |
| 259 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | 273 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); |
| @@ -264,7 +278,11 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 264 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 278 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); |
| 265 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 279 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| 266 | } else if (wacom->id[1]) { | 280 | } else if (wacom->id[1]) { |
| 267 | wacom_input_sync(wcombo); /* sync last event */ | 281 | if (penData) { |
| 282 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 283 | if (!wacom->id[0]) | ||
| 284 | penData = 0; | ||
| 285 | } | ||
| 268 | wacom->id[1] = 0; | 286 | wacom->id[1] = 0; |
| 269 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | 287 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); |
| 270 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | 288 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); |
| @@ -432,7 +450,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 432 | unsigned int t; | 450 | unsigned int t; |
| 433 | int idx = 0, result; | 451 | int idx = 0, result; |
| 434 | 452 | ||
| 435 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { | 453 | if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD |
| 454 | && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) { | ||
| 436 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | 455 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); |
| 437 | return 0; | 456 | return 0; |
| 438 | } | 457 | } |
| @@ -442,7 +461,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 442 | idx = data[1] & 0x01; | 461 | idx = data[1] & 0x01; |
| 443 | 462 | ||
| 444 | /* pad packets. Works as a second tool and is always in prox */ | 463 | /* pad packets. Works as a second tool and is always in prox */ |
| 445 | if (data[0] == 12) { | 464 | if (data[0] == WACOM_REPORT_INTUOSPAD) { |
| 446 | /* initiate the pad as a device */ | 465 | /* initiate the pad as a device */ |
| 447 | if (wacom->tool[1] != BTN_TOOL_FINGER) | 466 | if (wacom->tool[1] != BTN_TOOL_FINGER) |
| 448 | wacom->tool[1] = BTN_TOOL_FINGER; | 467 | wacom->tool[1] = BTN_TOOL_FINGER; |
| @@ -608,95 +627,163 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 608 | return 1; | 627 | return 1; |
| 609 | } | 628 | } |
| 610 | 629 | ||
| 630 | |||
| 631 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) | ||
| 632 | { | ||
| 633 | wacom_report_abs(wcombo, ABS_X, | ||
| 634 | (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); | ||
| 635 | wacom_report_abs(wcombo, ABS_Y, | ||
| 636 | (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); | ||
| 637 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 638 | wacom_report_key(wcombo, wacom->tool[idx], 1); | ||
| 639 | if (idx) | ||
| 640 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 641 | else | ||
| 642 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
| 643 | } | ||
| 644 | |||
| 645 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) | ||
| 646 | { | ||
| 647 | wacom_report_abs(wcombo, ABS_X, 0); | ||
| 648 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
| 649 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
| 650 | wacom_report_key(wcombo, wacom->tool[idx], 0); | ||
| 651 | if (idx) | ||
| 652 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 653 | else | ||
| 654 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
| 655 | return; | ||
| 656 | } | ||
| 657 | |||
| 658 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) | ||
| 659 | { | ||
| 660 | char *data = wacom->data; | ||
| 661 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | ||
| 662 | static int firstFinger = 0; | ||
| 663 | static int secondFinger = 0; | ||
| 664 | |||
| 665 | wacom->tool[0] = BTN_TOOL_DOUBLETAP; | ||
| 666 | wacom->id[0] = TOUCH_DEVICE_ID; | ||
| 667 | wacom->tool[1] = BTN_TOOL_TRIPLETAP; | ||
| 668 | |||
| 669 | if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { | ||
| 670 | switch (data[0]) { | ||
| 671 | case WACOM_REPORT_TPC1FG: | ||
| 672 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
| 673 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
| 674 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
| 675 | wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | ||
| 676 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 677 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
| 678 | break; | ||
| 679 | case WACOM_REPORT_TPC2FG: | ||
| 680 | /* keep this byte to send proper out-prox event */ | ||
| 681 | wacom->id[1] = data[1] & 0x03; | ||
| 682 | |||
| 683 | if (data[1] & 0x01) { | ||
| 684 | wacom_tpc_finger_in(wacom, wcombo, data, 0); | ||
| 685 | firstFinger = 1; | ||
| 686 | } else if (firstFinger) { | ||
| 687 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
| 688 | } | ||
| 689 | |||
| 690 | if (data[1] & 0x02) { | ||
| 691 | /* sync first finger data */ | ||
| 692 | if (firstFinger) | ||
| 693 | wacom_input_sync(wcombo); | ||
| 694 | |||
| 695 | wacom_tpc_finger_in(wacom, wcombo, data, 1); | ||
| 696 | secondFinger = 1; | ||
| 697 | } else if (secondFinger) { | ||
| 698 | /* sync first finger data */ | ||
| 699 | if (firstFinger) | ||
| 700 | wacom_input_sync(wcombo); | ||
| 701 | |||
| 702 | wacom_tpc_touch_out(wacom, wcombo, 1); | ||
| 703 | secondFinger = 0; | ||
| 704 | } | ||
| 705 | if (!(data[1] & 0x01)) | ||
| 706 | firstFinger = 0; | ||
| 707 | break; | ||
| 708 | } | ||
| 709 | } else { | ||
| 710 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
| 711 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
| 712 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
| 713 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 714 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
| 715 | } | ||
| 716 | return; | ||
| 717 | } | ||
| 718 | |||
| 611 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | 719 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) |
| 612 | { | 720 | { |
| 613 | char *data = wacom->data; | 721 | char *data = wacom->data; |
| 614 | int prox = 0, pressure; | 722 | int prox = 0, pressure, idx = -1; |
| 615 | static int stylusInProx, touchInProx = 1, touchOut; | 723 | static int stylusInProx, touchInProx = 1, touchOut; |
| 616 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | 724 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; |
| 617 | 725 | ||
| 618 | dbg("wacom_tpc_irq: received report #%d", data[0]); | 726 | dbg("wacom_tpc_irq: received report #%d", data[0]); |
| 619 | 727 | ||
| 620 | if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */ | 728 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG || /* single touch */ |
| 621 | if (urb->actual_length == 5) { /* with touch */ | 729 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ |
| 622 | prox = data[0] & 0x03; | 730 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ |
| 731 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ | ||
| 732 | prox = data[0] & 0x01; | ||
| 623 | } else { /* with capacity */ | 733 | } else { /* with capacity */ |
| 624 | prox = data[1] & 0x03; | 734 | if (data[0] == WACOM_REPORT_TPC1FG) |
| 735 | /* single touch */ | ||
| 736 | prox = data[1] & 0x01; | ||
| 737 | else | ||
| 738 | /* 2FG touch data */ | ||
| 739 | prox = data[1] & 0x03; | ||
| 625 | } | 740 | } |
| 626 | 741 | ||
| 627 | if (!stylusInProx) { /* stylus not in prox */ | 742 | if (!stylusInProx) { /* stylus not in prox */ |
| 628 | if (prox) { | 743 | if (prox) { |
| 629 | if (touchInProx) { | 744 | if (touchInProx) { |
| 630 | wacom->tool[1] = BTN_TOOL_DOUBLETAP; | 745 | wacom_tpc_touch_in(wacom, wcombo); |
| 631 | wacom->id[0] = TOUCH_DEVICE_ID; | ||
| 632 | if (urb->actual_length != 5) { | ||
| 633 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
| 634 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
| 635 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
| 636 | wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | ||
| 637 | } else { | ||
| 638 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
| 639 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
| 640 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
| 641 | } | ||
| 642 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 643 | wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | ||
| 644 | touchOut = 1; | 746 | touchOut = 1; |
| 645 | return 1; | 747 | return 1; |
| 646 | } | 748 | } |
| 647 | } else { | 749 | } else { |
| 648 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 750 | /* 2FGT out-prox */ |
| 649 | wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | 751 | if (data[0] == WACOM_REPORT_TPC2FG) { |
| 650 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 752 | idx = (wacom->id[1] & 0x01) - 1; |
| 753 | if (idx == 0) { | ||
| 754 | wacom_tpc_touch_out(wacom, wcombo, idx); | ||
| 755 | /* sync first finger event */ | ||
| 756 | if (wacom->id[1] & 0x02) | ||
| 757 | wacom_input_sync(wcombo); | ||
| 758 | } | ||
| 759 | idx = (wacom->id[1] & 0x02) - 1; | ||
| 760 | if (idx == 1) | ||
| 761 | wacom_tpc_touch_out(wacom, wcombo, idx); | ||
| 762 | } else /* one finger touch */ | ||
| 763 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
| 651 | touchOut = 0; | 764 | touchOut = 0; |
| 652 | touchInProx = 1; | 765 | touchInProx = 1; |
| 653 | return 1; | 766 | return 1; |
| 654 | } | 767 | } |
| 655 | } else if (touchOut || !prox) { /* force touch out-prox */ | 768 | } else if (touchOut || !prox) { /* force touch out-prox */ |
| 656 | wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); | 769 | wacom_tpc_touch_out(wacom, wcombo, 0); |
| 657 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
| 658 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
| 659 | touchOut = 0; | 770 | touchOut = 0; |
| 660 | touchInProx = 1; | 771 | touchInProx = 1; |
| 661 | return 1; | 772 | return 1; |
| 662 | } | 773 | } |
| 663 | } else if (data[0] == 2) { /* Penabled */ | 774 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ |
| 664 | prox = data[1] & 0x20; | 775 | prox = data[1] & 0x20; |
| 665 | 776 | ||
| 666 | touchInProx = 0; | 777 | touchInProx = 0; |
| 667 | 778 | ||
| 668 | wacom->id[0] = ERASER_DEVICE_ID; | ||
| 669 | |||
| 670 | /* | ||
| 671 | * if going from out of proximity into proximity select between the eraser | ||
| 672 | * and the pen based on the state of the stylus2 button, choose eraser if | ||
| 673 | * pressed else choose pen. if not a proximity change from out to in, send | ||
| 674 | * an out of proximity for previous tool then a in for new tool. | ||
| 675 | */ | ||
| 676 | if (prox) { /* in prox */ | 779 | if (prox) { /* in prox */ |
| 677 | if (!wacom->tool[0]) { | 780 | if (!wacom->id[0]) { |
| 678 | /* Going into proximity select tool */ | 781 | /* Going into proximity select tool */ |
| 679 | wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 782 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
| 680 | if (wacom->tool[1] == BTN_TOOL_PEN) | 783 | if (wacom->tool[0] == BTN_TOOL_PEN) |
| 681 | wacom->id[0] = STYLUS_DEVICE_ID; | 784 | wacom->id[0] = STYLUS_DEVICE_ID; |
| 682 | } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) { | 785 | else |
| 683 | /* | 786 | wacom->id[0] = ERASER_DEVICE_ID; |
| 684 | * was entered with stylus2 pressed | ||
| 685 | * report out proximity for previous tool | ||
| 686 | */ | ||
| 687 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 688 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
| 689 | wacom_input_sync(wcombo); | ||
| 690 | |||
| 691 | /* set new tool */ | ||
| 692 | wacom->tool[1] = BTN_TOOL_PEN; | ||
| 693 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
| 694 | return 0; | ||
| 695 | } | ||
| 696 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
| 697 | /* Unknown tool selected default to pen tool */ | ||
| 698 | wacom->tool[1] = BTN_TOOL_PEN; | ||
| 699 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
| 700 | } | 787 | } |
| 701 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 788 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); |
| 702 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | 789 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); |
| @@ -706,17 +793,21 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 706 | if (pressure < 0) | 793 | if (pressure < 0) |
| 707 | pressure = wacom->features->pressure_max + pressure + 1; | 794 | pressure = wacom->features->pressure_max + pressure + 1; |
| 708 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | 795 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); |
| 709 | wacom_report_key(wcombo, BTN_TOUCH, pressure); | 796 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); |
| 710 | } else { | 797 | } else { |
| 798 | wacom_report_abs(wcombo, ABS_X, 0); | ||
| 799 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
| 711 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 800 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); |
| 712 | wacom_report_key(wcombo, BTN_STYLUS, 0); | 801 | wacom_report_key(wcombo, BTN_STYLUS, 0); |
| 713 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 802 | wacom_report_key(wcombo, BTN_STYLUS2, 0); |
| 714 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 803 | wacom_report_key(wcombo, BTN_TOUCH, 0); |
| 804 | wacom->id[0] = 0; | ||
| 805 | /* pen is out so touch can be enabled now */ | ||
| 806 | touchInProx = 1; | ||
| 715 | } | 807 | } |
| 716 | wacom_report_key(wcombo, wacom->tool[1], prox); | 808 | wacom_report_key(wcombo, wacom->tool[0], prox); |
| 717 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 809 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); |
| 718 | stylusInProx = prox; | 810 | stylusInProx = prox; |
| 719 | wacom->tool[0] = prox; | ||
| 720 | return 1; | 811 | return 1; |
| 721 | } | 812 | } |
| 722 | return 0; | 813 | return 0; |
| @@ -751,6 +842,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | |||
| 751 | return wacom_intuos_irq(wacom_wac, wcombo); | 842 | return wacom_intuos_irq(wacom_wac, wcombo); |
| 752 | 843 | ||
| 753 | case TABLETPC: | 844 | case TABLETPC: |
| 845 | case TABLETPC2FG: | ||
| 754 | return wacom_tpc_irq(wacom_wac, wcombo); | 846 | return wacom_tpc_irq(wacom_wac, wcombo); |
| 755 | 847 | ||
| 756 | default: | 848 | default: |
| @@ -791,9 +883,17 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
| 791 | input_dev_i4s(input_dev, wacom_wac); | 883 | input_dev_i4s(input_dev, wacom_wac); |
| 792 | input_dev_i(input_dev, wacom_wac); | 884 | input_dev_i(input_dev, wacom_wac); |
| 793 | break; | 885 | break; |
| 886 | case TABLETPC2FG: | ||
| 887 | input_dev_tpc2fg(input_dev, wacom_wac); | ||
| 888 | /* fall through */ | ||
| 889 | case TABLETPC: | ||
| 890 | input_dev_tpc(input_dev, wacom_wac); | ||
| 891 | if (wacom_wac->features->device_type != BTN_TOOL_PEN) | ||
| 892 | break; /* no need to process stylus stuff */ | ||
| 893 | |||
| 894 | /* fall through */ | ||
| 794 | case PL: | 895 | case PL: |
| 795 | case PTU: | 896 | case PTU: |
| 796 | case TABLETPC: | ||
| 797 | input_dev_pl(input_dev, wacom_wac); | 897 | input_dev_pl(input_dev, wacom_wac); |
| 798 | /* fall through */ | 898 | /* fall through */ |
| 799 | case PENPARTNER: | 899 | case PENPARTNER: |
| @@ -804,66 +904,69 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
| 804 | } | 904 | } |
| 805 | 905 | ||
| 806 | static struct wacom_features wacom_features[] = { | 906 | static struct wacom_features wacom_features[] = { |
| 807 | { "Wacom Penpartner", 7, 5040, 3780, 255, 0, PENPARTNER }, | 907 | { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER }, |
| 808 | { "Wacom Graphire", 8, 10206, 7422, 511, 63, GRAPHIRE }, | 908 | { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }, |
| 809 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 63, GRAPHIRE }, | 909 | { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }, |
| 810 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 63, GRAPHIRE }, | 910 | { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE }, |
| 811 | { "Wacom Graphire3", 8, 10208, 7424, 511, 63, GRAPHIRE }, | 911 | { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE }, |
| 812 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE }, | 912 | { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }, |
| 813 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 }, | 913 | { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 }, |
| 814 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 }, | 914 | { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 }, |
| 815 | { "Wacom BambooFun 4x5", 9, 14760, 9225, 511, 63, WACOM_MO }, | 915 | { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }, |
| 816 | { "Wacom BambooFun 6x8", 9, 21648, 13530, 511, 63, WACOM_MO }, | 916 | { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO }, |
| 817 | { "Wacom Bamboo1 Medium",8, 16704, 12064, 511, 63, GRAPHIRE }, | 917 | { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }, |
| 818 | { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 918 | { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }, |
| 819 | { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE }, | 919 | { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE }, |
| 820 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 920 | { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }, |
| 821 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, | 921 | { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE }, |
| 822 | { "Wacom PenPartner2", 8, 3250, 2320, 511, 63, GRAPHIRE }, | 922 | { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE }, |
| 823 | { "Wacom Bamboo", 9, 14760, 9225, 511, 63, WACOM_MO }, | 923 | { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }, |
| 824 | { "Wacom Bamboo1", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 924 | { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }, |
| 825 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | 925 | { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }, |
| 826 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 926 | { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, |
| 827 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, | 927 | { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }, |
| 828 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, | 928 | { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }, |
| 829 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, | 929 | { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }, |
| 830 | { "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, | 930 | { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL }, |
| 831 | { "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, | 931 | { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL }, |
| 832 | { "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, | 932 | { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL }, |
| 833 | { "Wacom PL600SX", 8, 6260, 5016, 255, 0, PL }, | 933 | { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL }, |
| 834 | { "Wacom PL550", 8, 6144, 4608, 511, 0, PL }, | 934 | { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL }, |
| 835 | { "Wacom PL800", 8, 7220, 5780, 511, 0, PL }, | 935 | { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL }, |
| 836 | { "Wacom PL700", 8, 6758, 5406, 511, 0, PL }, | 936 | { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL }, |
| 837 | { "Wacom PL510", 8, 6282, 4762, 511, 0, PL }, | 937 | { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }, |
| 838 | { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, | 938 | { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL }, |
| 839 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, | 939 | { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }, |
| 840 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, | 940 | { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }, |
| 841 | { "Wacom DTF720a", 8, 6858, 5506, 511, 0, PL }, | 941 | { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }, |
| 842 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, | 942 | { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU }, |
| 843 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | 943 | { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }, |
| 844 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 944 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, |
| 845 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, | 945 | { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }, |
| 846 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, | 946 | { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }, |
| 847 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, | 947 | { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }, |
| 848 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, | 948 | { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S }, |
| 849 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, | 949 | { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 }, |
| 850 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, | 950 | { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 }, |
| 851 | { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L }, | 951 | { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L }, |
| 852 | { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, | 952 | { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L }, |
| 853 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, | 953 | { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 }, |
| 854 | { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, | 954 | { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S }, |
| 855 | { "Wacom Intuos4 4x6", 10, 31496, 19685, 2047, 63, INTUOS4S }, | 955 | { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S }, |
| 856 | { "Wacom Intuos4 6x9", 10, 44704, 27940, 2047, 63, INTUOS4 }, | 956 | { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 }, |
| 857 | { "Wacom Intuos4 8x13", 10, 65024, 40640, 2047, 63, INTUOS4L }, | 957 | { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }, |
| 858 | { "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L }, | 958 | { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }, |
| 859 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, | 959 | { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }, |
| 860 | { "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE }, | 960 | { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }, |
| 861 | { "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE }, | 961 | { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }, |
| 862 | { "Wacom DTU1931", 8, 37832, 30305, 511, 0, PL }, | 962 | { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }, |
| 863 | { "Wacom ISDv4 90", 8, 26202, 16325, 255, 0, TABLETPC }, | 963 | { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, |
| 864 | { "Wacom ISDv4 93", 8, 26202, 16325, 255, 0, TABLETPC }, | 964 | { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, |
| 865 | { "Wacom ISDv4 9A", 8, 26202, 16325, 255, 0, TABLETPC }, | 965 | { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, |
| 866 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 966 | { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }, |
| 967 | { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }, | ||
| 968 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }, | ||
| 969 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, | ||
| 867 | { } | 970 | { } |
| 868 | }; | 971 | }; |
| 869 | 972 | ||
| @@ -927,6 +1030,9 @@ static struct usb_device_id wacom_ids[] = { | |||
| 927 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, | 1030 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, |
| 928 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, | 1031 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, |
| 929 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, | 1032 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, |
| 1033 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) }, | ||
| 1034 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) }, | ||
| 1035 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) }, | ||
| 930 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | 1036 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, |
| 931 | { } | 1037 | { } |
| 932 | }; | 1038 | }; |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index c10235aba7e5..ee01e1902785 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
| @@ -9,12 +9,33 @@ | |||
| 9 | #ifndef WACOM_WAC_H | 9 | #ifndef WACOM_WAC_H |
| 10 | #define WACOM_WAC_H | 10 | #define WACOM_WAC_H |
| 11 | 11 | ||
| 12 | /* maximum packet length for USB devices */ | ||
| 13 | #define WACOM_PKGLEN_MAX 32 | ||
| 14 | |||
| 15 | /* packet length for individual models */ | ||
| 16 | #define WACOM_PKGLEN_PENPRTN 7 | ||
| 17 | #define WACOM_PKGLEN_GRAPHIRE 8 | ||
| 18 | #define WACOM_PKGLEN_BBFUN 9 | ||
| 19 | #define WACOM_PKGLEN_INTUOS 10 | ||
| 20 | #define WACOM_PKGLEN_PENABLED 8 | ||
| 21 | #define WACOM_PKGLEN_TPC1FG 5 | ||
| 22 | #define WACOM_PKGLEN_TPC2FG 14 | ||
| 23 | |||
| 24 | /* device IDs */ | ||
| 12 | #define STYLUS_DEVICE_ID 0x02 | 25 | #define STYLUS_DEVICE_ID 0x02 |
| 13 | #define TOUCH_DEVICE_ID 0x03 | 26 | #define TOUCH_DEVICE_ID 0x03 |
| 14 | #define CURSOR_DEVICE_ID 0x06 | 27 | #define CURSOR_DEVICE_ID 0x06 |
| 15 | #define ERASER_DEVICE_ID 0x0A | 28 | #define ERASER_DEVICE_ID 0x0A |
| 16 | #define PAD_DEVICE_ID 0x0F | 29 | #define PAD_DEVICE_ID 0x0F |
| 17 | 30 | ||
| 31 | /* wacom data packet report IDs */ | ||
| 32 | #define WACOM_REPORT_PENABLED 2 | ||
| 33 | #define WACOM_REPORT_INTUOSREAD 5 | ||
| 34 | #define WACOM_REPORT_INTUOSWRITE 6 | ||
| 35 | #define WACOM_REPORT_INTUOSPAD 12 | ||
| 36 | #define WACOM_REPORT_TPC1FG 6 | ||
| 37 | #define WACOM_REPORT_TPC2FG 13 | ||
| 38 | |||
| 18 | enum { | 39 | enum { |
| 19 | PENPARTNER = 0, | 40 | PENPARTNER = 0, |
| 20 | GRAPHIRE, | 41 | GRAPHIRE, |
| @@ -32,6 +53,7 @@ enum { | |||
| 32 | WACOM_BEE, | 53 | WACOM_BEE, |
| 33 | WACOM_MO, | 54 | WACOM_MO, |
| 34 | TABLETPC, | 55 | TABLETPC, |
| 56 | TABLETPC2FG, | ||
| 35 | MAX_TYPE | 57 | MAX_TYPE |
| 36 | }; | 58 | }; |
| 37 | 59 | ||
| @@ -43,8 +65,11 @@ struct wacom_features { | |||
| 43 | int pressure_max; | 65 | int pressure_max; |
| 44 | int distance_max; | 66 | int distance_max; |
| 45 | int type; | 67 | int type; |
| 46 | int touch_x_max; | 68 | int device_type; |
| 47 | int touch_y_max; | 69 | int x_phy; |
| 70 | int y_phy; | ||
| 71 | unsigned char unit; | ||
| 72 | unsigned char unitExpo; | ||
| 48 | }; | 73 | }; |
| 49 | 74 | ||
| 50 | struct wacom_wac { | 75 | struct wacom_wac { |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 32fc8ba039aa..dfafc76da4fb 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -450,6 +450,18 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 450 | To compile this driver as a module, choose M here: the | 450 | To compile this driver as a module, choose M here: the |
| 451 | module will be called usbtouchscreen. | 451 | module will be called usbtouchscreen. |
| 452 | 452 | ||
| 453 | config TOUCHSCREEN_MC13783 | ||
| 454 | tristate "Freescale MC13783 touchscreen input driver" | ||
| 455 | depends on MFD_MC13783 | ||
| 456 | help | ||
| 457 | Say Y here if you have an Freescale MC13783 PMIC on your | ||
| 458 | board and want to use its touchscreen | ||
| 459 | |||
| 460 | If unsure, say N. | ||
| 461 | |||
| 462 | To compile this driver as a module, choose M here: the | ||
| 463 | module will be called mc13783_ts. | ||
| 464 | |||
| 453 | config TOUCHSCREEN_USB_EGALAX | 465 | config TOUCHSCREEN_USB_EGALAX |
| 454 | default y | 466 | default y |
| 455 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED | 467 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index f1f59c9e1211..d61a3b4def9a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -18,6 +18,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | |||
| 18 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 18 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
| 19 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 19 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
| 20 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 20 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
| 21 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o | ||
| 21 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o | 22 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o |
| 22 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o | 23 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o |
| 23 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 24 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c new file mode 100644 index 000000000000..be115b3b65eb --- /dev/null +++ b/drivers/input/touchscreen/mc13783_ts.c | |||
| @@ -0,0 +1,258 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the Freescale Semiconductor MC13783 touchscreen. | ||
| 3 | * | ||
| 4 | * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. | ||
| 5 | * Copyright (C) 2009 Sascha Hauer, Pengutronix | ||
| 6 | * | ||
| 7 | * Initial development of this code was funded by | ||
| 8 | * Phytec Messtechnik GmbH, http://www.phytec.de/ | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License version 2 as published by | ||
| 12 | * the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/mfd/mc13783.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | |||
| 22 | #define MC13783_TS_NAME "mc13783-ts" | ||
| 23 | |||
| 24 | #define DEFAULT_SAMPLE_TOLERANCE 300 | ||
| 25 | |||
| 26 | static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE; | ||
| 27 | module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR); | ||
| 28 | MODULE_PARM_DESC(sample_tolerance, | ||
| 29 | "If the minimal and maximal value read out for one axis (out " | ||
| 30 | "of three) differ by this value (default: " | ||
| 31 | __stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading " | ||
| 32 | "is supposed to be wrong and is discarded. Set to 0 to " | ||
| 33 | "disable this check."); | ||
| 34 | |||
| 35 | struct mc13783_ts_priv { | ||
| 36 | struct input_dev *idev; | ||
| 37 | struct mc13783 *mc13783; | ||
| 38 | struct delayed_work work; | ||
| 39 | struct workqueue_struct *workq; | ||
| 40 | unsigned int sample[4]; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static irqreturn_t mc13783_ts_handler(int irq, void *data) | ||
| 44 | { | ||
| 45 | struct mc13783_ts_priv *priv = data; | ||
| 46 | |||
| 47 | mc13783_ackirq(priv->mc13783, irq); | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Kick off reading coordinates. Note that if work happens already | ||
| 51 | * be queued for future execution (it rearms itself) it will not | ||
| 52 | * be rescheduled for immediate execution here. However the rearm | ||
| 53 | * delay is HZ / 50 which is acceptable. | ||
| 54 | */ | ||
| 55 | queue_delayed_work(priv->workq, &priv->work, 0); | ||
| 56 | |||
| 57 | return IRQ_HANDLED; | ||
| 58 | } | ||
| 59 | |||
| 60 | #define sort3(a0, a1, a2) ({ \ | ||
| 61 | if (a0 > a1) \ | ||
| 62 | swap(a0, a1); \ | ||
| 63 | if (a1 > a2) \ | ||
| 64 | swap(a1, a2); \ | ||
| 65 | if (a0 > a1) \ | ||
| 66 | swap(a0, a1); \ | ||
| 67 | }) | ||
| 68 | |||
| 69 | static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv) | ||
| 70 | { | ||
| 71 | struct input_dev *idev = priv->idev; | ||
| 72 | int x0, x1, x2, y0, y1, y2; | ||
| 73 | int cr0, cr1; | ||
| 74 | |||
| 75 | /* | ||
| 76 | * the values are 10-bit wide only, but the two least significant | ||
| 77 | * bits are for future 12 bit use and reading yields 0 | ||
| 78 | */ | ||
| 79 | x0 = priv->sample[0] & 0xfff; | ||
| 80 | x1 = priv->sample[1] & 0xfff; | ||
| 81 | x2 = priv->sample[2] & 0xfff; | ||
| 82 | y0 = priv->sample[3] & 0xfff; | ||
| 83 | y1 = (priv->sample[0] >> 12) & 0xfff; | ||
| 84 | y2 = (priv->sample[1] >> 12) & 0xfff; | ||
| 85 | cr0 = (priv->sample[2] >> 12) & 0xfff; | ||
| 86 | cr1 = (priv->sample[3] >> 12) & 0xfff; | ||
| 87 | |||
| 88 | dev_dbg(&idev->dev, | ||
| 89 | "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n", | ||
| 90 | x0, x1, x2, y0, y1, y2, cr0, cr1); | ||
| 91 | |||
| 92 | sort3(x0, x1, x2); | ||
| 93 | sort3(y0, y1, y2); | ||
| 94 | |||
| 95 | cr0 = (cr0 + cr1) / 2; | ||
| 96 | |||
| 97 | if (!cr0 || !sample_tolerance || | ||
| 98 | (x2 - x0 < sample_tolerance && | ||
| 99 | y2 - y0 < sample_tolerance)) { | ||
| 100 | /* report the median coordinate and average pressure */ | ||
| 101 | if (cr0) { | ||
| 102 | input_report_abs(idev, ABS_X, x1); | ||
| 103 | input_report_abs(idev, ABS_Y, y1); | ||
| 104 | |||
| 105 | dev_dbg(&idev->dev, "report (%d, %d, %d)\n", | ||
| 106 | x1, y1, 0x1000 - cr0); | ||
| 107 | queue_delayed_work(priv->workq, &priv->work, HZ / 50); | ||
| 108 | } else | ||
| 109 | dev_dbg(&idev->dev, "report release\n"); | ||
| 110 | |||
| 111 | input_report_abs(idev, ABS_PRESSURE, | ||
| 112 | cr0 ? 0x1000 - cr0 : cr0); | ||
| 113 | input_report_key(idev, BTN_TOUCH, cr0); | ||
| 114 | input_sync(idev); | ||
| 115 | } else | ||
| 116 | dev_dbg(&idev->dev, "discard event\n"); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void mc13783_ts_work(struct work_struct *work) | ||
| 120 | { | ||
| 121 | struct mc13783_ts_priv *priv = | ||
| 122 | container_of(work, struct mc13783_ts_priv, work.work); | ||
| 123 | unsigned int mode = MC13783_ADC_MODE_TS; | ||
| 124 | unsigned int channel = 12; | ||
| 125 | |||
| 126 | if (mc13783_adc_do_conversion(priv->mc13783, | ||
| 127 | mode, channel, priv->sample) == 0) | ||
| 128 | mc13783_ts_report_sample(priv); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int mc13783_ts_open(struct input_dev *dev) | ||
| 132 | { | ||
| 133 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); | ||
| 134 | int ret; | ||
| 135 | |||
| 136 | mc13783_lock(priv->mc13783); | ||
| 137 | |||
| 138 | mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS); | ||
| 139 | |||
| 140 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS, | ||
| 141 | mc13783_ts_handler, MC13783_TS_NAME, priv); | ||
| 142 | if (ret) | ||
| 143 | goto out; | ||
| 144 | |||
| 145 | ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0, | ||
| 146 | MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0); | ||
| 147 | if (ret) | ||
| 148 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv); | ||
| 149 | out: | ||
| 150 | mc13783_unlock(priv->mc13783); | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | static void mc13783_ts_close(struct input_dev *dev) | ||
| 155 | { | ||
| 156 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); | ||
| 157 | |||
| 158 | mc13783_lock(priv->mc13783); | ||
| 159 | mc13783_reg_rmw(priv->mc13783, MC13783_ADC0, | ||
| 160 | MC13783_ADC0_TSMOD_MASK, 0); | ||
| 161 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv); | ||
| 162 | mc13783_unlock(priv->mc13783); | ||
| 163 | |||
| 164 | cancel_delayed_work_sync(&priv->work); | ||
| 165 | } | ||
| 166 | |||
| 167 | static int __init mc13783_ts_probe(struct platform_device *pdev) | ||
| 168 | { | ||
| 169 | struct mc13783_ts_priv *priv; | ||
| 170 | struct input_dev *idev; | ||
| 171 | int ret = -ENOMEM; | ||
| 172 | |||
| 173 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 174 | idev = input_allocate_device(); | ||
| 175 | if (!priv || !idev) | ||
| 176 | goto err_free_mem; | ||
| 177 | |||
| 178 | INIT_DELAYED_WORK(&priv->work, mc13783_ts_work); | ||
| 179 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
| 180 | priv->idev = idev; | ||
| 181 | |||
| 182 | /* | ||
| 183 | * We need separate workqueue because mc13783_adc_do_conversion | ||
| 184 | * uses keventd and thus would deadlock. | ||
| 185 | */ | ||
| 186 | priv->workq = create_singlethread_workqueue("mc13783_ts"); | ||
| 187 | if (!priv->workq) | ||
| 188 | goto err_free_mem; | ||
| 189 | |||
| 190 | idev->name = MC13783_TS_NAME; | ||
| 191 | idev->dev.parent = &pdev->dev; | ||
| 192 | |||
| 193 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 194 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 195 | input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0); | ||
| 196 | input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0); | ||
| 197 | input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0); | ||
| 198 | |||
| 199 | idev->open = mc13783_ts_open; | ||
| 200 | idev->close = mc13783_ts_close; | ||
| 201 | |||
| 202 | input_set_drvdata(idev, priv); | ||
| 203 | |||
| 204 | ret = input_register_device(priv->idev); | ||
| 205 | if (ret) { | ||
| 206 | dev_err(&pdev->dev, | ||
| 207 | "register input device failed with %d\n", ret); | ||
| 208 | goto err_destroy_wq; | ||
| 209 | } | ||
| 210 | |||
| 211 | platform_set_drvdata(pdev, priv); | ||
| 212 | return 0; | ||
| 213 | |||
| 214 | err_destroy_wq: | ||
| 215 | destroy_workqueue(priv->workq); | ||
| 216 | err_free_mem: | ||
| 217 | input_free_device(idev); | ||
| 218 | kfree(priv); | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | static int __devexit mc13783_ts_remove(struct platform_device *pdev) | ||
| 223 | { | ||
| 224 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); | ||
| 225 | |||
| 226 | platform_set_drvdata(pdev, NULL); | ||
| 227 | |||
| 228 | destroy_workqueue(priv->workq); | ||
| 229 | input_unregister_device(priv->idev); | ||
| 230 | kfree(priv); | ||
| 231 | |||
| 232 | return 0; | ||
| 233 | } | ||
| 234 | |||
| 235 | static struct platform_driver mc13783_ts_driver = { | ||
| 236 | .remove = __devexit_p(mc13783_ts_remove), | ||
| 237 | .driver = { | ||
| 238 | .owner = THIS_MODULE, | ||
| 239 | .name = MC13783_TS_NAME, | ||
| 240 | }, | ||
| 241 | }; | ||
| 242 | |||
| 243 | static int __init mc13783_ts_init(void) | ||
| 244 | { | ||
| 245 | return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe); | ||
| 246 | } | ||
| 247 | module_init(mc13783_ts_init); | ||
| 248 | |||
| 249 | static void __exit mc13783_ts_exit(void) | ||
| 250 | { | ||
| 251 | platform_driver_unregister(&mc13783_ts_driver); | ||
| 252 | } | ||
| 253 | module_exit(mc13783_ts_exit); | ||
| 254 | |||
| 255 | MODULE_DESCRIPTION("MC13783 input touchscreen driver"); | ||
| 256 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
| 257 | MODULE_LICENSE("GPL v2"); | ||
| 258 | MODULE_ALIAS("platform:" MC13783_TS_NAME); | ||
diff --git a/include/linux/i8042.h b/include/linux/i8042.h index 60c3360ef6ad..9bf6870ee5f4 100644 --- a/include/linux/i8042.h +++ b/include/linux/i8042.h | |||
| @@ -39,6 +39,10 @@ void i8042_lock_chip(void); | |||
| 39 | void i8042_unlock_chip(void); | 39 | void i8042_unlock_chip(void); |
| 40 | int i8042_command(unsigned char *param, int command); | 40 | int i8042_command(unsigned char *param, int command); |
| 41 | bool i8042_check_port_owner(const struct serio *); | 41 | bool i8042_check_port_owner(const struct serio *); |
| 42 | int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 43 | struct serio *serio)); | ||
| 44 | int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 45 | struct serio *serio)); | ||
| 42 | 46 | ||
| 43 | #else | 47 | #else |
| 44 | 48 | ||
| @@ -52,7 +56,7 @@ void i8042_unlock_chip(void) | |||
| 52 | 56 | ||
| 53 | int i8042_command(unsigned char *param, int command) | 57 | int i8042_command(unsigned char *param, int command) |
| 54 | { | 58 | { |
| 55 | return -ENOSYS; | 59 | return -ENODEV; |
| 56 | } | 60 | } |
| 57 | 61 | ||
| 58 | bool i8042_check_port_owner(const struct serio *serio) | 62 | bool i8042_check_port_owner(const struct serio *serio) |
| @@ -60,6 +64,18 @@ bool i8042_check_port_owner(const struct serio *serio) | |||
| 60 | return false; | 64 | return false; |
| 61 | } | 65 | } |
| 62 | 66 | ||
| 67 | int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 68 | struct serio *serio)) | ||
| 69 | { | ||
| 70 | return -ENODEV; | ||
| 71 | } | ||
| 72 | |||
| 73 | int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 74 | struct serio *serio)) | ||
| 75 | { | ||
| 76 | return -ENODEV; | ||
| 77 | } | ||
| 78 | |||
| 63 | #endif | 79 | #endif |
| 64 | 80 | ||
| 65 | #endif | 81 | #endif |
