On Mon, Jul 03, 2023 at 11:22:45AM +0200, Marc Espie wrote: > I hope Vladimir will find the time to complete this answer. > > As far as Vlad's work goes, he did a presentation last week-end: > https://www.lre.epita.fr/news_content/SS_summer_week_pres/Vladimir_Driver_OpenBSD.pptx > > (sorry for the medium, fortunately we have libreoffice) > > In the mean time, here is an updated diff. > > I removed the Gaomon stuff, which if anything should be a different patch. > > And I cleaned up the 20+ minor style violations I could find... > (tabs instead of +4 spaces for continued lines, a few non-style compliant > function declarations and/or code blocks, oh well) > > plus an extra malloc.h that snuck in and is not at all needed. > > And some typos in comments. > And a C++ style comment. Oh well > > I would really for some version of this to get in soonish. > I can vouch that my tablet "works" with it (well, as good as it can work > within the limitations of wscons not allowing it to be easily differentiated > from the normal mouse, which is really a pain for programs like gimp)
Thanks, I built a kernel with this and no issues observed. I have a Wacom Bamboo (CTH-470, product id 0x00de) that doesn't attach yet, but this can be left for future work. I don't see anything glaring. hid.c could probably use some refactoring at some point in the future because at least 3 functions now share 99% identical code (hid_is_collection, hid_get_collection_data, hid_get_id_of_collection). I recommend getting an ok from someone with more track record with dev/hid and/or dev/usb, but from my side this is ok thfr@. > > dmesg for the tablet with the diff > | uhidev1 at uhub1 port 4 configuration 1 interface 0 "Wacom Co.,Ltd. Intuos > S" rev 2.00/1.07 addr 6 > | uhidev1: iclass 3/0, 228 report ids > | uwacom0 at uhidev1: 9 buttons, Z and W dir, tip, barrel > | wsmouse5 at uwacom0 mux 0 > | uwacom1 at uhidev1: 9 buttons, Z and W dir, tip, barrel > | wsmouse6 at uwacom1 mux 0 > | uwacom2 at uhidev1: 9 buttons, Z and W dir, tip, barrel > | wsmouse7 at uwacom2 mux 0 > > as far as I understand, it appears as several mice because the stylus > acts as totally different devices depending on the mode/end used > (stuff that wscons completely hides from us). > > Without the patch, that tablet appears as 42 different uhid devices (!) > > The idea is that the parser for collections was really primitive. The > debug stuff can show the details of various collection. There is the actual > tablet mechanisms (which becomes one device) including scale, stylus, etc, > and some other wacky collections (!): a debug collection that the wacom guys > told us "oh some of our hw team needs that, but don't ever touch" and > some other stuff we can't support yet (like battery support for some > advanced models of stylus) > > Index: dev/hid/hid.c > =================================================================== > RCS file: /cvs/src/sys/dev/hid/hid.c,v > retrieving revision 1.5 > diff -u -p -r1.5 hid.c > --- dev/hid/hid.c 20 May 2022 05:03:45 -0000 1.5 > +++ dev/hid/hid.c 3 Jul 2023 09:04:50 -0000 > @@ -657,3 +657,51 @@ hid_is_collection(const void *desc, int > hid_end_parse(hd); > return (0); > } > + > +struct hid_data * > +hid_get_collection_data(const void *desc, int size, int32_t usage, > + uint32_t collection) > +{ > + struct hid_data *hd; > + struct hid_item hi; > + > + hd = hid_start_parse(desc, size, hid_all); > + > + DPRINTF("%s: usage=0x%x\n", __func__, usage); > + while (hid_get_item(hd, &hi)) { > + DPRINTF("%s: kind=%d id=%d usage=0x%x(0x%x)\n", __func__, > + hi.kind, hi.report_ID, hi.usage, usage); > + if (hi.kind == hid_collection && > + hi.collection == collection && hi.usage == usage){ > + DPRINTF("%s: found\n", __func__); > + return hd; > + } > + } > + DPRINTF("%s: not found\n", __func__); > + hid_end_parse(hd); > + return NULL; > +} > + > +int > +hid_get_id_of_collection(const void *desc, int size, int32_t usage, > + uint32_t collection) > +{ > + struct hid_data *hd; > + struct hid_item hi; > + > + hd = hid_start_parse(desc, size, hid_all); > + > + DPRINTF("%s: id=%d usage=0x%x\n", __func__, id, usage); > + while (hid_get_item(hd, &hi)) { > + DPRINTF("%s: kind=%d id=%d usage=0x%x(0x%x)\n", __func__, > + hi.kind, hi.report_ID, hi.usage, usage); > + if (hi.kind == hid_collection && > + hi.collection == collection && hi.usage == usage){ > + DPRINTF("%s: found\n", __func__); > + return hi.report_ID; > + } > + } > + DPRINTF("%s: not found\n", __func__); > + hid_end_parse(hd); > + return 0; > +} > Index: dev/hid/hid.h > =================================================================== > RCS file: /cvs/src/sys/dev/hid/hid.h,v > retrieving revision 1.10 > diff -u -p -r1.10 hid.h > --- dev/hid/hid.h 20 May 2022 05:03:45 -0000 1.10 > +++ dev/hid/hid.h 3 Jul 2023 09:04:50 -0000 > @@ -93,6 +93,10 @@ int hid_locate(const void *, int, int32_ > int32_t hid_get_data(const uint8_t *buf, int, struct hid_location *); > uint32_t hid_get_udata(const uint8_t *buf, int, struct hid_location *); > int hid_is_collection(const void *, int, uint8_t, int32_t); > +struct hid_data * hid_get_collection_data(const void *, int, int32_t, > + uint32_t); > +int hid_get_id_of_collection(const void *desc, int size, int32_t usage, > + uint32_t collection); > > #endif /* _KERNEL */ > > @@ -353,6 +357,7 @@ int hid_is_collection(const void *, int, > #define HUD_TOUCHSCREEN 0x0004 > #define HUD_TOUCHPAD 0x0005 > #define HUD_CONFIG 0x000e > +#define HUD_STYLUS 0x0020 > #define HUD_FINGER 0x0022 > #define HUD_TIP_PRESSURE 0x0030 > #define HUD_BARREL_PRESSURE 0x0031 > @@ -387,6 +392,12 @@ int hid_is_collection(const void *, int, > #define HUD_CONTACT_MAX 0x0055 > #define HUD_SCAN_TIME 0x0056 > #define HUD_BUTTON_TYPE 0x0059 > +#define HUD_SECONDARY_BARREL_SWITCH 0x005A > +#define HUD_WACOM_X 0x0130 > +#define HUD_WACOM_Y 0x0131 > +#define HUD_WACOM_DISTANCE 0x0132 > +#define HUD_WACOM_PAD_BUTTONS00 0x0910 > +#define HUD_WACOM_BATTERY 0x1013 > > /* Usages, LED */ > #define HUL_NUM_LOCK 0x0001 > Index: dev/hid/hidms.c > =================================================================== > RCS file: /cvs/src/sys/dev/hid/hidms.c,v > retrieving revision 1.9 > diff -u -p -r1.9 hidms.c > --- dev/hid/hidms.c 16 Jun 2022 20:52:38 -0000 1.9 > +++ dev/hid/hidms.c 3 Jul 2023 09:04:50 -0000 > @@ -61,6 +61,210 @@ int hidmsdebug = 0; > #define MOUSE_FLAGS_MASK (HIO_CONST | HIO_RELATIVE) > #define NOTMOUSE(f) (((f) & MOUSE_FLAGS_MASK) != HIO_RELATIVE) > > + > +int > +stylus_hid_parse(struct hidms *ms, struct hid_data *d, uint32_t *flags) > +{ > + /* Define stylus reported usages: (maybe macros?) */ > + const uint32_t stylus_usage_tip > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TIP_SWITCH); > + const uint32_t stylus_usage_barrel > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_BARREL_SWITCH); > + const uint32_t stylus_usage_sec_barrel = HID_USAGE2( > + HUP_WACOM | HUP_DIGITIZERS, HUD_SECONDARY_BARREL_SWITCH); > + const uint32_t stylus_usage_in_range > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_IN_RANGE); > + const uint32_t stylus_usage_quality > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_QUALITY); > + const uint32_t stylus_usage_x > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_X); > + const uint32_t stylus_usage_y > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_Y); > + const uint32_t stylus_usage_pressure > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TIP_PRESSURE); > + const uint32_t stylus_usage_distance > + = HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_DISTANCE); > + > + struct hid_item h; > + > + while (hid_get_item(d, &h)) { > + if (h.kind == hid_input && !(h.flags & HIO_CONST)) { > + /* All the possible stylus reported usages go here */ > +#ifdef HIDMS_DEBUG > + printf("stylus usage: 0x%x\n", h.usage); > +#endif > + switch (h.usage) { > + /* Buttons */ > + case stylus_usage_tip: > + DPRINTF("Stylus usage tip set\n"); > + ms->sc_loc_stylus_btn > + [ms->sc_num_stylus_buttons++] = h.loc; > + ms->sc_flags |= HIDMS_TIP; > + break; > + case stylus_usage_barrel: > + DPRINTF("Stylus usage barrel set\n"); > + ms->sc_loc_stylus_btn > + [ms->sc_num_stylus_buttons++] = h.loc; > + ms->sc_flags |= HIDMS_BARREL; > + break; > + case stylus_usage_sec_barrel: > + DPRINTF("Stylus usage secondary barrel set\n"); > + ms->sc_loc_stylus_btn > + [ms->sc_num_stylus_buttons++] = h.loc; > + ms->sc_flags |= HIDMS_SEC_BARREL; > + break; > + case stylus_usage_in_range: > + DPRINTF("Stylus usage in range set\n"); > + ms->sc_loc_stylus_btn > + [ms->sc_num_stylus_buttons++] = h.loc; > + break; > + case stylus_usage_quality: > + DPRINTF("Stylus usage quality set\n"); > + ms->sc_loc_stylus_btn > + [ms->sc_num_stylus_buttons++] = h.loc; > + break; > + /* Axes */ > + case stylus_usage_x: > + DPRINTF("Stylus usage x set\n"); > + ms->sc_loc_x = h.loc; > + ms->sc_tsscale.minx = h.logical_minimum; > + ms->sc_tsscale.maxx = h.logical_maximum; > + ms->sc_flags |= HIDMS_ABSX; > + break; > + case stylus_usage_y: > + DPRINTF("Stylus usage y set\n"); > + ms->sc_loc_y = h.loc; > + ms->sc_tsscale.miny = h.logical_minimum; > + ms->sc_tsscale.maxy = h.logical_maximum; > + ms->sc_flags |= HIDMS_ABSY; > + break; > + case stylus_usage_pressure: > + DPRINTF("Stylus usage pressure set\n"); > + ms->sc_loc_z = h.loc; > + ms->sc_tsscale.minz = h.logical_minimum; > + ms->sc_tsscale.maxz = h.logical_maximum; > + ms->sc_flags |= HIDMS_Z; > + break; > + case stylus_usage_distance: > + DPRINTF("Stylus usage distance set\n"); > + ms->sc_loc_w = h.loc; > + ms->sc_tsscale.minw = h.logical_minimum; > + ms->sc_tsscale.maxw = h.logical_maximum; > + ms->sc_flags |= HIDMS_W; > + break; > + default: > +#ifdef HIDMS_DEBUG > + printf("Unknown stylus usage: 0x%x, please > report to the devs!\n", > + h.usage); > +#endif > + break; > + } > + } > + if (h.kind == hid_endcollection) > + break; > + } > + hid_end_parse(d); > + if (flags != NULL) > + *flags = 0; > + return (0); > +} > + > +int > +pad_buttons_hid_parser(struct hidms *ms, struct hid_data *d, uint32_t > *flags) > +{ > + struct hid_item h; > + > + while (hid_get_item(d, &h)) { > + if (h.kind == hid_input && !(h.flags & HIO_CONST) > + && h.usage == HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, > + HUD_WACOM_PAD_BUTTONS00 | ms->sc_num_pad_buttons)) { > + ms->sc_loc_pad_btn[ms->sc_num_pad_buttons++] = h.loc; > + } > + if (h.kind == hid_endcollection) > + break; > + } > + hid_end_parse(d); > + if (flags != NULL) > + *flags = 0; > + return (0); > +} > + > +int > +hidms_wacom_setup(struct device *self, struct hidms *ms, uint32_t quirks, > + int id, void *desc, int dlen) > +{ > + struct hid_data *global; > + uint32_t flags; > + int i; > + > + quirks = 0; > + ms->sc_device = self; > + ms->sc_rawmode = 1; > + > + ms->sc_flags = quirks; > + > + /* Set x,y,z and w to zero by default */ > + ms->sc_loc_x.size = 0; > + ms->sc_loc_y.size = 0; > + ms->sc_loc_z.size = 0; > + ms->sc_loc_w.size = 0; > + > + if ((global = hid_get_collection_data(desc, dlen, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_DIGITIZER), > + HCOLL_APPLICATION))) { > + hid_end_parse(global); > + > + struct hid_data *stylus_col; > + struct hid_data *tablet_keys_col; > + struct hid_data *battery_col; > + > + DPRINTF("found the global collection\n"); > + if ((stylus_col = hid_get_collection_data(desc, dlen, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_STYLUS), > + HCOLL_PHYSICAL))) { > + DPRINTF("found stylus collection\n"); > + stylus_hid_parse(ms, stylus_col, &flags); > + } > + if ((tablet_keys_col = hid_get_collection_data(desc, dlen, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TABLET_FKEYS), > + HCOLL_PHYSICAL))) { > + DPRINTF("found tablet keys collection\n"); > + pad_buttons_hid_parser(ms, tablet_keys_col, &flags); > + } > + if ((battery_col = hid_get_collection_data(desc, dlen, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_BATTERY), > + HCOLL_PHYSICAL))) { > + DPRINTF("found battery collection\n"); > + /* parse and set the battery info */ > + /* not yet used */ > + hid_end_parse(battery_col); > + } > + /* > + * Ignore the device config, it's not really needed > + * Ignore the usage 0x10AC which is the debug collection, and > + * ignore firmware collection and other collections for now > + */ > + } > + > + /* Map the pad and stylus buttons to mouse buttons */ > + for (i = 0; i < ms->sc_num_stylus_buttons; i++) > + memcpy(&(ms->sc_loc_btn[i]), &(ms->sc_loc_stylus_btn[i]), > + sizeof(struct hid_location)); > + for (; i < ms->sc_num_pad_buttons + ms->sc_num_stylus_buttons; i++) > + memcpy(&(ms->sc_loc_btn[i]), &(ms->sc_loc_pad_btn[i]), > + sizeof(struct hid_location)); > + ms->sc_num_buttons = i; > + DPRINTF("Buttons inf\n"); > +#ifdef HIDMS_DEBUG > + for (i = 0; i < ms->sc_num_buttons; i++) > + printf("size: 0x%x, pos: 0x%x, count: 0x%x\n", > + ms->sc_loc_btn[i].size, ms->sc_loc_btn[i].pos, > + ms->sc_loc_btn[i].count); > +#endif > + return 0; > +} > + > + > int > hidms_setup(struct device *self, struct hidms *ms, uint32_t quirks, > int id, void *desc, int dlen) > @@ -74,6 +278,10 @@ hidms_setup(struct device *self, struct > ms->sc_rawmode = 1; > > ms->sc_flags = quirks; > + > + /* We are setting up a WACOM tablet, not a mouse */ > + if (quirks == HIDMS_WACOM_SETUP) > + return hidms_wacom_setup(self, ms, quirks, id, desc, dlen); > > if (!hid_locate(desc, dlen, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), id, > hid_input, &ms->sc_loc_x, &flags)) > Index: dev/hid/hidmsvar.h > =================================================================== > RCS file: /cvs/src/sys/dev/hid/hidmsvar.h,v > retrieving revision 1.2 > diff -u -p -r1.2 hidmsvar.h > --- dev/hid/hidmsvar.h 10 Jan 2021 16:32:48 -0000 1.2 > +++ dev/hid/hidmsvar.h 3 Jul 2023 09:04:50 -0000 > @@ -36,6 +36,8 @@ > struct tsscale { > int minx, maxx; > int miny, maxy; > + int minz, maxz; > + int minw, maxw; > int swapxy; > int resx, resy; > }; > @@ -56,19 +58,39 @@ struct hidms { > #define HIDMS_ERASER 0x0400 /* Eraser switch on a digitiser pen */ > #define HIDMS_MS_BAD_CLASS 0x0800 /* Mouse doesn't identify properly */ > #define HIDMS_VENDOR_BUTTONS 0x1000 /* extra buttons in vendor page */ > +#define HIDMS_SEC_BARREL 0x2000 /* Secondary Barrel switch on a > digitiser pen */ > +#define HIDMS_WACOM_SETUP 0xff0d /*Wacom*/ > > int sc_num_buttons; > u_int32_t sc_buttons; /* mouse button status */ > > struct device *sc_device; > struct device *sc_wsmousedev; > + /* Wacom */ > + int sc_num_pad_buttons; > + u_int32_t sc_pad_buttons; /* left to right, or top to bottom */ > + int sc_num_stylus_buttons; > + u_int32_t sc_stylus_buttons; /* tip, barrel switch, > + * secondary barrel switch, > + * ... Add the others in order */ > > + int sc_in_range; > + int sc_quality; > + > + u_int32_t sc_transducer_id_low; > + u_int32_t sc_transducer_id_high; > + > + u_int16_t sc_tool_type; > /* locators */ > struct hid_location sc_loc_x; > struct hid_location sc_loc_y; > struct hid_location sc_loc_z; > struct hid_location sc_loc_w; > struct hid_location sc_loc_btn[MAX_BUTTONS]; > + > + /* For WACOM tablets */ > + struct hid_location sc_loc_pad_btn[MAX_BUTTONS]; > + struct hid_location sc_loc_stylus_btn[MAX_BUTTONS]; > > struct tsscale sc_tsscale; > int sc_rawmode; > Index: dev/usb/uhidev.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/uhidev.c,v > retrieving revision 1.108 > diff -u -p -r1.108 uhidev.c > --- dev/usb/uhidev.c 20 May 2022 05:03:45 -0000 1.108 > +++ dev/usb/uhidev.c 3 Jul 2023 09:04:50 -0000 > @@ -283,6 +283,36 @@ uhidev_attach(struct device *parent, str > free(uha.claimed, M_TEMP, nrepid); > uha.claimed = NULL; > > + /* Special case for Wacom tablets */ > + if (uha.uaa->vendor == USB_VENDOR_WACOM) { > + /* > + * Get all the needed collections. > + * For now only 3 seem to be of interest, > + * but more can eventually be added. > + */ > + int repid_collection_list[3] = { 0 }; > + repid_collection_list[0] = hid_get_id_of_collection(desc, size, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_STYLUS), > + HCOLL_PHYSICAL); > + repid_collection_list[1] = hid_get_id_of_collection(desc, size, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TABLET_FKEYS), > + HCOLL_PHYSICAL); > + repid_collection_list[2] = hid_get_id_of_collection(desc, size, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_BATTERY), > + HCOLL_PHYSICAL); > + for (size_t i = 0; i < 3; i++) > + if (repid_collection_list[i]) { > + uha.reportid = repid_collection_list[i]; > + dev = config_found_sm(self, &uha, NULL, NULL); > + if (dev == NULL) > + printf("Nothing found for repid: " > + "%d\n", uha.reportid); > + sc->sc_subdevs[uha.reportid] > + = (struct uhidev *)dev; > + } > + return; > + } > + > for (repid = 0; repid < nrepid; repid++) { > DPRINTF(("%s: try repid=%d\n", __func__, repid)); > if (hid_report_size(desc, size, hid_input, repid) == 0 && > Index: dev/usb/usbdevs > =================================================================== > RCS file: /cvs/src/sys/dev/usb/usbdevs,v > retrieving revision 1.757 > diff -u -p -r1.757 usbdevs > --- dev/usb/usbdevs 12 Jun 2023 11:26:24 -0000 1.757 > +++ dev/usb/usbdevs 3 Jul 2023 09:04:50 -0000 > @@ -4637,6 +4637,7 @@ product WACOM INTUOS_DRAW 0x033b Intuos > product WACOM ONE_S 0x037a One S (CTL-472) > product WACOM ONE_M 0x037b One M (CTL-672) > product WACOM INTUOS_PRO_S 0x0392 Intuos Pro S > +product WACOM INTUOS_S 0x0374 Intuos S (CTL-4100) > > /* WAGO Kontakttechnik products */ > product WAGO SERVICECABLE 0x07a6 Service Cable 750-923 > Index: dev/usb/usbdevs.h > =================================================================== > RCS file: /cvs/src/sys/dev/usb/usbdevs.h,v > retrieving revision 1.769 > diff -u -p -r1.769 usbdevs.h > --- dev/usb/usbdevs.h 12 Jun 2023 11:26:54 -0000 1.769 > +++ dev/usb/usbdevs.h 3 Jul 2023 09:04:50 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: usbdevs.h,v 1.769 2023/06/12 11:26:54 jsg Exp $ */ > +/* $OpenBSD$ */ > > /* > * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. > @@ -2117,6 +2117,8 @@ > #define USB_PRODUCT_GARMIN_DAKOTA20 0x23c0 /* Dakota 20 */ > #define USB_PRODUCT_GARMIN_GPSMAP62S 0x2459 /* GPSmap 62s */ > > +/* Gaomon */ > + > /* GCT Semiconductor products */ > #define USB_PRODUCT_GCTSEMICON_INSTALL 0x7f40 /* GDM720x MASS > storage mode */ > > @@ -4644,6 +4646,7 @@ > #define USB_PRODUCT_WACOM_ONE_S 0x037a /* One S (CTL-472) */ > #define USB_PRODUCT_WACOM_ONE_M 0x037b /* One M (CTL-672) */ > #define USB_PRODUCT_WACOM_INTUOS_PRO_S 0x0392 /* Intuos Pro S > */ > +#define USB_PRODUCT_WACOM_INTUOS_S 0x0374 /* Intuos S > (CTL-4100) */ > > /* WAGO Kontakttechnik products */ > #define USB_PRODUCT_WAGO_SERVICECABLE 0x07a6 /* Service > Cable 750-923 */ > Index: dev/usb/usbdevs_data.h > =================================================================== > RCS file: /cvs/src/sys/dev/usb/usbdevs_data.h,v > retrieving revision 1.763 > diff -u -p -r1.763 usbdevs_data.h > --- dev/usb/usbdevs_data.h 12 Jun 2023 11:26:54 -0000 1.763 > +++ dev/usb/usbdevs_data.h 3 Jul 2023 09:04:50 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: usbdevs_data.h,v 1.763 2023/06/12 11:26:54 jsg Exp $ */ > +/* $OpenBSD$ */ > > /* > * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. > @@ -11908,6 +11908,10 @@ const struct usb_known_product usb_known > { > USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS_PRO_S, > "Intuos Pro S", > + }, > + { > + USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS_S, > + "Intuos S (CTL-4100)", > }, > { > USB_VENDOR_WAGO, USB_PRODUCT_WAGO_SERVICECABLE, > Index: dev/usb/uwacom.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/uwacom.c,v > retrieving revision 1.7 > diff -u -p -r1.7 uwacom.c > --- dev/usb/uwacom.c 8 Oct 2022 06:53:06 -0000 1.7 > +++ dev/usb/uwacom.c 3 Jul 2023 09:04:50 -0000 > @@ -38,11 +38,32 @@ > #define UWACOM_USE_PRESSURE 0x0001 /* button 0 is flaky, use tip > pressure */ > #define UWACOM_BIG_ENDIAN 0x0002 /* XY reporting byte order */ > > + > +#ifdef UWACOM_DEBUG > +#define UWACOM_PACKET_PRINTF(data, len) do { \ > + printf("Ox"); \ > + for (int i = 0; i < (len); i++) \ > + printf("%02x ",*((data)+i)); \ > + printf("\n"); \ > +} while(0) > +#define UWACOM_BUTTON_EVENT(buttons) do { \ > + printf("Current button event: 0x%x\n",buttons); \ > +} while (0) > +#endif > + > +#define UWACOM_USE_PRESSURE 0x0001 /* button 0 is flaky, use tip pressure */ > +#define UWACOM_BIG_ENDIAN 0x0002 /* xy reporting byte order */ > + > struct uwacom_softc { > struct uhidev sc_hdev; > struct hidms sc_ms; > struct hid_location sc_loc_tip_press; > int sc_flags; > + int sc_x; > + int sc_y; > + int sc_z; > + int sc_w; > + int sc_moved; > }; > > struct cfdriver uwacom_cd = { > @@ -53,7 +74,8 @@ struct cfdriver uwacom_cd = { > const struct usb_devno uwacom_devs[] = { > { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS_DRAW }, > { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_ONE_S }, > - { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_ONE_M } > + { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_ONE_M }, > + { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS_S } > }; > > int uwacom_match(struct device *, void *, void *); > @@ -80,7 +102,10 @@ uwacom_match(struct device *parent, void > struct uhidev_attach_arg *uha = aux; > int size; > void *desc; > - > +#ifdef UWACOM_DEBUG > + printf("Wacom Vendor: 0x%x, Product: 0x%x\n",uha->uaa->vendor, > + uha->uaa->product); > +#endif > if (UHIDEV_CLAIM_MULTIPLE_REPORTID(uha)) > return (UMATCH_NONE); > > @@ -90,6 +115,9 @@ uwacom_match(struct device *parent, void > > uhidev_get_report_desc(uha->parent, &desc, &size); > > + if (hid_is_collection(desc, size, uha->reportid, > + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUG_POINTER))) > + return UMATCH_IFACECLASS; > if (!hid_locate(desc, size, HID_USAGE2(HUP_WACOM, HUG_POINTER), > uha->reportid, hid_input, NULL, NULL)) > return (UMATCH_NONE); > @@ -112,41 +140,27 @@ uwacom_attach(struct device *parent, str > sc->sc_hdev.sc_udev = uaa->device; > sc->sc_hdev.sc_report_id = uha->reportid; > > - usbd_set_idle(uha->parent->sc_udev, uha->parent->sc_ifaceno, 0, 0); > + usbd_status usbd_req_stat = usbd_set_idle(uha->parent->sc_udev, > + uha->parent->sc_ifaceno, 0, 0); > + if (USBD_NORMAL_COMPLETION != usbd_req_stat) > + printf("0x%x\n", usbd_req_stat); > > uhidev_get_report_desc(uha->parent, &desc, &size); > repid = uha->reportid; > - > sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); > +#ifdef UWACOM_DEBUG > + printf("Wacom packet max size: %d\n",sc->sc_hdev.sc_isize); > +#endif > sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); > sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); > - > - ms->sc_device = self; > - ms->sc_rawmode = 1; > - ms->sc_flags = HIDMS_ABSX | HIDMS_ABSY; > - ms->sc_num_buttons = 3; > - > - ms->sc_loc_x.pos = 8; > - ms->sc_loc_x.size = 16; > - ms->sc_loc_y.pos = 24; > - ms->sc_loc_y.size = 16; > - > - ms->sc_tsscale.minx = 0; > - ms->sc_tsscale.miny = 0; > - > - ms->sc_loc_btn[0].pos = 0; > - ms->sc_loc_btn[0].size = 1; > - ms->sc_loc_btn[1].pos = 1; > - ms->sc_loc_btn[1].size = 1; > - ms->sc_loc_btn[2].pos = 2; > - ms->sc_loc_btn[2].size = 1; > - > - if (uha->uaa->product == USB_PRODUCT_WACOM_ONE_S) { > - static uByte reportbuf[2] = { 0x02, 0x02 }; > - uhidev_set_report(uha->parent, UHID_FEATURE_REPORT, 2, > - &reportbuf, 2); > - ms->sc_tsscale.maxx = 15200; > - ms->sc_tsscale.maxy = 9500; > + /* If a more modern tablet */ > + if (uha->uaa->product == USB_PRODUCT_WACOM_ONE_S > + || uha->uaa->product == USB_PRODUCT_WACOM_INTUOS_S) { > + static uByte report_buf[2] = { 0x02, 0x02 }; > + uhidev_set_report(uha->parent, UHID_FEATURE_REPORT, > + sc->sc_hdev.sc_report_id, &report_buf, sizeof(report_buf)); > + hidms_setup((struct device *)sc, ms, HIDMS_WACOM_SETUP, > + repid, desc, size); > } > > if (uha->uaa->product == USB_PRODUCT_WACOM_INTUOS_DRAW) { > @@ -174,40 +188,64 @@ uwacom_intr(struct uhidev *addr, void *b > { > struct uwacom_softc *sc = (struct uwacom_softc *)addr; > struct hidms *ms = &sc->sc_ms; > - u_int32_t buttons = 0; > + u_int32_t pad_buttons = 0; > + u_int32_t stylus_buttons = 0; > uint8_t *data = (uint8_t *)buf; > - int i, x, y, pressure; > + int x, y, pressure, distance; > > +#ifdef UWACOM_DEBUG > + UWACOM_PACKET_PRINTF(data, len); > +#endif > if (ms->sc_enabled == 0) > return; > > - /* ignore proximity, it will cause invalid button 2 events */ > - if ((data[0] & 0xf0) == 0xc0) > - return; > - > x = hid_get_data(data, len, &ms->sc_loc_x); > y = hid_get_data(data, len, &ms->sc_loc_y); > + pressure = hid_get_data(data, len, &ms->sc_loc_z); > + distance = hid_get_data(data, len, &ms->sc_loc_w); > + > + if (!sc->sc_moved) { > + sc->sc_x = x; > + sc->sc_y = y; > + sc->sc_z = pressure; > + sc->sc_w = distance; > + sc->sc_moved = 1; > + } > + > + int dx = sc->sc_x - x; > + int dy = sc->sc_y - y; > + int dz = sc->sc_z/32 - pressure/32; /* Clamp sensitivity to +/-127 */ > + int dw = sc->sc_w - distance; > + > + sc->sc_x = x; > + sc->sc_y = y; > + sc->sc_z = pressure; > + sc->sc_w = distance; > > if (sc->sc_flags & UWACOM_BIG_ENDIAN) { > x = be16toh(x); > y = be16toh(y); > } > - > - for (i = 0; i < ms->sc_num_buttons; i++) > - if (hid_get_data(data, len, &ms->sc_loc_btn[i])) > - buttons |= (1 << i); > - > - if (sc->sc_flags & UWACOM_USE_PRESSURE) { > - pressure = hid_get_data(data, len, &sc->sc_loc_tip_press); > - if (pressure > 10) > - buttons |= 1; > - else > - buttons &= ~1; > - } > - > - if (x != 0 || y != 0 || buttons != ms->sc_buttons) { > - wsmouse_position(ms->sc_wsmousedev, x, y); > - wsmouse_buttons(ms->sc_wsmousedev, buttons); > + > + for (int i = 0; i < ms->sc_num_stylus_buttons; i++) > + if (hid_get_data(data, len, &ms->sc_loc_stylus_btn[i])) > + stylus_buttons |= (1 << i); > + > + for (int i = 0; i < ms->sc_num_pad_buttons; i++) > + if (hid_get_data(data, len, &ms->sc_loc_pad_btn[i])) > + pad_buttons |= (1 << i); > + > +#ifdef UWACOM_DEBUG > + UWACOM_BUTTON_EVENT(pad_buttons); > + UWACOM_BUTTON_EVENT(stylus_buttons); > +#endif > + > + if (x != 0 || y != 0 || pressure != 0 || distance != 0 > + || pad_buttons != ms->sc_buttons > + || stylus_buttons != ms->sc_buttons) { > + wsmouse_buttons(ms->sc_wsmousedev, > + (pad_buttons | stylus_buttons)); > + wsmouse_motion(ms->sc_wsmousedev, -dx, dy, dz, dw); > wsmouse_input_sync(ms->sc_wsmousedev); > } > } > >