aboutsummaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/usb_hid.c
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2017-10-19 20:28:04 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2017-10-19 20:28:04 +0000
commit0f1ca5355fe0e666903e15ba3cd0277166156061 (patch)
treeb1c15ac63c3ea4447e73477dece01c315efb0ed5 /sys/dev/usb/usb_hid.c
parentb99304f34f675d4d07bae220e70cfb36ed07a620 (diff)
downloadsrc-0f1ca5355fe0e666903e15ba3cd0277166156061.tar.gz
src-0f1ca5355fe0e666903e15ba3cd0277166156061.zip
MFC r322695:
Add support for generic MS Windows 7/8/10-compatible USB HID touchscreens found in many laptops. Reviewed by: hps, gonzo, bcr (manpages) Approved by: gonzo (mentor) Differential Revision: https://reviews.freebsd.org/D12017
Notes
Notes: svn path=/stable/11/; revision=324769
Diffstat (limited to 'sys/dev/usb/usb_hid.c')
-rw-r--r--sys/dev/usb/usb_hid.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c
index fe85f0c5560c..2c045dbed442 100644
--- a/sys/dev/usb/usb_hid.c
+++ b/sys/dev/usb/usb_hid.c
@@ -849,6 +849,80 @@ usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx,
}
/*------------------------------------------------------------------------*
+ * calculate HID item resolution. unit/mm for distances, unit/rad for angles
+ *------------------------------------------------------------------------*/
+int32_t
+hid_item_resolution(struct hid_item *hi)
+{
+ /*
+ * hid unit scaling table according to HID Usage Table Review
+ * Request 39 Tbl 17 http://www.usb.org/developers/hidpage/HUTRR39b.pdf
+ */
+ static const int64_t scale[0x10][2] = {
+ [0x00] = { 1, 1 },
+ [0x01] = { 1, 10 },
+ [0x02] = { 1, 100 },
+ [0x03] = { 1, 1000 },
+ [0x04] = { 1, 10000 },
+ [0x05] = { 1, 100000 },
+ [0x06] = { 1, 1000000 },
+ [0x07] = { 1, 10000000 },
+ [0x08] = { 100000000, 1 },
+ [0x09] = { 10000000, 1 },
+ [0x0A] = { 1000000, 1 },
+ [0x0B] = { 100000, 1 },
+ [0x0C] = { 10000, 1 },
+ [0x0D] = { 1000, 1 },
+ [0x0E] = { 100, 1 },
+ [0x0F] = { 10, 1 },
+ };
+ int64_t logical_size;
+ int64_t physical_size;
+ int64_t multiplier;
+ int64_t divisor;
+ int64_t resolution;
+
+ switch (hi->unit) {
+ case HUM_CENTIMETER:
+ multiplier = 1;
+ divisor = 10;
+ break;
+ case HUM_INCH:
+ multiplier = 10;
+ divisor = 254;
+ break;
+ case HUM_RADIAN:
+ multiplier = 1;
+ divisor = 1;
+ break;
+ case HUM_DEGREE:
+ multiplier = 573;
+ divisor = 10;
+ break;
+ default:
+ return (0);
+ }
+
+ if ((hi->logical_maximum <= hi->logical_minimum) ||
+ (hi->physical_maximum <= hi->physical_minimum) ||
+ (hi->unit_exponent < 0) || (hi->unit_exponent >= nitems(scale)))
+ return (0);
+
+ logical_size = (int64_t)hi->logical_maximum -
+ (int64_t)hi->logical_minimum;
+ physical_size = (int64_t)hi->physical_maximum -
+ (int64_t)hi->physical_minimum;
+ /* Round to ceiling */
+ resolution = logical_size * multiplier * scale[hi->unit_exponent][0] /
+ (physical_size * divisor * scale[hi->unit_exponent][1]);
+
+ if (resolution > INT32_MAX)
+ return (0);
+
+ return (resolution);
+}
+
+/*------------------------------------------------------------------------*
* hid_is_mouse
*
* This function will decide if a USB descriptor belongs to a USB mouse.