diff options
Diffstat (limited to 'drivers/input/tablet/wacom_sys.c')
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 101 |
1 files changed, 91 insertions, 10 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8f9cde3e0ec2..2a97b7e76db1 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -28,7 +28,9 @@ | |||
28 | #define HID_USAGE_Y_TILT 0x3e | 28 | #define HID_USAGE_Y_TILT 0x3e |
29 | #define HID_USAGE_FINGER 0x22 | 29 | #define HID_USAGE_FINGER 0x22 |
30 | #define HID_USAGE_STYLUS 0x20 | 30 | #define HID_USAGE_STYLUS 0x20 |
31 | #define HID_COLLECTION 0xc0 | 31 | #define HID_COLLECTION 0xa1 |
32 | #define HID_COLLECTION_LOGICAL 0x02 | ||
33 | #define HID_COLLECTION_END 0xc0 | ||
32 | 34 | ||
33 | enum { | 35 | enum { |
34 | WCM_UNDEFINED = 0, | 36 | WCM_UNDEFINED = 0, |
@@ -66,7 +68,8 @@ static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id, | |||
66 | do { | 68 | do { |
67 | retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 69 | retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
68 | USB_REQ_GET_REPORT, | 70 | USB_REQ_GET_REPORT, |
69 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 71 | USB_DIR_IN | USB_TYPE_CLASS | |
72 | USB_RECIP_INTERFACE, | ||
70 | (type << 8) + id, | 73 | (type << 8) + id, |
71 | intf->altsetting[0].desc.bInterfaceNumber, | 74 | intf->altsetting[0].desc.bInterfaceNumber, |
72 | buf, size, 100); | 75 | buf, size, 100); |
@@ -164,7 +167,70 @@ static void wacom_close(struct input_dev *dev) | |||
164 | usb_autopm_put_interface(wacom->intf); | 167 | usb_autopm_put_interface(wacom->intf); |
165 | } | 168 | } |
166 | 169 | ||
167 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, | 170 | static int wacom_parse_logical_collection(unsigned char *report, |
171 | struct wacom_features *features) | ||
172 | { | ||
173 | int length = 0; | ||
174 | |||
175 | if (features->type == BAMBOO_PT) { | ||
176 | |||
177 | /* Logical collection is only used by 3rd gen Bamboo Touch */ | ||
178 | features->pktlen = WACOM_PKGLEN_BBTOUCH3; | ||
179 | features->device_type = BTN_TOOL_DOUBLETAP; | ||
180 | |||
181 | /* | ||
182 | * Stylus and Touch have same active area | ||
183 | * so compute physical size based on stylus | ||
184 | * data before its overwritten. | ||
185 | */ | ||
186 | features->x_phy = | ||
187 | (features->x_max * features->x_resolution) / 100; | ||
188 | features->y_phy = | ||
189 | (features->y_max * features->y_resolution) / 100; | ||
190 | |||
191 | features->x_max = features->y_max = | ||
192 | get_unaligned_le16(&report[10]); | ||
193 | |||
194 | length = 11; | ||
195 | } | ||
196 | return length; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * Interface Descriptor of wacom devices can be incomplete and | ||
201 | * inconsistent so wacom_features table is used to store stylus | ||
202 | * device's packet lengths, various maximum values, and tablet | ||
203 | * resolution based on product ID's. | ||
204 | * | ||
205 | * For devices that contain 2 interfaces, wacom_features table is | ||
206 | * inaccurate for the touch interface. Since the Interface Descriptor | ||
207 | * for touch interfaces has pretty complete data, this function exists | ||
208 | * to query tablet for this missing information instead of hard coding in | ||
209 | * an additional table. | ||
210 | * | ||
211 | * A typical Interface Descriptor for a stylus will contain a | ||
212 | * boot mouse application collection that is not of interest and this | ||
213 | * function will ignore it. | ||
214 | * | ||
215 | * It also contains a digitizer application collection that also is not | ||
216 | * of interest since any information it contains would be duplicate | ||
217 | * of what is in wacom_features. Usually it defines a report of an array | ||
218 | * of bytes that could be used as max length of the stylus packet returned. | ||
219 | * If it happens to define a Digitizer-Stylus Physical Collection then | ||
220 | * the X and Y logical values contain valid data but it is ignored. | ||
221 | * | ||
222 | * A typical Interface Descriptor for a touch interface will contain a | ||
223 | * Digitizer-Finger Physical Collection which will define both logical | ||
224 | * X/Y maximum as well as the physical size of tablet. Since touch | ||
225 | * interfaces haven't supported pressure or distance, this is enough | ||
226 | * information to override invalid values in the wacom_features table. | ||
227 | * | ||
228 | * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical | ||
229 | * Collection. Instead they define a Logical Collection with a single | ||
230 | * Logical Maximum for both X and Y. | ||
231 | */ | ||
232 | static int wacom_parse_hid(struct usb_interface *intf, | ||
233 | struct hid_descriptor *hid_desc, | ||
168 | struct wacom_features *features) | 234 | struct wacom_features *features) |
169 | { | 235 | { |
170 | struct usb_device *dev = interface_to_usbdev(intf); | 236 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -244,8 +310,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
244 | /* penabled only accepts exact bytes of data */ | 310 | /* penabled only accepts exact bytes of data */ |
245 | if (features->type == TABLETPC2FG) | 311 | if (features->type == TABLETPC2FG) |
246 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | 312 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; |
247 | if (features->type == BAMBOO_PT) | ||
248 | features->pktlen = WACOM_PKGLEN_BBFUN; | ||
249 | features->device_type = BTN_TOOL_PEN; | 313 | features->device_type = BTN_TOOL_PEN; |
250 | features->x_max = | 314 | features->x_max = |
251 | get_unaligned_le16(&report[i + 3]); | 315 | get_unaligned_le16(&report[i + 3]); |
@@ -287,8 +351,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
287 | /* penabled only accepts exact bytes of data */ | 351 | /* penabled only accepts exact bytes of data */ |
288 | if (features->type == TABLETPC2FG) | 352 | if (features->type == TABLETPC2FG) |
289 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | 353 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; |
290 | if (features->type == BAMBOO_PT) | ||
291 | features->pktlen = WACOM_PKGLEN_BBFUN; | ||
292 | features->device_type = BTN_TOOL_PEN; | 354 | features->device_type = BTN_TOOL_PEN; |
293 | features->y_max = | 355 | features->y_max = |
294 | get_unaligned_le16(&report[i + 3]); | 356 | get_unaligned_le16(&report[i + 3]); |
@@ -302,6 +364,11 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
302 | i++; | 364 | i++; |
303 | break; | 365 | break; |
304 | 366 | ||
367 | /* | ||
368 | * Requiring Stylus Usage will ignore boot mouse | ||
369 | * X/Y values and some cases of invalid Digitizer X/Y | ||
370 | * values commonly reported. | ||
371 | */ | ||
305 | case HID_USAGE_STYLUS: | 372 | case HID_USAGE_STYLUS: |
306 | pen = 1; | 373 | pen = 1; |
307 | i++; | 374 | i++; |
@@ -309,10 +376,20 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
309 | } | 376 | } |
310 | break; | 377 | break; |
311 | 378 | ||
312 | case HID_COLLECTION: | 379 | case HID_COLLECTION_END: |
313 | /* reset UsagePage and Finger */ | 380 | /* reset UsagePage and Finger */ |
314 | finger = usage = 0; | 381 | finger = usage = 0; |
315 | break; | 382 | break; |
383 | |||
384 | case HID_COLLECTION: | ||
385 | i++; | ||
386 | switch (report[i]) { | ||
387 | case HID_COLLECTION_LOGICAL: | ||
388 | i += wacom_parse_logical_collection(&report[i], | ||
389 | features); | ||
390 | break; | ||
391 | } | ||
392 | break; | ||
316 | } | 393 | } |
317 | } | 394 | } |
318 | 395 | ||
@@ -348,7 +425,8 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
348 | WAC_HID_FEATURE_REPORT, | 425 | WAC_HID_FEATURE_REPORT, |
349 | report_id, rep_data, 4, 1); | 426 | report_id, rep_data, 4, 1); |
350 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); | 427 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); |
351 | } else if (features->type != TABLETPC) { | 428 | } else if (features->type != TABLETPC && |
429 | features->device_type == BTN_TOOL_PEN) { | ||
352 | do { | 430 | do { |
353 | rep_data[0] = 2; | 431 | rep_data[0] = 2; |
354 | rep_data[1] = 2; | 432 | rep_data[1] = 2; |
@@ -485,7 +563,8 @@ static int wacom_led_control(struct wacom *wacom) | |||
485 | if (!buf) | 563 | if (!buf) |
486 | return -ENOMEM; | 564 | return -ENOMEM; |
487 | 565 | ||
488 | if (wacom->wacom_wac.features.type == WACOM_21UX2) | 566 | if (wacom->wacom_wac.features.type == WACOM_21UX2 || |
567 | wacom->wacom_wac.features.type == WACOM_24HD) | ||
489 | led = (wacom->led.select[1] << 4) | 0x40; | 568 | led = (wacom->led.select[1] << 4) | 0x40; |
490 | 569 | ||
491 | led |= wacom->led.select[0] | 0x4; | 570 | led |= wacom->led.select[0] | 0x4; |
@@ -704,6 +783,7 @@ static int wacom_initialize_leds(struct wacom *wacom) | |||
704 | &intuos4_led_attr_group); | 783 | &intuos4_led_attr_group); |
705 | break; | 784 | break; |
706 | 785 | ||
786 | case WACOM_24HD: | ||
707 | case WACOM_21UX2: | 787 | case WACOM_21UX2: |
708 | wacom->led.select[0] = 0; | 788 | wacom->led.select[0] = 0; |
709 | wacom->led.select[1] = 0; | 789 | wacom->led.select[1] = 0; |
@@ -738,6 +818,7 @@ static void wacom_destroy_leds(struct wacom *wacom) | |||
738 | &intuos4_led_attr_group); | 818 | &intuos4_led_attr_group); |
739 | break; | 819 | break; |
740 | 820 | ||
821 | case WACOM_24HD: | ||
741 | case WACOM_21UX2: | 822 | case WACOM_21UX2: |
742 | sysfs_remove_group(&wacom->intf->dev.kobj, | 823 | sysfs_remove_group(&wacom->intf->dev.kobj, |
743 | &cintiq_led_attr_group); | 824 | &cintiq_led_attr_group); |