diff options
Diffstat (limited to 'drivers/hid/hid-wacom.c')
-rw-r--r-- | drivers/hid/hid-wacom.c | 142 |
1 files changed, 135 insertions, 7 deletions
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index db2322310486..f2183486a9b6 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); |
@@ -290,6 +305,77 @@ static int wacom_gr_parse_report(struct hid_device *hdev, | |||
290 | #endif | 305 | #endif |
291 | return 1; | 306 | return 1; |
292 | } | 307 | } |
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 | |||
293 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | 379 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, |
294 | u8 *raw_data, int size) | 380 | u8 *raw_data, int size) |
295 | { | 381 | { |
@@ -297,6 +383,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
297 | struct hid_input *hidinput; | 383 | struct hid_input *hidinput; |
298 | struct input_dev *input; | 384 | struct input_dev *input; |
299 | unsigned char *data = (unsigned char *) raw_data; | 385 | unsigned char *data = (unsigned char *) raw_data; |
386 | int i; | ||
300 | 387 | ||
301 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) | 388 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) |
302 | return 0; | 389 | return 0; |
@@ -308,7 +395,30 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
308 | if (data[0] != 0x03) | 395 | if (data[0] != 0x03) |
309 | return 0; | 396 | return 0; |
310 | 397 | ||
311 | return wacom_gr_parse_report(hdev, wdata, input, data); | 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; | ||
312 | } | 422 | } |
313 | 423 | ||
314 | 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, |
@@ -345,10 +455,19 @@ static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
345 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | 455 | __set_bit(BTN_TOOL_RUBBER, input->keybit); |
346 | __set_bit(BTN_TOOL_MOUSE, input->keybit); | 456 | __set_bit(BTN_TOOL_MOUSE, input->keybit); |
347 | 457 | ||
348 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); | 458 | switch (hdev->product) { |
349 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); | 459 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: |
350 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | 460 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); |
351 | 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 | } | ||
352 | 471 | ||
353 | return 0; | 472 | return 0; |
354 | } | 473 | } |
@@ -385,8 +504,16 @@ static int wacom_probe(struct hid_device *hdev, | |||
385 | hid_warn(hdev, | 504 | hid_warn(hdev, |
386 | "can't create sysfs speed attribute err: %d\n", ret); | 505 | "can't create sysfs speed attribute err: %d\n", ret); |
387 | 506 | ||
388 | /* Set Wacom mode 2 with high reporting speed */ | 507 | switch (hdev->product) { |
389 | 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 | } | ||
390 | 517 | ||
391 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 518 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
392 | wdata->battery.properties = wacom_battery_props; | 519 | wdata->battery.properties = wacom_battery_props; |
@@ -448,6 +575,7 @@ static void wacom_remove(struct hid_device *hdev) | |||
448 | 575 | ||
449 | static const struct hid_device_id wacom_devices[] = { | 576 | static const struct hid_device_id wacom_devices[] = { |
450 | { 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) }, | ||
451 | 579 | ||
452 | { } | 580 | { } |
453 | }; | 581 | }; |