From d23daa93ca15f26291dcc30bf13a960580c31617 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 3 Oct 2012 17:24:32 -0700 Subject: [PATCH] --- yaml --- r: 334085 b: refs/heads/master c: 115d5e12a7d5fe62076f9dcc728905196162d709 h: refs/heads/master i: 334083: 22b334117465b33f77c567eda57969ab898f774e v: v3 --- [refs] | 2 +- trunk/drivers/input/tablet/wacom_sys.c | 71 ++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 2f88615bfd92..b60a6fcb348d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9d336daf3b502f594ce18d26a3a009adb2cf3729 +refs/heads/master: 115d5e12a7d5fe62076f9dcc728905196162d709 diff --git a/trunk/drivers/input/tablet/wacom_sys.c b/trunk/drivers/input/tablet/wacom_sys.c index 0d3219f29744..b44bba2a60c2 100644 --- a/trunk/drivers/input/tablet/wacom_sys.c +++ b/trunk/drivers/input/tablet/wacom_sys.c @@ -171,6 +171,76 @@ static void wacom_close(struct input_dev *dev) usb_autopm_put_interface(wacom->intf); } +/* + * Calculate the resolution of the X or Y axis, given appropriate HID data. + * This function is little more than hidinput_calc_abs_res stripped down. + */ +static int wacom_calc_hid_res(int logical_extents, int physical_extents, + unsigned char unit, unsigned char exponent) +{ + int prev, unit_exponent; + + /* Check if the extents are sane */ + if (logical_extents <= 0 || physical_extents <= 0) + return 0; + + /* Get signed value of nybble-sized twos-compliment exponent */ + unit_exponent = exponent; + if (unit_exponent > 7) + unit_exponent -= 16; + + /* Convert physical_extents to millimeters */ + if (unit == 0x11) { /* If centimeters */ + unit_exponent += 1; + } else if (unit == 0x13) { /* If inches */ + prev = physical_extents; + physical_extents *= 254; + if (physical_extents < prev) + return 0; + unit_exponent -= 1; + } else { + return 0; + } + + /* Apply negative unit exponent */ + for (; unit_exponent < 0; unit_exponent++) { + prev = logical_extents; + logical_extents *= 10; + if (logical_extents < prev) + return 0; + } + /* Apply positive unit exponent */ + for (; unit_exponent > 0; unit_exponent--) { + prev = physical_extents; + physical_extents *= 10; + if (physical_extents < prev) + return 0; + } + + /* Calculate resolution */ + return logical_extents / physical_extents; +} + +/* + * The physical dimension specified by the HID descriptor is likely not in + * the "100th of a mm" units expected by wacom_calculate_touch_res. This + * function adjusts the value of [xy]_phy based on the unit and exponent + * provided by the HID descriptor. If an error occurs durring conversion + * (e.g. from the unit being left unspecified) [xy]_phy is not modified. + */ +static void wacom_fix_phy_from_hid(struct wacom_features *features) +{ + int xres = wacom_calc_hid_res(features->x_max, features->x_phy, + features->unit, features->unitExpo); + int yres = wacom_calc_hid_res(features->y_max, features->y_phy, + features->unit, features->unitExpo); + + if (xres > 0 && yres > 0) { + features->x_phy = (100 * features->x_max) / xres; + features->y_phy = (100 * features->y_max) / yres; + } +} + /* * Static values for max X/Y and resolution of Pen interface is stored in * features. This mean physical size of active area can be computed. @@ -531,6 +601,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, error = wacom_parse_hid(intf, hid_desc, features); if (error) goto out; + wacom_fix_phy_from_hid(features); out: return error;