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

Reply via email to