diff options
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/input-mt.c | 115 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_wac.c | 23 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_wac.h | 4 | ||||
| -rw-r--r-- | drivers/input/touchscreen/wacom_w8001.c | 21 |
4 files changed, 120 insertions, 43 deletions
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index f400e47092c4..c48c81f0308d 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c | |||
| @@ -11,17 +11,18 @@ | |||
| 11 | #include <linux/input/mt.h> | 11 | #include <linux/input/mt.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | 13 | ||
| 14 | #define TRKID_SGN ((TRKID_MAX + 1) >> 1) | ||
| 15 | |||
| 14 | /** | 16 | /** |
| 15 | * input_mt_init_slots() - initialize MT input slots | 17 | * input_mt_init_slots() - initialize MT input slots |
| 16 | * @dev: input device supporting MT events and finger tracking | 18 | * @dev: input device supporting MT events and finger tracking |
| 17 | * @num_slots: number of slots used by the device | 19 | * @num_slots: number of slots used by the device |
| 18 | * | 20 | * |
| 19 | * This function allocates all necessary memory for MT slot handling | 21 | * This function allocates all necessary memory for MT slot handling |
| 20 | * in the input device, adds ABS_MT_SLOT to the device capabilities | 22 | * in the input device, prepares the ABS_MT_SLOT and |
| 21 | * and sets up appropriate event buffers. All slots are initially | 23 | * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers. |
| 22 | * marked as unused by setting ABS_MT_TRACKING_ID to -1. May be called | 24 | * May be called repeatedly. Returns -EINVAL if attempting to |
| 23 | * repeatedly. Returns -EINVAL if attempting to reinitialize with a | 25 | * reinitialize with a different number of slots. |
| 24 | * different number of slots. | ||
| 25 | */ | 26 | */ |
| 26 | int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) | 27 | int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) |
| 27 | { | 28 | { |
| @@ -38,6 +39,7 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) | |||
| 38 | 39 | ||
| 39 | dev->mtsize = num_slots; | 40 | dev->mtsize = num_slots; |
| 40 | input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); | 41 | input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); |
| 42 | input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); | ||
| 41 | input_set_events_per_packet(dev, 6 * num_slots); | 43 | input_set_events_per_packet(dev, 6 * num_slots); |
| 42 | 44 | ||
| 43 | /* Mark slots as 'unused' */ | 45 | /* Mark slots as 'unused' */ |
| @@ -61,5 +63,108 @@ void input_mt_destroy_slots(struct input_dev *dev) | |||
| 61 | dev->mt = NULL; | 63 | dev->mt = NULL; |
| 62 | dev->mtsize = 0; | 64 | dev->mtsize = 0; |
| 63 | dev->slot = 0; | 65 | dev->slot = 0; |
| 66 | dev->trkid = 0; | ||
| 64 | } | 67 | } |
| 65 | EXPORT_SYMBOL(input_mt_destroy_slots); | 68 | EXPORT_SYMBOL(input_mt_destroy_slots); |
| 69 | |||
| 70 | /** | ||
| 71 | * input_mt_report_slot_state() - report contact state | ||
| 72 | * @dev: input device with allocated MT slots | ||
| 73 | * @tool_type: the tool type to use in this slot | ||
| 74 | * @active: true if contact is active, false otherwise | ||
| 75 | * | ||
| 76 | * Reports a contact via ABS_MT_TRACKING_ID, and optionally | ||
| 77 | * ABS_MT_TOOL_TYPE. If active is true and the slot is currently | ||
| 78 | * inactive, or if the tool type is changed, a new tracking id is | ||
| 79 | * assigned to the slot. The tool type is only reported if the | ||
| 80 | * corresponding absbit field is set. | ||
| 81 | */ | ||
| 82 | void input_mt_report_slot_state(struct input_dev *dev, | ||
| 83 | unsigned int tool_type, bool active) | ||
| 84 | { | ||
| 85 | struct input_mt_slot *mt; | ||
| 86 | int id; | ||
| 87 | |||
| 88 | if (!dev->mt || !active) { | ||
| 89 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); | ||
| 90 | return; | ||
| 91 | } | ||
| 92 | |||
| 93 | mt = &dev->mt[dev->slot]; | ||
| 94 | id = input_mt_get_value(mt, ABS_MT_TRACKING_ID); | ||
| 95 | if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type) | ||
| 96 | id = input_mt_new_trkid(dev); | ||
| 97 | |||
| 98 | input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id); | ||
| 99 | input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type); | ||
| 100 | } | ||
| 101 | EXPORT_SYMBOL(input_mt_report_slot_state); | ||
| 102 | |||
| 103 | /** | ||
| 104 | * input_mt_report_finger_count() - report contact count | ||
| 105 | * @dev: input device with allocated MT slots | ||
| 106 | * @count: the number of contacts | ||
| 107 | * | ||
| 108 | * Reports the contact count via BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, | ||
| 109 | * BTN_TOOL_TRIPLETAP and BTN_TOOL_QUADTAP. | ||
| 110 | * | ||
| 111 | * The input core ensures only the KEY events already setup for | ||
| 112 | * this device will produce output. | ||
| 113 | */ | ||
| 114 | void input_mt_report_finger_count(struct input_dev *dev, int count) | ||
| 115 | { | ||
| 116 | input_event(dev, EV_KEY, BTN_TOOL_FINGER, count == 1); | ||
| 117 | input_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, count == 2); | ||
| 118 | input_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, count == 3); | ||
| 119 | input_event(dev, EV_KEY, BTN_TOOL_QUADTAP, count == 4); | ||
| 120 | } | ||
| 121 | EXPORT_SYMBOL(input_mt_report_finger_count); | ||
| 122 | |||
| 123 | /** | ||
| 124 | * input_mt_report_pointer_emulation() - common pointer emulation | ||
| 125 | * @dev: input device with allocated MT slots | ||
| 126 | * @use_count: report number of active contacts as finger count | ||
| 127 | * | ||
| 128 | * Performs legacy pointer emulation via BTN_TOUCH, ABS_X, ABS_Y and | ||
| 129 | * ABS_PRESSURE. Touchpad finger count is emulated if use_count is true. | ||
| 130 | * | ||
| 131 | * The input core ensures only the KEY and ABS axes already setup for | ||
| 132 | * this device will produce output. | ||
| 133 | */ | ||
| 134 | void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) | ||
| 135 | { | ||
| 136 | struct input_mt_slot *oldest = 0; | ||
| 137 | int oldid = dev->trkid; | ||
| 138 | int count = 0; | ||
| 139 | int i; | ||
| 140 | |||
| 141 | for (i = 0; i < dev->mtsize; ++i) { | ||
| 142 | struct input_mt_slot *ps = &dev->mt[i]; | ||
| 143 | int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); | ||
| 144 | |||
| 145 | if (id < 0) | ||
| 146 | continue; | ||
| 147 | if ((id - oldid) & TRKID_SGN) { | ||
| 148 | oldest = ps; | ||
| 149 | oldid = id; | ||
| 150 | } | ||
| 151 | count++; | ||
| 152 | } | ||
| 153 | |||
| 154 | input_event(dev, EV_KEY, BTN_TOUCH, count > 0); | ||
| 155 | if (use_count) | ||
| 156 | input_mt_report_finger_count(dev, count); | ||
| 157 | |||
| 158 | if (oldest) { | ||
| 159 | int x = input_mt_get_value(oldest, ABS_MT_POSITION_X); | ||
| 160 | int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y); | ||
| 161 | int p = input_mt_get_value(oldest, ABS_MT_PRESSURE); | ||
| 162 | |||
| 163 | input_event(dev, EV_ABS, ABS_X, x); | ||
| 164 | input_event(dev, EV_ABS, ABS_Y, y); | ||
| 165 | input_event(dev, EV_ABS, ABS_PRESSURE, p); | ||
| 166 | } else { | ||
| 167 | input_event(dev, EV_ABS, ABS_PRESSURE, 0); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | EXPORT_SYMBOL(input_mt_report_pointer_emulation); | ||
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index f26e2238f6ca..0b0525486711 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -863,19 +863,21 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) | |||
| 863 | struct wacom_features *features = &wacom->features; | 863 | struct wacom_features *features = &wacom->features; |
| 864 | struct input_dev *input = wacom->input; | 864 | struct input_dev *input = wacom->input; |
| 865 | unsigned char *data = wacom->data; | 865 | unsigned char *data = wacom->data; |
| 866 | int sp = 0, sx = 0, sy = 0, count = 0; | ||
| 867 | int i; | 866 | int i; |
| 868 | 867 | ||
| 869 | for (i = 0; i < 2; i++) { | 868 | for (i = 0; i < 2; i++) { |
| 870 | int p = data[9 * i + 2]; | 869 | int p = data[9 * i + 2]; |
| 870 | bool touch = p && !wacom->shared->stylus_in_proximity; | ||
| 871 | |||
| 871 | input_mt_slot(input, i); | 872 | input_mt_slot(input, i); |
| 873 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | ||
| 872 | /* | 874 | /* |
| 873 | * Touch events need to be disabled while stylus is | 875 | * Touch events need to be disabled while stylus is |
| 874 | * in proximity because user's hand is resting on touchpad | 876 | * in proximity because user's hand is resting on touchpad |
| 875 | * and sending unwanted events. User expects tablet buttons | 877 | * and sending unwanted events. User expects tablet buttons |
| 876 | * to continue working though. | 878 | * to continue working though. |
| 877 | */ | 879 | */ |
| 878 | if (p && !wacom->shared->stylus_in_proximity) { | 880 | if (touch) { |
| 879 | int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff; | 881 | int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff; |
| 880 | int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff; | 882 | int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff; |
| 881 | if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { | 883 | if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) { |
| @@ -885,23 +887,10 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) | |||
| 885 | input_report_abs(input, ABS_MT_PRESSURE, p); | 887 | input_report_abs(input, ABS_MT_PRESSURE, p); |
| 886 | input_report_abs(input, ABS_MT_POSITION_X, x); | 888 | input_report_abs(input, ABS_MT_POSITION_X, x); |
| 887 | input_report_abs(input, ABS_MT_POSITION_Y, y); | 889 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
| 888 | if (wacom->id[i] < 0) | ||
| 889 | wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID; | ||
| 890 | if (!count++) | ||
| 891 | sp = p, sx = x, sy = y; | ||
| 892 | } else { | ||
| 893 | wacom->id[i] = -1; | ||
| 894 | } | 890 | } |
| 895 | input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]); | ||
| 896 | } | 891 | } |
| 897 | 892 | ||
| 898 | input_report_key(input, BTN_TOUCH, count > 0); | 893 | input_mt_report_pointer_emulation(input, true); |
| 899 | input_report_key(input, BTN_TOOL_FINGER, count == 1); | ||
| 900 | input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2); | ||
| 901 | |||
| 902 | input_report_abs(input, ABS_PRESSURE, sp); | ||
| 903 | input_report_abs(input, ABS_X, sx); | ||
| 904 | input_report_abs(input, ABS_Y, sy); | ||
| 905 | 894 | ||
| 906 | input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); | 895 | input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0); |
| 907 | input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); | 896 | input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0); |
| @@ -1283,8 +1272,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 1283 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | 1272 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, |
| 1284 | 0, features->pressure_max, | 1273 | 0, features->pressure_max, |
| 1285 | features->pressure_fuzz, 0); | 1274 | features->pressure_fuzz, 0); |
| 1286 | input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, | ||
| 1287 | MAX_TRACKING_ID, 0, 0); | ||
| 1288 | } else if (features->device_type == BTN_TOOL_PEN) { | 1275 | } else if (features->device_type == BTN_TOOL_PEN) { |
| 1289 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | 1276 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
| 1290 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 1277 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 00ca01541d89..b1310ec9720c 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
| @@ -42,9 +42,6 @@ | |||
| 42 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 | 42 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 |
| 43 | #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 | 43 | #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 |
| 44 | 44 | ||
| 45 | /* largest reported tracking id */ | ||
| 46 | #define MAX_TRACKING_ID 0xfff | ||
| 47 | |||
| 48 | enum { | 45 | enum { |
| 49 | PENPARTNER = 0, | 46 | PENPARTNER = 0, |
| 50 | GRAPHIRE, | 47 | GRAPHIRE, |
| @@ -100,7 +97,6 @@ struct wacom_wac { | |||
| 100 | int id[3]; | 97 | int id[3]; |
| 101 | __u32 serial[2]; | 98 | __u32 serial[2]; |
| 102 | int last_finger; | 99 | int last_finger; |
| 103 | int trk_id; | ||
| 104 | struct wacom_features features; | 100 | struct wacom_features features; |
| 105 | struct wacom_shared *shared; | 101 | struct wacom_shared *shared; |
| 106 | struct input_dev *input; | 102 | struct input_dev *input; |
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 4a2e8cf4c8ef..2a0bec12d12a 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
| @@ -48,8 +48,6 @@ MODULE_LICENSE("GPL"); | |||
| 48 | #define W8001_PKTLEN_TPCCTL 11 /* control packet */ | 48 | #define W8001_PKTLEN_TPCCTL 11 /* control packet */ |
| 49 | #define W8001_PKTLEN_TOUCH2FG 13 | 49 | #define W8001_PKTLEN_TOUCH2FG 13 |
| 50 | 50 | ||
| 51 | #define MAX_TRACKING_ID 0xFF /* arbitrarily chosen */ | ||
| 52 | |||
| 53 | struct w8001_coord { | 51 | struct w8001_coord { |
| 54 | u8 rdy; | 52 | u8 rdy; |
| 55 | u8 tsw; | 53 | u8 tsw; |
| @@ -87,7 +85,6 @@ struct w8001 { | |||
| 87 | char phys[32]; | 85 | char phys[32]; |
| 88 | int type; | 86 | int type; |
| 89 | unsigned int pktlen; | 87 | unsigned int pktlen; |
| 90 | int trkid[2]; | ||
| 91 | }; | 88 | }; |
| 92 | 89 | ||
| 93 | static void parse_data(u8 *data, struct w8001_coord *coord) | 90 | static void parse_data(u8 *data, struct w8001_coord *coord) |
| @@ -116,28 +113,23 @@ static void parse_data(u8 *data, struct w8001_coord *coord) | |||
| 116 | 113 | ||
| 117 | static void parse_touch(struct w8001 *w8001) | 114 | static void parse_touch(struct w8001 *w8001) |
| 118 | { | 115 | { |
| 119 | static int trkid; | ||
| 120 | struct input_dev *dev = w8001->dev; | 116 | struct input_dev *dev = w8001->dev; |
| 121 | unsigned char *data = w8001->data; | 117 | unsigned char *data = w8001->data; |
| 122 | int i; | 118 | int i; |
| 123 | 119 | ||
| 124 | for (i = 0; i < 2; i++) { | 120 | for (i = 0; i < 2; i++) { |
| 125 | input_mt_slot(dev, i); | 121 | bool touch = data[0] & (1 << i); |
| 126 | 122 | ||
| 127 | if (data[0] & (1 << i)) { | 123 | input_mt_slot(dev, i); |
| 124 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch); | ||
| 125 | if (touch) { | ||
| 128 | int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); | 126 | int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); |
| 129 | int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); | 127 | int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); |
| 130 | /* data[5,6] and [11,12] is finger capacity */ | 128 | /* data[5,6] and [11,12] is finger capacity */ |
| 131 | 129 | ||
| 132 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 130 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
| 133 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | 131 | input_report_abs(dev, ABS_MT_POSITION_Y, y); |
| 134 | input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER); | ||
| 135 | if (w8001->trkid[i] < 0) | ||
| 136 | w8001->trkid[i] = trkid++ & MAX_TRACKING_ID; | ||
| 137 | } else { | ||
| 138 | w8001->trkid[i] = -1; | ||
| 139 | } | 132 | } |
| 140 | input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]); | ||
| 141 | } | 133 | } |
| 142 | 134 | ||
| 143 | input_sync(dev); | 135 | input_sync(dev); |
| @@ -319,14 +311,12 @@ static int w8001_setup(struct w8001 *w8001) | |||
| 319 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; | 311 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; |
| 320 | 312 | ||
| 321 | input_mt_init_slots(dev, 2); | 313 | input_mt_init_slots(dev, 2); |
| 322 | input_set_abs_params(dev, ABS_MT_TRACKING_ID, | ||
| 323 | 0, MAX_TRACKING_ID, 0, 0); | ||
| 324 | input_set_abs_params(dev, ABS_MT_POSITION_X, | 314 | input_set_abs_params(dev, ABS_MT_POSITION_X, |
| 325 | 0, touch.x, 0, 0); | 315 | 0, touch.x, 0, 0); |
| 326 | input_set_abs_params(dev, ABS_MT_POSITION_Y, | 316 | input_set_abs_params(dev, ABS_MT_POSITION_Y, |
| 327 | 0, touch.y, 0, 0); | 317 | 0, touch.y, 0, 0); |
| 328 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, | 318 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, |
| 329 | 0, 0, 0, 0); | 319 | 0, MT_TOOL_MAX, 0, 0); |
| 330 | break; | 320 | break; |
| 331 | } | 321 | } |
| 332 | } | 322 | } |
| @@ -372,7 +362,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
| 372 | w8001->serio = serio; | 362 | w8001->serio = serio; |
| 373 | w8001->id = serio->id.id; | 363 | w8001->id = serio->id.id; |
| 374 | w8001->dev = input_dev; | 364 | w8001->dev = input_dev; |
| 375 | w8001->trkid[0] = w8001->trkid[1] = -1; | ||
| 376 | init_completion(&w8001->cmd_done); | 365 | init_completion(&w8001->cmd_done); |
| 377 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); | 366 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); |
| 378 | 367 | ||
