📄 ums.c
字号:
void *p;{ struct ums_softc *sc = p; DPRINTF(("ums_disco: sc=%p\n", sc)); usbd_abort_pipe(sc->sc_intrpipe); sc->sc_disconnected = 1;}voidums_intr(reqh, addr, status) usbd_request_handle reqh; usbd_private_handle addr; usbd_status status;{ struct ums_softc *sc = addr; u_char *ibuf; int dx, dy, dz; u_char buttons = 0; int i;#if defined(__NetBSD__)#define UMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i)#elif defined(__FreeBSD__)#define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i))#endif DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status)); DPRINTFN(5, ("ums_intr: data = %02x %02x %02x\n", sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2])); if (status == USBD_CANCELLED) return; if (status != USBD_NORMAL_COMPLETION) { DPRINTF(("ums_intr: status=%d\n", status)); usbd_clear_endpoint_stall_async(sc->sc_intrpipe); return; } ibuf = sc->sc_ibuf; 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); for (i = 0; i < sc->nbuttons; i++) if (hid_get_data(ibuf, &sc->sc_loc_btn[i])) buttons |= (1 << UMS_BUT(i));#if defined(__NetBSD__) if (dx || dy || buttons != sc->sc_buttons) { DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n", dx, dy, dz, buttons)); sc->sc_buttons = buttons; if (sc->sc_wsmousedev) wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, dz);#elif defined(__FreeBSD__) if (dx || dy || dz || (sc->flags & UMS_Z) || buttons != sc->status.button) { DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n", dx, dy, dz, buttons)); sc->status.button = buttons; sc->status.dx += dx; sc->status.dy += dy; sc->status.dz += dz; /* Discard data in case of full buffer */ if (sc->qcount == sizeof(sc->qbuf)) { DPRINTF(("Buffer full, discarded packet")); return; } if (dx > 254) dx = 254; if (dx < -256) dx = -256; if (dy > 254) dy = 254; if (dy < -256) dy = -256; if (dz > 126) dz = 126; if (dz < -128) dz = -128; sc->qbuf[sc->qhead] = sc->mode.syncmask[1]; sc->qbuf[sc->qhead] |= ~buttons & MOUSE_MSC_BUTTONS; sc->qbuf[sc->qhead+1] = dx >> 1; sc->qbuf[sc->qhead+2] = dy >> 1; sc->qbuf[sc->qhead+3] = dx - (dx >> 1); sc->qbuf[sc->qhead+4] = dy - (dy >> 1); if (sc->mode.level == 1) { sc->qbuf[sc->qhead+5] = dz >> 1; sc->qbuf[sc->qhead+6] = dz - (dz >> 1); sc->qbuf[sc->qhead+7] = ((~buttons >> 3) & MOUSE_SYS_EXTBUTTONS); } sc->qhead += sc->mode.packetsize; sc->qcount += sc->mode.packetsize;#ifdef UMS_DEBUG if (sc->qhead > sizeof(sc->qbuf)) DPRINTF(("Buffer overrun! %d %d\n", sc->qhead, sizeof(sc->qbuf)));#endif /* wrap round at end of buffer */ if (sc->qhead >= sizeof(sc->qbuf)) sc->qhead = 0; /* someone waiting for data */ if (sc->state & UMS_ASLEEP) { sc->state &= ~UMS_ASLEEP; wakeup(sc); } if (sc->state & UMS_SELECT) { sc->state &= ~UMS_SELECT; selwakeup(&sc->rsel); }#endif }}static intums_enable(v) void *v;{ struct ums_softc *sc = v; usbd_status r; if (sc->sc_enabled) return EBUSY; sc->sc_enabled = 1;#if defined(__NetBSD__) sc->sc_buttons = 0;#elif defined(__FreeBSD__) sc->qcount = 0; sc->qhead = sc->qtail = 0; sc->status.flags = 0; sc->status.button = sc->status.obutton = 0; sc->status.dx = sc->status.dy = sc->status.dz = 0;#endif /* Set up interrupt pipe. */ r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf, sc->sc_isize, ums_intr); if (r != USBD_NORMAL_COMPLETION) { DPRINTF(("ums_enable: usbd_open_pipe_intr failed, error=%d\n", r)); sc->sc_enabled = 0; return (EIO); } usbd_set_disco(sc->sc_intrpipe, ums_disco, sc); return (0);}static voidums_disable(v) void *v;{ struct ums_softc *sc = v; /* Disable interrupts. */ usbd_abort_pipe(sc->sc_intrpipe); usbd_close_pipe(sc->sc_intrpipe); sc->sc_enabled = 0;#if defined(__FreeBSD__) if (sc->qcount != 0) DPRINTF(("Discarded %d bytes in queue\n", sc->qcount));#endif}#if defined(__NetBSD__)static intums_ioctl(v, cmd, data, flag, p) void *v; u_long cmd; caddr_t data; int flag; struct proc *p;{ switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = WSMOUSE_TYPE_USB; return (0); } return (-1);}#elif defined(__FreeBSD__)static intums_open(dev_t dev, int flag, int fmt, struct proc *p){ USB_GET_SC_OPEN(ums, UMSUNIT(dev), sc); return ums_enable(sc);}static intums_close(dev_t dev, int flag, int fmt, struct proc *p){ USB_GET_SC(ums, UMSUNIT(dev), sc); if (sc->sc_enabled) ums_disable(sc); return 0;}static intums_read(dev_t dev, struct uio *uio, int flag){ USB_GET_SC(ums, UMSUNIT(dev), sc); int s; char buf[sizeof(sc->qbuf)]; int l = 0; int error; s = splusb(); while (sc->qcount == 0 ) { /* NWH XXX non blocking I/O ?? if (non blocking I/O ) { splx(s); return EWOULDBLOCK; } else { */ sc->state |= UMS_ASLEEP; error = tsleep(sc, PZERO | PCATCH, "umsrea", 0); if (error) { splx(s); return error; } else if (!sc->sc_enabled) { splx(s); return EINTR; } } while ((sc->qcount > 0) && (uio->uio_resid > 0)) { l = (sc->qcount < uio->uio_resid? sc->qcount:uio->uio_resid); if (l > sizeof(buf)) l = sizeof(buf); if (l > sizeof(sc->qbuf) - sc->qtail) /* transfer till end of buf */ l = sizeof(sc->qbuf) - sc->qtail; splx(s); uiomove(&sc->qbuf[sc->qtail], l, uio); s = splusb(); if ( sc->qcount - l < 0 ) { DPRINTF(("qcount below 0, count=%d l=%d\n", sc->qcount, l)); sc->qcount = l; } sc->qcount -= l; /* remove the bytes from the buffer */ sc->qtail = (sc->qtail + l) % sizeof(sc->qbuf); } splx(s); return 0;}static intums_poll(dev_t dev, int events, struct proc *p){ USB_GET_SC(ums, UMSUNIT(dev), sc); int revents = 0; int s; s = splusb(); if (events & (POLLIN | POLLRDNORM)) { if (sc->qcount) { revents = events & (POLLIN | POLLRDNORM); } else { sc->state |= UMS_SELECT; selrecord(p, &sc->rsel); } } splx(s); return revents;} intums_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p){ USB_GET_SC(ums, UMSUNIT(dev), sc); int error = 0; int s; mousemode_t mode; switch(cmd) { case MOUSE_GETHWINFO: *(mousehw_t *)addr = sc->hw; break; case MOUSE_GETMODE: *(mousemode_t *)addr = sc->mode; break; case MOUSE_SETMODE: mode = *(mousemode_t *)addr; if (mode.level == -1) /* don't change the current setting */ ; else if ((mode.level < 0) || (mode.level > 1)) return (EINVAL); s = splusb(); sc->mode.level = mode.level; if (sc->mode.level == 0) { if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) sc->hw.buttons = MOUSE_MSC_MAXBUTTON; else sc->hw.buttons = sc->nbuttons; sc->mode.protocol = MOUSE_PROTO_MSC; sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; sc->mode.syncmask[1] = MOUSE_MSC_SYNC; } else if (sc->mode.level == 1) { if (sc->nbuttons > MOUSE_SYS_MAXBUTTON) sc->hw.buttons = MOUSE_SYS_MAXBUTTON; else sc->hw.buttons = sc->nbuttons; sc->mode.protocol = MOUSE_PROTO_SYSMOUSE; sc->mode.packetsize = MOUSE_SYS_PACKETSIZE; sc->mode.syncmask[0] = MOUSE_SYS_SYNCMASK; sc->mode.syncmask[1] = MOUSE_SYS_SYNC; } bzero(sc->qbuf, sizeof(sc->qbuf)); sc->qhead = sc->qtail = sc->qcount = 0; splx(s); break; case MOUSE_GETLEVEL: *(int *)addr = sc->mode.level; break; case MOUSE_SETLEVEL: if (*(int *)addr < 0 || *(int *)addr > 1) return (EINVAL); s = splusb(); sc->mode.level = *(int *)addr; if (sc->mode.level == 0) { if (sc->nbuttons > MOUSE_MSC_MAXBUTTON) sc->hw.buttons = MOUSE_MSC_MAXBUTTON; else sc->hw.buttons = sc->nbuttons; sc->mode.protocol = MOUSE_PROTO_MSC; sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; sc->mode.syncmask[0] = MOUSE_MSC_SYNCMASK; sc->mode.syncmask[1] = MOUSE_MSC_SYNC; } else if (sc->mode.level == 1) { if (sc->nbuttons > MOUSE_SYS_MAXBUTTON) sc->hw.buttons = MOUSE_SYS_MAXBUTTON; else sc->hw.buttons = sc->nbuttons; sc->mode.protocol = MOUSE_PROTO_SYSMOUSE; sc->mode.packetsize = MOUSE_SYS_PACKETSIZE; sc->mode.syncmask[0] = MOUSE_SYS_SYNCMASK; sc->mode.syncmask[1] = MOUSE_SYS_SYNC; } bzero(sc->qbuf, sizeof(sc->qbuf)); sc->qhead = sc->qtail = sc->qcount = 0; splx(s); break; case MOUSE_GETSTATUS: { mousestatus_t *status = (mousestatus_t *) addr; s = splusb(); *status = sc->status; sc->status.obutton = sc->status.button; sc->status.button = 0; sc->status.dx = sc->status.dy = sc->status.dz = 0; splx(s); if (status->dx || status->dy || status->dz) status->flags |= MOUSE_POSCHANGED; if (status->button != status->obutton) status->flags |= MOUSE_BUTTONSCHANGED; break; } default: error = ENOTTY; } return error;}#endif#if defined(__FreeBSD__)CDEV_DRIVER_MODULE(ums, uhub, ums_driver, ums_devclass, UMS_CDEV_MAJOR, ums_cdevsw, usbd_driver_load, 0);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -