ref: f57df708538093ffb47727a522a0217b9ee81125
parent: 8188b4f4f0e07b6669e6ae3c6c1099af917eaab4
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jan 29 11:36:57 EST 2023
nusb/kb: GAOMON S620 tablet support The GAOMON S620 tablet is recognized as a HID device, but is restricted in the X-axis to the width of a mobile phone. I sniffed usb traffic for generic windows 10 hid driver and there didnt seem anything out of the ordinary. It turns out that this is some kind of phone feature and i suspect they have some heuristic for how windows reads the device and config descriptors to decide if this is windows or android. Checking the DIGImend project git repository, they suggest this is some kind of UCLOGIC compatible tablet, which once a series of string properties have been read will switch itself to some different mode. The report descriptor is supposed to be generated from the string properties, but the report format didnt really match theirs. So i ignore the string properties and just looked at the report data. The format after reading the magic string properties seems to be: 08 - report id bb - buttons: 0x80 = inrange, 0x04 = eraser, 0x02, barrel, 0x01 = touch xx xx - x-axis: [0x0000-0x80000) yy yy - y-axis: [0x0000-0x50000) pp pp - pressure: [0x0000-0xffff] ?? ?? - unknown So i hand rolled a hid report descriptor for this and call it a day :)
--- a/sys/src/cmd/nusb/kb/kb.c
+++ b/sys/src/cmd/nusb/kb/kb.c
@@ -898,11 +898,78 @@
}
static void
+gaomons620(Hiddev *f)
+{
+ static uchar descr[] = {
+ 0x05, 0x0D, /* Usage Page (Digitizer), */
+ 0x09, 0x01, /* Usage (Digitizer), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, 0x08, /* Report ID (8), */
+ 0x09, 0x20, /* Usage (Stylus), */
+ 0xA0, /* Collection (Physical), */
+ 0x14, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x09, 0x42, /* Usage (Tip Switch), */
+ 0x09, 0x44, /* Usage (Barrel Switch), */
+ 0x09, 0x45, /* Usage (Eraser), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x02, /* Input (Variable), */
+
+ 0x95, 0x04, /* Report Count (4), */
+ 0x81, 0x03, /* Input (Constant, Variable), */
+
+ 0x09, 0x32, /* Usage (In Range), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x02, /* Input (Variable), */
+
+ 0xA4, /* Push, */
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x65, 0x13, /* Unit (Inch), */
+ 0x55, 0xFD, /* Unit Exponent (-3), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x34, /* Physical Minimum (0), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x27, 0x00, 0x80, 0x00, 0x00, /* Logical Maximum, */
+ 0x47, 0x00, 0x80, 0x00, 0x00, /* Physical Maximum, */
+ 0x81, 0x02, /* Input (Variable), */
+
+ 0x09, 0x31, /* Usage (Y), */
+ 0x27, 0x00, 0x50, 0x00, 0x00, /* Logical Maximum, */
+ 0x47, 0x00, 0x50, 0x00, 0x00, /* Physical Maximum, */
+ 0x81, 0x02, /* Input (Variable), */
+
+ 0xB4, /* Pop, */
+ 0x09, 0x30, /* Usage (Tip Pressure), */
+ 0x75, 0x10, /* Report Size (16), */
+ 0x27, 0x00, 0x00, 0x01, 0x00, /* Logical Maximum, */
+ 0x81, 0x02, /* Input (Variable), */
+ 0xC0, /* End Collection, */
+ 0xC0 /* End Collection */
+ };
+ static int idx[] = { 0x64, 0x65, 0x6e, 0x79, 0x7a, 0x7b, 0xc8, 0xc9 };
+ Dev *d = f->dev;
+ int i;
+
+ /* we have to fetch a bunch of strings to switch to non-phone mode */
+ for(i=0; i < nelem(idx); i++)
+ free(loaddevstr(d, idx[i]));
+
+ /* override report descriptor */
+ memmove(f->rep, descr, f->nrep = sizeof(descr));
+}
+
+static void
quirks(Hiddev *f)
{
Dev *d;
d = f->dev;
+
+ if(d->usb->vid == 0x256c && d->usb->did == 0x006d){
+ gaomons620(f);
+ return;
+ }
/* Elecom trackball report descriptor lies by
* omission, failing to mention all its buttons.
@@ -921,6 +988,7 @@
f->rep[13] = 8;
f->rep[21] = 8;
f->rep[31] = 0;
+ return;
}
}