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