diff options
| author | Jason Gerecke <killertofu@gmail.com> | 2012-10-21 03:38:04 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-25 19:02:36 -0400 |
| commit | b1e4279e4ef5549bf6ebf8f6f17dd26f0af8e8a2 (patch) | |
| tree | d3bcb7957ca8c37bdf579738f0431ce3635b7783 | |
| parent | aea2bf6a57a9e4596bfad164f986ba10ddc6adf3 (diff) | |
Input: wacom - add touch sensor support for Cintiq 24HD touch
Decode multitouch reports from the touch sensor of the Cintiq 24HD
touch.
Signed-off-by: Jason Gerecke <killertofu@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | drivers/input/tablet/wacom_sys.c | 19 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_wac.c | 85 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_wac.h | 3 |
3 files changed, 104 insertions, 3 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 8b89e15bcf32..2c1e12bf2ab4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
| @@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
| 391 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 391 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | if (features->type == MTSCREEN) | 394 | if (features->type == MTSCREEN || WACOM_24HDT) |
| 395 | features->pktlen = WACOM_PKGLEN_MTOUCH; | 395 | features->pktlen = WACOM_PKGLEN_MTOUCH; |
| 396 | 396 | ||
| 397 | if (features->type == BAMBOO_PT) { | 397 | if (features->type == BAMBOO_PT) { |
| @@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
| 402 | features->x_max = | 402 | features->x_max = |
| 403 | get_unaligned_le16(&report[i + 8]); | 403 | get_unaligned_le16(&report[i + 8]); |
| 404 | i += 15; | 404 | i += 15; |
| 405 | } else if (features->type == WACOM_24HDT) { | ||
| 406 | features->x_max = | ||
| 407 | get_unaligned_le16(&report[i + 3]); | ||
| 408 | features->x_phy = | ||
| 409 | get_unaligned_le16(&report[i + 8]); | ||
| 410 | features->unit = report[i - 1]; | ||
| 411 | features->unitExpo = report[i - 3]; | ||
| 412 | i += 12; | ||
| 405 | } else { | 413 | } else { |
| 406 | features->x_max = | 414 | features->x_max = |
| 407 | get_unaligned_le16(&report[i + 3]); | 415 | get_unaligned_le16(&report[i + 3]); |
| @@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
| 434 | features->y_phy = | 442 | features->y_phy = |
| 435 | get_unaligned_le16(&report[i + 6]); | 443 | get_unaligned_le16(&report[i + 6]); |
| 436 | i += 7; | 444 | i += 7; |
| 445 | } else if (type == WACOM_24HDT) { | ||
| 446 | features->y_max = | ||
| 447 | get_unaligned_le16(&report[i + 3]); | ||
| 448 | features->y_phy = | ||
| 449 | get_unaligned_le16(&report[i - 2]); | ||
| 450 | i += 7; | ||
| 437 | } else if (type == BAMBOO_PT) { | 451 | } else if (type == BAMBOO_PT) { |
| 438 | features->y_phy = | 452 | features->y_phy = |
| 439 | get_unaligned_le16(&report[i + 3]); | 453 | get_unaligned_le16(&report[i + 3]); |
| @@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
| 541 | /* MT Tablet PC touch */ | 555 | /* MT Tablet PC touch */ |
| 542 | return wacom_set_device_mode(intf, 3, 4, 4); | 556 | return wacom_set_device_mode(intf, 3, 4, 4); |
| 543 | } | 557 | } |
| 558 | else if (features->type == WACOM_24HDT) { | ||
| 559 | return wacom_set_device_mode(intf, 18, 3, 2); | ||
| 560 | } | ||
| 544 | } else if (features->device_type == BTN_TOOL_PEN) { | 561 | } else if (features->device_type == BTN_TOOL_PEN) { |
| 545 | if (features->type <= BAMBOO_PT && features->type != WIRELESS) { | 562 | if (features->type <= BAMBOO_PT && features->type != WIRELESS) { |
| 546 | return wacom_set_device_mode(intf, 2, 2, 2); | 563 | return wacom_set_device_mode(intf, 2, 2, 2); |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 21d1f4eaff53..aa6010131179 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) | |||
| 806 | return -1; | 806 | return -1; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | static int int_dist(int x1, int y1, int x2, int y2) | ||
| 810 | { | ||
| 811 | int x = x2 - x1; | ||
| 812 | int y = y2 - y1; | ||
| 813 | |||
| 814 | return int_sqrt(x*x + y*y); | ||
| 815 | } | ||
| 816 | |||
| 817 | static int wacom_24hdt_irq(struct wacom_wac *wacom) | ||
| 818 | { | ||
| 819 | struct input_dev *input = wacom->input; | ||
| 820 | char *data = wacom->data; | ||
| 821 | int i; | ||
| 822 | int current_num_contacts = data[61]; | ||
| 823 | int contacts_to_send = 0; | ||
| 824 | |||
| 825 | /* | ||
| 826 | * First packet resets the counter since only the first | ||
| 827 | * packet in series will have non-zero current_num_contacts. | ||
| 828 | */ | ||
| 829 | if (current_num_contacts) | ||
| 830 | wacom->num_contacts_left = current_num_contacts; | ||
| 831 | |||
| 832 | /* There are at most 4 contacts per packet */ | ||
| 833 | contacts_to_send = min(4, wacom->num_contacts_left); | ||
| 834 | |||
| 835 | for (i = 0; i < contacts_to_send; i++) { | ||
| 836 | int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1; | ||
| 837 | bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity; | ||
| 838 | int id = data[offset + 1]; | ||
| 839 | int slot = find_slot_from_contactid(wacom, id); | ||
| 840 | |||
| 841 | if (slot < 0) | ||
| 842 | continue; | ||
| 843 | input_mt_slot(input, slot); | ||
| 844 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | ||
| 845 | |||
| 846 | if (touch) { | ||
| 847 | int t_x = le16_to_cpup((__le16 *)&data[offset + 2]); | ||
| 848 | int c_x = le16_to_cpup((__le16 *)&data[offset + 4]); | ||
| 849 | int t_y = le16_to_cpup((__le16 *)&data[offset + 6]); | ||
| 850 | int c_y = le16_to_cpup((__le16 *)&data[offset + 8]); | ||
| 851 | int w = le16_to_cpup((__le16 *)&data[offset + 10]); | ||
| 852 | int h = le16_to_cpup((__le16 *)&data[offset + 12]); | ||
| 853 | |||
| 854 | input_report_abs(input, ABS_MT_POSITION_X, t_x); | ||
| 855 | input_report_abs(input, ABS_MT_POSITION_Y, t_y); | ||
| 856 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h)); | ||
| 857 | input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y)); | ||
| 858 | input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); | ||
| 859 | input_report_abs(input, ABS_MT_ORIENTATION, w > h); | ||
| 860 | } | ||
| 861 | wacom->slots[slot] = touch ? id : -1; | ||
| 862 | } | ||
| 863 | |||
| 864 | input_mt_report_pointer_emulation(input, true); | ||
| 865 | |||
| 866 | wacom->num_contacts_left -= contacts_to_send; | ||
| 867 | if (wacom->num_contacts_left <= 0) | ||
| 868 | wacom->num_contacts_left = 0; | ||
| 869 | |||
| 870 | return 1; | ||
| 871 | } | ||
| 872 | |||
| 809 | static int wacom_mt_touch(struct wacom_wac *wacom) | 873 | static int wacom_mt_touch(struct wacom_wac *wacom) |
| 810 | { | 874 | { |
| 811 | struct input_dev *input = wacom->input; | 875 | struct input_dev *input = wacom->input; |
| @@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
| 1255 | sync = wacom_intuos_irq(wacom_wac); | 1319 | sync = wacom_intuos_irq(wacom_wac); |
| 1256 | break; | 1320 | break; |
| 1257 | 1321 | ||
| 1322 | case WACOM_24HDT: | ||
| 1323 | sync = wacom_24hdt_irq(wacom_wac); | ||
| 1324 | break; | ||
| 1325 | |||
| 1258 | case INTUOS5S: | 1326 | case INTUOS5S: |
| 1259 | case INTUOS5: | 1327 | case INTUOS5: |
| 1260 | case INTUOS5L: | 1328 | case INTUOS5L: |
| @@ -1576,6 +1644,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 1576 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | 1644 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
| 1577 | break; | 1645 | break; |
| 1578 | 1646 | ||
| 1647 | case WACOM_24HDT: | ||
| 1648 | if (features->device_type == BTN_TOOL_FINGER) { | ||
| 1649 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); | ||
| 1650 | input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); | ||
| 1651 | input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); | ||
| 1652 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); | ||
| 1653 | } | ||
| 1654 | /* fall through */ | ||
| 1655 | |||
| 1579 | case MTSCREEN: | 1656 | case MTSCREEN: |
| 1580 | if (features->device_type == BTN_TOOL_FINGER) { | 1657 | if (features->device_type == BTN_TOOL_FINGER) { |
| 1581 | wacom_wac->slots = kmalloc(features->touch_max * | 1658 | wacom_wac->slots = kmalloc(features->touch_max * |
| @@ -1870,8 +1947,11 @@ static const struct wacom_features wacom_features_0xF4 = | |||
| 1870 | { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, | 1947 | { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, |
| 1871 | 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | 1948 | 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
| 1872 | static const struct wacom_features wacom_features_0xF8 = | 1949 | static const struct wacom_features wacom_features_0xF8 = |
| 1873 | { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, | 1950 | { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, /* Pen */ |
| 1874 | 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | 1951 | 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; |
| 1952 | static const struct wacom_features wacom_features_0xF6 = | ||
| 1953 | { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ | ||
| 1954 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 }; | ||
| 1875 | static const struct wacom_features wacom_features_0x3F = | 1955 | static const struct wacom_features wacom_features_0x3F = |
| 1876 | { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, | 1956 | { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, |
| 1877 | 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | 1957 | 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
| @@ -2114,6 +2194,7 @@ const struct usb_device_id wacom_ids[] = { | |||
| 2114 | { USB_DEVICE_WACOM(0x47) }, | 2194 | { USB_DEVICE_WACOM(0x47) }, |
| 2115 | { USB_DEVICE_WACOM(0xF4) }, | 2195 | { USB_DEVICE_WACOM(0xF4) }, |
| 2116 | { USB_DEVICE_WACOM(0xF8) }, | 2196 | { USB_DEVICE_WACOM(0xF8) }, |
| 2197 | { USB_DEVICE_WACOM(0xF6) }, | ||
| 2117 | { USB_DEVICE_WACOM(0xFA) }, | 2198 | { USB_DEVICE_WACOM(0xFA) }, |
| 2118 | { USB_DEVICE_LENOVO(0x6004) }, | 2199 | { USB_DEVICE_LENOVO(0x6004) }, |
| 2119 | { } | 2200 | { } |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 3f926ec19ef9..345f1e76975e 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | /* wacom data size per MT contact */ | 30 | /* wacom data size per MT contact */ |
| 31 | #define WACOM_BYTES_PER_MT_PACKET 11 | 31 | #define WACOM_BYTES_PER_MT_PACKET 11 |
| 32 | #define WACOM_BYTES_PER_24HDT_PACKET 14 | ||
| 32 | 33 | ||
| 33 | /* device IDs */ | 34 | /* device IDs */ |
| 34 | #define STYLUS_DEVICE_ID 0x02 | 35 | #define STYLUS_DEVICE_ID 0x02 |
| @@ -49,6 +50,7 @@ | |||
| 49 | #define WACOM_REPORT_TPCHID 15 | 50 | #define WACOM_REPORT_TPCHID 15 |
| 50 | #define WACOM_REPORT_TPCST 16 | 51 | #define WACOM_REPORT_TPCST 16 |
| 51 | #define WACOM_REPORT_TPC1FGE 18 | 52 | #define WACOM_REPORT_TPC1FGE 18 |
| 53 | #define WACOM_REPORT_24HDT 1 | ||
| 52 | 54 | ||
| 53 | /* device quirks */ | 55 | /* device quirks */ |
| 54 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 | 56 | #define WACOM_QUIRK_MULTI_INPUT 0x0001 |
| @@ -81,6 +83,7 @@ enum { | |||
| 81 | WACOM_MO, | 83 | WACOM_MO, |
| 82 | WIRELESS, | 84 | WIRELESS, |
| 83 | BAMBOO_PT, | 85 | BAMBOO_PT, |
| 86 | WACOM_24HDT, | ||
| 84 | TABLETPC, /* add new TPC below */ | 87 | TABLETPC, /* add new TPC below */ |
| 85 | TABLETPCE, | 88 | TABLETPCE, |
| 86 | TABLETPC2FG, | 89 | TABLETPC2FG, |
