summaryrefslogtreecommitdiff
path: root/sys/dev/usb/ums.c
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-07-31 16:04:51 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-07-31 16:04:51 +0000
commit719914f7d11cca5a6e29b46198ed50c4f1e1fa27 (patch)
treeb2a3c1737c957e2304815cde026ae0dce5ac6ff6 /sys/dev/usb/ums.c
parent6aa735007a06d259dcbcbfa42a14b0285e4a6474 (diff)
Factorization of the bluetooth and usb hid input driver logic, to reduce code
duplication and divergence. Thanks to mlarkin@ for bluetooth devices tests.
Diffstat (limited to 'sys/dev/usb/ums.c')
-rw-r--r--sys/dev/usb/ums.c341
1 files changed, 39 insertions, 302 deletions
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index 00b3b5fd06c..2a72197acb1 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ums.c,v 1.31 2009/10/13 19:33:19 pirofti Exp $ */
+/* $OpenBSD: ums.c,v 1.32 2010/07/31 16:04:50 miod Exp $ */
/* $NetBSD: ums.c,v 1.60 2003/03/11 16:44:00 augustss Exp $ */
/*
@@ -40,12 +40,6 @@
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/file.h>
-#include <sys/selinfo.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/poll.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
@@ -60,48 +54,14 @@
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
-#ifdef USB_DEBUG
-#define DPRINTF(x) do { if (umsdebug) printf x; } while (0)
-#define DPRINTFN(n,x) do { if (umsdebug>(n)) printf x; } while (0)
-int umsdebug = 0;
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif
-
-#define UMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i)
-
-#define UMSUNIT(s) (minor(s))
-
-#define MAX_BUTTONS 16 /* must not exceed size of sc_buttons */
+#include <dev/usb/hidmsvar.h>
struct ums_softc {
- struct uhidev sc_hdev;
-
- struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, sc_loc_w;
- struct hid_location sc_loc_btn[MAX_BUTTONS];
-
- int sc_enabled;
-
- int flags; /* device configuration */
-#define UMS_Z 0x01 /* Z direction available */
-#define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */
-#define UMS_REVZ 0x04 /* Z-axis is reversed */
-#define UMS_W 0x08 /* W direction available */
-#define UMS_REVW 0x10 /* W-axis is reversed */
-#define UMS_LEADINGBYTE 0x20 /* Unknown leading byte */
-
- int nbuttons;
-
- u_int32_t sc_buttons; /* mouse button status */
- struct device *sc_wsmousedev;
-
- char sc_dying;
+ struct uhidev sc_hdev;
+ struct hidms sc_ms;
+ char sc_dying;
};
-#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
-#define MOUSE_FLAGS (HIO_RELATIVE)
-
void ums_intr(struct uhidev *addr, void *ibuf, u_int len);
int ums_enable(void *);
@@ -151,146 +111,22 @@ void
ums_attach(struct device *parent, struct device *self, void *aux)
{
struct ums_softc *sc = (struct ums_softc *)self;
+ struct hidms *ms = &sc->sc_ms;
struct usb_attach_arg *uaa = aux;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
- struct wsmousedev_attach_args a;
int size;
void *desc;
- u_int32_t flags, quirks;
- int i, wheel, twheel;
+ u_int32_t quirks;
sc->sc_hdev.sc_intr = ums_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
- if (quirks & UQ_MS_REVZ)
- sc->flags |= UMS_REVZ;
- if (quirks & UQ_SPUR_BUT_UP)
- sc->flags |= UMS_SPUR_BUT_UP;
- if (quirks & UQ_MS_LEADING_BYTE)
- sc->flags |= UMS_LEADINGBYTE;
-
uhidev_get_report_desc(uha->parent, &desc, &size);
- if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
- uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
- printf("\n%s: mouse has no X report\n",
- sc->sc_hdev.sc_dev.dv_xname);
- return;
- }
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
- printf("\n%s: X report 0x%04x not supported\n",
- sc->sc_hdev.sc_dev.dv_xname, flags);
- return;
- }
-
- if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
- uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
- printf("\n%s: mouse has no Y report\n",
- sc->sc_hdev.sc_dev.dv_xname);
- return;
- }
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
- printf("\n%s: Y report 0x%04x not supported\n",
- sc->sc_hdev.sc_dev.dv_xname, flags);
+ if (hidms_setup(self, ms, quirks, uha->reportid, desc, size) != 0)
return;
- }
-
- /*
- * Try to guess the Z activator: check WHEEL, TWHEEL, and Z,
- * in that order.
- */
-
- wheel = hid_locate(desc, size,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
- uha->reportid, hid_input, &sc->sc_loc_z, &flags);
- if (wheel == 0)
- twheel = hid_locate(desc, size,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
- uha->reportid, hid_input, &sc->sc_loc_z, &flags);
- else
- twheel = 0;
-
- if (wheel || twheel) {
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
- DPRINTF(("\n%s: Wheel report 0x%04x not supported\n",
- sc->sc_hdev.sc_dev.dv_xname, flags));
- sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
- } else {
- sc->flags |= UMS_Z;
- /* Wheels need the Z axis reversed. */
- sc->flags ^= UMS_REVZ;
- }
- /*
- * We might have both a wheel and Z direction; in this case,
- * report the Z direction on the W axis.
- */
- if (hid_locate(desc, size,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
- uha->reportid, hid_input, &sc->sc_loc_w, &flags)) {
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
- DPRINTF(("\n%s: Z report 0x%04x not supported\n",
- sc->sc_hdev.sc_dev.dv_xname, flags));
- /* Bad Z coord, ignore it */
- sc->sc_loc_w.size = 0;
- }
- else
- sc->flags |= UMS_W;
- }
- } else if (hid_locate(desc, size,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
- uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
- DPRINTF(("\n%s: Z report 0x%04x not supported\n",
- sc->sc_hdev.sc_dev.dv_xname, flags));
- sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
- } else {
- sc->flags |= UMS_Z;
- }
- }
-
- /*
- * The Microsoft Wireless Intellimouse 2.0 reports its wheel
- * using 0x0048 (I've called it HUG_TWHEEL) and seems to expect
- * us to know that the byte after the wheel is the tilt axis.
- * There are no other HID axis descriptors other than X, Y and
- * TWHEEL, so we report TWHEEL on the W axis.
- */
- if (twheel) {
- sc->sc_loc_w = sc->sc_loc_z;
- sc->sc_loc_w.pos = sc->sc_loc_w.pos + 8;
- sc->flags |= UMS_W | UMS_LEADINGBYTE;
- /* Wheels need their axis reversed. */
- sc->flags ^= UMS_REVW;
- }
-
- /* figure out the number of buttons */
- for (i = 1; i <= MAX_BUTTONS; i++)
- if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
- uha->reportid, hid_input, &sc->sc_loc_btn[i - 1], 0))
- break;
- sc->nbuttons = i - 1;
-
- /*
- * The Microsoft Wireless Notebook Optical Mouse seems to be in worse
- * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and
- * all of its other button positions are all off. It also reports that
- * it has two addional buttons and a tilt wheel.
- */
- if (quirks & UQ_MS_BAD_CLASS) {
- /* UMS_LEADINGBYTE cleared on purpose */
- sc->flags = UMS_Z | UMS_SPUR_BUT_UP;
- sc->nbuttons = 3;
- /* XXX change sc_hdev isize to 5? */
- /* 1st byte of descriptor report contains garbage */
- sc->sc_loc_x.pos = 16;
- sc->sc_loc_y.pos = 24;
- sc->sc_loc_z.pos = 32;
- sc->sc_loc_btn[0].pos = 8;
- sc->sc_loc_btn[1].pos = 9;
- sc->sc_loc_btn[2].pos = 10;
- }
/*
* The Microsoft Wireless Notebook Optical Mouse 3000 Model 1049 has
@@ -301,60 +137,25 @@ ums_attach(struct device *parent, struct device *self, void *aux)
*/
if (uaa->vendor == USB_VENDOR_MICROSOFT &&
uaa->product == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3) {
- sc->flags = UMS_Z;
- sc->nbuttons = 3;
+ ms->sc_flags = HIDMS_Z;
+ ms->sc_num_buttons = 3;
/* XXX change sc_hdev isize to 5? */
- sc->sc_loc_x.pos = 8;
- sc->sc_loc_y.pos = 16;
- sc->sc_loc_z.pos = 24;
- sc->sc_loc_btn[0].pos = 0;
- sc->sc_loc_btn[1].pos = 1;
- sc->sc_loc_btn[2].pos = 2;
+ ms->sc_loc_x.pos = 8;
+ ms->sc_loc_y.pos = 16;
+ ms->sc_loc_z.pos = 24;
+ ms->sc_loc_btn[0].pos = 0;
+ ms->sc_loc_btn[1].pos = 1;
+ ms->sc_loc_btn[2].pos = 2;
}
- printf(": %d button%s",
- sc->nbuttons, sc->nbuttons <= 1 ? "" : "s");
- switch (sc->flags & (UMS_Z | UMS_W)) {
- case UMS_Z:
- printf(", Z dir");
- break;
- case UMS_W:
- printf(", W dir");
- break;
- case UMS_Z | UMS_W:
- printf(", Z and W dir");
- break;
- }
- printf("\n");
-
-#ifdef USB_DEBUG
- DPRINTF(("ums_attach: sc=%p\n", sc));
- DPRINTF(("ums_attach: X\t%d/%d\n",
- sc->sc_loc_x.pos, sc->sc_loc_x.size));
- DPRINTF(("ums_attach: Y\t%d/%d\n",
- sc->sc_loc_y.pos, sc->sc_loc_y.size));
- if (sc->flags & UMS_Z)
- DPRINTF(("ums_attach: Z\t%d/%d\n",
- sc->sc_loc_z.pos, sc->sc_loc_z.size));
- if (sc->flags & UMS_W)
- DPRINTF(("ums_attach: W\t%d/%d\n",
- sc->sc_loc_w.pos, sc->sc_loc_w.size));
- for (i = 1; i <= sc->nbuttons; i++) {
- DPRINTF(("ums_attach: B%d\t%d/%d\n",
- i, sc->sc_loc_btn[i - 1].pos, sc->sc_loc_btn[i - 1].size));
- }
-#endif
-
- a.accessops = &ums_accessops;
- a.accesscookie = sc;
-
- sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+ hidms_attach(ms, &ums_accessops);
}
int
ums_activate(struct device *self, int act)
{
struct ums_softc *sc = (struct ums_softc *)self;
+ struct hidms *ms = &sc->sc_ms;
int rv = 0;
switch (act) {
@@ -362,8 +163,8 @@ ums_activate(struct device *self, int act)
break;
case DVACT_DEACTIVATE:
- if (sc->sc_wsmousedev != NULL)
- rv = config_deactivate(sc->sc_wsmousedev);
+ if (ms->sc_wsmousedev != NULL)
+ rv = config_deactivate(ms->sc_wsmousedev);
sc->sc_dying = 1;
break;
}
@@ -374,122 +175,58 @@ int
ums_detach(struct device *self, int flags)
{
struct ums_softc *sc = (struct ums_softc *)self;
- int rv = 0;
+ struct hidms *ms = &sc->sc_ms;
- DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags));
-
- /* No need to do reference counting of ums, wsmouse has all the goo. */
- if (sc->sc_wsmousedev != NULL)
- rv = config_detach(sc->sc_wsmousedev, flags);
-
- return (rv);
+ return hidms_detach(ms, flags);
}
void
ums_intr(struct uhidev *addr, void *buf, u_int len)
{
struct ums_softc *sc = (struct ums_softc *)addr;
- u_char *ibuf = (u_char *)buf;
- int dx, dy, dz, dw;
- u_int32_t buttons = 0;
- int i;
- int s;
+ struct hidms *ms = &sc->sc_ms;
- DPRINTFN(5,("ums_intr: len=%d\n", len));
-
- /*
- * The Microsoft Wireless Intellimouse 2.0 sends one extra leading
- * byte of data compared to most USB mice. This byte frequently
- * switches from 0x01 (usual state) to 0x02. It may be used to
- * report non-standard events (such as battery life). However,
- * at the same time, it generates a left click event on the
- * button byte, where there shouldn't be any. We simply discard
- * the packet in this case.
- *
- * This problem affects the MS Wireless Notebook Optical Mouse, too.
- * However, the leading byte for this mouse is normally 0x11, and
- * the phantom mouse click occurs when it's 0x14.
- */
- if (sc->flags & UMS_LEADINGBYTE) {
- if (*ibuf++ == 0x02)
- return;
- /* len--; */
- } else if (sc->flags & UMS_SPUR_BUT_UP) {
- if (*ibuf == 0x14 || *ibuf == 0x15)
- return;
- }
-
- 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_REVW)
- dw = -dw;
- for (i = 0; i < sc->nbuttons; i++)
- if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
- buttons |= (1 << UMS_BUT(i));
-
- if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
- buttons != sc->sc_buttons) {
- DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d w:%d buttons:0x%x\n",
- dx, dy, dz, dw, buttons));
- sc->sc_buttons = buttons;
- if (sc->sc_wsmousedev != NULL) {
- s = spltty();
- wsmouse_input(sc->sc_wsmousedev, buttons,
- dx, dy, dz, dw, WSMOUSE_INPUT_DELTA);
- splx(s);
- }
- }
+ if (ms->sc_enabled != 0)
+ hidms_input(ms, (uint8_t *)buf, len);
}
int
ums_enable(void *v)
{
struct ums_softc *sc = v;
-
- DPRINTFN(1,("ums_enable: sc=%p\n", sc));
+ struct hidms *ms = &sc->sc_ms;
+ int rv;
if (sc->sc_dying)
- return (EIO);
-
- if (sc->sc_enabled)
- return (EBUSY);
+ return EIO;
- sc->sc_enabled = 1;
- sc->sc_buttons = 0;
+ if ((rv = hidms_enable(ms)) != 0)
+ return rv;
- return (uhidev_open(&sc->sc_hdev));
+ return uhidev_open(&sc->sc_hdev);
}
void
ums_disable(void *v)
{
struct ums_softc *sc = v;
+ struct hidms *ms = &sc->sc_ms;
- DPRINTFN(1,("ums_disable: sc=%p\n", sc));
-#ifdef DIAGNOSTIC
- if (!sc->sc_enabled) {
- printf("ums_disable: not enabled\n");
- return;
- }
-#endif
-
- sc->sc_enabled = 0;
+ hidms_disable(ms);
uhidev_close(&sc->sc_hdev);
}
int
ums_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
-
{
+ struct ums_softc *sc = v;
+ struct hidms *ms = &sc->sc_ms;
+
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_USB;
- return (0);
+ return 0;
+ default:
+ return hidms_ioctl(ms, cmd, data, flag, p);
}
-
- return (-1);
}