diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/input-mt.c | 30 | ||||
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 8 | ||||
-rw-r--r-- | drivers/input/keyboard/cap1106.c | 4 | ||||
-rw-r--r-- | drivers/input/keyboard/matrix_keypad.c | 9 | ||||
-rw-r--r-- | drivers/input/mouse/alps.c | 8 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.c | 148 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.h | 3 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.c | 68 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 11 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics_usb.c | 6 | ||||
-rw-r--r-- | drivers/input/mouse/trackpoint.c | 3 | ||||
-rw-r--r-- | drivers/input/serio/i8042-sparcio.h | 3 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 22 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/serport.c | 45 | ||||
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 25 | ||||
-rw-r--r-- | drivers/input/touchscreen/wm9712.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/wm9713.c | 2 |
19 files changed, 332 insertions, 69 deletions
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index c30204f2fa30..fbe29fcb15c5 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c | |||
@@ -236,6 +236,18 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) | |||
236 | } | 236 | } |
237 | EXPORT_SYMBOL(input_mt_report_pointer_emulation); | 237 | EXPORT_SYMBOL(input_mt_report_pointer_emulation); |
238 | 238 | ||
239 | static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt) | ||
240 | { | ||
241 | int i; | ||
242 | |||
243 | for (i = 0; i < mt->num_slots; i++) { | ||
244 | if (!input_mt_is_used(mt, &mt->slots[i])) { | ||
245 | input_mt_slot(dev, i); | ||
246 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
239 | /** | 251 | /** |
240 | * input_mt_drop_unused() - Inactivate slots not seen in this frame | 252 | * input_mt_drop_unused() - Inactivate slots not seen in this frame |
241 | * @dev: input device with allocated MT slots | 253 | * @dev: input device with allocated MT slots |
@@ -245,19 +257,11 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation); | |||
245 | void input_mt_drop_unused(struct input_dev *dev) | 257 | void input_mt_drop_unused(struct input_dev *dev) |
246 | { | 258 | { |
247 | struct input_mt *mt = dev->mt; | 259 | struct input_mt *mt = dev->mt; |
248 | int i; | ||
249 | 260 | ||
250 | if (!mt) | 261 | if (mt) { |
251 | return; | 262 | __input_mt_drop_unused(dev, mt); |
252 | 263 | mt->frame++; | |
253 | for (i = 0; i < mt->num_slots; i++) { | ||
254 | if (!input_mt_is_used(mt, &mt->slots[i])) { | ||
255 | input_mt_slot(dev, i); | ||
256 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); | ||
257 | } | ||
258 | } | 264 | } |
259 | |||
260 | mt->frame++; | ||
261 | } | 265 | } |
262 | EXPORT_SYMBOL(input_mt_drop_unused); | 266 | EXPORT_SYMBOL(input_mt_drop_unused); |
263 | 267 | ||
@@ -278,12 +282,14 @@ void input_mt_sync_frame(struct input_dev *dev) | |||
278 | return; | 282 | return; |
279 | 283 | ||
280 | if (mt->flags & INPUT_MT_DROP_UNUSED) | 284 | if (mt->flags & INPUT_MT_DROP_UNUSED) |
281 | input_mt_drop_unused(dev); | 285 | __input_mt_drop_unused(dev, mt); |
282 | 286 | ||
283 | if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT)) | 287 | if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT)) |
284 | use_count = true; | 288 | use_count = true; |
285 | 289 | ||
286 | input_mt_report_pointer_emulation(dev, use_count); | 290 | input_mt_report_pointer_emulation(dev, use_count); |
291 | |||
292 | mt->frame++; | ||
287 | } | 293 | } |
288 | EXPORT_SYMBOL(input_mt_sync_frame); | 294 | EXPORT_SYMBOL(input_mt_sync_frame); |
289 | 295 | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 2dd1d0dd4f7d..6f5d79569136 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -1791,14 +1791,6 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { | |||
1791 | { | 1791 | { |
1792 | .matches = { | 1792 | .matches = { |
1793 | DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), | 1793 | DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), |
1794 | DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"), | ||
1795 | }, | ||
1796 | .callback = atkbd_deactivate_fixup, | ||
1797 | }, | ||
1798 | { | ||
1799 | .matches = { | ||
1800 | DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), | ||
1801 | DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"), | ||
1802 | }, | 1794 | }, |
1803 | .callback = atkbd_deactivate_fixup, | 1795 | .callback = atkbd_deactivate_fixup, |
1804 | }, | 1796 | }, |
diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c index 180b184ab90f..d70b65a14ced 100644 --- a/drivers/input/keyboard/cap1106.c +++ b/drivers/input/keyboard/cap1106.c | |||
@@ -33,8 +33,8 @@ | |||
33 | #define CAP1106_REG_SENSOR_CONFIG 0x22 | 33 | #define CAP1106_REG_SENSOR_CONFIG 0x22 |
34 | #define CAP1106_REG_SENSOR_CONFIG2 0x23 | 34 | #define CAP1106_REG_SENSOR_CONFIG2 0x23 |
35 | #define CAP1106_REG_SAMPLING_CONFIG 0x24 | 35 | #define CAP1106_REG_SAMPLING_CONFIG 0x24 |
36 | #define CAP1106_REG_CALIBRATION 0x25 | 36 | #define CAP1106_REG_CALIBRATION 0x26 |
37 | #define CAP1106_REG_INT_ENABLE 0x26 | 37 | #define CAP1106_REG_INT_ENABLE 0x27 |
38 | #define CAP1106_REG_REPEAT_RATE 0x28 | 38 | #define CAP1106_REG_REPEAT_RATE 0x28 |
39 | #define CAP1106_REG_MT_CONFIG 0x2a | 39 | #define CAP1106_REG_MT_CONFIG 0x2a |
40 | #define CAP1106_REG_MT_PATTERN_CONFIG 0x2b | 40 | #define CAP1106_REG_MT_PATTERN_CONFIG 0x2b |
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 8d2e19e81e1e..e651fa692afe 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -332,23 +332,24 @@ static int matrix_keypad_init_gpio(struct platform_device *pdev, | |||
332 | } | 332 | } |
333 | 333 | ||
334 | if (pdata->clustered_irq > 0) { | 334 | if (pdata->clustered_irq > 0) { |
335 | err = request_irq(pdata->clustered_irq, | 335 | err = request_any_context_irq(pdata->clustered_irq, |
336 | matrix_keypad_interrupt, | 336 | matrix_keypad_interrupt, |
337 | pdata->clustered_irq_flags, | 337 | pdata->clustered_irq_flags, |
338 | "matrix-keypad", keypad); | 338 | "matrix-keypad", keypad); |
339 | if (err) { | 339 | if (err < 0) { |
340 | dev_err(&pdev->dev, | 340 | dev_err(&pdev->dev, |
341 | "Unable to acquire clustered interrupt\n"); | 341 | "Unable to acquire clustered interrupt\n"); |
342 | goto err_free_rows; | 342 | goto err_free_rows; |
343 | } | 343 | } |
344 | } else { | 344 | } else { |
345 | for (i = 0; i < pdata->num_row_gpios; i++) { | 345 | for (i = 0; i < pdata->num_row_gpios; i++) { |
346 | err = request_irq(gpio_to_irq(pdata->row_gpios[i]), | 346 | err = request_any_context_irq( |
347 | gpio_to_irq(pdata->row_gpios[i]), | ||
347 | matrix_keypad_interrupt, | 348 | matrix_keypad_interrupt, |
348 | IRQF_TRIGGER_RISING | | 349 | IRQF_TRIGGER_RISING | |
349 | IRQF_TRIGGER_FALLING, | 350 | IRQF_TRIGGER_FALLING, |
350 | "matrix-keypad", keypad); | 351 | "matrix-keypad", keypad); |
351 | if (err) { | 352 | if (err < 0) { |
352 | dev_err(&pdev->dev, | 353 | dev_err(&pdev->dev, |
353 | "Unable to acquire interrupt for GPIO line %i\n", | 354 | "Unable to acquire interrupt for GPIO line %i\n", |
354 | pdata->row_gpios[i]); | 355 | pdata->row_gpios[i]); |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index a59a1a64b674..35a49bf57227 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -2234,8 +2234,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2234 | return 0; | 2234 | return 0; |
2235 | } | 2235 | } |
2236 | 2236 | ||
2237 | psmouse_info(psmouse, | 2237 | psmouse_dbg(psmouse, |
2238 | "Unknown ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); | 2238 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); |
2239 | 2239 | ||
2240 | return -EINVAL; | 2240 | return -EINVAL; |
2241 | } | 2241 | } |
@@ -2373,6 +2373,10 @@ int alps_init(struct psmouse *psmouse) | |||
2373 | dev2->keybit[BIT_WORD(BTN_LEFT)] = | 2373 | dev2->keybit[BIT_WORD(BTN_LEFT)] = |
2374 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 2374 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
2375 | 2375 | ||
2376 | __set_bit(INPUT_PROP_POINTER, dev2->propbit); | ||
2377 | if (priv->flags & ALPS_DUALPOINT) | ||
2378 | __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit); | ||
2379 | |||
2376 | if (input_register_device(priv->dev2)) | 2380 | if (input_register_device(priv->dev2)) |
2377 | goto init_fail; | 2381 | goto init_fail; |
2378 | 2382 | ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index ee2a04d90d20..06fc6e76ffbe 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/input/mt.h> | 18 | #include <linux/input/mt.h> |
19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
20 | #include <linux/libps2.h> | 20 | #include <linux/libps2.h> |
21 | #include <asm/unaligned.h> | ||
21 | #include "psmouse.h" | 22 | #include "psmouse.h" |
22 | #include "elantech.h" | 23 | #include "elantech.h" |
23 | 24 | ||
@@ -403,6 +404,68 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
403 | input_sync(dev); | 404 | input_sync(dev); |
404 | } | 405 | } |
405 | 406 | ||
407 | static void elantech_report_trackpoint(struct psmouse *psmouse, | ||
408 | int packet_type) | ||
409 | { | ||
410 | /* | ||
411 | * byte 0: 0 0 sx sy 0 M R L | ||
412 | * byte 1:~sx 0 0 0 0 0 0 0 | ||
413 | * byte 2:~sy 0 0 0 0 0 0 0 | ||
414 | * byte 3: 0 0 ~sy ~sx 0 1 1 0 | ||
415 | * byte 4: x7 x6 x5 x4 x3 x2 x1 x0 | ||
416 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | ||
417 | * | ||
418 | * x and y are written in two's complement spread | ||
419 | * over 9 bits with sx/sy the relative top bit and | ||
420 | * x7..x0 and y7..y0 the lower bits. | ||
421 | * The sign of y is opposite to what the input driver | ||
422 | * expects for a relative movement | ||
423 | */ | ||
424 | |||
425 | struct elantech_data *etd = psmouse->private; | ||
426 | struct input_dev *tp_dev = etd->tp_dev; | ||
427 | unsigned char *packet = psmouse->packet; | ||
428 | int x, y; | ||
429 | u32 t; | ||
430 | |||
431 | if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev, | ||
432 | !tp_dev, | ||
433 | psmouse_fmt("Unexpected trackpoint message\n"))) { | ||
434 | if (etd->debug == 1) | ||
435 | elantech_packet_dump(psmouse); | ||
436 | return; | ||
437 | } | ||
438 | |||
439 | t = get_unaligned_le32(&packet[0]); | ||
440 | |||
441 | switch (t & ~7U) { | ||
442 | case 0x06000030U: | ||
443 | case 0x16008020U: | ||
444 | case 0x26800010U: | ||
445 | case 0x36808000U: | ||
446 | x = packet[4] - (int)((packet[1]^0x80) << 1); | ||
447 | y = (int)((packet[2]^0x80) << 1) - packet[5]; | ||
448 | |||
449 | input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01); | ||
450 | input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02); | ||
451 | input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04); | ||
452 | |||
453 | input_report_rel(tp_dev, REL_X, x); | ||
454 | input_report_rel(tp_dev, REL_Y, y); | ||
455 | |||
456 | input_sync(tp_dev); | ||
457 | |||
458 | break; | ||
459 | |||
460 | default: | ||
461 | /* Dump unexpected packet sequences if debug=1 (default) */ | ||
462 | if (etd->debug == 1) | ||
463 | elantech_packet_dump(psmouse); | ||
464 | |||
465 | break; | ||
466 | } | ||
467 | } | ||
468 | |||
406 | /* | 469 | /* |
407 | * Interpret complete data packets and report absolute mode input events for | 470 | * Interpret complete data packets and report absolute mode input events for |
408 | * hardware version 3. (12 byte packets for two fingers) | 471 | * hardware version 3. (12 byte packets for two fingers) |
@@ -715,6 +778,8 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) | |||
715 | 778 | ||
716 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) | 779 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) |
717 | return PACKET_V3_TAIL; | 780 | return PACKET_V3_TAIL; |
781 | if ((packet[3] & 0x0f) == 0x06) | ||
782 | return PACKET_TRACKPOINT; | ||
718 | } | 783 | } |
719 | 784 | ||
720 | return PACKET_UNKNOWN; | 785 | return PACKET_UNKNOWN; |
@@ -791,14 +856,23 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | |||
791 | 856 | ||
792 | case 3: | 857 | case 3: |
793 | packet_type = elantech_packet_check_v3(psmouse); | 858 | packet_type = elantech_packet_check_v3(psmouse); |
794 | /* ignore debounce */ | 859 | switch (packet_type) { |
795 | if (packet_type == PACKET_DEBOUNCE) | 860 | case PACKET_UNKNOWN: |
796 | return PSMOUSE_FULL_PACKET; | ||
797 | |||
798 | if (packet_type == PACKET_UNKNOWN) | ||
799 | return PSMOUSE_BAD_DATA; | 861 | return PSMOUSE_BAD_DATA; |
800 | 862 | ||
801 | elantech_report_absolute_v3(psmouse, packet_type); | 863 | case PACKET_DEBOUNCE: |
864 | /* ignore debounce */ | ||
865 | break; | ||
866 | |||
867 | case PACKET_TRACKPOINT: | ||
868 | elantech_report_trackpoint(psmouse, packet_type); | ||
869 | break; | ||
870 | |||
871 | default: | ||
872 | elantech_report_absolute_v3(psmouse, packet_type); | ||
873 | break; | ||
874 | } | ||
875 | |||
802 | break; | 876 | break; |
803 | 877 | ||
804 | case 4: | 878 | case 4: |
@@ -1018,8 +1092,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, | |||
1018 | * Asus UX31 0x361f00 20, 15, 0e clickpad | 1092 | * Asus UX31 0x361f00 20, 15, 0e clickpad |
1019 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad | 1093 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad |
1020 | * Avatar AVIU-145A2 0x361f00 ? clickpad | 1094 | * Avatar AVIU-145A2 0x361f00 ? clickpad |
1095 | * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**) | ||
1021 | * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons | 1096 | * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons |
1022 | * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) | 1097 | * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*) |
1098 | * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*) | ||
1023 | * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons | 1099 | * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons |
1024 | * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad | 1100 | * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad |
1025 | * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad | 1101 | * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad |
@@ -1029,6 +1105,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, | |||
1029 | * Samsung RF710 0x450f00 ? 2 hw buttons | 1105 | * Samsung RF710 0x450f00 ? 2 hw buttons |
1030 | * System76 Pangolin 0x250f01 ? 2 hw buttons | 1106 | * System76 Pangolin 0x250f01 ? 2 hw buttons |
1031 | * (*) + 3 trackpoint buttons | 1107 | * (*) + 3 trackpoint buttons |
1108 | * (**) + 0 trackpoint buttons | ||
1109 | * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps | ||
1032 | */ | 1110 | */ |
1033 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) | 1111 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) |
1034 | { | 1112 | { |
@@ -1253,6 +1331,13 @@ static bool elantech_is_signature_valid(const unsigned char *param) | |||
1253 | if (param[1] == 0) | 1331 | if (param[1] == 0) |
1254 | return true; | 1332 | return true; |
1255 | 1333 | ||
1334 | /* | ||
1335 | * Some models have a revision higher then 20. Meaning param[2] may | ||
1336 | * be 10 or 20, skip the rates check for these. | ||
1337 | */ | ||
1338 | if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40) | ||
1339 | return true; | ||
1340 | |||
1256 | for (i = 0; i < ARRAY_SIZE(rates); i++) | 1341 | for (i = 0; i < ARRAY_SIZE(rates); i++) |
1257 | if (param[2] == rates[i]) | 1342 | if (param[2] == rates[i]) |
1258 | return false; | 1343 | return false; |
@@ -1324,6 +1409,10 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
1324 | */ | 1409 | */ |
1325 | static void elantech_disconnect(struct psmouse *psmouse) | 1410 | static void elantech_disconnect(struct psmouse *psmouse) |
1326 | { | 1411 | { |
1412 | struct elantech_data *etd = psmouse->private; | ||
1413 | |||
1414 | if (etd->tp_dev) | ||
1415 | input_unregister_device(etd->tp_dev); | ||
1327 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | 1416 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, |
1328 | &elantech_attr_group); | 1417 | &elantech_attr_group); |
1329 | kfree(psmouse->private); | 1418 | kfree(psmouse->private); |
@@ -1438,8 +1527,10 @@ static int elantech_set_properties(struct elantech_data *etd) | |||
1438 | int elantech_init(struct psmouse *psmouse) | 1527 | int elantech_init(struct psmouse *psmouse) |
1439 | { | 1528 | { |
1440 | struct elantech_data *etd; | 1529 | struct elantech_data *etd; |
1441 | int i, error; | 1530 | int i; |
1531 | int error = -EINVAL; | ||
1442 | unsigned char param[3]; | 1532 | unsigned char param[3]; |
1533 | struct input_dev *tp_dev; | ||
1443 | 1534 | ||
1444 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); | 1535 | psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); |
1445 | if (!etd) | 1536 | if (!etd) |
@@ -1498,14 +1589,53 @@ int elantech_init(struct psmouse *psmouse) | |||
1498 | goto init_fail; | 1589 | goto init_fail; |
1499 | } | 1590 | } |
1500 | 1591 | ||
1592 | /* The MSB indicates the presence of the trackpoint */ | ||
1593 | if ((etd->capabilities[0] & 0x80) == 0x80) { | ||
1594 | tp_dev = input_allocate_device(); | ||
1595 | |||
1596 | if (!tp_dev) { | ||
1597 | error = -ENOMEM; | ||
1598 | goto init_fail_tp_alloc; | ||
1599 | } | ||
1600 | |||
1601 | etd->tp_dev = tp_dev; | ||
1602 | snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1", | ||
1603 | psmouse->ps2dev.serio->phys); | ||
1604 | tp_dev->phys = etd->tp_phys; | ||
1605 | tp_dev->name = "Elantech PS/2 TrackPoint"; | ||
1606 | tp_dev->id.bustype = BUS_I8042; | ||
1607 | tp_dev->id.vendor = 0x0002; | ||
1608 | tp_dev->id.product = PSMOUSE_ELANTECH; | ||
1609 | tp_dev->id.version = 0x0000; | ||
1610 | tp_dev->dev.parent = &psmouse->ps2dev.serio->dev; | ||
1611 | tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | ||
1612 | tp_dev->relbit[BIT_WORD(REL_X)] = | ||
1613 | BIT_MASK(REL_X) | BIT_MASK(REL_Y); | ||
1614 | tp_dev->keybit[BIT_WORD(BTN_LEFT)] = | ||
1615 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | | ||
1616 | BIT_MASK(BTN_RIGHT); | ||
1617 | |||
1618 | __set_bit(INPUT_PROP_POINTER, tp_dev->propbit); | ||
1619 | __set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit); | ||
1620 | |||
1621 | error = input_register_device(etd->tp_dev); | ||
1622 | if (error < 0) | ||
1623 | goto init_fail_tp_reg; | ||
1624 | } | ||
1625 | |||
1501 | psmouse->protocol_handler = elantech_process_byte; | 1626 | psmouse->protocol_handler = elantech_process_byte; |
1502 | psmouse->disconnect = elantech_disconnect; | 1627 | psmouse->disconnect = elantech_disconnect; |
1503 | psmouse->reconnect = elantech_reconnect; | 1628 | psmouse->reconnect = elantech_reconnect; |
1504 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; | 1629 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; |
1505 | 1630 | ||
1506 | return 0; | 1631 | return 0; |
1507 | 1632 | init_fail_tp_reg: | |
1633 | input_free_device(tp_dev); | ||
1634 | init_fail_tp_alloc: | ||
1635 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | ||
1636 | &elantech_attr_group); | ||
1508 | init_fail: | 1637 | init_fail: |
1638 | psmouse_reset(psmouse); | ||
1509 | kfree(etd); | 1639 | kfree(etd); |
1510 | return -1; | 1640 | return error; |
1511 | } | 1641 | } |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 9e0e2a1f340d..6f3afec02f03 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -94,6 +94,7 @@ | |||
94 | #define PACKET_V4_HEAD 0x05 | 94 | #define PACKET_V4_HEAD 0x05 |
95 | #define PACKET_V4_MOTION 0x06 | 95 | #define PACKET_V4_MOTION 0x06 |
96 | #define PACKET_V4_STATUS 0x07 | 96 | #define PACKET_V4_STATUS 0x07 |
97 | #define PACKET_TRACKPOINT 0x08 | ||
97 | 98 | ||
98 | /* | 99 | /* |
99 | * track up to 5 fingers for v4 hardware | 100 | * track up to 5 fingers for v4 hardware |
@@ -114,6 +115,8 @@ struct finger_pos { | |||
114 | }; | 115 | }; |
115 | 116 | ||
116 | struct elantech_data { | 117 | struct elantech_data { |
118 | struct input_dev *tp_dev; /* Relative device for trackpoint */ | ||
119 | char tp_phys[32]; | ||
117 | unsigned char reg_07; | 120 | unsigned char reg_07; |
118 | unsigned char reg_10; | 121 | unsigned char reg_10; |
119 | unsigned char reg_11; | 122 | unsigned char reg_11; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 3ab941d425ae..26994f6a2b2a 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -685,6 +685,8 @@ static void psmouse_apply_defaults(struct psmouse *psmouse) | |||
685 | __set_bit(REL_X, input_dev->relbit); | 685 | __set_bit(REL_X, input_dev->relbit); |
686 | __set_bit(REL_Y, input_dev->relbit); | 686 | __set_bit(REL_Y, input_dev->relbit); |
687 | 687 | ||
688 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
689 | |||
688 | psmouse->set_rate = psmouse_set_rate; | 690 | psmouse->set_rate = psmouse_set_rate; |
689 | psmouse->set_resolution = psmouse_set_resolution; | 691 | psmouse->set_resolution = psmouse_set_resolution; |
690 | psmouse->poll = psmouse_poll; | 692 | psmouse->poll = psmouse_poll; |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 854caca6e86e..6394d9b5bfd3 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -618,10 +618,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
618 | ((buf[0] & 0x04) >> 1) | | 618 | ((buf[0] & 0x04) >> 1) | |
619 | ((buf[3] & 0x04) >> 2)); | 619 | ((buf[3] & 0x04) >> 2)); |
620 | 620 | ||
621 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | ||
622 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && | ||
623 | hw->w == 2) { | ||
624 | synaptics_parse_agm(buf, priv, hw); | ||
625 | return 1; | ||
626 | } | ||
627 | |||
628 | hw->x = (((buf[3] & 0x10) << 8) | | ||
629 | ((buf[1] & 0x0f) << 8) | | ||
630 | buf[4]); | ||
631 | hw->y = (((buf[3] & 0x20) << 7) | | ||
632 | ((buf[1] & 0xf0) << 4) | | ||
633 | buf[5]); | ||
634 | hw->z = buf[2]; | ||
635 | |||
621 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 636 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
622 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 637 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
623 | 638 | ||
624 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 639 | if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) { |
640 | /* | ||
641 | * ForcePads, like Clickpads, use middle button | ||
642 | * bits to report primary button clicks. | ||
643 | * Unfortunately they report primary button not | ||
644 | * only when user presses on the pad above certain | ||
645 | * threshold, but also when there are more than one | ||
646 | * finger on the touchpad, which interferes with | ||
647 | * out multi-finger gestures. | ||
648 | */ | ||
649 | if (hw->z == 0) { | ||
650 | /* No contacts */ | ||
651 | priv->press = priv->report_press = false; | ||
652 | } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) { | ||
653 | /* | ||
654 | * Single-finger touch with pressure above | ||
655 | * the threshold. If pressure stays long | ||
656 | * enough, we'll start reporting primary | ||
657 | * button. We rely on the device continuing | ||
658 | * sending data even if finger does not | ||
659 | * move. | ||
660 | */ | ||
661 | if (!priv->press) { | ||
662 | priv->press_start = jiffies; | ||
663 | priv->press = true; | ||
664 | } else if (time_after(jiffies, | ||
665 | priv->press_start + | ||
666 | msecs_to_jiffies(50))) { | ||
667 | priv->report_press = true; | ||
668 | } | ||
669 | } else { | ||
670 | priv->press = false; | ||
671 | } | ||
672 | |||
673 | hw->left = priv->report_press; | ||
674 | |||
675 | } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | ||
625 | /* | 676 | /* |
626 | * Clickpad's button is transmitted as middle button, | 677 | * Clickpad's button is transmitted as middle button, |
627 | * however, since it is primary button, we will report | 678 | * however, since it is primary button, we will report |
@@ -640,21 +691,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
640 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; | 691 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; |
641 | } | 692 | } |
642 | 693 | ||
643 | if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) || | ||
644 | SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) && | ||
645 | hw->w == 2) { | ||
646 | synaptics_parse_agm(buf, priv, hw); | ||
647 | return 1; | ||
648 | } | ||
649 | |||
650 | hw->x = (((buf[3] & 0x10) << 8) | | ||
651 | ((buf[1] & 0x0f) << 8) | | ||
652 | buf[4]); | ||
653 | hw->y = (((buf[3] & 0x20) << 7) | | ||
654 | ((buf[1] & 0xf0) << 4) | | ||
655 | buf[5]); | ||
656 | hw->z = buf[2]; | ||
657 | |||
658 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && | 694 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && |
659 | ((buf[0] ^ buf[3]) & 0x02)) { | 695 | ((buf[0] ^ buf[3]) & 0x02)) { |
660 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { | 696 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index e594af0b264b..fb2e076738ae 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -78,6 +78,11 @@ | |||
78 | * 2 0x08 image sensor image sensor tracks 5 fingers, but only | 78 | * 2 0x08 image sensor image sensor tracks 5 fingers, but only |
79 | * reports 2. | 79 | * reports 2. |
80 | * 2 0x20 report min query 0x0f gives min coord reported | 80 | * 2 0x20 report min query 0x0f gives min coord reported |
81 | * 2 0x80 forcepad forcepad is a variant of clickpad that | ||
82 | * does not have physical buttons but rather | ||
83 | * uses pressure above certain threshold to | ||
84 | * report primary clicks. Forcepads also have | ||
85 | * clickpad bit set. | ||
81 | */ | 86 | */ |
82 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ | 87 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ |
83 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ | 88 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ |
@@ -86,6 +91,7 @@ | |||
86 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) | 91 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) |
87 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) | 92 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) |
88 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) | 93 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) |
94 | #define SYN_CAP_FORCEPAD(ex0c) ((ex0c) & 0x008000) | ||
89 | 95 | ||
90 | /* synaptics modes query bits */ | 96 | /* synaptics modes query bits */ |
91 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 97 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
@@ -177,6 +183,11 @@ struct synaptics_data { | |||
177 | */ | 183 | */ |
178 | struct synaptics_hw_state agm; | 184 | struct synaptics_hw_state agm; |
179 | bool agm_pending; /* new AGM packet received */ | 185 | bool agm_pending; /* new AGM packet received */ |
186 | |||
187 | /* ForcePad handling */ | ||
188 | unsigned long press_start; | ||
189 | bool press; | ||
190 | bool report_press; | ||
180 | }; | 191 | }; |
181 | 192 | ||
182 | void synaptics_module_init(void); | 193 | void synaptics_module_init(void); |
diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c index e122bda16aab..6bcc0189c1c9 100644 --- a/drivers/input/mouse/synaptics_usb.c +++ b/drivers/input/mouse/synaptics_usb.c | |||
@@ -387,6 +387,7 @@ static int synusb_probe(struct usb_interface *intf, | |||
387 | __set_bit(EV_REL, input_dev->evbit); | 387 | __set_bit(EV_REL, input_dev->evbit); |
388 | __set_bit(REL_X, input_dev->relbit); | 388 | __set_bit(REL_X, input_dev->relbit); |
389 | __set_bit(REL_Y, input_dev->relbit); | 389 | __set_bit(REL_Y, input_dev->relbit); |
390 | __set_bit(INPUT_PROP_POINTING_STICK, input_dev->propbit); | ||
390 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); | 391 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0); |
391 | } else { | 392 | } else { |
392 | input_set_abs_params(input_dev, ABS_X, | 393 | input_set_abs_params(input_dev, ABS_X, |
@@ -401,6 +402,11 @@ static int synusb_probe(struct usb_interface *intf, | |||
401 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | 402 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); |
402 | } | 403 | } |
403 | 404 | ||
405 | if (synusb->flags & SYNUSB_TOUCHSCREEN) | ||
406 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); | ||
407 | else | ||
408 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
409 | |||
404 | __set_bit(BTN_LEFT, input_dev->keybit); | 410 | __set_bit(BTN_LEFT, input_dev->keybit); |
405 | __set_bit(BTN_RIGHT, input_dev->keybit); | 411 | __set_bit(BTN_RIGHT, input_dev->keybit); |
406 | __set_bit(BTN_MIDDLE, input_dev->keybit); | 412 | __set_bit(BTN_MIDDLE, input_dev->keybit); |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index ca843b6cf6bd..30c8b6998808 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -393,6 +393,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | |||
393 | if ((button_info & 0x0f) >= 3) | 393 | if ((button_info & 0x0f) >= 3) |
394 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 394 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
395 | 395 | ||
396 | __set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit); | ||
397 | __set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit); | ||
398 | |||
396 | trackpoint_defaults(psmouse->private); | 399 | trackpoint_defaults(psmouse->private); |
397 | 400 | ||
398 | error = trackpoint_power_on_reset(&psmouse->ps2dev); | 401 | error = trackpoint_power_on_reset(&psmouse->ps2dev); |
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index d6aa4c67dbb6..93cb7912703c 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
@@ -17,7 +17,6 @@ static int i8042_aux_irq = -1; | |||
17 | #define I8042_MUX_PHYS_DESC "sparcps2/serio%d" | 17 | #define I8042_MUX_PHYS_DESC "sparcps2/serio%d" |
18 | 18 | ||
19 | static void __iomem *kbd_iobase; | 19 | static void __iomem *kbd_iobase; |
20 | static struct resource *kbd_res; | ||
21 | 20 | ||
22 | #define I8042_COMMAND_REG (kbd_iobase + 0x64UL) | 21 | #define I8042_COMMAND_REG (kbd_iobase + 0x64UL) |
23 | #define I8042_DATA_REG (kbd_iobase + 0x60UL) | 22 | #define I8042_DATA_REG (kbd_iobase + 0x60UL) |
@@ -44,6 +43,8 @@ static inline void i8042_write_command(int val) | |||
44 | 43 | ||
45 | #ifdef CONFIG_PCI | 44 | #ifdef CONFIG_PCI |
46 | 45 | ||
46 | static struct resource *kbd_res; | ||
47 | |||
47 | #define OBP_PS2KBD_NAME1 "kb_ps2" | 48 | #define OBP_PS2KBD_NAME1 "kb_ps2" |
48 | #define OBP_PS2KBD_NAME2 "keyboard" | 49 | #define OBP_PS2KBD_NAME2 "keyboard" |
49 | #define OBP_PS2MS_NAME1 "kdmouse" | 50 | #define OBP_PS2MS_NAME1 "kdmouse" |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 136b7b204f56..40b7d6c0ff17 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -465,6 +465,20 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { | |||
465 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), | 465 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), |
466 | }, | 466 | }, |
467 | }, | 467 | }, |
468 | { | ||
469 | /* Asus X450LCP */ | ||
470 | .matches = { | ||
471 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
472 | DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"), | ||
473 | }, | ||
474 | }, | ||
475 | { | ||
476 | /* Avatar AVIU-145A6 */ | ||
477 | .matches = { | ||
478 | DMI_MATCH(DMI_SYS_VENDOR, "Intel"), | ||
479 | DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"), | ||
480 | }, | ||
481 | }, | ||
468 | { } | 482 | { } |
469 | }; | 483 | }; |
470 | 484 | ||
@@ -608,6 +622,14 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { | |||
608 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), | 622 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), |
609 | }, | 623 | }, |
610 | }, | 624 | }, |
625 | { | ||
626 | /* Fujitsu U574 laptop */ | ||
627 | /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ | ||
628 | .matches = { | ||
629 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
630 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"), | ||
631 | }, | ||
632 | }, | ||
611 | { } | 633 | { } |
612 | }; | 634 | }; |
613 | 635 | ||
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 3807c3e971cc..f5a98af3b325 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -1254,6 +1254,8 @@ static int __init i8042_create_aux_port(int idx) | |||
1254 | } else { | 1254 | } else { |
1255 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); | 1255 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); |
1256 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); | 1256 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); |
1257 | strlcpy(serio->firmware_id, i8042_aux_firmware_id, | ||
1258 | sizeof(serio->firmware_id)); | ||
1257 | } | 1259 | } |
1258 | 1260 | ||
1259 | port->serio = serio; | 1261 | port->serio = serio; |
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 0cb7ef59071b..69175b825346 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/serio.h> | 22 | #include <linux/serio.h> |
23 | #include <linux/tty.h> | 23 | #include <linux/tty.h> |
24 | #include <linux/compat.h> | ||
24 | 25 | ||
25 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 26 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
26 | MODULE_DESCRIPTION("Input device TTY line discipline"); | 27 | MODULE_DESCRIPTION("Input device TTY line discipline"); |
@@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u | |||
198 | return 0; | 199 | return 0; |
199 | } | 200 | } |
200 | 201 | ||
202 | static void serport_set_type(struct tty_struct *tty, unsigned long type) | ||
203 | { | ||
204 | struct serport *serport = tty->disc_data; | ||
205 | |||
206 | serport->id.proto = type & 0x000000ff; | ||
207 | serport->id.id = (type & 0x0000ff00) >> 8; | ||
208 | serport->id.extra = (type & 0x00ff0000) >> 16; | ||
209 | } | ||
210 | |||
201 | /* | 211 | /* |
202 | * serport_ldisc_ioctl() allows to set the port protocol, and device ID | 212 | * serport_ldisc_ioctl() allows to set the port protocol, and device ID |
203 | */ | 213 | */ |
204 | 214 | ||
205 | static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg) | 215 | static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file, |
216 | unsigned int cmd, unsigned long arg) | ||
206 | { | 217 | { |
207 | struct serport *serport = (struct serport*) tty->disc_data; | ||
208 | unsigned long type; | ||
209 | |||
210 | if (cmd == SPIOCSTYPE) { | 218 | if (cmd == SPIOCSTYPE) { |
219 | unsigned long type; | ||
220 | |||
211 | if (get_user(type, (unsigned long __user *) arg)) | 221 | if (get_user(type, (unsigned long __user *) arg)) |
212 | return -EFAULT; | 222 | return -EFAULT; |
213 | 223 | ||
214 | serport->id.proto = type & 0x000000ff; | 224 | serport_set_type(tty, type); |
215 | serport->id.id = (type & 0x0000ff00) >> 8; | 225 | return 0; |
216 | serport->id.extra = (type & 0x00ff0000) >> 16; | 226 | } |
227 | |||
228 | return -EINVAL; | ||
229 | } | ||
230 | |||
231 | #ifdef CONFIG_COMPAT | ||
232 | #define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t) | ||
233 | static long serport_ldisc_compat_ioctl(struct tty_struct *tty, | ||
234 | struct file *file, | ||
235 | unsigned int cmd, unsigned long arg) | ||
236 | { | ||
237 | if (cmd == COMPAT_SPIOCSTYPE) { | ||
238 | void __user *uarg = compat_ptr(arg); | ||
239 | compat_ulong_t compat_type; | ||
240 | |||
241 | if (get_user(compat_type, (compat_ulong_t __user *)uarg)) | ||
242 | return -EFAULT; | ||
217 | 243 | ||
244 | serport_set_type(tty, compat_type); | ||
218 | return 0; | 245 | return 0; |
219 | } | 246 | } |
220 | 247 | ||
221 | return -EINVAL; | 248 | return -EINVAL; |
222 | } | 249 | } |
250 | #endif | ||
223 | 251 | ||
224 | static void serport_ldisc_write_wakeup(struct tty_struct * tty) | 252 | static void serport_ldisc_write_wakeup(struct tty_struct * tty) |
225 | { | 253 | { |
@@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldisc = { | |||
243 | .close = serport_ldisc_close, | 271 | .close = serport_ldisc_close, |
244 | .read = serport_ldisc_read, | 272 | .read = serport_ldisc_read, |
245 | .ioctl = serport_ldisc_ioctl, | 273 | .ioctl = serport_ldisc_ioctl, |
274 | #ifdef CONFIG_COMPAT | ||
275 | .compat_ioctl = serport_ldisc_compat_ioctl, | ||
276 | #endif | ||
246 | .receive_buf = serport_ldisc_receive, | 277 | .receive_buf = serport_ldisc_receive, |
247 | .write_wakeup = serport_ldisc_write_wakeup | 278 | .write_wakeup = serport_ldisc_write_wakeup |
248 | }; | 279 | }; |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index db178ed2b47e..aaacf8bfa61f 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -837,7 +837,12 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data) | |||
837 | count = data->msg_buf[0]; | 837 | count = data->msg_buf[0]; |
838 | 838 | ||
839 | if (count == 0) { | 839 | if (count == 0) { |
840 | dev_warn(dev, "Interrupt triggered but zero messages\n"); | 840 | /* |
841 | * This condition is caused by the CHG line being configured | ||
842 | * in Mode 0. It results in unnecessary I2C operations but it | ||
843 | * is benign. | ||
844 | */ | ||
845 | dev_dbg(dev, "Interrupt triggered but zero messages\n"); | ||
841 | return IRQ_NONE; | 846 | return IRQ_NONE; |
842 | } else if (count > data->max_reportid) { | 847 | } else if (count > data->max_reportid) { |
843 | dev_err(dev, "T44 count %d exceeded max report id\n", count); | 848 | dev_err(dev, "T44 count %d exceeded max report id\n", count); |
@@ -1374,11 +1379,16 @@ static int mxt_get_info(struct mxt_data *data) | |||
1374 | return 0; | 1379 | return 0; |
1375 | } | 1380 | } |
1376 | 1381 | ||
1377 | static void mxt_free_object_table(struct mxt_data *data) | 1382 | static void mxt_free_input_device(struct mxt_data *data) |
1378 | { | 1383 | { |
1379 | input_unregister_device(data->input_dev); | 1384 | if (data->input_dev) { |
1380 | data->input_dev = NULL; | 1385 | input_unregister_device(data->input_dev); |
1386 | data->input_dev = NULL; | ||
1387 | } | ||
1388 | } | ||
1381 | 1389 | ||
1390 | static void mxt_free_object_table(struct mxt_data *data) | ||
1391 | { | ||
1382 | kfree(data->object_table); | 1392 | kfree(data->object_table); |
1383 | data->object_table = NULL; | 1393 | data->object_table = NULL; |
1384 | kfree(data->msg_buf); | 1394 | kfree(data->msg_buf); |
@@ -1957,11 +1967,13 @@ static int mxt_load_fw(struct device *dev, const char *fn) | |||
1957 | ret = mxt_lookup_bootloader_address(data, 0); | 1967 | ret = mxt_lookup_bootloader_address(data, 0); |
1958 | if (ret) | 1968 | if (ret) |
1959 | goto release_firmware; | 1969 | goto release_firmware; |
1970 | |||
1971 | mxt_free_input_device(data); | ||
1972 | mxt_free_object_table(data); | ||
1960 | } else { | 1973 | } else { |
1961 | enable_irq(data->irq); | 1974 | enable_irq(data->irq); |
1962 | } | 1975 | } |
1963 | 1976 | ||
1964 | mxt_free_object_table(data); | ||
1965 | reinit_completion(&data->bl_completion); | 1977 | reinit_completion(&data->bl_completion); |
1966 | 1978 | ||
1967 | ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); | 1979 | ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); |
@@ -2210,6 +2222,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
2210 | return 0; | 2222 | return 0; |
2211 | 2223 | ||
2212 | err_free_object: | 2224 | err_free_object: |
2225 | mxt_free_input_device(data); | ||
2213 | mxt_free_object_table(data); | 2226 | mxt_free_object_table(data); |
2214 | err_free_irq: | 2227 | err_free_irq: |
2215 | free_irq(client->irq, data); | 2228 | free_irq(client->irq, data); |
@@ -2224,7 +2237,7 @@ static int mxt_remove(struct i2c_client *client) | |||
2224 | 2237 | ||
2225 | sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); | 2238 | sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); |
2226 | free_irq(data->irq, data); | 2239 | free_irq(data->irq, data); |
2227 | input_unregister_device(data->input_dev); | 2240 | mxt_free_input_device(data); |
2228 | mxt_free_object_table(data); | 2241 | mxt_free_object_table(data); |
2229 | kfree(data); | 2242 | kfree(data); |
2230 | 2243 | ||
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 16b52115c27f..705ffa1e064a 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c | |||
@@ -41,7 +41,7 @@ | |||
41 | */ | 41 | */ |
42 | static int rpu = 8; | 42 | static int rpu = 8; |
43 | module_param(rpu, int, 0); | 43 | module_param(rpu, int, 0); |
44 | MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); | 44 | MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect."); |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Set current used for pressure measurement. | 47 | * Set current used for pressure measurement. |
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 7405353199d7..572a5a64face 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c | |||
@@ -41,7 +41,7 @@ | |||
41 | */ | 41 | */ |
42 | static int rpu = 8; | 42 | static int rpu = 8; |
43 | module_param(rpu, int, 0); | 43 | module_param(rpu, int, 0); |
44 | MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect."); | 44 | MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect."); |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Set current used for pressure measurement. | 47 | * Set current used for pressure measurement. |