diff options
-rw-r--r-- | hel.nix | 11 | ||||
-rw-r--r-- | hel/wacom.patch | 206 |
2 files changed, 217 insertions, 0 deletions
@@ -41,6 +41,17 @@ | |||
41 | defaultLocale = "en_US.UTF-8"; | 41 | defaultLocale = "en_US.UTF-8"; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | nixpkgs.config = { | ||
45 | packageOverrides = pkgs: { | ||
46 | stdenv = pkgs.stdenv // { | ||
47 | platform = pkgs.stdenv.platform // { | ||
48 | kernelPatches = [ { patch = ./hel/wacom.patch; name = "wacom-fix"; } | ||
49 | ]; | ||
50 | }; | ||
51 | }; | ||
52 | }; | ||
53 | }; | ||
54 | |||
44 | environment.systemPackages = with pkgs; [ | 55 | environment.systemPackages = with pkgs; [ |
45 | git | 56 | git |
46 | slock | 57 | slock |
diff --git a/hel/wacom.patch b/hel/wacom.patch new file mode 100644 index 00000000..61500efc --- /dev/null +++ b/hel/wacom.patch | |||
@@ -0,0 +1,206 @@ | |||
1 | From 326ea2a90500fe4add86c5fb95d914d46910e780 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jason Gerecke <killertofu@gmail.com> | ||
3 | Date: Mon, 4 Apr 2016 11:26:52 -0700 | ||
4 | Subject: [PATCH] HID: wacom: Support switching from vendor-defined device mode | ||
5 | on G9 and G11 | ||
6 | |||
7 | A tablet PC booted into Windows may have its pen/touch hardware switched | ||
8 | into "Wacom mode" similar to what we do with explicitly-supported hardware. | ||
9 | Some devices appear to maintain this state across reboots, preventing their | ||
10 | use with the generic HID driver. This patch adds support for detecting the | ||
11 | presence of the mode switch feature report used by devices based on the G9 | ||
12 | and G11 chips and has the HID codepath always attempt to reset the device | ||
13 | back to sending standard HID reports. | ||
14 | |||
15 | Fixes: https://sourceforge.net/p/linuxwacom/bugs/307/ | ||
16 | Fixes: https://sourceforge.net/p/linuxwacom/bugs/310/ | ||
17 | Fixes: https://github.com/linuxwacom/input-wacom/issues/15 | ||
18 | |||
19 | Co-authored-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||
20 | Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com> | ||
21 | Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> | ||
22 | Signed-off-by: Jiri Kosina <jkosina@suse.cz> | ||
23 | --- | ||
24 | drivers/hid/wacom_sys.c | 100 ++++++++++++++++++++++++++++++++++-------------- | ||
25 | drivers/hid/wacom_wac.h | 8 ++++ | ||
26 | 2 files changed, 80 insertions(+), 28 deletions(-) | ||
27 | |||
28 | diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c | ||
29 | index b338bbf..ccf1883 100644 | ||
30 | --- a/drivers/hid/wacom_sys.c | ||
31 | +++ b/drivers/hid/wacom_sys.c | ||
32 | @@ -152,6 +152,25 @@ static void wacom_feature_mapping(struct hid_device *hdev, | ||
33 | hid_data->inputmode = field->report->id; | ||
34 | hid_data->inputmode_index = usage->usage_index; | ||
35 | break; | ||
36 | + | ||
37 | + case HID_UP_DIGITIZER: | ||
38 | + if (field->report->id == 0x0B && | ||
39 | + (field->application == WACOM_G9_DIGITIZER || | ||
40 | + field->application == WACOM_G11_DIGITIZER)) { | ||
41 | + wacom->wacom_wac.mode_report = field->report->id; | ||
42 | + wacom->wacom_wac.mode_value = 0; | ||
43 | + } | ||
44 | + break; | ||
45 | + | ||
46 | + case WACOM_G9_PAGE: | ||
47 | + case WACOM_G11_PAGE: | ||
48 | + if (field->report->id == 0x03 && | ||
49 | + (field->application == WACOM_G9_TOUCHSCREEN || | ||
50 | + field->application == WACOM_G11_TOUCHSCREEN)) { | ||
51 | + wacom->wacom_wac.mode_report = field->report->id; | ||
52 | + wacom->wacom_wac.mode_value = 0; | ||
53 | + } | ||
54 | + break; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | @@ -322,26 +341,41 @@ static int wacom_hid_set_device_mode(struct hid_device *hdev) | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | -static int wacom_set_device_mode(struct hid_device *hdev, int report_id, | ||
63 | - int length, int mode) | ||
64 | +static int wacom_set_device_mode(struct hid_device *hdev, | ||
65 | + struct wacom_wac *wacom_wac) | ||
66 | { | ||
67 | - unsigned char *rep_data; | ||
68 | + u8 *rep_data; | ||
69 | + struct hid_report *r; | ||
70 | + struct hid_report_enum *re; | ||
71 | + int length; | ||
72 | int error = -ENOMEM, limit = 0; | ||
73 | |||
74 | - rep_data = kzalloc(length, GFP_KERNEL); | ||
75 | + if (wacom_wac->mode_report < 0) | ||
76 | + return 0; | ||
77 | + | ||
78 | + re = &(hdev->report_enum[HID_FEATURE_REPORT]); | ||
79 | + r = re->report_id_hash[wacom_wac->mode_report]; | ||
80 | + if (!r) | ||
81 | + return -EINVAL; | ||
82 | + | ||
83 | + rep_data = hid_alloc_report_buf(r, GFP_KERNEL); | ||
84 | if (!rep_data) | ||
85 | - return error; | ||
86 | + return -ENOMEM; | ||
87 | + | ||
88 | + length = hid_report_len(r); | ||
89 | |||
90 | do { | ||
91 | - rep_data[0] = report_id; | ||
92 | - rep_data[1] = mode; | ||
93 | + rep_data[0] = wacom_wac->mode_report; | ||
94 | + rep_data[1] = wacom_wac->mode_value; | ||
95 | |||
96 | error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, | ||
97 | length, 1); | ||
98 | if (error >= 0) | ||
99 | error = wacom_get_report(hdev, HID_FEATURE_REPORT, | ||
100 | rep_data, length, 1); | ||
101 | - } while (error >= 0 && rep_data[1] != mode && limit++ < WAC_MSG_RETRIES); | ||
102 | + } while (error >= 0 && | ||
103 | + rep_data[1] != wacom_wac->mode_report && | ||
104 | + limit++ < WAC_MSG_RETRIES); | ||
105 | |||
106 | kfree(rep_data); | ||
107 | |||
108 | @@ -411,32 +445,41 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, | ||
109 | static int wacom_query_tablet_data(struct hid_device *hdev, | ||
110 | struct wacom_features *features) | ||
111 | { | ||
112 | + struct wacom *wacom = hid_get_drvdata(hdev); | ||
113 | + struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
114 | + | ||
115 | if (hdev->bus == BUS_BLUETOOTH) | ||
116 | return wacom_bt_query_tablet_data(hdev, 1, features); | ||
117 | |||
118 | - if (features->type == HID_GENERIC) | ||
119 | - return wacom_hid_set_device_mode(hdev); | ||
120 | - | ||
121 | - if (features->device_type & WACOM_DEVICETYPE_TOUCH) { | ||
122 | - if (features->type > TABLETPC) { | ||
123 | - /* MT Tablet PC touch */ | ||
124 | - return wacom_set_device_mode(hdev, 3, 4, 4); | ||
125 | - } | ||
126 | - else if (features->type == WACOM_24HDT) { | ||
127 | - return wacom_set_device_mode(hdev, 18, 3, 2); | ||
128 | - } | ||
129 | - else if (features->type == WACOM_27QHDT) { | ||
130 | - return wacom_set_device_mode(hdev, 131, 3, 2); | ||
131 | - } | ||
132 | - else if (features->type == BAMBOO_PAD) { | ||
133 | - return wacom_set_device_mode(hdev, 2, 2, 2); | ||
134 | - } | ||
135 | - } else if (features->device_type & WACOM_DEVICETYPE_PEN) { | ||
136 | - if (features->type <= BAMBOO_PT) { | ||
137 | - return wacom_set_device_mode(hdev, 2, 2, 2); | ||
138 | + if (features->type != HID_GENERIC) { | ||
139 | + if (features->device_type & WACOM_DEVICETYPE_TOUCH) { | ||
140 | + if (features->type > TABLETPC) { | ||
141 | + /* MT Tablet PC touch */ | ||
142 | + wacom_wac->mode_report = 3; | ||
143 | + wacom_wac->mode_value = 4; | ||
144 | + } else if (features->type == WACOM_24HDT) { | ||
145 | + wacom_wac->mode_report = 18; | ||
146 | + wacom_wac->mode_value = 2; | ||
147 | + } else if (features->type == WACOM_27QHDT) { | ||
148 | + wacom_wac->mode_report = 131; | ||
149 | + wacom_wac->mode_value = 2; | ||
150 | + } else if (features->type == BAMBOO_PAD) { | ||
151 | + wacom_wac->mode_report = 2; | ||
152 | + wacom_wac->mode_value = 2; | ||
153 | + } | ||
154 | + } else if (features->device_type & WACOM_DEVICETYPE_PEN) { | ||
155 | + if (features->type <= BAMBOO_PT) { | ||
156 | + wacom_wac->mode_report = 2; | ||
157 | + wacom_wac->mode_value = 2; | ||
158 | + } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | + wacom_set_device_mode(hdev, wacom_wac); | ||
163 | + | ||
164 | + if (features->type == HID_GENERIC) | ||
165 | + return wacom_hid_set_device_mode(hdev); | ||
166 | + | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | @@ -1818,6 +1861,7 @@ static int wacom_probe(struct hid_device *hdev, | ||
171 | } | ||
172 | |||
173 | wacom_wac->hid_data.inputmode = -1; | ||
174 | + wacom_wac->mode_report = -1; | ||
175 | |||
176 | wacom->usbdev = dev; | ||
177 | wacom->intf = intf; | ||
178 | diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h | ||
179 | index 25baa7f..e2084d9 100644 | ||
180 | --- a/drivers/hid/wacom_wac.h | ||
181 | +++ b/drivers/hid/wacom_wac.h | ||
182 | @@ -84,6 +84,12 @@ | ||
183 | #define WACOM_DEVICETYPE_WL_MONITOR 0x0008 | ||
184 | |||
185 | #define WACOM_VENDORDEFINED_PEN 0xff0d0001 | ||
186 | +#define WACOM_G9_PAGE 0xff090000 | ||
187 | +#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) | ||
188 | +#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) | ||
189 | +#define WACOM_G11_PAGE 0xff110000 | ||
190 | +#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) | ||
191 | +#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) | ||
192 | |||
193 | #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ | ||
194 | ((f)->physical == HID_DG_STYLUS) || \ | ||
195 | @@ -238,6 +244,8 @@ struct wacom_wac { | ||
196 | int ps_connected; | ||
197 | u8 bt_features; | ||
198 | u8 bt_high_speed; | ||
199 | + int mode_report; | ||
200 | + int mode_value; | ||
201 | struct hid_data hid_data; | ||
202 | }; | ||
203 | |||
204 | -- | ||
205 | 2.1.4 | ||
206 | |||