summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/ums.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index ca3b5d7..875539b 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -96,7 +96,7 @@ struct ums_softc {
u_char *sc_ibuf;
u_int8_t sc_iid;
int sc_isize;
- struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, sc_loc_t;
+ struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, sc_loc_t, sc_loc_w;
struct hid_location *sc_loc_btn;
struct callout callout_handle; /* for spurious button ups */
@@ -108,6 +108,7 @@ struct ums_softc {
#define UMS_Z 0x01 /* z direction available */
#define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */
#define UMS_T 0x04 /* aa direction available (tilt) */
+#define UMS_REVZ 0x08 /* Z-axis is reversed */
int nbuttons;
#define MAX_BUTTONS 31 /* chosen because sc_buttons is int */
@@ -220,7 +221,7 @@ ums_attach(device_t self)
void *desc;
usbd_status err;
u_int32_t flags;
- int i;
+ int i, wheel;
struct hid_location loc_btn;
sc->sc_disconnected = 1;
@@ -276,14 +277,44 @@ ums_attach(device_t self)
return ENXIO;
}
- /* try to guess the Z activator: first check Z, then WHEEL */
- if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
- hid_input, &sc->sc_loc_z, &flags) ||
- hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
- hid_input, &sc->sc_loc_z, &flags) ||
- hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
- hid_input, &sc->sc_loc_z, &flags)) {
+ /* Try the wheel first as the Z activator since it's tradition. */
+ wheel = hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_WHEEL),
+ hid_input, &sc->sc_loc_z, &flags);
+
+ if (wheel) {
+ if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ printf("\n%s: Wheel report 0x%04x not supported\n",
+ device_get_nameunit(sc->sc_dev), flags);
+ sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
+ } else {
+ sc->flags |= UMS_Z;
+ if (usbd_get_quirks(uaa->device)->uq_flags &
+ UQ_MS_REVZ) {
+ /* Some wheels need the Z axis reversed. */
+ sc->flags |= UMS_REVZ;
+ }
+
+ }
+ /*
+ * We might have both a wheel and Z direction, if so put
+ * put the Z on the W coordinate.
+ */
+ if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_Z),
+ hid_input, &sc->sc_loc_w, &flags)) {
+ if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ printf("\n%s: Z report 0x%04x not supported\n",
+ device_get_nameunit(sc->sc_dev), flags);
+ sc->sc_loc_w.size = 0; /* Bad Z, ignore */
+ }
+ }
+ } else if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_Z),
+ hid_input, &sc->sc_loc_z, &flags)) {
if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ printf("\n%s: Z report 0x%04x not supported\n",
+ device_get_nameunit(sc->sc_dev), flags);
sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
} else {
sc->flags |= UMS_Z;
@@ -449,7 +480,7 @@ ums_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
{
struct ums_softc *sc = addr;
u_char *ibuf;
- int dx, dy, dz, dt;
+ int dx, dy, dz, dw, dt;
int buttons = 0;
int i;
@@ -507,6 +538,9 @@ ums_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
dx = hid_get_data(ibuf, &sc->sc_loc_x);
dy = -hid_get_data(ibuf, &sc->sc_loc_y);
dz = -hid_get_data(ibuf, &sc->sc_loc_z);
+ dw = hid_get_data(ibuf, &sc->sc_loc_w);
+ if (sc->flags & UMS_REVZ)
+ dz = -dz;
if (sc->flags & UMS_T)
dt = -hid_get_data(ibuf, &sc->sc_loc_t);
else
@@ -515,16 +549,17 @@ ums_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
buttons |= (1 << UMS_BUT(i));
- if (dx || dy || dz || dt || (sc->flags & UMS_Z)
+ if (dx || dy || dz || dt || dw || (sc->flags & UMS_Z)
|| buttons != sc->status.button) {
- DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d t:%d buttons:0x%x\n",
- dx, dy, dz, dt, buttons));
+ DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d w:%d t:%d buttons:0x%x\n",
+ dx, dy, dz, dw, dt, buttons));
sc->status.button = buttons;
sc->status.dx += dx;
sc->status.dy += dy;
sc->status.dz += dz;
- /* sc->status.dt += dt;*/ /* no way to export this yet */
+ /* sc->status.dt += dt; */ /* no way to export this yet */
+ /* sc->status.dw += dw; */ /* idem */
/* Discard data in case of full buffer */
if (sc->qcount == sizeof(sc->qbuf)) {
OpenPOWER on IntegriCloud