I recently acquired a new Wacom drawing tablet: an Intuos Draw, which
seems to be called an Intuos S 2 internally. I couldn't get this tablet
to work in OpenBSD. One of the HID descriptors describes a mouse, so
ums(4) attaches to it, but no data is ever registered. After digging
around in the Linux driver, it appears that the actual data is reported
in a different descriptor, one that is (possibly on purpose) incorrect.

After writing a correct device descriptor I had to work around two other
problems:

- X & Y data is reported in big endian format.
- Mouse button 1 data is flakey, the linux driver uses pressure to work
  around this.

To get the tablet to function correctly, I chose to implement quirks for
this in hidms(4). Attached patch makes the tablet function with mouse
movement and all three stylus events (tip touch and 2 buttons) without
any needed configuration. This is enough functionality for for me, I
just use it as a mouse replacement to avoid getting RSI.

Example dmesg output on attachment:

uhidev0 at uhub3 port 2 configuration 1 interface 0 "Wacom Co.,Ltd.
Intuos PS" rev 2.00/1.00 addr 3
uhidev0: iclass 3/0, 192 report ids
ums0 at uhidev0 reportid 16: 3 buttons
wsmouse1 at ums0 mux 0
uhid0 at uhidev0 reportid 192: input=4, output=0, feature=0
uhidev1 at uhub3 port 2 configuration 1 interface 1 "Wacom Co.,Ltd.
Intuos PS" rev 2.00/1.00 addr 3
uhidev1: iclass 3/0, 3 report ids
uhid1 at uhidev1 reportid 2: input=63, output=0, feature=0
uhid2 at uhidev1 reportid 3: input=63, output=0, feature=0
uhidev2 at uhub3 port 2 configuration 1 interface 2 "Wacom Co.,Ltd.
Intuos PS" rev 2.00/1.00 addr 3
uhidev2: iclass 3/1, 1 report id
ums1 at uhidev2 reportid 1: 5 buttons
wsmouse2 at ums1 mux 0

The first tattached umse is the functioning one that is added by this
patch.

Is the attached patch acceptable? Or would it be better to write a
seperate driver, such as uwacom, that does the same as ums, except that
it doesn't call hidms_input, but implements that itself?

Frank
Index: hid/hidms.c
===================================================================
RCS file: /cvs/src/sys/dev/hid/hidms.c,v
retrieving revision 1.3
diff -u -p -r1.3 hidms.c
--- hid/hidms.c 22 May 2016 22:06:11 -0000      1.3
+++ hid/hidms.c 2 Aug 2016 19:15:09 -0000
@@ -109,6 +109,9 @@ hidms_setup(struct device *self, struct 
                return ENXIO;
        }
 
+       hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_PRESSURE),
+           id, hid_input, &ms->sc_loc_tip_press, &flags);
+
        /*
         * Try to guess the Z activator: check WHEEL, TWHEEL, and Z,
         * in that order.
@@ -368,6 +371,11 @@ hidms_input(struct hidms *ms, uint8_t *d
                dz = -dz;
        if (ms->sc_flags & HIDMS_REVW)
                dw = -dw;
+       if (ms->sc_flags & HIDMS_BE16_X)
+               dx = be16toh(dx);
+       if (ms->sc_flags & HIDMS_BE16_Y)
+               dy = be16toh(dy);
+
 
        if (ms->sc_tsscale.swapxy && !ms->sc_rawmode) {
                int tmp = dx;
@@ -388,6 +396,13 @@ hidms_input(struct hidms *ms, uint8_t *d
        for (i = 0; i < ms->sc_num_buttons; i++)
                if (hid_get_data(data, len, &ms->sc_loc_btn[i]))
                        buttons |= (1 << HIDMS_BUT(i));
+
+       if (ms->sc_flags & HIDMS_USE_TIP_PRESS) {
+               if (hid_get_data(data, len, &ms->sc_loc_tip_press) > 10)
+                       buttons |= (1 << HIDMS_BUT(0));
+               else
+                       buttons &= ~(1 << HIDMS_BUT(0));
+       }
 
        if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
            buttons != ms->sc_buttons) {
Index: hid/hidmsvar.h
===================================================================
RCS file: /cvs/src/sys/dev/hid/hidmsvar.h,v
retrieving revision 1.1
diff -u -p -r1.1 hidmsvar.h
--- hid/hidmsvar.h      8 Jan 2016 15:54:13 -0000       1.1
+++ hid/hidmsvar.h      2 Aug 2016 19:15:09 -0000
@@ -43,18 +43,21 @@ struct tsscale {
 struct hidms {
        int             sc_enabled;
        int             sc_flags;       /* device configuration */
