On Sun, Sep 04, 2016 at 02:25:06PM +0200, Martin Pieuchot wrote:
> >- 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.

Correction: the problem can only be fixed by making sure the device is
plugged in before starting X. After suspend a restart of X is needed to
make scaling work again.

> 
> This is a common problem for drivers needing calibration.  Does the X driver
> opens your device through /dev/wsmouseN or does it uses the mux?

I think that's weird for this device tough: input is always report from
zero till the maximum values in the driver. No matter how or when you
attach it.
I'm not sure how the X driver opens the device. I've based it off ums(4)
mostly, so it will probably be the same as ums(4) does.

> >- Documentation is still absent, I'll gladly write it when you guys
> >  apporve of the code I wrote.
> 
> I'll be happy to do so, could you provide a man page for this driver?

Attached a new diff with documentation.

> >What do you guys think? Any comments or suggestions? Any ideas on how to
> >attach to all three uhidevs?
> 
> Yes, you have to match the device id.  uhidev(4) attaches to the 3 first
> interfaces of your first configuration.  And you want a single piece of code
> driving all these interfaces.  Do you have some documentation for the device
> you're hacking on?  Do you know what you can do with these interfaces?  It's
> important to know otherwise you
> might spend as much work refactoring the driver to extend it than you
> spent in the beginning.

Unfortunately I couldn't find any documentation except for the Linux
device driver implementation (but it supports all kinds of Wacom
tablets, so it isn't exactly readable).
I've written this driver by using the broken device descriptor
and reverse-engeneering with commands such as:

cat /dev/uhid6 | hexdump -e '9/1 "%02x " "\n"'

And just moving the pen and seeing which bytes change.

It seems only the first uhidev device actually reports inputs. The last
uhidev device seems to have the most correct descriptor, but never
reports any data. My guess is that it's there for Windows users without
the driver: they can recognize the tablet as a reported generic mouse.

As far as I can understand the Linux driver, they only use the data from
the reportid that my driver uses. For completeness I've attached lsusb
output from a Linux computer as well.

Frank
Bus 004 Device 005: ID 056a:033b Wacom Co., Ltd 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x056a Wacom Co., Ltd
  idProduct          0x033b 
  bcdDevice            1.00
  iManufacturer           1 Wacom Co.,Ltd.
  iProduct                2 Intuos PS
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           84
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              498mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     208
          Report Descriptor: (length is 208)
            Item(Global): Usage Page, data= [ 0x0d 0xff ] 65293
                            (null)
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x10 ] 16
            Item(Main  ): Collection, data= [ 0x00 ] 0
                            Physical
            Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x09 ] 9
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Main  ): End Collection, data=none
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x02 ] 2
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x03 ] 3
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x04 ] 4
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x05 ] 5
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x10 ] 16
            Item(Global): Report Count, data= [ 0x02 ] 2
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x11 ] 17
            Item(Global): Report Count, data= [ 0x10 ] 16
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x13 ] 19
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x07 ] 7
            Item(Global): Report Count, data= [ 0x09 ] 9
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x09 ] 9
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x20 ] 32
            Item(Global): Report Count, data= [ 0x05 ] 5
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x21 ] 33
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x22 ] 34
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x23 ] 35
            Item(Global): Report Count, data= [ 0x0e ] 14
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x14 ] 20
            Item(Global): Report Count, data= [ 0x1f ] 31
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x40 ] 64
            Item(Global): Report Count, data= [ 0x0a ] 10
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x30 ] 48
            Item(Global): Report Count, data= [ 0x02 0x00 ] 2
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x31 ] 49
            Item(Global): Report Count, data= [ 0x21 0x00 ] 33
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x32 ] 50
            Item(Global): Report Count, data= [ 0x21 0x00 ] 33
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x33 ] 51
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x24 ] 36
            Item(Global): Report Count, data= [ 0x1f ] 31
            Item(Main  ): Feature, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Report ID, data= [ 0x25 ] 37
            Item(Global): Report Count, data= [ 0x04 ] 4
            Item(Main  ): Feature, data= [ 0x1f ] 31
                            Constant Variable Relative Wrap Non_Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Global): Report ID, data= [ 0xc0 ] 192
            Item(Local ): Usage, data= [ 0x00 ] 0
                            (null)
            Item(Global): Report Count, data= [ 0x09 ] 9
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      38
          Report Descriptor: (length is 38)
            Item(Global): Usage Page, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Local ): Usage, data= [ 0x80 ] 128
                            (null)
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x02 ] 2
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x3f ] 63
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Global): Report ID, data= [ 0x03 ] 3
            Item(Local ): Usage, data= [ 0x01 ] 1
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x3f ] 63
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      52
          Report Descriptor: (length is 52)
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x02 ] 2
                            Mouse
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Local ): Usage, data= [ 0x01 ] 1
                            Pointer
            Item(Main  ): Collection, data= [ 0x00 ] 0
                            Physical
            Item(Global): Usage Page, data= [ 0x09 ] 9
                            Buttons
            Item(Local ): Usage Minimum, data= [ 0x01 ] 1
                            Button 1 (Primary)
            Item(Local ): Usage Maximum, data= [ 0x05 ] 5
                            Button 5
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x05 ] 5
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x03 ] 3
            Item(Main  ): Input, data= [ 0x01 ] 1
                            Constant Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x30 ] 48
                            Direction-X
            Item(Local ): Usage, data= [ 0x31 ] 49
                            Direction-Y
            Item(Global): Logical Minimum, data= [ 0x81 ] 129
            Item(Global): Logical Maximum, data= [ 0x7f ] 127
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x02 ] 2
            Item(Main  ): Input, data= [ 0x06 ] 6
                            Data Variable Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile 
