diff options
Diffstat (limited to 'drivers/input/tablet')
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 145 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.c | 36 |
2 files changed, 133 insertions, 48 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 0d3219f29744..9edf9806cff9 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -172,6 +172,76 @@ static void wacom_close(struct input_dev *dev) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * Calculate the resolution of the X or Y axis, given appropriate HID data. | ||
176 | * This function is little more than hidinput_calc_abs_res stripped down. | ||
177 | */ | ||
178 | static int wacom_calc_hid_res(int logical_extents, int physical_extents, | ||
179 | unsigned char unit, unsigned char exponent) | ||
180 | { | ||
181 | int prev, unit_exponent; | ||
182 | |||
183 | /* Check if the extents are sane */ | ||
184 | if (logical_extents <= 0 || physical_extents <= 0) | ||
185 | return 0; | ||
186 | |||
187 | /* Get signed value of nybble-sized twos-compliment exponent */ | ||
188 | unit_exponent = exponent; | ||
189 | if (unit_exponent > 7) | ||
190 | unit_exponent -= 16; | ||
191 | |||
192 | /* Convert physical_extents to millimeters */ | ||
193 | if (unit == 0x11) { /* If centimeters */ | ||
194 | unit_exponent += 1; | ||
195 | } else if (unit == 0x13) { /* If inches */ | ||
196 | prev = physical_extents; | ||
197 | physical_extents *= 254; | ||
198 | if (physical_extents < prev) | ||
199 | return 0; | ||
200 | unit_exponent -= 1; | ||
201 | } else { | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /* Apply negative unit exponent */ | ||
206 | for (; unit_exponent < 0; unit_exponent++) { | ||
207 | prev = logical_extents; | ||
208 | logical_extents *= 10; | ||
209 | if (logical_extents < prev) | ||
210 | return 0; | ||
211 | } | ||
212 | /* Apply positive unit exponent */ | ||
213 | for (; unit_exponent > 0; unit_exponent--) { | ||
214 | prev = physical_extents; | ||
215 | physical_extents *= 10; | ||
216 | if (physical_extents < prev) | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /* Calculate resolution */ | ||
221 | return logical_extents / physical_extents; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * The physical dimension specified by the HID descriptor is likely not in | ||
226 | * the "100th of a mm" units expected by wacom_calculate_touch_res. This | ||
227 | * function adjusts the value of [xy]_phy based on the unit and exponent | ||
228 | * provided by the HID descriptor. If an error occurs durring conversion | ||
229 | * (e.g. from the unit being left unspecified) [xy]_phy is not modified. | ||
230 | */ | ||
231 | static void wacom_fix_phy_from_hid(struct wacom_features *features) | ||
232 | { | ||
233 | int xres = wacom_calc_hid_res(features->x_max, features->x_phy, | ||
234 | features->unit, features->unitExpo); | ||
235 | int yres = wacom_calc_hid_res(features->y_max, features->y_phy, | ||
236 | features->unit, features->unitExpo); | ||
237 | |||
238 | if (xres > 0 && yres > 0) { | ||
239 | features->x_phy = (100 * features->x_max) / xres; | ||
240 | features->y_phy = (100 * features->y_max) / yres; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /* | ||
175 | * Static values for max X/Y and resolution of Pen interface is stored in | 245 | * Static values for max X/Y and resolution of Pen interface is stored in |
176 | * features. This mean physical size of active area can be computed. | 246 | * features. This mean physical size of active area can be computed. |
177 | * This is useful to do when Pen and Touch have same active area of tablet. | 247 | * This is useful to do when Pen and Touch have same active area of tablet. |
@@ -432,56 +502,52 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
432 | return result; | 502 | return result; |
433 | } | 503 | } |
434 | 504 | ||
435 | static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features) | 505 | static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode) |
436 | { | 506 | { |
437 | unsigned char *rep_data; | 507 | unsigned char *rep_data; |
438 | int limit = 0, report_id = 2; | 508 | int error = -ENOMEM, limit = 0; |
439 | int error = -ENOMEM; | ||
440 | 509 | ||
441 | rep_data = kmalloc(4, GFP_KERNEL); | 510 | rep_data = kzalloc(length, GFP_KERNEL); |
442 | if (!rep_data) | 511 | if (!rep_data) |
443 | return error; | 512 | return error; |
444 | 513 | ||
445 | /* ask to report Wacom data */ | 514 | rep_data[0] = report_id; |
515 | rep_data[1] = mode; | ||
516 | |||
517 | do { | ||
518 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, | ||
519 | report_id, rep_data, length, 1); | ||
520 | if (error >= 0) | ||
521 | error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, | ||
522 | report_id, rep_data, length, 1); | ||
523 | } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES); | ||
524 | |||
525 | kfree(rep_data); | ||
526 | |||
527 | return error < 0 ? error : 0; | ||
528 | } | ||
529 | |||
530 | /* | ||
531 | * Switch the tablet into its most-capable mode. Wacom tablets are | ||
532 | * typically configured to power-up in a mode which sends mouse-like | ||
533 | * reports to the OS. To get absolute position, pressure data, etc. | ||
534 | * from the tablet, it is necessary to switch the tablet out of this | ||
535 | * mode and into one which sends the full range of tablet data. | ||
536 | */ | ||
537 | static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features) | ||
538 | { | ||
446 | if (features->device_type == BTN_TOOL_FINGER) { | 539 | if (features->device_type == BTN_TOOL_FINGER) { |
447 | /* if it is an MT Tablet PC touch */ | ||
448 | if (features->type > TABLETPC) { | 540 | if (features->type > TABLETPC) { |
449 | do { | 541 | /* MT Tablet PC touch */ |
450 | rep_data[0] = 3; | 542 | return wacom_set_device_mode(intf, 3, 4, 4); |
451 | rep_data[1] = 4; | 543 | } |
452 | rep_data[2] = 0; | 544 | } else if (features->device_type == BTN_TOOL_PEN) { |
453 | rep_data[3] = 0; | 545 | if (features->type <= BAMBOO_PT && features->type != WIRELESS) { |
454 | report_id = 3; | 546 | return wacom_set_device_mode(intf, 2, 2, 2); |
455 | error = wacom_set_report(intf, | ||
456 | WAC_HID_FEATURE_REPORT, | ||
457 | report_id, | ||
458 | rep_data, 4, 1); | ||
459 | if (error >= 0) | ||
460 | error = wacom_get_report(intf, | ||
461 | WAC_HID_FEATURE_REPORT, | ||
462 | report_id, | ||
463 | rep_data, 4, 1); | ||
464 | } while ((error < 0 || rep_data[1] != 4) && | ||
465 | limit++ < WAC_MSG_RETRIES); | ||
466 | } | 547 | } |
467 | } else if (features->type <= BAMBOO_PT && | ||
468 | features->type != WIRELESS && | ||
469 | features->device_type == BTN_TOOL_PEN) { | ||
470 | do { | ||
471 | rep_data[0] = 2; | ||
472 | rep_data[1] = 2; | ||
473 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, | ||
474 | report_id, rep_data, 2, 1); | ||
475 | if (error >= 0) | ||
476 | error = wacom_get_report(intf, | ||
477 | WAC_HID_FEATURE_REPORT, | ||
478 | report_id, rep_data, 2, 1); | ||
479 | } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES); | ||
480 | } | 548 | } |
481 | 549 | ||
482 | kfree(rep_data); | 550 | return 0; |
483 | |||
484 | return error < 0 ? error : 0; | ||
485 | } | 551 | } |
486 | 552 | ||
487 | static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | 553 | static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, |
@@ -531,6 +597,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | |||
531 | error = wacom_parse_hid(intf, hid_desc, features); | 597 | error = wacom_parse_hid(intf, hid_desc, features); |
532 | if (error) | 598 | if (error) |
533 | goto out; | 599 | goto out; |
600 | wacom_fix_phy_from_hid(features); | ||
534 | 601 | ||
535 | out: | 602 | out: |
536 | return error; | 603 | return error; |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 93171098abbd..c3468c8dbd89 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -25,6 +25,11 @@ | |||
25 | #define WACOM_INTUOS_RES 100 | 25 | #define WACOM_INTUOS_RES 100 |
26 | #define WACOM_INTUOS3_RES 200 | 26 | #define WACOM_INTUOS3_RES 200 |
27 | 27 | ||
28 | /* Scale factor relating reported contact size to logical contact area. | ||
29 | * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo | ||
30 | */ | ||
31 | #define WACOM_CONTACT_AREA_SCALE 2607 | ||
32 | |||
28 | static int wacom_penpartner_irq(struct wacom_wac *wacom) | 33 | static int wacom_penpartner_irq(struct wacom_wac *wacom) |
29 | { | 34 | { |
30 | unsigned char *data = wacom->data; | 35 | unsigned char *data = wacom->data; |
@@ -326,7 +331,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) | |||
326 | 331 | ||
327 | /* Enter report */ | 332 | /* Enter report */ |
328 | if ((data[1] & 0xfc) == 0xc0) { | 333 | if ((data[1] & 0xfc) == 0xc0) { |
329 | if (features->type >= INTUOS5S && features->type <= INTUOS5L) | 334 | if (features->quirks == WACOM_QUIRK_MULTI_INPUT) |
330 | wacom->shared->stylus_in_proximity = true; | 335 | wacom->shared->stylus_in_proximity = true; |
331 | 336 | ||
332 | /* serial number of the tool */ | 337 | /* serial number of the tool */ |
@@ -414,7 +419,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) | |||
414 | 419 | ||
415 | /* Exit report */ | 420 | /* Exit report */ |
416 | if ((data[1] & 0xfe) == 0x80) { | 421 | if ((data[1] & 0xfe) == 0x80) { |
417 | if (features->type >= INTUOS5S && features->type <= INTUOS5L) | 422 | if (features->quirks == WACOM_QUIRK_MULTI_INPUT) |
418 | wacom->shared->stylus_in_proximity = false; | 423 | wacom->shared->stylus_in_proximity = false; |
419 | 424 | ||
420 | /* | 425 | /* |
@@ -1043,11 +1048,19 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) | |||
1043 | if (touch) { | 1048 | if (touch) { |
1044 | int x = (data[2] << 4) | (data[4] >> 4); | 1049 | int x = (data[2] << 4) | (data[4] >> 4); |
1045 | int y = (data[3] << 4) | (data[4] & 0x0f); | 1050 | int y = (data[3] << 4) | (data[4] & 0x0f); |
1046 | int w = data[6]; | 1051 | int a = data[5]; |
1052 | |||
1053 | // "a" is a scaled-down area which we assume is roughly | ||
1054 | // circular and which can be described as: a=(pi*r^2)/C. | ||
1055 | int x_res = input_abs_get_res(input, ABS_X); | ||
1056 | int y_res = input_abs_get_res(input, ABS_Y); | ||
1057 | int width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); | ||
1058 | int height = width * y_res / x_res; | ||
1047 | 1059 | ||
1048 | input_report_abs(input, ABS_MT_POSITION_X, x); | 1060 | input_report_abs(input, ABS_MT_POSITION_X, x); |
1049 | input_report_abs(input, ABS_MT_POSITION_Y, y); | 1061 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
1050 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, w); | 1062 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, width); |
1063 | input_report_abs(input, ABS_MT_TOUCH_MINOR, height); | ||
1051 | } | 1064 | } |
1052 | } | 1065 | } |
1053 | 1066 | ||
@@ -1530,10 +1543,12 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1530 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | 1543 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); |
1531 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | 1544 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); |
1532 | 1545 | ||
1533 | input_mt_init_slots(input_dev, features->touch_max); | 1546 | input_mt_init_slots(input_dev, features->touch_max, 0); |
1534 | 1547 | ||
1535 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | 1548 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, |
1536 | 0, 255, 0, 0); | 1549 | 0, features->x_max, 0, 0); |
1550 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, | ||
1551 | 0, features->y_max, 0, 0); | ||
1537 | 1552 | ||
1538 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1553 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
1539 | 0, features->x_max, | 1554 | 0, features->x_max, |
@@ -1575,7 +1590,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1575 | 1590 | ||
1576 | case TABLETPC2FG: | 1591 | case TABLETPC2FG: |
1577 | if (features->device_type == BTN_TOOL_FINGER) { | 1592 | if (features->device_type == BTN_TOOL_FINGER) { |
1578 | input_mt_init_slots(input_dev, features->touch_max); | 1593 | input_mt_init_slots(input_dev, features->touch_max, 0); |
1579 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, | 1594 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, |
1580 | 0, MT_TOOL_MAX, 0, 0); | 1595 | 0, MT_TOOL_MAX, 0, 0); |
1581 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1596 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
@@ -1631,7 +1646,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1631 | 1646 | ||
1632 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | 1647 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
1633 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | 1648 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); |
1634 | input_mt_init_slots(input_dev, features->touch_max); | 1649 | input_mt_init_slots(input_dev, features->touch_max, 0); |
1635 | 1650 | ||
1636 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { | 1651 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { |
1637 | __set_bit(BTN_TOOL_TRIPLETAP, | 1652 | __set_bit(BTN_TOOL_TRIPLETAP, |
@@ -1641,7 +1656,10 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
1641 | 1656 | ||
1642 | input_set_abs_params(input_dev, | 1657 | input_set_abs_params(input_dev, |
1643 | ABS_MT_TOUCH_MAJOR, | 1658 | ABS_MT_TOUCH_MAJOR, |
1644 | 0, 255, 0, 0); | 1659 | 0, features->x_max, 0, 0); |
1660 | input_set_abs_params(input_dev, | ||
1661 | ABS_MT_TOUCH_MINOR, | ||
1662 | 0, features->y_max, 0, 0); | ||
1645 | } | 1663 | } |
1646 | 1664 | ||
1647 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1665 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |