On Sun, Jun 18, 2023 at 09:36:25AM +0000, Vladimir Meshcheriakov wrote:
> Good day,
> 
> I am currently trying to work on an implementation
> of a driver for the WACOM tablet on openBSD
> I am therefore submitting this diff so that it could potentially be evaluated.
> Please if you have a moment, could you have a look at this diff?
> I have tested it with my Wacom tablet
> and it seems to work correctly,
> the coding style is normally respected,
> but I apologize in advance if my keen eyes have missed out something.

Hi there! i tested the diff with a wacom intuos s
(CS-4100). It attaches sucessfully 

uhidev1 at uhub1 port 1 configuration 1 interface 0 "Wacom Co.,Ltd. Intuos S" 
rev 2.00/1.11 addr 5
uhidev1: iclass 3/0, 228 report ids
uwacom0 at uhidev1: 9 buttons, Z and W dir, tip, barrel
wsmouse3 at uwacom0 mux 0
uwacom1 at uhidev1: 9 buttons, Z and W dir, tip, barrel
wsmouse4 at uwacom1 mux 0
uwacom2 at uhidev1: 9 buttons, Z and W dir, tip, barrel
wsmouse5 at uwacom2 mux 0

I don't have any of the previous wacom products to see
if they still work. One thing i am trying to do is 
to somehow scale the tablet so that it is actually
usable. I looked a bit into running xtsscale 
but it outputs

xtsscale -v -d /dev/wsmouse1
XRandR extension version 1.6 present
Unable to find the "WS Pointer Axis Calibration" device property.
There are probably no calibrable devices on this system.

Finally in the patch it seems there is another rogue
usbdevs entry (a GAOMON M10k device). 

Thanks for taking the time to write this.
 
> 
> diff --git a/sys/dev/hid/hid.c b/sys/dev/hid/hid.c
> index c758764f17a..20c0c501e91 100644
> --- a/sys/dev/hid/hid.c
> +++ b/sys/dev/hid/hid.c
> @@ -657,3 +657,49 @@ hid_is_collection(const void *desc, int size, uint8_t 
> id, int32_t usage)
>       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;
> +}
> diff --git a/sys/dev/hid/hid.h b/sys/dev/hid/hid.h
> index 7400e920bc2..78bc4c403c5 100644
> --- a/sys/dev/hid/hid.h
> +++ b/sys/dev/hid/hid.h
> @@ -93,6 +93,8 @@ int hid_locate(const void *, int, int32_t, uint8_t, enum 
> hid_kind,
>  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 +355,7 @@ int       hid_is_collection(const void *, int, uint8_t, 
> int32_t);
>  #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 +390,12 @@ int      hid_is_collection(const void *, int, uint8_t, 
> int32_t);
>  #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
> diff --git a/sys/dev/hid/hidms.c b/sys/dev/hid/hidms.c
> index 622d5d9bc33..ec5c8d34d1b 100644
> --- a/sys/dev/hid/hidms.c
> +++ b/sys/dev/hid/hidms.c
> @@ -37,6 +37,7 @@
>  
>  #include <sys/param.h>
>  #include <sys/systm.h>
> +#include <sys/malloc.h>
>  #include <sys/kernel.h>
>  #include <sys/device.h>
>  #include <sys/ioctl.h>
> @@ -61,6 +62,219 @@ 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, its not really needed
> +              * Ignore the usage 0x10AC which is the debug collection, and
> +              * ignore firmware collection and other collections that we
> +              * will omit 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)
> @@ -75,6 +289,10 @@ hidms_setup(struct device *self, struct hidms *ms, 
> uint32_t quirks,
>  
>       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))
>               ms->sc_loc_x.size = 0;
> diff --git a/sys/dev/hid/hidmsvar.h b/sys/dev/hid/hidmsvar.h
> index a430b90ddae..55105ec11fa 100644
> --- a/sys/dev/hid/hidmsvar.h
> +++ b/sys/dev/hid/hidmsvar.h
> @@ -36,6 +36,8 @@
>  struct tsscale {
>       int     minx, maxx;
>       int     miny, maxy;
> +     int minz, maxz;
> +     int minw, maxw;
>       int     swapxy;
>       int     resx, resy;
>  };
> @@ -56,13 +58,27 @@ 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;
> @@ -70,6 +86,10 @@ struct hidms {
>       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;
>  };
> diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
> index 26b5b04088d..3c045a26051 100644
> --- a/sys/dev/usb/uhidev.c
> +++ b/sys/dev/usb/uhidev.c
> @@ -283,6 +283,43 @@ uhidev_attach(struct device *parent, struct device 
> *self, void *aux)
>       free(uha.claimed, M_TEMP, nrepid);
>       uha.claimed = NULL;
>  
> +     /* Secial 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 &&
> diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
> index edb86ebbf5e..8c7cb13a925 100644
> --- a/sys/dev/usb/usbdevs
> +++ b/sys/dev/usb/usbdevs
> @@ -637,6 +637,7 @@ vendor ARDUINO            0x2341  Arduino SA
>  vendor TPLINK                0x2357  TP-Link
>  vendor WMR           0x2405  West Mountain Radio
>  vendor TRIPPLITE     0x2478  Tripp-Lite
> +vendor GAOMON                0x256c  Gaomon
>  vendor HAILUCK               0x258a  HAILUCK Co., Ltd
>  vendor ARUBA         0x2626  Aruba
>  vendor XIAOMI                0x2717  Xiaomi
> @@ -2109,6 +2110,9 @@ product GARMIN IQUE3600         0x0004  Ique 3600
>  product GARMIN DAKOTA20              0x23c0  Dakota 20
>  product GARMIN GPSMAP62S     0x2459  GPSmap 62s
>  
> +/* Gaomon */
> +product GAOMON M10K          0x006e  M10K
> +
>  /* GCT Semiconductor products */
>  product GCTSEMICON INSTALL   0x7f40  GDM720x MASS storage mode       
>  
> @@ -4633,6 +4637,7 @@ product WACOM INTUOS_DRAW       0x033b  Intuos Draw 
> (CTL-490)
>  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
> diff --git a/sys/dev/usb/usbdevs.h b/sys/dev/usb/usbdevs.h
> index 022a71013f3..75e938e5614 100644
> --- a/sys/dev/usb/usbdevs.h
> +++ b/sys/dev/usb/usbdevs.h
> @@ -644,6 +644,7 @@
>  #define      USB_VENDOR_TPLINK       0x2357          /* TP-Link */
>  #define      USB_VENDOR_WMR  0x2405          /* West Mountain Radio */
>  #define      USB_VENDOR_TRIPPLITE    0x2478          /* Tripp-Lite */
> +#define      USB_VENDOR_GAOMON       0x256c          /* Gaomon */
>  #define      USB_VENDOR_HAILUCK      0x258a          /* HAILUCK Co., Ltd */
>  #define      USB_VENDOR_ARUBA        0x2626          /* Aruba */
>  #define      USB_VENDOR_XIAOMI       0x2717          /* Xiaomi */
> @@ -2116,6 +2117,9 @@
>  #define      USB_PRODUCT_GARMIN_DAKOTA20     0x23c0          /* Dakota 20 */
>  #define      USB_PRODUCT_GARMIN_GPSMAP62S    0x2459          /* GPSmap 62s */
>  
> +/* Gaomon */
> +#define      USB_PRODUCT_GAOMON_M10K 0x006e          /* M10K */
> +
>  /* GCT Semiconductor products */
>  #define      USB_PRODUCT_GCTSEMICON_INSTALL  0x7f40          /* GDM720x MASS 
> storage mode */
>  
> @@ -4640,6 +4644,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 */
> diff --git a/sys/dev/usb/usbdevs_data.h b/sys/dev/usb/usbdevs_data.h
> index 92c80f0cede..20ba8354fa7 100644
> --- a/sys/dev/usb/usbdevs_data.h
> +++ b/sys/dev/usb/usbdevs_data.h
> @@ -4337,6 +4337,10 @@ const struct usb_known_product usb_known_products[] = {
>           USB_VENDOR_GARMIN, USB_PRODUCT_GARMIN_GPSMAP62S,
>           "GPSmap 62s",
>       },
> +     {
> +         USB_VENDOR_GAOMON, USB_PRODUCT_GAOMON_M10K,
> +         "M10K",
> +     },
>       {
>           USB_VENDOR_GCTSEMICON, USB_PRODUCT_GCTSEMICON_INSTALL,
>           "GDM720x MASS storage mode",
> @@ -11905,6 +11909,10 @@ const struct usb_known_product usb_known_products[] 
> = {
>           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,
>           "Service Cable 750-923",
> @@ -14649,6 +14657,10 @@ const struct usb_known_vendor usb_known_vendors[] = {
>           USB_VENDOR_TRIPPLITE,
>           "Tripp-Lite",
>       },
> +     {
> +         USB_VENDOR_GAOMON,
> +         "Gaomon",
> +     },
>       {
>           USB_VENDOR_HAILUCK,
>           "HAILUCK Co., Ltd",
> diff --git a/sys/dev/usb/uwacom.c b/sys/dev/usb/uwacom.c
> index f9af276a641..fde5b5cecd7 100644
> --- a/sys/dev/usb/uwacom.c
> +++ b/sys/dev/usb/uwacom.c
> @@ -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,9 @@ uwacom_match(struct device *parent, void *match, void *aux)
>       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 +114,9 @@ uwacom_match(struct device *parent, void *match, void *aux)
>  
>       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 +139,26 @@ uwacom_attach(struct device *parent, struct device 
> *self, void *aux)
>       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;
> +     sc->sc_hdev.sc_fsize
> +             = hid_report_size(desc, size, hid_feature, repid);
> +     /* 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 +186,64 @@ uwacom_intr(struct uhidev *addr, void *buf, u_int len)
>  {
>       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 the sensetivity to be in 
> the range of -127 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