Bitfield
            Item(Main  ): End Collection, data=none
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               2
Device Status:     0x0000
  (Bus Powered)
Index: share/man/man4/uwacom.4
===================================================================
RCS file: share/man/man4/uwacom.4
diff -N share/man/man4/uwacom.4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ share/man/man4/uwacom.4     5 Sep 2016 18:36:32 -0000
@@ -0,0 +1,60 @@
+.\" $OpenBSD$
+.\"
+.\" Copyright (c) 2016 Frank Groeneveld <[email protected]>
+.\"
+.\" 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.
+.\"
+.Dd $Mdocdate: September 5 2016 $
+.Dt UWACOM 4
+.Os
+.Sh NAME
+.Nm uwacom
+.Nd Wacom USB tablets
+.Sh SYNOPSIS
+.Cd "uwacom*  at uhidev?"
+.Cd "wsmouse* at uwacom? mux 0"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides basic support for Wacom USB tablets.
+Access to these devices is through the
+.Xr wscons 4
+framework.
+.Pp
+Absolute positioning of the mouse cursor can be done by hovering the pen above 
the tablet. Touching the tablet with the pen tip will emulate mouse button 0, 
while the two pen buttons will emulate button 1 and button 2.
+.Pp
+The
+.Nm
+driver supports the following Wacom tablets:
+.Pp
+.Bl -column "Intuos Draw" "Model Number" -offset 6n
+.It Em Name Ta Model Number
+.It Li Intuos Draw Ta CTL-490
+.Sh SEE ALSO
+.Xr uhidev 4 ,
+.Xr usb 4 ,
+.Xr wsmouse 4
+.Sh HISTORY
+The
+.Nm
+driver
+first appeared in
+.Ox 6.1 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Frank Groeneveld [email protected] .
+.Sh BUGS
+To make axis scaling work correctly, the device should be plugged in when X 
starts. Advanced features such as pen tip pressure are not supported.
Index: sys/arch/amd64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.432
diff -u -p -r1.432 GENERIC
--- sys/arch/amd64/conf/GENERIC 4 Sep 2016 10:22:05 -0000       1.432
+++ sys/arch/amd64/conf/GENERIC 5 Sep 2016 18:36:32 -0000
@@ -244,6 +244,8 @@ umass*      at uhub?                # USB Mass Storage devi
 ubcmtp*        at uhub?                # Broadcom USB trackpad
 wsmouse* at ubcmtp? mux 0
 uhidev*        at uhub?                # Human Interface Devices
+uwacom*        at uhidev?              # USB Wacom tablet
+wsmouse* at uwacom? mux 0
 ums*   at uhidev?              # USB mouse
 wsmouse* at ums? mux 0
 uts*   at uhub?                # USB touchscreen
Index: sys/dev/hid/hid.h
===================================================================
RCS file: /cvs/src/sys/dev/hid/hid.h,v
retrieving revision 1.4
diff -u -p -r1.4 hid.h
--- sys/dev/hid/hid.h   20 Jan 2016 01:26:00 -0000      1.4
+++ sys/dev/hid/hid.h   5 Sep 2016 18:36:32 -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: sys/dev/usb/files.usb
===================================================================
RCS file: /cvs/src/sys/dev/usb/files.usb,v
retrieving revision 1.130
diff -u -p -r1.130 files.usb
--- sys/dev/usb/files.usb       3 Sep 2016 13:37:45 -0000       1.130
+++ sys/dev/usb/files.usb       5 Sep 2016 18:36:32 -0000
@@ -435,3 +435,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: sys/dev/usb/usbdevs
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs,v
retrieving revision 1.666
diff -u -p -r1.666 usbdevs
--- sys/dev/usb/usbdevs 1 Jun 2016 09:48:20 -0000       1.666
+++ sys/dev/usb/usbdevs 5 Sep 2016 18:36:32 -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 INTUOS_DRAW      0x033b  Intuos Draw (CTL-490)
 
 /* WAGO Kontakttechnik products */
 product WAGO SERVICECABLE      0x07a6  Service Cable 750-923
Index: sys/dev/usb/usbdevs.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs.h,v
retrieving revision 1.678
diff -u -p -r1.678 usbdevs.h
--- sys/dev/usb/usbdevs.h       1 Jun 2016 09:48:54 -0000       1.678
+++ sys/dev/usb/usbdevs.h       5 Sep 2016 18:36:32 -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_INTUOS_DRAW   0x033b          /* Intuos Draw 
(CTL-490) */
 
 /* WAGO Kontakttechnik products */
 #define        USB_PRODUCT_WAGO_SERVICECABLE   0x07a6          /* Service 
Cable 750-923 */
Index: sys/dev/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
--- sys/dev/usb/usbdevs_data.h  1 Jun 2016 09:48:54 -0000       1.672
+++ sys/dev/usb/usbdevs_data.h  5 Sep 2016 18:36:32 -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_INTUOS_DRAW,
+           "Intuos Draw (CTL-490)",
        },
        {
            USB_VENDOR_WAGO, USB_PRODUCT_WAGO_SERVICECABLE,
Index: sys/dev/usb/uwacom.c
===================================================================
RCS file: sys/dev/usb/uwacom.c
diff -N sys/dev/usb/uwacom.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ sys/dev/usb/uwacom.c        5 Sep 2016 18:36:32 -0000
@@ -0,0 +1,233 @@
+/*     $OpenBSD$       */
+
+/*
+ * Copyright (c) 2016 Frank Groeneveld <[email protected]>
+ *
+ * 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_INTUOS_DRAW }
+};
+
+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;
+       }
+}

Reply via email to