This diff adds touchscreen support to ums(4). This works great for newer Gunze USB touchscreens in "WHQL" mode. That means that it is Microsoft approved, so it should be some sort of standard way to hook these things up. Rather than hardcoding the calibration for the device I have (like uts(4) seems to) I make it default to raw mode. At least for the device that I have that isn't too far off.
ok? Index: usb/hidms.c =================================================================== RCS file: /cvs/src/sys/dev/usb/hidms.c,v retrieving revision 1.1 diff -u -p -r1.1 hidms.c --- usb/hidms.c 31 Jul 2010 16:04:50 -0000 1.1 +++ usb/hidms.c 2 Mar 2011 20:14:37 -0000 @@ -63,7 +63,8 @@ int hidmsdebug = 0; #define HIDMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i) -#define NOTMOUSE(f) (((f) & (HIO_CONST | HIO_RELATIVE)) != HIO_RELATIVE) +#define MOUSE_FLAGS_MASK (HIO_CONST | HIO_RELATIVE) +#define NOTMOUSE(f) (((f) & MOUSE_FLAGS_MASK) != HIO_RELATIVE) int hidms_setup(struct device *self, struct hidms *ms, uint32_t quirks, @@ -73,6 +74,7 @@ hidms_setup(struct device *self, struct int i, wheel, twheel; ms->sc_device = self; + ms->sc_rawmode = 1; if (quirks & UQ_MS_REVZ) ms->sc_flags |= HIDMS_REVZ; @@ -86,7 +88,13 @@ hidms_setup(struct device *self, struct printf("\n%s: mouse has no X report\n", self->dv_xname); return ENXIO; } - if (NOTMOUSE(flags)) { + switch(flags & MOUSE_FLAGS_MASK) { + case 0: + ms->sc_flags |= HIDMS_ABSX; + break; + case HIO_RELATIVE: + break; + default: printf("\n%s: X report 0x%04x not supported\n", self->dv_xname, flags); return ENXIO; @@ -97,7 +105,13 @@ hidms_setup(struct device *self, struct printf("\n%s: mouse has no Y report\n", self->dv_xname); return ENXIO; } - if (NOTMOUSE(flags)) { + switch(flags & MOUSE_FLAGS_MASK) { + case 0: + ms->sc_flags |= HIDMS_ABSY; + break; + case HIO_RELATIVE: + break; + default: printf("\n%s: Y report 0x%04x not supported\n", self->dv_xname, flags); return ENXIO; @@ -225,7 +239,7 @@ hidms_attach(struct hidms *ms, const str printf("\n"); #ifdef HIDMS_DEBUG - DPRINTF(("hidms_attach: sc=%p\n", sc)); + DPRINTF(("hidms_attach: ms=%p\n", ms)); DPRINTF(("hidms_attach: X\t%d/%d\n", ms->sc_loc_x.pos, ms->sc_loc_x.size)); DPRINTF(("hidms_attach: Y\t%d/%d\n", @@ -252,7 +266,7 @@ hidms_detach(struct hidms *ms, int flags { int rv = 0; - DPRINTF(("hidms_detach: sc=%p flags=%d\n", sc, flags)); + DPRINTF(("hidms_detach: ms=%p flags=%d\n", ms, flags)); /* No need to do reference counting of hidms, wsmouse has all the goo */ if (ms->sc_wsmousedev != NULL) @@ -266,6 +280,7 @@ hidms_input(struct hidms *ms, uint8_t *d { int dx, dy, dz, dw; u_int32_t buttons = 0; + int flags; int i, s; DPRINTFN(5,("hidms_input: len=%d\n", len)); @@ -292,16 +307,40 @@ hidms_input(struct hidms *ms, uint8_t *d return; } + flags = WSMOUSE_INPUT_DELTA; + if (ms->sc_flags & HIDMS_ABSX) + flags |= WSMOUSE_INPUT_ABSOLUTE_X; + if (ms->sc_flags & HIDMS_ABSY) + flags |= WSMOUSE_INPUT_ABSOLUTE_Y; + dx = hid_get_data(data, &ms->sc_loc_x); dy = -hid_get_data(data, &ms->sc_loc_y); dz = hid_get_data(data, &ms->sc_loc_z); dw = hid_get_data(data, &ms->sc_loc_w); + if (ms->sc_flags & HIDMS_ABSY) + dy = -dy; if (ms->sc_flags & HIDMS_REVZ) dz = -dz; if (ms->sc_flags & HIDMS_REVW) dw = -dw; + if (ms->sc_tsscale.swapxy && !ms->sc_rawmode) { + int tmp = dx; + dx = dy; + dy = tmp; + } + + if (!ms->sc_rawmode && + (ms->sc_tsscale.maxx - ms->sc_tsscale.minx) != 0 && + (ms->sc_tsscale.maxy - ms->sc_tsscale.miny) != 0) { + /* Scale down to the screen resolution. */ + dx = ((dx - ms->sc_tsscale.minx) * ms->sc_tsscale.resx) / + (ms->sc_tsscale.maxx - ms->sc_tsscale.minx); + dy = ((dy - ms->sc_tsscale.miny) * ms->sc_tsscale.resy) / + (ms->sc_tsscale.maxy - ms->sc_tsscale.miny); + } + for (i = 0; i < ms->sc_num_buttons; i++) if (hid_get_data(data, &ms->sc_loc_btn[i])) buttons |= (1 << HIDMS_BUT(i)); @@ -314,7 +353,7 @@ hidms_input(struct hidms *ms, uint8_t *d if (ms->sc_wsmousedev != NULL) { s = spltty(); wsmouse_input(ms->sc_wsmousedev, buttons, - dx, dy, dz, dw, WSMOUSE_INPUT_DELTA); + dx, dy, dz, dw, flags); splx(s); } } @@ -335,7 +374,47 @@ int hidms_ioctl(struct hidms *ms, u_long cmd, caddr_t data, int flag, struct proc *p) { + struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data; + switch (cmd) { + case WSMOUSEIO_SCALIBCOORDS: + if (!(wsmc->minx >= 0 && wsmc->maxx >= 0 && + wsmc->miny >= 0 && wsmc->maxy >= 0 && + wsmc->resx >= 0 && wsmc->resy >= 0 && + wsmc->minx < 32768 && wsmc->maxx < 32768 && + wsmc->miny < 32768 && wsmc->maxy < 32768 && + (wsmc->maxx - wsmc->minx) != 0 && + (wsmc->maxy - wsmc->miny) != 0 && + wsmc->resx < 32768 && wsmc->resy < 32768 && + wsmc->swapxy >= 0 && wsmc->swapxy <= 1 && + wsmc->samplelen >= 0 && wsmc->samplelen <= 1)) + return (EINVAL); + + ms->sc_tsscale.minx = wsmc->minx; + ms->sc_tsscale.maxx = wsmc->maxx; + ms->sc_tsscale.miny = wsmc->miny; + ms->sc_tsscale.maxy = wsmc->maxy; + ms->sc_tsscale.swapxy = wsmc->swapxy; + ms->sc_tsscale.resx = wsmc->resx; + ms->sc_tsscale.resy = wsmc->resy; + ms->sc_rawmode = wsmc->samplelen; + return 0; + case WSMOUSEIO_GCALIBCOORDS: + wsmc->minx = ms->sc_tsscale.minx; + wsmc->maxx = ms->sc_tsscale.maxx; + wsmc->miny = ms->sc_tsscale.miny; + wsmc->maxy = ms->sc_tsscale.maxy; + wsmc->swapxy = ms->sc_tsscale.swapxy; + wsmc->resx = ms->sc_tsscale.resx; + wsmc->resy = ms->sc_tsscale.resy; + wsmc->samplelen = ms->sc_rawmode; + return 0; + case WSMOUSEIO_GTYPE: + if (ms->sc_flags & HIDMS_ABSX && ms->sc_flags & HIDMS_ABSY) { + *(u_int *)data = WSMOUSE_TYPE_TPANEL; + return 0; + } + /* FALLTHROUGH */ default: return -1; } Index: usb/ums.c =================================================================== RCS file: /cvs/src/sys/dev/usb/ums.c,v retrieving revision 1.33 diff -u -p -r1.33 ums.c --- usb/ums.c 2 Aug 2010 23:17:34 -0000 1.33 +++ usb/ums.c 2 Mar 2011 20:14:37 -0000 @@ -227,15 +227,18 @@ ums_ioctl(void *v, u_long cmd, caddr_t d 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: - rc = uhidev_ioctl(&sc->sc_hdev, cmd, data, flag, p); - if (rc != -1) - return rc; - else - return hidms_ioctl(ms, cmd, data, flag, p); + return -1; } } Index: bluetooth/btms.c =================================================================== RCS file: /cvs/src/sys/dev/bluetooth/btms.c,v retrieving revision 1.5 diff -u -p -r1.5 btms.c --- bluetooth/btms.c 31 Jul 2010 16:04:50 -0000 1.5 +++ bluetooth/btms.c 2 Mar 2011 20:14:37 -0000 @@ -170,13 +170,18 @@ btms_wsmouse_ioctl(void *self, u_long cm { struct btms_softc *sc = (struct btms_softc *)self; struct hidms *ms = &sc->sc_ms; + int rc; + + rc = hidms_ioctl(ms, cmd, data, flag, p); + if (rc != -1) + return rc; switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = WSMOUSE_TYPE_BLUETOOTH; return 0; default: - return hidms_ioctl(ms, cmd, data, flag, p); + return -1; } }