aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorJason Gerecke <killertofu@gmail.com>2014-04-19 16:46:40 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-04-19 16:57:34 -0400
commit5866d9e3b7ecdf96a6089d12bb65736d7c473bce (patch)
tree9f856291cb41ed1c3c852b676c2b1cfa84cb219b /drivers/input
parent91ae0e77836b4a13f511b4fc62dc31c523858187 (diff)
Input: wacom - use full 32-bit HID Usage value in switch statement
A HID Usage is a 32-bit value: an upper 16-bit "page" and a lower 16-bit ID. While the two halves are normally reported seperately, only the combination uniquely idenfifes a particular HID Usage. The existing code performs the comparison in two steps, first performing a switch on the ID and then verifying the page within each case. While this works fine, it is very akward to handle two Usages that share a single ID, such as HID_USAGE_PRESSURE and HID_USAGE_X because the case statement can only have a single identifier. To work around this, we now check the full 32-bit HID Usage directly rather than first checking the ID and then the page. This allows the switch statement to have distinct cases for e.g. HID_USAGE_PRESSURE and HID_USAGE_X. Signed-off-by: Jason Gerecke <killertofu@gmail.com> Tested-by: Aaron Skomra <Aaron.Skomra@wacom.com> Reviewed-by: Carl Worth <cworth@cworth.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/tablet/wacom_sys.c237
1 files changed, 109 insertions, 128 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b16ebef5b911..5be617755461 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -22,23 +22,17 @@
22#define HID_USAGE_PAGE_DIGITIZER 0x0d 22#define HID_USAGE_PAGE_DIGITIZER 0x0d
23#define HID_USAGE_PAGE_DESKTOP 0x01 23#define HID_USAGE_PAGE_DESKTOP 0x01
24#define HID_USAGE 0x09 24#define HID_USAGE 0x09
25#define HID_USAGE_X 0x30 25#define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
26#define HID_USAGE_Y 0x31 26#define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
27#define HID_USAGE_X_TILT 0x3d 27#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
28#define HID_USAGE_Y_TILT 0x3e 28#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
29#define HID_USAGE_FINGER 0x22 29#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
30#define HID_USAGE_STYLUS 0x20 30#define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
31#define HID_USAGE_CONTACTMAX 0x55 31#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
32#define HID_COLLECTION 0xa1 32#define HID_COLLECTION 0xa1
33#define HID_COLLECTION_LOGICAL 0x02 33#define HID_COLLECTION_LOGICAL 0x02
34#define HID_COLLECTION_END 0xc0 34#define HID_COLLECTION_END 0xc0
35 35
36enum {
37 WCM_UNDEFINED = 0,
38 WCM_DESKTOP,
39 WCM_DIGITIZER,
40};
41
42struct hid_descriptor { 36struct hid_descriptor {
43 struct usb_descriptor_header header; 37 struct usb_descriptor_header header;
44 __le16 bcdHID; 38 __le16 bcdHID;
@@ -305,7 +299,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
305 char limit = 0; 299 char limit = 0;
306 /* result has to be defined as int for some devices */ 300 /* result has to be defined as int for some devices */
307 int result = 0, touch_max = 0; 301 int result = 0, touch_max = 0;
308 int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; 302 int i = 0, page = 0, finger = 0, pen = 0;
309 unsigned char *report; 303 unsigned char *report;
310 304
311 report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); 305 report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
@@ -332,134 +326,121 @@ static int wacom_parse_hid(struct usb_interface *intf,
332 326
333 switch (report[i]) { 327 switch (report[i]) {
334 case HID_USAGE_PAGE: 328 case HID_USAGE_PAGE:
335 switch (report[i + 1]) { 329 page = report[i + 1];
336 case HID_USAGE_PAGE_DIGITIZER: 330 i++;
337 usage = WCM_DIGITIZER;
338 i++;
339 break;
340
341 case HID_USAGE_PAGE_DESKTOP:
342 usage = WCM_DESKTOP;
343 i++;
344 break;
345 }
346 break; 331 break;
347 332
348 case HID_USAGE: 333 case HID_USAGE:
349 switch (report[i + 1]) { 334 switch (page << 16 | report[i + 1]) {
350 case HID_USAGE_X: 335 case HID_USAGE_X:
351 if (usage == WCM_DESKTOP) { 336 if (finger) {
352 if (finger) { 337 features->device_type = BTN_TOOL_FINGER;
353 features->device_type = BTN_TOOL_FINGER; 338 /* touch device at least supports one touch point */
354 /* touch device at least supports one touch point */ 339 touch_max = 1;
355 touch_max = 1; 340 switch (features->type) {
356 switch (features->type) { 341 case TABLETPC2FG:
357 case TABLETPC2FG: 342 features->pktlen = WACOM_PKGLEN_TPC2FG;
358 features->pktlen = WACOM_PKGLEN_TPC2FG; 343 break;
359 break; 344
360 345 case MTSCREEN:
361 case MTSCREEN: 346 case WACOM_24HDT:
362 case WACOM_24HDT: 347 features->pktlen = WACOM_PKGLEN_MTOUCH;
363 features->pktlen = WACOM_PKGLEN_MTOUCH; 348 break;
364 break; 349
365 350 case MTTPC:
366 case MTTPC: 351 features->pktlen = WACOM_PKGLEN_MTTPC;
367 features->pktlen = WACOM_PKGLEN_MTTPC; 352 break;
368 break; 353
369 354 case BAMBOO_PT:
370 case BAMBOO_PT: 355 features->pktlen = WACOM_PKGLEN_BBTOUCH;
371 features->pktlen = WACOM_PKGLEN_BBTOUCH; 356 break;
372 break; 357
373 358 default:
374 default: 359 features->pktlen = WACOM_PKGLEN_GRAPHIRE;
375 features->pktlen = WACOM_PKGLEN_GRAPHIRE; 360 break;
376 break; 361 }
377 } 362
378 363 switch (features->type) {
379 switch (features->type) { 364 case BAMBOO_PT:
380 case BAMBOO_PT: 365 features->x_phy =
381 features->x_phy = 366 get_unaligned_le16(&report[i + 5]);
382 get_unaligned_le16(&report[i + 5]); 367 features->x_max =
383 features->x_max = 368 get_unaligned_le16(&report[i + 8]);
384 get_unaligned_le16(&report[i + 8]); 369 i += 15;
385 i += 15; 370 break;
386 break; 371
387 372 case WACOM_24HDT:
388 case WACOM_24HDT:
389 features->x_max =
390 get_unaligned_le16(&report[i + 3]);
391 features->x_phy =
392 get_unaligned_le16(&report[i + 8]);
393 features->unit = report[i - 1];
394 features->unitExpo = report[i - 3];
395 i += 12;
396 break;
397
398 default:
399 features->x_max =
400 get_unaligned_le16(&report[i + 3]);
401 features->x_phy =
402 get_unaligned_le16(&report[i + 6]);
403 features->unit = report[i + 9];
404 features->unitExpo = report[i + 11];
405 i += 12;
406 break;
407 }
408 } else if (pen) {
409 /* penabled only accepts exact bytes of data */
410 if (features->type >= TABLETPC)
411 features->pktlen = WACOM_PKGLEN_GRAPHIRE;
412 features->device_type = BTN_TOOL_PEN;
413 features->x_max = 373 features->x_max =
414 get_unaligned_le16(&report[i + 3]); 374 get_unaligned_le16(&report[i + 3]);
415 i += 4; 375 features->x_phy =
376 get_unaligned_le16(&report[i + 8]);
377 features->unit = report[i - 1];
378 features->unitExpo = report[i - 3];
379 i += 12;
380 break;
381
382 default:
383 features->x_max =
384 get_unaligned_le16(&report[i + 3]);
385 features->x_phy =
386 get_unaligned_le16(&report[i + 6]);
387 features->unit = report[i + 9];
388 features->unitExpo = report[i + 11];
389 i += 12;
390 break;
416 } 391 }
392 } else if (pen) {
393 /* penabled only accepts exact bytes of data */
394 if (features->type >= TABLETPC)
395 features->pktlen = WACOM_PKGLEN_GRAPHIRE;
396 features->device_type = BTN_TOOL_PEN;
397 features->x_max =
398 get_unaligned_le16(&report[i + 3]);
399 i += 4;
417 } 400 }
418 break; 401 break;
419 402
420 case HID_USAGE_Y: 403 case HID_USAGE_Y:
421 if (usage == WCM_DESKTOP) { 404 if (finger) {
422 if (finger) { 405 switch (features->type) {
423 switch (features->type) { 406 case TABLETPC2FG:
424 case TABLETPC2FG: 407 case MTSCREEN:
425 case MTSCREEN: 408 case MTTPC:
426 case MTTPC: 409 features->y_max =
427 features->y_max = 410 get_unaligned_le16(&report[i + 3]);
428 get_unaligned_le16(&report[i + 3]); 411 features->y_phy =
429 features->y_phy = 412 get_unaligned_le16(&report[i + 6]);
430 get_unaligned_le16(&report[i + 6]); 413 i += 7;
431 i += 7; 414 break;
432 break; 415
433 416 case WACOM_24HDT:
434 case WACOM_24HDT: 417 features->y_max =
435 features->y_max = 418 get_unaligned_le16(&report[i + 3]);
436 get_unaligned_le16(&report[i + 3]); 419 features->y_phy =
437 features->y_phy = 420 get_unaligned_le16(&report[i - 2]);
438 get_unaligned_le16(&report[i - 2]); 421 i += 7;
439 i += 7; 422 break;
440 break; 423
441 424 case BAMBOO_PT:
442 case BAMBOO_PT: 425 features->y_phy =
443 features->y_phy = 426 get_unaligned_le16(&report[i + 3]);
444 get_unaligned_le16(&report[i + 3]); 427 features->y_max =
445 features->y_max = 428 get_unaligned_le16(&report[i + 6]);
446 get_unaligned_le16(&report[i + 6]); 429 i += 12;
447 i += 12; 430 break;
448 break; 431
449 432 default:
450 default:
451 features->y_max =
452 features->x_max;
453 features->y_phy =
454 get_unaligned_le16(&report[i + 3]);
455 i += 4;
456 break;
457 }
458 } else if (pen) {
459 features->y_max = 433 features->y_max =
434 features->x_max;
435 features->y_phy =
460 get_unaligned_le16(&report[i + 3]); 436 get_unaligned_le16(&report[i + 3]);
461 i += 4; 437 i += 4;
438 break;
462 } 439 }
440 } else if (pen) {
441 features->y_max =
442 get_unaligned_le16(&report[i + 3]);
443 i += 4;
463 } 444 }
464 break; 445 break;
465 446
@@ -489,7 +470,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
489 470
490 case HID_COLLECTION_END: 471 case HID_COLLECTION_END:
491 /* reset UsagePage and Finger */ 472 /* reset UsagePage and Finger */
492 finger = usage = 0; 473 finger = page = 0;
493 break; 474 break;
494 475
495 case HID_COLLECTION: 476 case HID_COLLECTION: