diff options
author | Ping Cheng <pinglinux@gmail.com> | 2015-01-27 16:30:03 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-01-29 08:05:05 -0500 |
commit | 500d4160abe9a2e88b12e319c13ae3ebd1e18108 (patch) | |
tree | b592fb9443e6621d2d51ab4dec42139481f614c1 | |
parent | a2f71c6c878e664cce4591fc1de36dce2bf44d8d (diff) |
HID: wacom: add support for Cintiq 27QHD and 27QHD touch
These devices have accelerometers. To report accelerometer coordinates, a new
property, INPUT_PROP_ACCELEROMETER, is added.
Signed-off-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/wacom_sys.c | 3 | ||||
-rw-r--r-- | drivers/hid/wacom_wac.c | 87 | ||||
-rw-r--r-- | drivers/hid/wacom_wac.h | 7 | ||||
-rw-r--r-- | include/uapi/linux/input.h | 1 |
4 files changed, 83 insertions, 15 deletions
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index f01ab3a0c5f5..f0568a7e6de9 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c | |||
@@ -403,6 +403,9 @@ static int wacom_query_tablet_data(struct hid_device *hdev, | |||
403 | else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) { | 403 | else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) { |
404 | return wacom_set_device_mode(hdev, 18, 3, 2); | 404 | return wacom_set_device_mode(hdev, 18, 3, 2); |
405 | } | 405 | } |
406 | else if (features->type == WACOM_27QHDT) { | ||
407 | return wacom_set_device_mode(hdev, 131, 3, 2); | ||
408 | } | ||
406 | } else if (features->device_type == BTN_TOOL_PEN) { | 409 | } else if (features->device_type == BTN_TOOL_PEN) { |
407 | if (features->type <= BAMBOO_PT && features->type != WIRELESS) { | 410 | if (features->type <= BAMBOO_PT && features->type != WIRELESS) { |
408 | return wacom_set_device_mode(hdev, 2, 2, 2); | 411 | return wacom_set_device_mode(hdev, 2, 2, 2); |
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index d239d82a1f90..1a6507999a65 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c | |||
@@ -656,6 +656,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
656 | data[0] != WACOM_REPORT_INTUOSREAD && | 656 | data[0] != WACOM_REPORT_INTUOSREAD && |
657 | data[0] != WACOM_REPORT_INTUOSWRITE && | 657 | data[0] != WACOM_REPORT_INTUOSWRITE && |
658 | data[0] != WACOM_REPORT_INTUOSPAD && | 658 | data[0] != WACOM_REPORT_INTUOSPAD && |
659 | data[0] != WACOM_REPORT_CINTIQ && | ||
660 | data[0] != WACOM_REPORT_CINTIQPAD && | ||
659 | data[0] != WACOM_REPORT_INTUOS5PAD) { | 661 | data[0] != WACOM_REPORT_INTUOS5PAD) { |
660 | dev_dbg(input->dev.parent, | 662 | dev_dbg(input->dev.parent, |
661 | "%s: received unknown report #%d\n", __func__, data[0]); | 663 | "%s: received unknown report #%d\n", __func__, data[0]); |
@@ -667,7 +669,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
667 | idx = data[1] & 0x01; | 669 | idx = data[1] & 0x01; |
668 | 670 | ||
669 | /* pad packets. Works as a second tool and is always in prox */ | 671 | /* pad packets. Works as a second tool and is always in prox */ |
670 | if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) { | 672 | if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD || |
673 | data[0] == WACOM_REPORT_CINTIQPAD) { | ||
671 | input = wacom->pad_input; | 674 | input = wacom->pad_input; |
672 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { | 675 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { |
673 | input_report_key(input, BTN_0, (data[2] & 0x01)); | 676 | input_report_key(input, BTN_0, (data[2] & 0x01)); |
@@ -767,6 +770,14 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
767 | } else { | 770 | } else { |
768 | input_report_abs(input, ABS_MISC, 0); | 771 | input_report_abs(input, ABS_MISC, 0); |
769 | } | 772 | } |
773 | } else if (features->type == WACOM_27QHD) { | ||
774 | input_report_key(input, KEY_PROG1, data[2] & 0x01); | ||
775 | input_report_key(input, KEY_PROG2, data[2] & 0x02); | ||
776 | input_report_key(input, KEY_PROG3, data[2] & 0x04); | ||
777 | |||
778 | input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4])); | ||
779 | input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6])); | ||
780 | input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8])); | ||
770 | } else if (features->type == CINTIQ_HYBRID) { | 781 | } else if (features->type == CINTIQ_HYBRID) { |
771 | /* | 782 | /* |
772 | * Do not send hardware buttons under Android. They | 783 | * Do not send hardware buttons under Android. They |
@@ -1027,8 +1038,20 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) | |||
1027 | struct input_dev *input = wacom->input; | 1038 | struct input_dev *input = wacom->input; |
1028 | unsigned char *data = wacom->data; | 1039 | unsigned char *data = wacom->data; |
1029 | int i; | 1040 | int i; |
1030 | int current_num_contacts = data[61]; | 1041 | int current_num_contacts = 0; |
1031 | int contacts_to_send = 0; | 1042 | int contacts_to_send = 0; |
1043 | int num_contacts_left = 4; /* maximum contacts per packet */ | ||
1044 | int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET; | ||
1045 | int y_offset = 2; | ||
1046 | |||
1047 | if (wacom->features.type == WACOM_27QHDT) { | ||
1048 | current_num_contacts = data[63]; | ||
1049 | num_contacts_left = 10; | ||
1050 | byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET; | ||
1051 | y_offset = 0; | ||
1052 | } else { | ||
1053 | current_num_contacts = data[61]; | ||
1054 | } | ||
1032 | 1055 | ||
1033 | /* | 1056 | /* |
1034 | * First packet resets the counter since only the first | 1057 | * First packet resets the counter since only the first |
@@ -1037,11 +1060,10 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) | |||
1037 | if (current_num_contacts) | 1060 | if (current_num_contacts) |
1038 | wacom->num_contacts_left = current_num_contacts; | 1061 | wacom->num_contacts_left = current_num_contacts; |
1039 | 1062 | ||
1040 | /* There are at most 4 contacts per packet */ | 1063 | contacts_to_send = min(num_contacts_left, wacom->num_contacts_left); |
1041 | contacts_to_send = min(4, wacom->num_contacts_left); | ||
1042 | 1064 | ||
1043 | for (i = 0; i < contacts_to_send; i++) { | 1065 | for (i = 0; i < contacts_to_send; i++) { |
1044 | int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1; | 1066 | int offset = (byte_per_packet * i) + 1; |
1045 | bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity; | 1067 | bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity; |
1046 | int slot = input_mt_get_slot_by_key(input, data[offset + 1]); | 1068 | int slot = input_mt_get_slot_by_key(input, data[offset + 1]); |
1047 | 1069 | ||
@@ -1052,18 +1074,23 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) | |||
1052 | 1074 | ||
1053 | if (touch) { | 1075 | if (touch) { |
1054 | int t_x = get_unaligned_le16(&data[offset + 2]); | 1076 | int t_x = get_unaligned_le16(&data[offset + 2]); |
1055 | int c_x = get_unaligned_le16(&data[offset + 4]); | 1077 | int t_y = get_unaligned_le16(&data[offset + 4 + y_offset]); |
1056 | int t_y = get_unaligned_le16(&data[offset + 6]); | ||
1057 | int c_y = get_unaligned_le16(&data[offset + 8]); | ||
1058 | int w = get_unaligned_le16(&data[offset + 10]); | ||
1059 | int h = get_unaligned_le16(&data[offset + 12]); | ||
1060 | 1078 | ||
1061 | input_report_abs(input, ABS_MT_POSITION_X, t_x); | 1079 | input_report_abs(input, ABS_MT_POSITION_X, t_x); |
1062 | input_report_abs(input, ABS_MT_POSITION_Y, t_y); | 1080 | input_report_abs(input, ABS_MT_POSITION_Y, t_y); |
1063 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h)); | 1081 | |
1064 | input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y)); | 1082 | if (wacom->features.type != WACOM_27QHDT) { |
1065 | input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); | 1083 | int c_x = get_unaligned_le16(&data[offset + 4]); |
1066 | input_report_abs(input, ABS_MT_ORIENTATION, w > h); | 1084 | int c_y = get_unaligned_le16(&data[offset + 8]); |
1085 | int w = get_unaligned_le16(&data[offset + 10]); | ||
1086 | int h = get_unaligned_le16(&data[offset + 12]); | ||
1087 | |||
1088 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h)); | ||
1089 | input_report_abs(input, ABS_MT_WIDTH_MAJOR, | ||
1090 | min(w, h) + int_dist(t_x, t_y, c_x, c_y)); | ||
1091 | input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); | ||
1092 | input_report_abs(input, ABS_MT_ORIENTATION, w > h); | ||
1093 | } | ||
1067 | } | 1094 | } |
1068 | } | 1095 | } |
1069 | input_mt_report_pointer_emulation(input, true); | 1096 | input_mt_report_pointer_emulation(input, true); |
@@ -1894,6 +1921,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
1894 | case WACOM_21UX2: | 1921 | case WACOM_21UX2: |
1895 | case WACOM_22HD: | 1922 | case WACOM_22HD: |
1896 | case WACOM_24HD: | 1923 | case WACOM_24HD: |
1924 | case WACOM_27QHD: | ||
1897 | case DTK: | 1925 | case DTK: |
1898 | case CINTIQ_HYBRID: | 1926 | case CINTIQ_HYBRID: |
1899 | sync = wacom_intuos_irq(wacom_wac); | 1927 | sync = wacom_intuos_irq(wacom_wac); |
@@ -1904,6 +1932,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
1904 | break; | 1932 | break; |
1905 | 1933 | ||
1906 | case WACOM_24HDT: | 1934 | case WACOM_24HDT: |
1935 | case WACOM_27QHDT: | ||
1907 | sync = wacom_24hdt_irq(wacom_wac); | 1936 | sync = wacom_24hdt_irq(wacom_wac); |
1908 | break; | 1937 | break; |
1909 | 1938 | ||
@@ -2115,6 +2144,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, | |||
2115 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | 2144 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
2116 | break; | 2145 | break; |
2117 | 2146 | ||
2147 | case WACOM_27QHD: | ||
2118 | case WACOM_24HD: | 2148 | case WACOM_24HD: |
2119 | case DTK: | 2149 | case DTK: |
2120 | case WACOM_22HD: | 2150 | case WACOM_22HD: |
@@ -2183,6 +2213,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, | |||
2183 | } | 2213 | } |
2184 | /* fall through */ | 2214 | /* fall through */ |
2185 | 2215 | ||
2216 | case WACOM_27QHDT: | ||
2186 | case MTSCREEN: | 2217 | case MTSCREEN: |
2187 | case MTTPC: | 2218 | case MTTPC: |
2188 | case MTTPC_B: | 2219 | case MTTPC_B: |
@@ -2330,6 +2361,19 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
2330 | input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); | 2361 | input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); |
2331 | break; | 2362 | break; |
2332 | 2363 | ||
2364 | case WACOM_27QHD: | ||
2365 | __set_bit(KEY_PROG1, input_dev->keybit); | ||
2366 | __set_bit(KEY_PROG2, input_dev->keybit); | ||
2367 | __set_bit(KEY_PROG3, input_dev->keybit); | ||
2368 | input_set_abs_params(input_dev, ABS_X, -2048, 2048, 0, 0); | ||
2369 | input_abs_set_res(input_dev, ABS_X, 1024); /* points/g */ | ||
2370 | input_set_abs_params(input_dev, ABS_Y, -2048, 2048, 0, 0); | ||
2371 | input_abs_set_res(input_dev, ABS_Y, 1024); | ||
2372 | input_set_abs_params(input_dev, ABS_Z, -2048, 2048, 0, 0); | ||
2373 | input_abs_set_res(input_dev, ABS_Z, 1024); | ||
2374 | __set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit); | ||
2375 | break; | ||
2376 | |||
2333 | case DTK: | 2377 | case DTK: |
2334 | for (i = 0; i < 6; i++) | 2378 | for (i = 0; i < 6; i++) |
2335 | __set_bit(BTN_0 + i, input_dev->keybit); | 2379 | __set_bit(BTN_0 + i, input_dev->keybit); |
@@ -2680,6 +2724,18 @@ static const struct wacom_features wacom_features_0xF6 = | |||
2680 | { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ | 2724 | { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ |
2681 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, | 2725 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10, |
2682 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 2726 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
2727 | static const struct wacom_features wacom_features_0x32A = | ||
2728 | { "Wacom Cintiq 27QHD", 119740, 67520, 2047, | ||
2729 | 63, WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, | ||
2730 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
2731 | static const struct wacom_features wacom_features_0x32B = | ||
2732 | { "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63, | ||
2733 | WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, | ||
2734 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
2735 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C }; | ||
2736 | static const struct wacom_features wacom_features_0x32C = | ||
2737 | { "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT, | ||
2738 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32B, .touch_max = 10 }; | ||
2683 | static const struct wacom_features wacom_features_0x3F = | 2739 | static const struct wacom_features wacom_features_0x3F = |
2684 | { "Wacom Cintiq 21UX", 87200, 65600, 1023, 63, | 2740 | { "Wacom Cintiq 21UX", 87200, 65600, 1023, 63, |
2685 | CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | 2741 | CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
@@ -3046,6 +3102,9 @@ const struct hid_device_id wacom_ids[] = { | |||
3046 | { USB_DEVICE_WACOM(0x315) }, | 3102 | { USB_DEVICE_WACOM(0x315) }, |
3047 | { USB_DEVICE_WACOM(0x317) }, | 3103 | { USB_DEVICE_WACOM(0x317) }, |
3048 | { USB_DEVICE_WACOM(0x323) }, | 3104 | { USB_DEVICE_WACOM(0x323) }, |
3105 | { USB_DEVICE_WACOM(0x32A) }, | ||
3106 | { USB_DEVICE_WACOM(0x32B) }, | ||
3107 | { USB_DEVICE_WACOM(0x32C) }, | ||
3049 | { USB_DEVICE_WACOM(0x32F) }, | 3108 | { USB_DEVICE_WACOM(0x32F) }, |
3050 | { USB_DEVICE_WACOM(0x4001) }, | 3109 | { USB_DEVICE_WACOM(0x4001) }, |
3051 | { USB_DEVICE_WACOM(0x4004) }, | 3110 | { USB_DEVICE_WACOM(0x4004) }, |
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 72e78cc18933..021ee1c1980a 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/hid.h> | 13 | #include <linux/hid.h> |
14 | 14 | ||
15 | /* maximum packet length for USB devices */ | 15 | /* maximum packet length for USB devices */ |
16 | #define WACOM_PKGLEN_MAX 68 | 16 | #define WACOM_PKGLEN_MAX 192 |
17 | 17 | ||
18 | #define WACOM_NAME_MAX 64 | 18 | #define WACOM_NAME_MAX 64 |
19 | 19 | ||
@@ -37,6 +37,7 @@ | |||
37 | /* wacom data size per MT contact */ | 37 | /* wacom data size per MT contact */ |
38 | #define WACOM_BYTES_PER_MT_PACKET 11 | 38 | #define WACOM_BYTES_PER_MT_PACKET 11 |
39 | #define WACOM_BYTES_PER_24HDT_PACKET 14 | 39 | #define WACOM_BYTES_PER_24HDT_PACKET 14 |
40 | #define WACOM_BYTES_PER_QHDTHID_PACKET 6 | ||
40 | 41 | ||
41 | /* device IDs */ | 42 | /* device IDs */ |
42 | #define STYLUS_DEVICE_ID 0x02 | 43 | #define STYLUS_DEVICE_ID 0x02 |
@@ -58,6 +59,8 @@ | |||
58 | #define WACOM_REPORT_TPCMT 13 | 59 | #define WACOM_REPORT_TPCMT 13 |
59 | #define WACOM_REPORT_TPCMT2 3 | 60 | #define WACOM_REPORT_TPCMT2 3 |
60 | #define WACOM_REPORT_TPCHID 15 | 61 | #define WACOM_REPORT_TPCHID 15 |
62 | #define WACOM_REPORT_CINTIQ 16 | ||
63 | #define WACOM_REPORT_CINTIQPAD 17 | ||
61 | #define WACOM_REPORT_TPCST 16 | 64 | #define WACOM_REPORT_TPCST 16 |
62 | #define WACOM_REPORT_DTUS 17 | 65 | #define WACOM_REPORT_DTUS 17 |
63 | #define WACOM_REPORT_TPC1FGE 18 | 66 | #define WACOM_REPORT_TPC1FGE 18 |
@@ -109,6 +112,7 @@ enum { | |||
109 | WACOM_22HD, | 112 | WACOM_22HD, |
110 | DTK, | 113 | DTK, |
111 | WACOM_24HD, | 114 | WACOM_24HD, |
115 | WACOM_27QHD, | ||
112 | CINTIQ_HYBRID, | 116 | CINTIQ_HYBRID, |
113 | CINTIQ, | 117 | CINTIQ, |
114 | WACOM_BEE, | 118 | WACOM_BEE, |
@@ -117,6 +121,7 @@ enum { | |||
117 | WIRELESS, | 121 | WIRELESS, |
118 | BAMBOO_PT, | 122 | BAMBOO_PT, |
119 | WACOM_24HDT, | 123 | WACOM_24HDT, |
124 | WACOM_27QHDT, | ||
120 | TABLETPC, /* add new TPC below */ | 125 | TABLETPC, /* add new TPC below */ |
121 | TABLETPCE, | 126 | TABLETPCE, |
122 | TABLETPC2FG, | 127 | TABLETPC2FG, |
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index a1d7e931ab72..b0a813079852 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h | |||
@@ -166,6 +166,7 @@ struct input_keymap_entry { | |||
166 | #define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */ | 166 | #define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */ |
167 | #define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ | 167 | #define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ |
168 | #define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ | 168 | #define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ |
169 | #define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */ | ||
169 | 170 | ||
170 | #define INPUT_PROP_MAX 0x1f | 171 | #define INPUT_PROP_MAX 0x1f |
171 | #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) | 172 | #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) |