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