-#define HIDMS_SPUR_BUT_UP      0x001   /* spurious button up events */
-#define HIDMS_Z                        0x002   /* Z direction available */
-#define HIDMS_REVZ             0x004   /* Z-axis is reversed */
-#define HIDMS_W                        0x008   /* W direction available */
-#define HIDMS_REVW             0x010   /* W-axis is reversed */
-#define HIDMS_LEADINGBYTE      0x020   /* Unknown leading byte */
-#define HIDMS_ABSX             0x040   /* X-axis is absolute */
-#define HIDMS_ABSY             0x080   /* Y-axis is absolute */
-#define HIDMS_TIP              0x100   /* Tip switch on a digitiser pen */
-#define HIDMS_BARREL           0x200   /* Barrel switch on a digitiser pen */
-#define HIDMS_ERASER           0x400   /* Eraser switch on a digitiser pen */
-#define HIDMS_MS_BAD_CLASS     0x800   /* Mouse doesn't identify properly */
+#define HIDMS_SPUR_BUT_UP      0x0001  /* spurious button up events */
+#define HIDMS_Z                        0x0002  /* Z direction available */
+#define HIDMS_REVZ             0x0004  /* Z-axis is reversed */
+#define HIDMS_W                        0x0008  /* W direction available */
+#define HIDMS_REVW             0x0010  /* W-axis is reversed */
+#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_BARREL           0x0200  /* Barrel 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_BE16_X           0x1000  /* X-axis in 16 bit big endian */
+#define HIDMS_BE16_Y           0x2000  /* Y-axis in 16 bit big endian */
+#define HIDMS_USE_TIP_PRESS    0x4000  /* Use tip pressure for button 0 */
 
        int             sc_num_buttons;
        u_int32_t       sc_buttons;     /* mouse button status */
@@ -68,6 +71,7 @@ struct hidms {
        struct hid_location sc_loc_z;
        struct hid_location sc_loc_w;
        struct hid_location sc_loc_btn[MAX_BUTTONS];
+       struct hid_location sc_loc_tip_press;
 
        struct tsscale  sc_tsscale;
        int             sc_rawmode;
Index: usb/uhid_rdesc.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhid_rdesc.h,v
retrieving revision 1.1
diff -u -p -r1.1 uhid_rdesc.h
--- usb/uhid_rdesc.h    25 Oct 2013 03:09:59 -0000      1.1
+++ usb/uhid_rdesc.h    2 Aug 2016 19:15:09 -0000
@@ -273,3 +273,55 @@ static const uByte uhid_xb360gp_report_d
     0x81, 0x01,                /*  INPUT (Constant)                    */
     0xc0,              /* END COLLECTION                       */
 };
