Commit 115d5e12 authored by Jason Gerecke's avatar Jason Gerecke Committed by Dmitry Torokhov

Input: wacom - introduce wacom_fix_phy_from_hid

The Cintiq 24HD touch cannot use wacom_set_phy_from_res to determine
the physical size of the touch sensor since the pen and touch are
on separate USB devices. The physical size is, however, provided in
the HID descriptor, just scaled to a unit we don't use.

This patch introduces the function wacom_fix_phy_from_hid to let
us make use of the unit and exponent data provided by HID to set
the [xy]_phy variables to an appropriate value. This function
relies on a trimmed-down version of hidinput_calc_abs_res from
the hid-input.c.
Signed-off-by: default avatarJason Gerecke <killertofu@gmail.com>
Tested-by: default avatarPing Cheng <pingc@wacom.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 9d336daf
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment