Third time's (hopefully) the charm. How about that diff? Too much things have been removed in uwacom.
Index: dev/hid/hid.c =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -0000 @@ -657,3 +657,52 @@ 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__); + hid_end_parse(hd); + return hi.report_ID; + } + } + DPRINTF("%s: not found\n", __func__); + hid_end_parse(hd); + return 0; +} Index: dev/hid/hid.h =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -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: /OpenBSD/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 12 Aug 2023 14:24:53 -0000 @@ -61,6 +61,188 @@ int hidmsdebug = 0; #define MOUSE_FLAGS_MASK (HIO_CONST | HIO_RELATIVE) #define NOTMOUSE(f) (((f) & MOUSE_FLAGS_MASK) != HIO_RELATIVE) +void +hidms_stylus_hid_parse(struct hidms *ms, struct hid_data *d, + struct hid_location *loc_stylus_btn) +{ + struct hid_item h; + + while (hid_get_item(d, &h)) { + if (h.kind == hid_endcollection) + break; + if (h.kind != hid_input || (h.flags & HIO_CONST) != 0) + continue; + /* 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 HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TIP_SWITCH): + DPRINTF("Stylus usage tip set\n"); + if (ms->sc_num_stylus_buttons >= MAX_BUTTONS) + break; + loc_stylus_btn[ms->sc_num_stylus_buttons++] = h.loc; + ms->sc_flags |= HIDMS_TIP; + break; + case HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_BARREL_SWITCH): + DPRINTF("Stylus usage barrel set\n"); + if (ms->sc_num_stylus_buttons >= MAX_BUTTONS) + break; + loc_stylus_btn[ms->sc_num_stylus_buttons++] = h.loc; + ms->sc_flags |= HIDMS_BARREL; + break; + case HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, + HUD_SECONDARY_BARREL_SWITCH): + DPRINTF("Stylus usage secondary barrel set\n"); + if (ms->sc_num_stylus_buttons >= MAX_BUTTONS) + break; + loc_stylus_btn[ms->sc_num_stylus_buttons++] = h.loc; + ms->sc_flags |= HIDMS_SEC_BARREL; + break; + case HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_IN_RANGE): + DPRINTF("Stylus usage in range set\n"); + if (ms->sc_num_stylus_buttons >= MAX_BUTTONS) + break; + loc_stylus_btn[ms->sc_num_stylus_buttons++] = h.loc; + break; + case HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_QUALITY): + DPRINTF("Stylus usage quality set\n"); + if (ms->sc_num_stylus_buttons >= MAX_BUTTONS) + break; + loc_stylus_btn[ms->sc_num_stylus_buttons++] = h.loc; + break; + /* Axes */ + case HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_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 HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_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 HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TIP_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 HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_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\n", + h.usage); +#endif + break; + } + } +} + +void +hidms_pad_buttons_hid_parse(struct hidms *ms, struct hid_data *d, + struct hid_location *loc_pad_btn) +{ + struct hid_item h; + + while (hid_get_item(d, &h)) { + if (h.kind == hid_endcollection) + break; + if (h.kind == hid_input && (h.flags & HIO_CONST) != 0 && + h.usage == HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, + HUD_WACOM_PAD_BUTTONS00 | ms->sc_num_pad_buttons)) { + if (ms->sc_num_pad_buttons >= MAX_BUTTONS) + break; + loc_pad_btn[ms->sc_num_pad_buttons++] = h.loc; + } + } +} + +int +hidms_wacom_setup(struct device *self, struct hidms *ms, void *desc, int dlen) +{ + struct hid_data *hd; + int i; + struct hid_location loc_pad_btn[MAX_BUTTONS]; + struct hid_location loc_stylus_btn[MAX_BUTTONS]; + + ms->sc_flags = 0; + + /* 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 ((hd = hid_get_collection_data(desc, dlen, + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_DIGITIZER), + HCOLL_APPLICATION))) { + DPRINTF("found the global collection\n"); + hid_end_parse(hd); + if ((hd = hid_get_collection_data(desc, dlen, + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_STYLUS), + HCOLL_PHYSICAL))) { + DPRINTF("found stylus collection\n"); + hidms_stylus_hid_parse(ms, hd, loc_stylus_btn); + hid_end_parse(hd); + } + if ((hd = hid_get_collection_data(desc, dlen, + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TABLET_FKEYS), + HCOLL_PHYSICAL))) { + DPRINTF("found tablet keys collection\n"); + hidms_pad_buttons_hid_parse(ms, hd, loc_pad_btn); + hid_end_parse(hd); + } +#ifdef notyet + if ((hd = 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(hd); + } +#endif + /* + * 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], &loc_stylus_btn[i], + sizeof(struct hid_location)); + if (ms->sc_num_pad_buttons + ms->sc_num_stylus_buttons >= MAX_BUTTONS) + ms->sc_num_pad_buttons = + MAX_BUTTONS - ms->sc_num_stylus_buttons; + for (; i < ms->sc_num_pad_buttons + ms->sc_num_stylus_buttons; i++) + memcpy(&ms->sc_loc_btn[i], &loc_pad_btn[i], + sizeof(struct hid_location)); + ms->sc_num_buttons = i; + DPRINTF("Button information\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,11 +257,15 @@ hidms_setup(struct device *self, struct ms->sc_flags = quirks; + /* We are setting up a Wacom tablet, not a regular mouse */ + if (quirks & HIDMS_WACOM_SETUP) + return hidms_wacom_setup(self, ms, 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; - switch(flags & MOUSE_FLAGS_MASK) { + switch (flags & MOUSE_FLAGS_MASK) { case 0: ms->sc_flags |= HIDMS_ABSX; break; Index: dev/hid/hidmsvar.h =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -0000 @@ -36,11 +36,16 @@ struct tsscale { int minx, maxx; int miny, maxy; + int minz, maxz; + int minw, maxw; int swapxy; int resx, resy; }; struct hidms { + struct device *sc_device; + struct device *sc_wsmousedev; + int sc_enabled; int sc_flags; /* device configuration */ #define HIDMS_SPUR_BUT_UP 0x0001 /* spurious button up events */ @@ -51,17 +56,32 @@ struct hidms { #define HIDMS_LEADINGBYTE 0x0020 /* Unknown leading byte */ #define HIDMS_ABSX 0x0040 /* X-axis is absolute */ #define HIDMS_ABSY 0x0080 /* Y-axis is absolute */ -#define HIDMS_TIP 0x0100 /* Tip switch on a digitiser pen */ +#define HIDMS_TIP 0x0100 /* Tip switch on a digitiser pen */ #define HIDMS_BARREL 0x0200 /* Barrel switch on a digitiser pen */ -#define HIDMS_ERASER 0x0400 /* Eraser switch on a digitiser pen */ +#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 0x4000 /* Requires Wacom-style setup */ int sc_num_buttons; u_int32_t sc_buttons; /* mouse button status */ - struct device *sc_device; - struct device *sc_wsmousedev; + /* Wacom-specific fields */ + int sc_num_pad_buttons; + /* left to right, or top to bottom */ + u_int32_t sc_pad_buttons; + int sc_num_stylus_buttons; + /* tip, barrel switch, secondary barrel switch, and any other */ + u_int32_t sc_stylus_buttons; + + 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; Index: dev/usb/uhidev.c =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -0000 @@ -139,6 +139,22 @@ uhidev_match(struct device *parent, void return (UMATCH_IFACECLASS_GENERIC); } +int +uhidev_attach_repid(struct uhidev_softc *sc, struct uhidev_attach_arg *uha, + int repid) +{ + struct device *dev; + + /* Could already be assigned by uhidev_set_report_dev(). */ + if (sc->sc_subdevs[repid] != NULL) + return 0; + + uha->reportid = repid; + dev = config_found_sm(&sc->sc_dev, uha, uhidevprint, NULL); + sc->sc_subdevs[repid] = (struct uhidev *)dev; + return 1; +} + void uhidev_attach(struct device *parent, struct device *self, void *aux) { @@ -283,6 +299,33 @@ 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) { + int ndigitizers = 0; + /* + * Get all the needed collections (only 3 seem to be of + * interest currently). + */ + repid = hid_get_id_of_collection(desc, size, + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_STYLUS), + HCOLL_PHYSICAL); + if (repid != 0) + ndigitizers += uhidev_attach_repid(sc, &uha, repid); + repid = hid_get_id_of_collection(desc, size, + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_TABLET_FKEYS), + HCOLL_PHYSICAL); + if (repid != 0) + ndigitizers += uhidev_attach_repid(sc, &uha, repid); + repid = hid_get_id_of_collection(desc, size, + HID_USAGE2(HUP_WACOM | HUP_DIGITIZERS, HUD_WACOM_BATTERY), + HCOLL_PHYSICAL); + if (repid != 0) + ndigitizers += uhidev_attach_repid(sc, &uha, repid); + + if (ndigitizers != 0) + 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 && @@ -290,13 +333,7 @@ uhidev_attach(struct device *parent, str hid_report_size(desc, size, hid_feature, repid) == 0) continue; - /* Could already be assigned by uhidev_set_report_dev(). */ - if (sc->sc_subdevs[repid] != NULL) - continue; - - uha.reportid = repid; - dev = config_found_sm(self, &uha, uhidevprint, NULL); - sc->sc_subdevs[repid] = (struct uhidev *)dev; + uhidev_attach_repid(sc, &uha, repid); } } Index: dev/usb/usbdevs =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -0000 @@ -4634,6 +4634,7 @@ product WACOM GRAPHIRE3_4X5 0x0013 Graph product WACOM GRAPHIRE4_4X5 0x0015 Graphire4 Classic A6 product WACOM INTUOSA5 0x0021 Intuos A5 product WACOM INTUOS_DRAW 0x033b Intuos Draw (CTL-490) +product WACOM INTUOS_S 0x0374 Intuos S (CTL-4100) 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 Index: dev/usb/usbdevs.h =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -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. @@ -4641,6 +4641,7 @@ #define USB_PRODUCT_WACOM_GRAPHIRE4_4X5 0x0015 /* Graphire4 Classic A6 */ #define USB_PRODUCT_WACOM_INTUOSA5 0x0021 /* Intuos A5 */ #define USB_PRODUCT_WACOM_INTUOS_DRAW 0x033b /* Intuos Draw (CTL-490) */ +#define USB_PRODUCT_WACOM_INTUOS_S 0x0374 /* Intuos S (CTL-4100) */ #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 */ Index: dev/usb/usbdevs_data.h =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -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. @@ -11896,6 +11896,10 @@ const struct usb_known_product usb_known { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS_DRAW, "Intuos Draw (CTL-490)", + }, + { + USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOS_S, + "Intuos S (CTL-4100)", }, { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_ONE_S, Index: dev/usb/uwacom.c =================================================================== RCS file: /OpenBSD/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 12 Aug 2023 14:24:53 -0000 @@ -43,17 +43,19 @@ struct uwacom_softc { struct hidms sc_ms; struct hid_location sc_loc_tip_press; int sc_flags; + int sc_x, sc_y, sc_z, sc_w; + int sc_moved; }; struct cfdriver uwacom_cd = { NULL, "uwacom", DV_DULL }; - 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 *); @@ -90,6 +92,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); @@ -104,6 +109,7 @@ uwacom_attach(struct device *parent, str struct hidms *ms = &sc->sc_ms; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; struct usb_attach_arg *uaa = uha->uaa; + static uByte wacom_report_buf[2] = { 0x02, 0x02 }; int size, repid; void *desc; @@ -141,20 +147,22 @@ uwacom_attach(struct device *parent, str 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 (uha->uaa->product == USB_PRODUCT_WACOM_INTUOS_DRAW) { + switch (uha->uaa->product) { + case USB_PRODUCT_WACOM_ONE_S: + case USB_PRODUCT_WACOM_INTUOS_S: + uhidev_set_report(uha->parent, UHID_FEATURE_REPORT, + sc->sc_hdev.sc_report_id, &wacom_report_buf, + sizeof(wacom_report_buf)); + hidms_setup((struct device *)sc, ms, HIDMS_WACOM_SETUP, + repid, desc, size); + break; + case USB_PRODUCT_WACOM_INTUOS_DRAW: sc->sc_flags = UWACOM_USE_PRESSURE | UWACOM_BIG_ENDIAN; sc->sc_loc_tip_press.pos = 43; sc->sc_loc_tip_press.size = 8; ms->sc_tsscale.maxx = 7600; ms->sc_tsscale.maxy = 4750; + break; } hidms_attach(ms, &uwacom_accessops); @@ -174,40 +182,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 i, j, x, y, dx, dy, dz, dw, pressure, distance; 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; + } + + dx = sc->sc_x - x; + dy = sc->sc_y - y; + /* Clamp sensitivity to +/-127 */ + dz = sc->sc_z / 32 - pressure / 32; + 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++) + + for (i = 0; i < ms->sc_num_stylus_buttons; i++) if (hid_get_data(data, len, &ms->sc_loc_btn[i])) - buttons |= (1 << i); - + stylus_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; + stylus_buttons |= 1; else - buttons &= ~1; + stylus_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 (j = 0; i < ms->sc_num_buttons; i++, j++) + if (hid_get_data(data, len, &ms->sc_loc_btn[i])) + pad_buttons |= 1 << j; + + 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); } }