diff options
Diffstat (limited to 'drivers/hid/hid-wacom.c')
-rw-r--r-- | drivers/hid/hid-wacom.c | 179 |
1 files changed, 157 insertions, 22 deletions
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 17bb88f782b..f2183486a9b 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> | 9 | * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> |
10 | * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru> | 10 | * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru> |
11 | * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net> | 11 | * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net> |
12 | * Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu> | ||
12 | */ | 13 | */ |
13 | 14 | ||
14 | /* | 15 | /* |
@@ -33,6 +34,7 @@ | |||
33 | struct wacom_data { | 34 | struct wacom_data { |
34 | __u16 tool; | 35 | __u16 tool; |
35 | unsigned char butstate; | 36 | unsigned char butstate; |
37 | __u8 features; | ||
36 | unsigned char high_speed; | 38 | unsigned char high_speed; |
37 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 39 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
38 | int battery_capacity; | 40 | int battery_capacity; |
@@ -107,6 +109,19 @@ static int wacom_ac_get_property(struct power_supply *psy, | |||
107 | } | 109 | } |
108 | #endif | 110 | #endif |
109 | 111 | ||
112 | static void wacom_set_features(struct hid_device *hdev) | ||
113 | { | ||
114 | int ret; | ||
115 | __u8 rep_data[2]; | ||
116 | |||
117 | /*set high speed, tablet mode*/ | ||
118 | rep_data[0] = 0x03; | ||
119 | rep_data[1] = 0x20; | ||
120 | ret = hdev->hid_output_raw_report(hdev, rep_data, 2, | ||
121 | HID_FEATURE_REPORT); | ||
122 | return; | ||
123 | } | ||
124 | |||
110 | static void wacom_poke(struct hid_device *hdev, u8 speed) | 125 | static void wacom_poke(struct hid_device *hdev, u8 speed) |
111 | { | 126 | { |
112 | struct wacom_data *wdata = hid_get_drvdata(hdev); | 127 | struct wacom_data *wdata = hid_get_drvdata(hdev); |
@@ -177,26 +192,13 @@ static ssize_t wacom_store_speed(struct device *dev, | |||
177 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, | 192 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, |
178 | wacom_show_speed, wacom_store_speed); | 193 | wacom_show_speed, wacom_store_speed); |
179 | 194 | ||
180 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | 195 | static int wacom_gr_parse_report(struct hid_device *hdev, |
181 | u8 *raw_data, int size) | 196 | struct wacom_data *wdata, |
197 | struct input_dev *input, unsigned char *data) | ||
182 | { | 198 | { |
183 | struct wacom_data *wdata = hid_get_drvdata(hdev); | ||
184 | struct hid_input *hidinput; | ||
185 | struct input_dev *input; | ||
186 | unsigned char *data = (unsigned char *) raw_data; | ||
187 | int tool, x, y, rw; | 199 | int tool, x, y, rw; |
188 | 200 | ||
189 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) | ||
190 | return 0; | ||
191 | |||
192 | tool = 0; | 201 | tool = 0; |
193 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | ||
194 | input = hidinput->input; | ||
195 | |||
196 | /* Check if this is a tablet report */ | ||
197 | if (data[0] != 0x03) | ||
198 | return 0; | ||
199 | |||
200 | /* Get X & Y positions */ | 202 | /* Get X & Y positions */ |
201 | x = le16_to_cpu(*(__le16 *) &data[2]); | 203 | x = le16_to_cpu(*(__le16 *) &data[2]); |
202 | y = le16_to_cpu(*(__le16 *) &data[4]); | 204 | y = le16_to_cpu(*(__le16 *) &data[4]); |
@@ -304,6 +306,121 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
304 | return 1; | 306 | return 1; |
305 | } | 307 | } |
306 | 308 | ||
309 | static void wacom_i4_parse_pen_report(struct wacom_data *wdata, | ||
310 | struct input_dev *input, unsigned char *data) | ||
311 | { | ||
312 | __u16 x, y, pressure; | ||
313 | __u32 id; | ||
314 | |||
315 | switch (data[1]) { | ||
316 | case 0x80: /* Out of proximity report */ | ||
317 | wdata->tool = 0; | ||
318 | input_report_key(input, BTN_TOUCH, 0); | ||
319 | input_report_abs(input, ABS_PRESSURE, 0); | ||
320 | input_report_key(input, wdata->tool, 0); | ||
321 | input_sync(input); | ||
322 | break; | ||
323 | case 0xC2: /* Tool report */ | ||
324 | id = ((data[2] << 4) | (data[3] >> 4) | | ||
325 | ((data[7] & 0x0f) << 20) | | ||
326 | ((data[8] & 0xf0) << 12)) & 0xfffff; | ||
327 | |||
328 | switch (id) { | ||
329 | case 0x802: | ||
330 | wdata->tool = BTN_TOOL_PEN; | ||
331 | break; | ||
332 | case 0x80A: | ||
333 | wdata->tool = BTN_TOOL_RUBBER; | ||
334 | break; | ||
335 | } | ||
336 | break; | ||
337 | default: /* Position/pressure report */ | ||
338 | x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1); | ||
339 | y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01); | ||
340 | pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | ||
341 | | (data[1] & 0x01); | ||
342 | |||
343 | input_report_key(input, BTN_TOUCH, pressure > 1); | ||
344 | |||
345 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); | ||
346 | input_report_key(input, BTN_STYLUS2, data[1] & 0x04); | ||
347 | input_report_key(input, wdata->tool, 1); | ||
348 | input_report_abs(input, ABS_X, x); | ||
349 | input_report_abs(input, ABS_Y, y); | ||
350 | input_report_abs(input, ABS_PRESSURE, pressure); | ||
351 | input_sync(input); | ||
352 | break; | ||
353 | } | ||
354 | |||
355 | return; | ||
356 | } | ||
357 | |||
358 | static void wacom_i4_parse_report(struct hid_device *hdev, | ||
359 | struct wacom_data *wdata, | ||
360 | struct input_dev *input, unsigned char *data) | ||
361 | { | ||
362 | switch (data[0]) { | ||
363 | case 0x00: /* Empty report */ | ||
364 | break; | ||
365 | case 0x02: /* Pen report */ | ||
366 | wacom_i4_parse_pen_report(wdata, input, data); | ||
367 | break; | ||
368 | case 0x03: /* Features Report */ | ||
369 | wdata->features = data[2]; | ||
370 | break; | ||
371 | case 0x0C: /* Button report */ | ||
372 | break; | ||
373 | default: | ||
374 | hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]); | ||
375 | break; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
380 | u8 *raw_data, int size) | ||
381 | { | ||
382 | struct wacom_data *wdata = hid_get_drvdata(hdev); | ||
383 | struct hid_input *hidinput; | ||
384 | struct input_dev *input; | ||
385 | unsigned char *data = (unsigned char *) raw_data; | ||
386 | int i; | ||
387 | |||
388 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) | ||
389 | return 0; | ||
390 | |||
391 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | ||
392 | input = hidinput->input; | ||
393 | |||
394 | /* Check if this is a tablet report */ | ||
395 | if (data[0] != 0x03) | ||
396 | return 0; | ||
397 | |||
398 | switch (hdev->product) { | ||
399 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: | ||
400 | return wacom_gr_parse_report(hdev, wdata, input, data); | ||
401 | break; | ||
402 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
403 | i = 1; | ||
404 | |||
405 | switch (data[0]) { | ||
406 | case 0x04: | ||
407 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
408 | i += 10; | ||
409 | /* fall through */ | ||
410 | case 0x03: | ||
411 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
412 | i += 10; | ||
413 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
414 | break; | ||
415 | default: | ||
416 | hid_err(hdev, "Unknown report: %d,%d size:%d\n", | ||
417 | data[0], data[1], size); | ||
418 | return 0; | ||
419 | } | ||
420 | } | ||
421 | return 1; | ||
422 | } | ||
423 | |||
307 | static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | 424 | static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
308 | struct hid_field *field, struct hid_usage *usage, unsigned long **bit, | 425 | struct hid_field *field, struct hid_usage *usage, unsigned long **bit, |
309 | int *max) | 426 | int *max) |
@@ -338,10 +455,19 @@ static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
338 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | 455 | __set_bit(BTN_TOOL_RUBBER, input->keybit); |
339 | __set_bit(BTN_TOOL_MOUSE, input->keybit); | 456 | __set_bit(BTN_TOOL_MOUSE, input->keybit); |
340 | 457 | ||
341 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); | 458 | switch (hdev->product) { |
342 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); | 459 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: |
343 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | 460 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); |
344 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | 461 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); |
462 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | ||
463 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | ||
464 | break; | ||
465 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
466 | input_set_abs_params(input, ABS_X, 0, 40640, 4, 0); | ||
467 | input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0); | ||
468 | input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0); | ||
469 | break; | ||
470 | } | ||
345 | 471 | ||
346 | return 0; | 472 | return 0; |
347 | } | 473 | } |
@@ -378,8 +504,16 @@ static int wacom_probe(struct hid_device *hdev, | |||
378 | hid_warn(hdev, | 504 | hid_warn(hdev, |
379 | "can't create sysfs speed attribute err: %d\n", ret); | 505 | "can't create sysfs speed attribute err: %d\n", ret); |
380 | 506 | ||
381 | /* Set Wacom mode 2 with high reporting speed */ | 507 | switch (hdev->product) { |
382 | wacom_poke(hdev, 1); | 508 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: |
509 | /* Set Wacom mode 2 with high reporting speed */ | ||
510 | wacom_poke(hdev, 1); | ||
511 | break; | ||
512 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
513 | wdata->features = 0; | ||
514 | wacom_set_features(hdev); | ||
515 | break; | ||
516 | } | ||
383 | 517 | ||
384 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 518 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
385 | wdata->battery.properties = wacom_battery_props; | 519 | wdata->battery.properties = wacom_battery_props; |
@@ -441,6 +575,7 @@ static void wacom_remove(struct hid_device *hdev) | |||
441 | 575 | ||
442 | static const struct hid_device_id wacom_devices[] = { | 576 | static const struct hid_device_id wacom_devices[] = { |
443 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 577 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
578 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, | ||
444 | 579 | ||
445 | { } | 580 | { } |
446 | }; | 581 | }; |