diff options
author | weixing <weixing@hanwang.com.cn> | 2012-07-13 03:08:42 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-07-13 03:14:27 -0400 |
commit | 8a90c034ae0d4282e2aeb9cf8311dc90c855d815 (patch) | |
tree | 475d003d61378939ef6b6c328a39856999f1e9d2 | |
parent | 8314f532ebd55f1d6dc23b143cda3c1714ffe201 (diff) |
Input: hanwang - add support for Art Master II tablet
This change adds support for old Hanwang Art master II tablet
Signed-off-by: weixing <weixing@hanwang.com.cn>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r-- | drivers/input/tablet/hanwang.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c index b2db3cfe3084..5cc04124995c 100644 --- a/drivers/input/tablet/hanwang.c +++ b/drivers/input/tablet/hanwang.c | |||
@@ -63,6 +63,7 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
63 | enum hanwang_tablet_type { | 63 | enum hanwang_tablet_type { |
64 | HANWANG_ART_MASTER_III, | 64 | HANWANG_ART_MASTER_III, |
65 | HANWANG_ART_MASTER_HD, | 65 | HANWANG_ART_MASTER_HD, |
66 | HANWANG_ART_MASTER_II, | ||
66 | }; | 67 | }; |
67 | 68 | ||
68 | struct hanwang { | 69 | struct hanwang { |
@@ -99,6 +100,8 @@ static const struct hanwang_features features_array[] = { | |||
99 | ART_MASTER_PKGLEN_MAX, 0x7f00, 0x4f60, 0x3f, 0x7f, 2048 }, | 100 | ART_MASTER_PKGLEN_MAX, 0x7f00, 0x4f60, 0x3f, 0x7f, 2048 }, |
100 | { 0x8401, "Hanwang Art Master HD 5012", HANWANG_ART_MASTER_HD, | 101 | { 0x8401, "Hanwang Art Master HD 5012", HANWANG_ART_MASTER_HD, |
101 | ART_MASTER_PKGLEN_MAX, 0x678e, 0x4150, 0x3f, 0x7f, 1024 }, | 102 | ART_MASTER_PKGLEN_MAX, 0x678e, 0x4150, 0x3f, 0x7f, 1024 }, |
103 | { 0x8503, "Hanwang Art Master II", HANWANG_ART_MASTER_II, | ||
104 | ART_MASTER_PKGLEN_MAX, 0x27de, 0x1cfe, 0x3f, 0x7f, 1024 }, | ||
102 | }; | 105 | }; |
103 | 106 | ||
104 | static const int hw_eventtypes[] = { | 107 | static const int hw_eventtypes[] = { |
@@ -127,14 +130,30 @@ static void hanwang_parse_packet(struct hanwang *hanwang) | |||
127 | struct usb_device *dev = hanwang->usbdev; | 130 | struct usb_device *dev = hanwang->usbdev; |
128 | enum hanwang_tablet_type type = hanwang->features->type; | 131 | enum hanwang_tablet_type type = hanwang->features->type; |
129 | int i; | 132 | int i; |
130 | u16 x, y, p; | 133 | u16 p; |
134 | |||
135 | if (type == HANWANG_ART_MASTER_II) { | ||
136 | hanwang->current_tool = BTN_TOOL_PEN; | ||
137 | hanwang->current_id = STYLUS_DEVICE_ID; | ||
138 | } | ||
131 | 139 | ||
132 | switch (data[0]) { | 140 | switch (data[0]) { |
133 | case 0x02: /* data packet */ | 141 | case 0x02: /* data packet */ |
134 | switch (data[1]) { | 142 | switch (data[1]) { |
135 | case 0x80: /* tool prox out */ | 143 | case 0x80: /* tool prox out */ |
136 | hanwang->current_id = 0; | 144 | if (type != HANWANG_ART_MASTER_II) { |
137 | input_report_key(input_dev, hanwang->current_tool, 0); | 145 | hanwang->current_id = 0; |
146 | input_report_key(input_dev, | ||
147 | hanwang->current_tool, 0); | ||
148 | } | ||
149 | break; | ||
150 | |||
151 | case 0x00: /* artmaster ii pen leave */ | ||
152 | if (type == HANWANG_ART_MASTER_II) { | ||
153 | hanwang->current_id = 0; | ||
154 | input_report_key(input_dev, | ||
155 | hanwang->current_tool, 0); | ||
156 | } | ||
138 | break; | 157 | break; |
139 | 158 | ||
140 | case 0xc2: /* first time tool prox in */ | 159 | case 0xc2: /* first time tool prox in */ |
@@ -154,15 +173,12 @@ static void hanwang_parse_packet(struct hanwang *hanwang) | |||
154 | default: | 173 | default: |
155 | hanwang->current_id = 0; | 174 | hanwang->current_id = 0; |
156 | dev_dbg(&dev->dev, | 175 | dev_dbg(&dev->dev, |
157 | "unknown tablet tool %02x ", data[0]); | 176 | "unknown tablet tool %02x\n", data[0]); |
158 | break; | 177 | break; |
159 | } | 178 | } |
160 | break; | 179 | break; |
161 | 180 | ||
162 | default: /* tool data packet */ | 181 | default: /* tool data packet */ |
163 | x = (data[2] << 8) | data[3]; | ||
164 | y = (data[4] << 8) | data[5]; | ||
165 | |||
166 | switch (type) { | 182 | switch (type) { |
167 | case HANWANG_ART_MASTER_III: | 183 | case HANWANG_ART_MASTER_III: |
168 | p = (data[6] << 3) | | 184 | p = (data[6] << 3) | |
@@ -171,6 +187,7 @@ static void hanwang_parse_packet(struct hanwang *hanwang) | |||
171 | break; | 187 | break; |
172 | 188 | ||
173 | case HANWANG_ART_MASTER_HD: | 189 | case HANWANG_ART_MASTER_HD: |
190 | case HANWANG_ART_MASTER_II: | ||
174 | p = (data[7] >> 6) | (data[6] << 2); | 191 | p = (data[7] >> 6) | (data[6] << 2); |
175 | break; | 192 | break; |
176 | 193 | ||
@@ -180,17 +197,23 @@ static void hanwang_parse_packet(struct hanwang *hanwang) | |||
180 | } | 197 | } |
181 | 198 | ||
182 | input_report_abs(input_dev, ABS_X, | 199 | input_report_abs(input_dev, ABS_X, |
183 | le16_to_cpup((__le16 *)&x)); | 200 | be16_to_cpup((__be16 *)&data[2])); |
184 | input_report_abs(input_dev, ABS_Y, | 201 | input_report_abs(input_dev, ABS_Y, |
185 | le16_to_cpup((__le16 *)&y)); | 202 | be16_to_cpup((__be16 *)&data[4])); |
186 | input_report_abs(input_dev, ABS_PRESSURE, | 203 | input_report_abs(input_dev, ABS_PRESSURE, p); |
187 | le16_to_cpup((__le16 *)&p)); | ||
188 | input_report_abs(input_dev, ABS_TILT_X, data[7] & 0x3f); | 204 | input_report_abs(input_dev, ABS_TILT_X, data[7] & 0x3f); |
189 | input_report_abs(input_dev, ABS_TILT_Y, data[8] & 0x7f); | 205 | input_report_abs(input_dev, ABS_TILT_Y, data[8] & 0x7f); |
190 | input_report_key(input_dev, BTN_STYLUS, data[1] & 0x02); | 206 | input_report_key(input_dev, BTN_STYLUS, data[1] & 0x02); |
191 | input_report_key(input_dev, BTN_STYLUS2, data[1] & 0x04); | 207 | |
208 | if (type != HANWANG_ART_MASTER_II) | ||
209 | input_report_key(input_dev, BTN_STYLUS2, | ||
210 | data[1] & 0x04); | ||
211 | else | ||
212 | input_report_key(input_dev, BTN_TOOL_PEN, 1); | ||
213 | |||
192 | break; | 214 | break; |
193 | } | 215 | } |
216 | |||
194 | input_report_abs(input_dev, ABS_MISC, hanwang->current_id); | 217 | input_report_abs(input_dev, ABS_MISC, hanwang->current_id); |
195 | input_event(input_dev, EV_MSC, MSC_SERIAL, | 218 | input_event(input_dev, EV_MSC, MSC_SERIAL, |
196 | hanwang->features->pid); | 219 | hanwang->features->pid); |
@@ -202,8 +225,8 @@ static void hanwang_parse_packet(struct hanwang *hanwang) | |||
202 | 225 | ||
203 | switch (type) { | 226 | switch (type) { |
204 | case HANWANG_ART_MASTER_III: | 227 | case HANWANG_ART_MASTER_III: |
205 | input_report_key(input_dev, BTN_TOOL_FINGER, data[1] || | 228 | input_report_key(input_dev, BTN_TOOL_FINGER, |
206 | data[2] || data[3]); | 229 | data[1] || data[2] || data[3]); |
207 | input_report_abs(input_dev, ABS_WHEEL, data[1]); | 230 | input_report_abs(input_dev, ABS_WHEEL, data[1]); |
208 | input_report_key(input_dev, BTN_0, data[2]); | 231 | input_report_key(input_dev, BTN_0, data[2]); |
209 | for (i = 0; i < 8; i++) | 232 | for (i = 0; i < 8; i++) |
@@ -227,6 +250,10 @@ static void hanwang_parse_packet(struct hanwang *hanwang) | |||
227 | BTN_5 + i, data[6] & (1 << i)); | 250 | BTN_5 + i, data[6] & (1 << i)); |
228 | } | 251 | } |
229 | break; | 252 | break; |
253 | |||
254 | case HANWANG_ART_MASTER_II: | ||
255 | dev_dbg(&dev->dev, "error packet %02x\n", data[0]); | ||
256 | return; | ||
230 | } | 257 | } |
231 | 258 | ||
232 | input_report_abs(input_dev, ABS_MISC, hanwang->current_id); | 259 | input_report_abs(input_dev, ABS_MISC, hanwang->current_id); |
@@ -234,7 +261,7 @@ static void hanwang_parse_packet(struct hanwang *hanwang) | |||
234 | break; | 261 | break; |
235 | 262 | ||
236 | default: | 263 | default: |
237 | dev_dbg(&dev->dev, "error packet %02x ", data[0]); | 264 | dev_dbg(&dev->dev, "error packet %02x\n", data[0]); |
238 | break; | 265 | break; |
239 | } | 266 | } |
240 | 267 | ||