Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Aug 2008 01:13:22 +0400
From:      =?koi8-r?B?7cHLwdLFzsvP1yDhzMXL08HOxNIg88XNz9fJ3iA=?= <asim@nm.ru>
To:        freebsd-usb@freebsd.org
Cc:        amb@amb.kiev.ua
Subject:   Microsoft Wireless Optical Desktop 3000 doesn't work correctly
Message-ID:  <1219526002.17589.denwebmail-344@makarenkov>

next in thread | raw e-mail | index | archive | help

Hi, Andrew!
Recently. I had a similar problem with Microsoft Wireless MultiMedia Keyboard 1.1 and FreeBSD 7.0 i386
Below the letter  my ums.c  that working correctly with this hardware.
My modifications of ums.c was inspired by    
http://accima.com/members/dhesser/fbsd_mouse_stuff/

The most significant modification in this source file is:


        else
            if (
            id->bInterfaceClass == UICLASS_HID
            && uaa->product == 0x009d
            && uaa->vendor == 0x045e
            && uaa->ifaceno == 1  // iface0 for keyboard, iface1 for mice
            ){
            id->bInterfaceSubClass = UISUBCLASS_BOOT;
            id->bInterfaceProtocol = UIPROTO_MOUSE;
                printf("\nMicosoft Wireles Desktop Mouse\n");
                ret = UMATCH_IFACECLASS;
            }
Please, keep in mind, that I wrote product and vendor code especially for my hardware. You may have to use another values.

Have a good time,
Alexander Makarenkov 

/*-
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Lennart Augustsson (lennart@augustsson.net) at
 * Carlstedt Research & Technology.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by the NetBSD
 *        Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/usb/ums.c,v 1.96.2.3 2008/06/12 16:45:46 kaiw Exp $");

/*
 * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/ioccom.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/selinfo.h>
#include <sys/poll.h>
#include <sys/sysctl.h>
#include <sys/uio.h>

#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>

#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include "usbdevs.h"
#include <dev/usb/usb_quirks.h>
#include <dev/usb/hid.h>

#include <sys/mouse.h>

#ifdef USB_DEBUG
#define DPRINTF(x)      if (umsdebug) printf x
#define DPRINTFN(n,x)   if (umsdebug>(n)) printf x
int     umsdebug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, ums, CTLFLAG_RW, 0, "USB ums");
SYSCTL_INT(_hw_usb_ums, OID_AUTO, debug, CTLFLAG_RW,
           &umsdebug, 0, "ums debug level");
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif

#define UMSUNIT(s)      (minor(s)&0x1f)

#define MS_TO_TICKS(ms) ((ms) * hz / 1000)

#define QUEUE_BUFSIZE   400     /* MUST be divisible by 5 _and_ 8 */

struct ums_softc {
        device_t sc_dev;                /* base device */
        usbd_interface_handle sc_iface; /* interface */
        usbd_pipe_handle sc_intrpipe;   /* interrupt pipe */
        int sc_ep_addr;

        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, sc_loc_w;
        struct hid_location *sc_loc_btn;

        struct callout callout_handle;  /* for spurious button ups */

        int sc_enabled;
        int sc_disconnected;    /* device is gone */

        int flags;              /* device configuration */
#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 */

        u_char          qbuf[QUEUE_BUFSIZE];    /* must be divisable by 3&4 */
        u_char          dummy[100];     /* XXX just for safety and for now */
        int             qcount, qhead, qtail;
        mousehw_t       hw;
        mousemode_t     mode;
        mousestatus_t   status;

        int             state;
#         define        UMS_ASLEEP      0x01    /* readFromDevice is waiting */
#         define        UMS_SELECT      0x02    /* select is waiting */
        struct selinfo  rsel;           /* process waiting in select */

        struct cdev *dev;               /* specfs */
};

#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
#define MOUSE_FLAGS (HIO_RELATIVE)

static void ums_intr(usbd_xfer_handle xfer,
                          usbd_private_handle priv, usbd_status status);

static void ums_add_to_queue(struct ums_softc *sc,
                                int dx, int dy, int dz, int dt, int buttons);
static void ums_add_to_queue_timeout(void *priv);

static int  ums_enable(void *);
static void ums_disable(void *);