+
+static uByte uhid_intuos_s2_report_descr[] = {
+    0x05, 0x01,                /* USAGE_PAGE (Generic Desktop)         */
+    0x09, 0x02,                /* USAGE (Mouse)                        */
+    0xa1, 0x01,                /* COLLECTION (Application)             */
+    0x85, 0x10,                /*   REPORT_ID (16)                     */
+    0x09, 0x01,                /*   USAGE (Pointer)                    */
+    0xa1, 0x00,                /*   COLLECTION (Physical)              */
+    0x05, 0x09,                /*     USAGE_PAGE (Button)              */
+    0x15, 0x00,                /*     LOGICAL_MINIMUM (0)              */
+    0x25, 0x01,                /*     LOGICAL_MAXIMUM (1)              */
+    0x09, 0x01,                /*     USAGE (Button 1)                 */
+    0x09, 0x03,                /*     USAGE (Button 3)                 */
+    0x09, 0x02,                /*     USAGE (Button 2)                 */
+    0x95, 0x03,                /*     REPORT_COUNT (3)                 */
+    0x75, 0x01,                /*     REPORT_SIZE (1)                  */
+    0x81, 0x02,                /*     INPUT (Data,Var,Abs)             */
+    0x95, 0x01,                /*     REPORT_COUNT (1)                 */
+    0x75, 0x05,                /*     REPORT_SIZE (5)                  */
+    0x81, 0x01,                /*     INPUT (Cnst,Ary,Abs)             */
+    0x05, 0x01,                /*     USAGE_PAGE (Generic Desktop)     */
+    0x09, 0x30,                /*     USAGE (X)                        */
+    0x26, 0xb0, 0x1d,  /*     LOGICAL_MAXIMUM (7600)           */
+    0x75, 0x10,                /*     REPORT_SIZE (16)                 */
+    0x95, 0x01,                /*     REPORT_COUNT (1)                 */
+    0x81, 0x02,                /*     INPUT (Data,Var,Abs)             */
+    0x09, 0x31,                /*     USAGE (Y)                        */
+    0x26, 0x8e, 0x12,  /*     LOGICAL_MAXIMUM (4750)           */
+    0x75, 0x10,                /*     REPORT_SIZE (16)                 */
+    0x95, 0x01,                /*     REPORT_COUNT (1)                 */
+    0x81, 0x02,                /*     INPUT (Data,Var,Abs)             */
+    0x75, 0x01,                /*     REPORT SIZE (1)                  */
+    0x95, 0x03,                /*     REPORT COUNT (3)                 */
+    0x81, 0x01,                /*     INPUT (Cnst,Ary,Abs)             */
+    0x05, 0x0d,                /*     USAGE_PAGE (Digitizers)          */
+    0x09, 0x30,                /*     USAGE (Tip Pressure)             */
+    0x26, 0xff, 0x00,  /*     LOGICAL_MAXIMUM (255)            */
+    0x95, 0x01,                /*     REPORT_COUNT (1)                 */
+    0x75, 0x08,                /*     REPORT_SIZE (8)                  */
+    0x81, 0x02,                /*     INPUT (Data,Var,Abs)             */
+    0x75, 0x01,                /*     REPORT SIZE (1)                  */
+    0x95, 0x1d,                /*     REPORT COUNT (29)                */
+    0x81, 0x01,                /*     INPUT (Cnst,Ary,Abs)             */
+    0xc0,              /*   END_COLLECTION                     */
+    0xc0,              /* END_COLLECTION                       */
+    0x05, 0x00,                /* USAGE_PAGE (Undefined)               */
+    0x09, 0x00,                /* USAGE (Undefined)                    */
+    0xa1, 0x01,                /* COLLECTION (Application)             */
+    0x85, 0xc0,                /*   REPORT_ID (192)                    */
+    0x81, 0x01,                /*   INPUT (Cnst,Ary,Abs)               */
+    0xc0               /* END_COLLECTION                       */
+};
Index: usb/uhidev.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhidev.c,v
retrieving revision 1.74
diff -u -p -r1.74 uhidev.c
--- usb/uhidev.c        13 Jun 2016 10:15:03 -0000      1.74
+++ usb/uhidev.c        2 Aug 2016 19:15:09 -0000
@@ -298,6 +298,12 @@ uhidev_use_rdesc(struct uhidev_softc *sc
                        size = sizeof(uhid_graphire3_4x5_report_descr);
                        descptr = uhid_graphire3_4x5_report_descr;
                        break;
+               case USB_PRODUCT_WACOM_INTUOSS2:
+                       if (sc->sc_ifaceno == 0) {
+                               size = sizeof(uhid_intuos_s2_report_descr);
+                               descptr = uhid_intuos_s2_report_descr;
+                       }
+                       break;
                default:
                        break;
                }
Index: usb/ums.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ums.c,v
retrieving revision 1.43
diff -u -p -r1.43 ums.c
--- usb/ums.c   12 Jan 2016 19:16:21 -0000      1.43
+++ usb/ums.c   2 Aug 2016 19:15:10 -0000
@@ -143,6 +143,12 @@ ums_attach(struct device *parent, struct
                qflags |= HIDMS_MS_BAD_CLASS;
        if (quirks & UQ_MS_LEADING_BYTE)
                qflags |= HIDMS_LEADINGBYTE;
+       if (quirks & UQ_BE16_X)
+               qflags |= HIDMS_BE16_X;
+       if (quirks & UQ_BE16_Y)
+               qflags |= HIDMS_BE16_Y;
+       if (quirks & UQ_USE_TIP_PRESS)
+               qflags |= HIDMS_USE_TIP_PRESS;
 
        if (hidms_setup(self, ms, qflags, uha->reportid, desc, size) != 0)
                return;
Index: usb/usb_quirks.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_quirks.c,v
retrieving revision 1.74
diff -u -p -r1.74 usb_quirks.c
--- usb/usb_quirks.c    27 Nov 2015 10:59:32 -0000      1.74
+++ usb/usb_quirks.c    2 Aug 2016 19:15:10 -0000
@@ -150,6 +150,9 @@ const struct usbd_quirk_entry {
  { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK2,
        ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }},
 
+ { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOSS2,
+       ANY, { UQ_BE16_X | UQ_BE16_Y | UQ_USE_TIP_PRESS }},
+
  { 0, 0, 0, { 0 } }
 };
 
