On Wed, Aug 10, 2016 at 03:42:34PM +0200, Martin Pieuchot wrote:
> I'd ignore it as a first step, then revisit this later.

Attached a first stab at a seperate driver. Some points of interest:

- I've decided against using a custom hid descriptor, but instead define
  the needed inputs in the driver. This seems more readable to me.
- Driver attaches to one uhid, but there are three uhidev devices and
  numerous uhids in this device, including a non-working uhid that ums 
  attaches to (ums0 in the attached dmesg output).
- One bug still left: when the device is attached after X has started,
  it seems the scaling is done wrongly. I had this problem with the
  hacked ums driver as well. Most of the time it is fixed by switching
  between console and X.
- Documentation is still absent, I'll gladly write it when you guys
  apporve of the code I wrote.

What do you guys think? Any comments or suggestions? Any ideas on how to
attach to all three uhidevs?

Thanks.

Frank
Index: hid/hid.h
===================================================================
RCS file: /cvs/src/sys/dev/hid/hid.h,v
retrieving revision 1.4
diff -u -p -r1.4 hid.h
--- hid/hid.h   20 Jan 2016 01:26:00 -0000      1.4
+++ hid/hid.h   3 Sep 2016 13:09:24 -0000
@@ -127,6 +127,7 @@ int hid_is_collection(const void *, int,
 #define HUP_MICROSOFT          0xff00
 /* XXX compat */
 #define HUP_APPLE              0x00ff
+#define HUP_WACOM              0xff00
 
 /* Usages, Power Device */
 #define HUP_INAME              0x0001
Index: usb/files.usb
===================================================================
RCS file: /cvs/src/sys/dev/usb/files.usb,v
retrieving revision 1.129
diff -u -p -r1.129 files.usb
--- usb/files.usb       27 Jun 2016 11:42:47 -0000      1.129
+++ usb/files.usb       3 Sep 2016 13:09:25 -0000
@@ -446,3 +446,8 @@ file        dev/usb/uberry.c                uberry
 device upd: hid
 attach upd at uhidbus
 file   dev/usb/upd.c                   upd
+
+# Wacom tablets
+device uwacom: hid, hidms, wsmousedev
+attach uwacom at uhidbus
+file   dev/usb/uwacom.c                uwacom
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 3 Sep 2016 13:09:25 -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 (CTL-490)
 
 /* 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       3 Sep 2016 13:09:25 -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 
(CTL-490) */
 
 /* 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  3 Sep 2016 13:09:25 -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 (CTL-490)",
        },
        {
            USB_VENDOR_WAGO, USB_PRODUCT_WAGO_SERVICECABLE,
Index: usb/uwacom.c
===================================================================
RCS file: usb/uwacom.c
diff -N usb/uwacom.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ usb/uwacom.c        3 Sep 2016 13:09:25 -0000
@@ -0,0 +1,233 @@
+/*     $OpenBSD$ */
+
+/*
+ * Copyright (c) 2016 Frank Groeneveld <fr...@frankgroeneveld.nl>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Driver for USB Wacom tablets */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbhid.h>
+
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdevs.h>
+#include <dev/usb/uhidev.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+
+#include <dev/hid/hidmsvar.h>
+
+struct uwacom_softc {
+       struct uhidev           sc_hdev;
+       struct hidms            sc_ms;
+       struct hid_location     sc_loc_tip_press;
+};
+
+struct cfdriver uwacom_cd = {
+       NULL, "uwacom", DV_DULL
+};
+
+
+const struct usb_devno uwacom_devs[] = {
+       { USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOSS2 }
+};
+
+int    uwacom_match(struct device *, void *, void *);
+void   uwacom_attach(struct device *, struct device *, void *);
+int    uwacom_detach(struct device *, int);
+void   uwacom_intr(struct uhidev *, void *, u_int);
+int    uwacom_enable(void *);
+void   uwacom_disable(void *);
+int    uwacom_ioctl(void *, u_long, caddr_t, int, struct proc *);
+
+const struct cfattach uwacom_ca = {
+       sizeof(struct uwacom_softc), uwacom_match, uwacom_attach, uwacom_detach
+};
+
+const struct wsmouse_accessops uwacom_accessops = {
+       uwacom_enable,
+       uwacom_ioctl,
+       uwacom_disable,
+};
+
+int
+uwacom_match(struct device *parent, void *match, void *aux)
+{
+       struct uhidev_attach_arg *uha = aux;
+       int size;
+       void *desc;
+
+       if (usb_lookup(uwacom_devs, uha->uaa->vendor,
+           uha->uaa->product) == NULL)
+               return (UMATCH_NONE);
+
+       uhidev_get_report_desc(uha->parent, &desc, &size);
+
+       if (!hid_locate(desc, size, HID_USAGE2(HUP_WACOM, HUG_POINTER),
+           uha->reportid, hid_input, NULL, NULL))
+               return (UMATCH_NONE);
+
+       return (UMATCH_IFACECLASS);
+}
+
+void
+uwacom_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct uwacom_softc *sc = (struct uwacom_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
+       struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
+       struct usb_attach_arg *uaa = uha->uaa;
+       int size, repid;
+       void *desc;
+
+       sc->sc_hdev.sc_intr = uwacom_intr;
+       sc->sc_hdev.sc_parent = uha->parent;
+       sc->sc_hdev.sc_udev = uaa->device;
+       sc->sc_hdev.sc_report_id = uha->reportid;
+
+       uhidev_get_report_desc(uha->parent, &desc, &size);
+       repid = uha->reportid;
+       sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
+       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.maxx = 7600;
+       ms->sc_tsscale.miny = 0;
+       ms->sc_tsscale.maxy = 4750;
+
+       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;
+
+       sc->sc_loc_tip_press.pos = 43;
+       sc->sc_loc_tip_press.size = 8;
+
+       hidms_attach(ms, &uwacom_accessops);
+}
+
+int
+uwacom_detach(struct device *self, int flags)
+{
+       struct uwacom_softc *sc = (struct uwacom_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
+
+       return hidms_detach(ms, flags);
+}
+
+void
+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;
+       uint8_t *data = (uint8_t *)buf;
+       int i, x, y, pressure;
+
+       if (ms->sc_enabled == 0)
+               return;
+
+       if(!(data[0] & 0xa0) && !(data[0] & 0xe0))
+               return;
+
+       x = be16toh(hid_get_data(data, len, &ms->sc_loc_x));
+       y = be16toh(hid_get_data(data, len, &ms->sc_loc_y));
+       pressure = hid_get_data(data, len, &sc->sc_loc_tip_press);
+
+       for (i = 0; i < ms->sc_num_buttons; i++)
+               if (hid_get_data(data, len, &ms->sc_loc_btn[i]))
+                       buttons |= (1 << i);
+
+       /* button 0 reporting is flaky, use tip pressure for it */
+       if (pressure > 10)
+               buttons |= 1;
+       else
+               buttons &= ~1;
+
+       if (x != 0 || y != 0 || buttons != ms->sc_buttons) {
+               wsmouse_set(ms->sc_wsmousedev, WSMOUSE_ABS_X, x, 0);
+               wsmouse_set(ms->sc_wsmousedev, WSMOUSE_ABS_Y, y, 0);
+
+               /* ignore proximity, it will cause invalid button 2 events */
+               if ((data[0] & 0xf0) != 0xc0)
+                       WSMOUSE_INPUT(ms->sc_wsmousedev, buttons, 0, 0, 0, 0);
+       }
+}
+
+int
+uwacom_enable(void *v)
+{
+       struct uwacom_softc *sc = v;
+       struct hidms *ms = &sc->sc_ms;
+       int rv;
+
+       if (usbd_is_dying(sc->sc_hdev.sc_udev))
+               return EIO;
+
+       if ((rv = hidms_enable(ms)) != 0)
+               return rv;
+
+       return uhidev_open(&sc->sc_hdev);
+}
+
+void
+uwacom_disable(void *v)
+{
+       struct uwacom_softc *sc = v;
+       struct hidms *ms = &sc->sc_ms;
+
+       hidms_disable(ms);
+       uhidev_close(&sc->sc_hdev);
+}
+
+int
+uwacom_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+       struct uwacom_softc *sc = v;
+       struct hidms *ms = &sc->sc_ms;
+       int rc;
+
+       rc = uhidev_ioctl(&sc->sc_hdev, cmd, data, flag, p);
+       if (rc != -1)
+               return rc;
+       rc = hidms_ioctl(ms, cmd, data, flag, p);
+       if (rc != -1)
+               return rc;
+
+       switch (cmd) {
+       case WSMOUSEIO_GTYPE:
+               *(u_int *)data = WSMOUSE_TYPE_USB;
+               return 0;
+       default:
+               return -1;
+       }
+}
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
uhid0 at uhidev0 reportid 2: input=0, output=0, feature=1
uhid1 at uhidev0 reportid 3: input=0, output=0, feature=1
uhid2 at uhidev0 reportid 4: input=0, output=0, feature=1
uhid3 at uhidev0 reportid 5: input=0, output=0, feature=1
uhid4 at uhidev0 reportid 7: input=0, output=0, feature=9
uhid5 at uhidev0 reportid 8: input=0, output=0, feature=9
uwacom0 at uhidev0 reportid 16: 3 buttons
wsmouse1 at uwacom0 mux 0
uhid6 at uhidev0 reportid 17: input=0, output=0, feature=16
uhid7 at uhidev0 reportid 19: input=0, output=0, feature=1
uhid8 at uhidev0 reportid 20: input=0, output=0, feature=31
uhid9 at uhidev0 reportid 32: input=0, output=0, feature=5
uhid10 at uhidev0 reportid 33: input=0, output=0, feature=1
uhid11 at uhidev0 reportid 34: input=0, output=0, feature=1
uhid12 at uhidev0 reportid 35: input=0, output=0, feature=14
uhid13 at uhidev0 reportid 36: input=0, output=0, feature=31
uhid14 at uhidev0 reportid 37: input=0, output=0, feature=4
uhid15 at uhidev0 reportid 48: input=0, output=0, feature=2
uhid16 at uhidev0 reportid 49: input=0, output=0, feature=33
uhid17 at uhidev0 reportid 50: input=0, output=0, feature=33
uhid18 at uhidev0 reportid 51: input=0, output=0, feature=1
uhid19 at uhidev0 reportid 64: input=0, output=0, feature=10
uhid20 at uhidev0 reportid 192: input=9, 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
uhid21 at uhidev1 reportid 2: input=63, output=0, feature=0
uhid22 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
ums0 at uhidev2 reportid 1: 5 buttons
wsmouse2 at ums0 mux 0

Reply via email to