diff options
Diffstat (limited to 'drivers/hid/hid-wacom.c')
-rw-r--r-- | drivers/hid/hid-wacom.c | 95 |
1 files changed, 84 insertions, 11 deletions
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index acab74cde727..067e2963314c 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -31,10 +31,15 @@ | |||
31 | 31 | ||
32 | #include "hid-ids.h" | 32 | #include "hid-ids.h" |
33 | 33 | ||
34 | #define PAD_DEVICE_ID 0x0F | ||
35 | |||
34 | struct wacom_data { | 36 | struct wacom_data { |
35 | __u16 tool; | 37 | __u16 tool; |
36 | unsigned char butstate; | 38 | __u16 butstate; |
39 | __u8 whlstate; | ||
37 | __u8 features; | 40 | __u8 features; |
41 | __u32 id; | ||
42 | __u32 serial; | ||
38 | unsigned char high_speed; | 43 | unsigned char high_speed; |
39 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 44 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
40 | int battery_capacity; | 45 | int battery_capacity; |
@@ -314,30 +319,82 @@ static int wacom_gr_parse_report(struct hid_device *hdev, | |||
314 | return 1; | 319 | return 1; |
315 | } | 320 | } |
316 | 321 | ||
322 | static void wacom_i4_parse_button_report(struct wacom_data *wdata, | ||
323 | struct input_dev *input, unsigned char *data) | ||
324 | { | ||
325 | __u16 new_butstate; | ||
326 | __u8 new_whlstate; | ||
327 | __u8 sync = 0; | ||
328 | |||
329 | new_whlstate = data[1]; | ||
330 | if (new_whlstate != wdata->whlstate) { | ||
331 | wdata->whlstate = new_whlstate; | ||
332 | if (new_whlstate & 0x80) { | ||
333 | input_report_key(input, BTN_TOUCH, 1); | ||
334 | input_report_abs(input, ABS_WHEEL, (new_whlstate & 0x7f)); | ||
335 | input_report_key(input, BTN_TOOL_FINGER, 1); | ||
336 | } else { | ||
337 | input_report_key(input, BTN_TOUCH, 0); | ||
338 | input_report_abs(input, ABS_WHEEL, 0); | ||
339 | input_report_key(input, BTN_TOOL_FINGER, 0); | ||
340 | } | ||
341 | sync = 1; | ||
342 | } | ||
343 | |||
344 | new_butstate = (data[3] << 1) | (data[2] & 0x01); | ||
345 | if (new_butstate != wdata->butstate) { | ||
346 | wdata->butstate = new_butstate; | ||
347 | input_report_key(input, BTN_0, new_butstate & 0x001); | ||
348 | input_report_key(input, BTN_1, new_butstate & 0x002); | ||
349 | input_report_key(input, BTN_2, new_butstate & 0x004); | ||
350 | input_report_key(input, BTN_3, new_butstate & 0x008); | ||
351 | input_report_key(input, BTN_4, new_butstate & 0x010); | ||
352 | input_report_key(input, BTN_5, new_butstate & 0x020); | ||
353 | input_report_key(input, BTN_6, new_butstate & 0x040); | ||
354 | input_report_key(input, BTN_7, new_butstate & 0x080); | ||
355 | input_report_key(input, BTN_8, new_butstate & 0x100); | ||
356 | input_report_key(input, BTN_TOOL_FINGER, 1); | ||
357 | sync = 1; | ||
358 | } | ||
359 | |||
360 | if (sync) { | ||
361 | input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); | ||
362 | input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); | ||
363 | input_sync(input); | ||
364 | } | ||
365 | } | ||
366 | |||
317 | static void wacom_i4_parse_pen_report(struct wacom_data *wdata, | 367 | static void wacom_i4_parse_pen_report(struct wacom_data *wdata, |
318 | struct input_dev *input, unsigned char *data) | 368 | struct input_dev *input, unsigned char *data) |
319 | { | 369 | { |
320 | __u16 x, y, pressure; | 370 | __u16 x, y, pressure; |
321 | __u32 id; | 371 | __u8 distance; |
322 | 372 | ||
323 | switch (data[1]) { | 373 | switch (data[1]) { |
324 | case 0x80: /* Out of proximity report */ | 374 | case 0x80: /* Out of proximity report */ |
325 | wdata->tool = 0; | ||
326 | input_report_key(input, BTN_TOUCH, 0); | 375 | input_report_key(input, BTN_TOUCH, 0); |
327 | input_report_abs(input, ABS_PRESSURE, 0); | 376 | input_report_abs(input, ABS_PRESSURE, 0); |
377 | input_report_key(input, BTN_STYLUS, 0); | ||
378 | input_report_key(input, BTN_STYLUS2, 0); | ||
328 | input_report_key(input, wdata->tool, 0); | 379 | input_report_key(input, wdata->tool, 0); |
380 | input_report_abs(input, ABS_MISC, 0); | ||
381 | input_event(input, EV_MSC, MSC_SERIAL, wdata->serial); | ||
382 | wdata->tool = 0; | ||
329 | input_sync(input); | 383 | input_sync(input); |
330 | break; | 384 | break; |
331 | case 0xC2: /* Tool report */ | 385 | case 0xC2: /* Tool report */ |
332 | id = ((data[2] << 4) | (data[3] >> 4) | | 386 | wdata->id = ((data[2] << 4) | (data[3] >> 4) | |
333 | ((data[7] & 0x0f) << 20) | | 387 | ((data[7] & 0x0f) << 20) | |
334 | ((data[8] & 0xf0) << 12)) & 0xfffff; | 388 | ((data[8] & 0xf0) << 12)); |
389 | wdata->serial = ((data[3] & 0x0f) << 28) + | ||
390 | (data[4] << 20) + (data[5] << 12) + | ||
391 | (data[6] << 4) + (data[7] >> 4); | ||
335 | 392 | ||
336 | switch (id) { | 393 | switch (wdata->id) { |
337 | case 0x802: | 394 | case 0x100802: |
338 | wdata->tool = BTN_TOOL_PEN; | 395 | wdata->tool = BTN_TOOL_PEN; |
339 | break; | 396 | break; |
340 | case 0x80A: | 397 | case 0x10080A: |
341 | wdata->tool = BTN_TOOL_RUBBER; | 398 | wdata->tool = BTN_TOOL_RUBBER; |
342 | break; | 399 | break; |
343 | } | 400 | } |
@@ -347,6 +404,7 @@ static void wacom_i4_parse_pen_report(struct wacom_data *wdata, | |||
347 | y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01); | 404 | y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01); |
348 | pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | 405 | pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5) |
349 | | (data[1] & 0x01); | 406 | | (data[1] & 0x01); |
407 | distance = (data[9] >> 2) & 0x3f; | ||
350 | 408 | ||
351 | input_report_key(input, BTN_TOUCH, pressure > 1); | 409 | input_report_key(input, BTN_TOUCH, pressure > 1); |
352 | 410 | ||
@@ -356,6 +414,10 @@ static void wacom_i4_parse_pen_report(struct wacom_data *wdata, | |||
356 | input_report_abs(input, ABS_X, x); | 414 | input_report_abs(input, ABS_X, x); |
357 | input_report_abs(input, ABS_Y, y); | 415 | input_report_abs(input, ABS_Y, y); |
358 | input_report_abs(input, ABS_PRESSURE, pressure); | 416 | input_report_abs(input, ABS_PRESSURE, pressure); |
417 | input_report_abs(input, ABS_DISTANCE, distance); | ||
418 | input_report_abs(input, ABS_MISC, wdata->id); | ||
419 | input_event(input, EV_MSC, MSC_SERIAL, wdata->serial); | ||
420 | input_report_key(input, wdata->tool, 1); | ||
359 | input_sync(input); | 421 | input_sync(input); |
360 | break; | 422 | break; |
361 | } | 423 | } |
@@ -377,6 +439,7 @@ static void wacom_i4_parse_report(struct hid_device *hdev, | |||
377 | wdata->features = data[2]; | 439 | wdata->features = data[2]; |
378 | break; | 440 | break; |
379 | case 0x0C: /* Button report */ | 441 | case 0x0C: /* Button report */ |
442 | wacom_i4_parse_button_report(wdata, input, data); | ||
380 | break; | 443 | break; |
381 | default: | 444 | default: |
382 | hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]); | 445 | hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]); |
@@ -451,9 +514,7 @@ static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
451 | __set_bit(BTN_MIDDLE, input->keybit); | 514 | __set_bit(BTN_MIDDLE, input->keybit); |
452 | 515 | ||
453 | /* Pad */ | 516 | /* Pad */ |
454 | input->evbit[0] |= BIT(EV_MSC); | 517 | input_set_capability(input, EV_MSC, MSC_SERIAL); |
455 | |||
456 | __set_bit(MSC_SERIAL, input->mscbit); | ||
457 | 518 | ||
458 | __set_bit(BTN_0, input->keybit); | 519 | __set_bit(BTN_0, input->keybit); |
459 | __set_bit(BTN_1, input->keybit); | 520 | __set_bit(BTN_1, input->keybit); |
@@ -471,9 +532,20 @@ static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
471 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | 532 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); |
472 | break; | 533 | break; |
473 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | 534 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: |
535 | __set_bit(ABS_WHEEL, input->absbit); | ||
536 | __set_bit(ABS_MISC, input->absbit); | ||
537 | __set_bit(BTN_2, input->keybit); | ||
538 | __set_bit(BTN_3, input->keybit); | ||
539 | __set_bit(BTN_4, input->keybit); | ||
540 | __set_bit(BTN_5, input->keybit); | ||
541 | __set_bit(BTN_6, input->keybit); | ||
542 | __set_bit(BTN_7, input->keybit); | ||
543 | __set_bit(BTN_8, input->keybit); | ||
544 | input_set_abs_params(input, ABS_WHEEL, 0, 71, 0, 0); | ||
474 | input_set_abs_params(input, ABS_X, 0, 40640, 4, 0); | 545 | input_set_abs_params(input, ABS_X, 0, 40640, 4, 0); |
475 | input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0); | 546 | input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0); |
476 | input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0); | 547 | input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0); |
548 | input_set_abs_params(input, ABS_DISTANCE, 0, 63, 0, 0); | ||
477 | break; | 549 | break; |
478 | } | 550 | } |
479 | 551 | ||
@@ -518,6 +590,7 @@ static int wacom_probe(struct hid_device *hdev, | |||
518 | wacom_poke(hdev, 1); | 590 | wacom_poke(hdev, 1); |
519 | break; | 591 | break; |
520 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | 592 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: |
593 | sprintf(hdev->name, "%s", "Wacom Intuos4 WL"); | ||
521 | wdata->features = 0; | 594 | wdata->features = 0; |
522 | wacom_set_features(hdev); | 595 | wacom_set_features(hdev); |
523 | break; | 596 | break; |