Index: usb/usb_quirks.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_quirks.h,v
retrieving revision 1.16
diff -u -p -r1.16 usb_quirks.h
--- usb/usb_quirks.h    19 Jul 2010 05:08:37 -0000      1.16
+++ usb/usb_quirks.h    2 Aug 2016 19:15:10 -0000
@@ -49,6 +49,10 @@ struct usbd_quirks {
 #define UQ_MS_LEADING_BYTE     0x00010000 /* mouse sends unknown leading byte 
*/
 #define UQ_EHCI_NEEDTO_DISOWN  0x00020000 /* must hand device over to USB 1.1
                                                if attached to EHCI */
+#define UQ_BE16_X              0x00040000 /* mouse reports x in big endian 16 
*/
+#define UQ_BE16_Y              0x00080000 /* mouse reports x in big endian 16 
*/
+#define UQ_USE_TIP_PRESS       0x00100000 /* use mouse reported pressure for
+                                               button 0 */
 };
 
 extern const struct usbd_quirks usbd_no_quirk;
Index: usb/usbdevs
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs,v
retrieving revision 1.666
diff -u -p -r1.666 usbdevs
--- usb/usbdevs 1 Jun 2016 09:48:20 -0000       1.666
+++ usb/usbdevs 2 Aug 2016 19:15:10 -0000
@@ -4397,6 +4397,7 @@ product WACOM GRAPHIRE            0x0010  Graphire
 product WACOM GRAPHIRE3_4X5    0x0013  Graphire3 4x5
 product WACOM GRAPHIRE4_4X5    0x0015  Graphire4 Classic A6
 product WACOM INTUOSA5         0x0021  Intuos A5
+product WACOM INTUOSS2         0x033b  Intuos S 2
 
 /* WAGO Kontakttechnik products */
 product WAGO SERVICECABLE      0x07a6  Service Cable 750-923
Index: usb/usbdevs.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs.h,v
retrieving revision 1.678
diff -u -p -r1.678 usbdevs.h
--- usb/usbdevs.h       1 Jun 2016 09:48:54 -0000       1.678
+++ usb/usbdevs.h       2 Aug 2016 19:15:11 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs.h,v 1.678 2016/06/01 09:48:54 mglocker Exp $  */
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -4404,6 +4404,7 @@
 #define        USB_PRODUCT_WACOM_GRAPHIRE3_4X5 0x0013          /* Graphire3 
4x5 */
 #define        USB_PRODUCT_WACOM_GRAPHIRE4_4X5 0x0015          /* Graphire4 
Classic A6 */
 #define        USB_PRODUCT_WACOM_INTUOSA5      0x0021          /* Intuos A5 */
+#define        USB_PRODUCT_WACOM_INTUOSS2      0x033b          /* Intuos S 2 */
 
 /* WAGO Kontakttechnik products */
 #define        USB_PRODUCT_WAGO_SERVICECABLE   0x07a6          /* Service 
Cable 750-923 */
Index: usb/usbdevs_data.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs_data.h,v
retrieving revision 1.672
diff -u -p -r1.672 usbdevs_data.h
--- usb/usbdevs_data.h  1 Jun 2016 09:48:54 -0000       1.672
+++ usb/usbdevs_data.h  2 Aug 2016 19:15:12 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs_data.h,v 1.672 2016/06/01 09:48:54 mglocker Exp $     
*/
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -11208,6 +11208,10 @@ const struct usb_known_product usb_known
        {
            USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOSA5,
            "Intuos A5",
+       },
+       {
+           USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOSS2,
+           "Intuos S 2",
        },
        {
            USB_VENDOR_WAGO, USB_PRODUCT_WAGO_SERVICECABLE,

Reply via email to