static d_open_t  ums_open;
static d_close_t ums_close;
static d_read_t  ums_read;
static d_ioctl_t ums_ioctl;
static d_poll_t  ums_poll;


static struct cdevsw ums_cdevsw = {
        .d_version =    D_VERSION,
        .d_flags =      D_NEEDGIANT,
        .d_open =       ums_open,
        .d_close =      ums_close,
        .d_read =       ums_read,
        .d_ioctl =      ums_ioctl,
        .d_poll =       ums_poll,
        .d_name =       "ums",
};

static device_probe_t ums_match;
static device_attach_t ums_attach;
static device_detach_t ums_detach;

static device_method_t ums_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,         ums_match),
        DEVMETHOD(device_attach,        ums_attach),
        DEVMETHOD(device_detach,        ums_detach),

        { 0, 0 }
};

static driver_t ums_driver = {
        "ums",
        ums_methods,
        sizeof(struct ums_softc)
};

static devclass_t ums_devclass;

static int
ums_match(device_t self)
{
        struct usb_attach_arg *uaa = device_get_ivars(self);
        usb_interface_descriptor_t *id;
        int size, ret;
        void *desc;
        usbd_status err;

        if (!uaa->iface)
                return (UMATCH_NONE);
        id = usbd_get_interface_descriptor(uaa->iface);
        if (!id || id->bInterfaceClass != UICLASS_HID)
        {
                //printf("\nNot a  HID\n");
                return (UMATCH_NONE);
                }

        err = usbd_read_report_desc(uaa->iface, &desc, &size, M_TEMP);
        if (err){
                //printf("\nERR\n");
                return (UMATCH_NONE);
                }
        //printf("\nOK1\n");
        if (hid_is_collection(desc, size,
                              HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))){
                //printf("\nOK2\n");
                ret = UMATCH_IFACECLASS;
                }
        else if (
            id->bInterfaceClass == UICLASS_HID
            && id->bInterfaceSubClass == UISUBCLASS_BOOT
            && id->bInterfaceProtocol == UIPROTO_MOUSE
            ){
                //printf("\nOK3\n");
                ret = UMATCH_IFACECLASS;
                }
        else
            if (
            id->bInterfaceClass == UICLASS_HID
            && uaa->product == 0x009d
            && uaa->vendor == 0x045e
            && uaa->ifaceno == 1
            ){
            id->bInterfaceSubClass = UISUBCLASS_BOOT;
            id->bInterfaceProtocol = UIPROTO_MOUSE;
                printf("\nMicosoft Wireles Desktop Mouse\n");
                ret = UMATCH_IFACECLASS;
            }

        else    {
//              printf("\nOK4\n");
                ret = UMATCH_NONE;
                }

        free(desc, M_TEMP);
        return (ret);
}

