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)

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);
        }
 }


Reply via email to