static int
ums_attach(device_t self)
{
        struct ums_softc *sc = device_get_softc(self);
        struct usb_attach_arg *uaa = device_get_ivars(self);
        usbd_interface_handle iface = uaa->iface;
        usb_interface_descriptor_t *id;
        usb_endpoint_descriptor_t *ed;
        int size;
        void *desc;
        usbd_status err;
        u_int32_t flags;
        int i, wheel;
        struct hid_location loc_btn;

        sc->sc_disconnected = 1;
        sc->sc_iface = iface;
        id = usbd_get_interface_descriptor(iface);
        sc->sc_dev = self;
        ed = usbd_interface2endpoint_descriptor(iface, 0);
        if (!ed) {
                printf("%s: could not read endpoint descriptor\n",
                       device_get_nameunit(sc->sc_dev));
                return ENXIO;
        }

        DPRINTFN(10,("ums_attach: bLength=%d bDescriptorType=%d "
                     "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
                     " bInterval=%d\n",
                     ed->bLength, ed->bDescriptorType,
                     UE_GET_ADDR(ed->bEndpointAddress),
                     UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ? "in":"out",
                     UE_GET_XFERTYPE(ed->bmAttributes),
                     UGETW(ed->wMaxPacketSize), ed->bInterval));

        if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
            UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) {
                printf("%s: unexpected endpoint\n",
                       device_get_nameunit(sc->sc_dev));
                return ENXIO;
        }

        err = usbd_read_report_desc(uaa->iface, &desc, &size, M_TEMP);
        if (err)
                return ENXIO;

        if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
                       hid_input, &sc->sc_loc_x, &flags)) {
                printf("%s: mouse has no X report\n", device_get_nameunit(sc->sc_dev));
                return ENXIO;
        }
        if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
                printf("%s: X report 0x%04x not supported\n",
                       device_get_nameunit(sc->sc_dev), flags);
                return ENXIO;
        }

        if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
                       hid_input, &sc->sc_loc_y, &flags)) {
                printf("%s: mouse has no Y report\n", device_get_nameunit(sc->sc_dev));
                return ENXIO;
        }
        if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
                printf("%s: Y report 0x%04x not supported\n",
                       device_get_nameunit(sc->sc_dev), flags);
                return ENXIO;
        }

        /* 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;
                }
        }

        /*
         * The Microsoft Wireless Intellimouse 2.0 reports it's wheel
         * using 0x0048 (i've called it HUG_TWHEEL) and seems to expect
         * you 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
         */
        if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
                        hid_input, &sc->sc_loc_t, &flags)) {
                        sc->sc_loc_t.pos = sc->sc_loc_t.pos + 8;
                        sc->flags |= UMS_T;
        }

        /* figure out the number of buttons */
        for (i = 1; i <= MAX_BUTTONS; i++)
                if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
                                hid_input, &loc_btn, 0))
                        break;
        sc->nbuttons = i - 1;
        sc->sc_loc_btn = malloc(sizeof(struct hid_location)*sc->nbuttons,
                                M_USBDEV, M_NOWAIT);
        if (!sc->sc_loc_btn) {
                printf("%s: no memory\n", device_get_nameunit(sc->sc_dev));
                return ENXIO;
        }

        printf("%s: %d buttons%s%s.\n", device_get_nameunit(sc->sc_dev),
               sc->nbuttons, sc->flags & UMS_Z? " and Z dir" : "",
               sc->flags & UMS_T?" and a TILT dir": "");

        for (i = 1; i <= sc->nbuttons; i++)
                hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
                                hid_input, &sc->sc_loc_btn[i-1], 0);

        sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid);
        sc->sc_ibuf = malloc(sc->sc_isize, M_USB, M_NOWAIT);
        if (!sc->sc_ibuf) {
                printf("%s: no memory\n", device_get_nameunit(sc->sc_dev));
                free(sc->sc_loc_btn, M_USB);
                return ENXIO;
        }

        /*
         * 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 (usbd_get_quirks(uaa->device)->uq_flags & UQ_MS_BAD_CLASS) {
                sc->flags = UMS_Z;
                sc->flags |= UMS_SPUR_BUT_UP;
                sc->nbuttons = 3;
                sc->sc_isize = 5;
                sc->sc_iid = 0;
                /* 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
         * five Report IDs: 19 23 24 17 18 (in the order they appear in report
         * descriptor), it seems that report id 17 contains the necessary
         * mouse information(3-buttons,X,Y,wheel) so we specify it manually.
         */
        if ((uaa->vendor == USB_VENDOR_MICROSOFT &&
            uaa->product == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3)
            ||(
                uaa->product == 0x009d
                && uaa->vendor == 0x045e
                && uaa->ifaceno == 1
                )

            ){
                sc->flags = UMS_Z;
                sc->nbuttons = 3;
                sc->sc_isize = 5;
                sc->sc_iid = 17;
                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;
        }

        sc->sc_ep_addr = ed->bEndpointAddress;
        sc->sc_disconnected = 0;
        free(desc, M_TEMP);

#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));
        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));
        }
        DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid));
#endif

        if (sc->nbuttons > MOUSE_MSC_MAXBUTTON)
                sc->hw.buttons = MOUSE_MSC_MAXBUTTON;
        else
                sc->hw.buttons = sc->nbuttons;
        sc->hw.iftype = MOUSE_IF_USB;
        sc->hw.type = MOUSE_MOUSE;
        sc->hw.model = MOUSE_MODEL_GENERIC;
        sc->hw.hwid = 0;
        sc->mode.protocol = MOUSE_PROTO_MSC;
        sc->mode.rate = -1;
        sc->mode.resolution = MOUSE_RES_UNKNOWN;
        sc->mode.accelfactor = 0;
        sc->mode.level = 0;
        sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
        sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
        sc->mode.syncmask[1] = MOUSE_MSC_SYNC;

        sc->status.flags = 0;
        sc->status.button = sc->status.obutton = 0;
        sc->status.dx = sc->status.dy = sc->status.dz = 0;

        sc->dev = make_dev(&ums_cdevsw, device_get_unit(self),
                        UID_ROOT, GID_OPERATOR,
                        0644, "ums%d", device_get_unit(self));

        callout_init(&sc->callout_handle, 0);
        if (usbd_get_quirks(uaa->device)->uq_flags & UQ_SPUR_BUT_UP) {
                DPRINTF(("%s: Spurious button up events\n",
                        device_get_nameunit(sc->sc_dev)));
                sc->flags |= UMS_SPUR_BUT_UP;
        }

        return 0;
}


static int
ums_detach(device_t self)
{
        struct ums_softc *sc = device_get_softc(self);

        if (sc->sc_enabled)
                ums_disable(sc);

        DPRINTF(("%s: disconnected\n", device_get_nameunit(self)));

        free(sc->sc_loc_btn, M_USB);
        free(sc->sc_ibuf, M_USB);

        /* someone waiting for data */
        /*
         * XXX If we wakeup the process here, the device will be gone by
         * the time the process gets a chance to notice. *_close and friends
         * should be fixed to handle this case.
         * Or we should do a delayed detach for this.
         * Does this delay now force tsleep to exit with an error?
         */
        if (sc->state & UMS_ASLEEP) {
                sc->state &= ~UMS_ASLEEP;
                wakeup(sc);
        }
        if (sc->state & UMS_SELECT) {
                sc->state &= ~UMS_SELECT;
                selwakeuppri(&sc->rsel, PZERO);
        }

        destroy_dev(sc->dev);

        return 0;
}

void
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, dw, dt;
        int buttons = 0;
        int i;

#define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i))

        DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status));
        DPRINTFN(5, ("ums_intr: data ="));
        for (i = 0; i < sc->sc_isize; i++)
                DPRINTFN(5, (" %02x", sc->sc_ibuf[i]));
        DPRINTFN(5, ("\n"));

        if (status == USBD_CANCELLED)
                return;

        if (status != USBD_NORMAL_COMPLETION) {
                DPRINTF(("ums_intr: status=%d\n", status));
                if (status == USBD_STALLED)
                    usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
                if(status != USBD_IOERROR)
                        return;
        }

        ibuf = sc->sc_ibuf;
        /*
         * The M$ Wireless Intellimouse 2.0 sends 1 extra leading byte of
         * data compared to most USB mice. This byte frequently switches
         * from 0x01 (usual state) to 0x02. I assume it is to allow
         * extra, non-standard, reporting (say battery-life). However
         * at the same time it generates a left-click message on the button
         * byte which causes spurious left-click's where there shouldn't be.
         * This should sort that.
         * Currently it's the only user of UMS_T so use it as an identifier.
         * We probably should switch to some more official quirk.
         *
         * UPDATE: This problem affects the M$ Wireless Notebook Optical Mouse,
         * too. However, the leading byte for this mouse is normally 0x11,
         * and the phantom mouse click occurs when its 0x14.
         */
        if (sc->flags & UMS_T) {
                if (sc->sc_iid) {
                        if (*ibuf++ == 0x02)
                                return;
                }
        } else if (sc->flags & UMS_SPUR_BUT_UP) {
                DPRINTFN(5, ("ums_intr: #### ibuf[0] =3D %d ####\n", *ibuf));
                if (*ibuf == 0x14 || *ibuf == 0x15)
                        return;
        } else {
                if (sc->sc_iid) {
                        if (*ibuf++ != sc->sc_iid)
                                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_T)
                dt = -hid_get_data(ibuf, &sc->sc_loc_t);
        else
                dt = 0;
        for (i = 0; i < sc->nbuttons; i++)
                if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
                        buttons |= (1 << UMS_BUT(i));

        if (dx || dy || dz || dt || dw || (sc->flags & UMS_Z)
            || buttons != sc->status.button) {
                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.dw += dw; */ /* idem */

                /* Discard data in case of full buffer */
                if (sc->qcount == sizeof(sc->qbuf)) {
                        DPRINTF(("Buffer full, discarded packet"));
                        return;
                }

   



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1219526002.17589.denwebmail-344>