From 737d705b8780db06a36e2cfc49360998fb7264ee Mon Sep 17 00:00:00 2001 From: jcs Date: Sat, 25 Aug 2018 20:31:31 +0000 Subject: [PATCH] Add umt(4) for USB Windows Precision Touchpad devices Based on imt(4) Rename HIDMT_INPUT_MODE_MT to HIDMT_INPUT_MODE_MT_TOUCHPAD ok deraadt --- share/man/man4/Makefile | 6 +- share/man/man4/uhidev.4 | 6 +- share/man/man4/umt.4 | 47 +++++++ share/man/man4/usb.4 | 6 +- sys/arch/amd64/conf/GENERIC | 4 +- sys/dev/hid/hidmt.c | 4 +- sys/dev/hid/hidmtvar.h | 5 +- sys/dev/i2c/imt.c | 4 +- sys/dev/usb/files.usb | 7 +- sys/dev/usb/umt.c | 253 ++++++++++++++++++++++++++++++++++++ 10 files changed, 327 insertions(+), 15 deletions(-) create mode 100644 share/man/man4/umt.4 create mode 100644 sys/dev/usb/umt.c diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index fdb3ca2e130..8ed455bc546 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.690 2018/08/19 11:42:33 anton Exp $ +# $OpenBSD: Makefile,v 1.691 2018/08/25 20:31:31 jcs Exp $ MAN= aac.4 ac97.4 acphy.4 acrtc.4 \ acpi.4 acpiac.4 acpials.4 acpiasus.4 acpibat.4 \ @@ -75,8 +75,8 @@ MAN= aac.4 ac97.4 acphy.4 acrtc.4 \ uftdi.4 ugen.4 ugl.4 ugold.4 uguru.4 uhci.4 uhid.4 uhidev.4 uipaq.4 \ uk.4 ukbd.4 \ ukphy.4 ulpt.4 umass.4 umb.4 umbg.4 umcs.4 umct.4 umidi.4 umodem.4 \ - ums.4 umsm.4 unix.4 uonerng.4 uow.4 uoaklux.4 uoakrh.4 uoakv.4 upd.4 \ - upgt.4 upl.4 uplcom.4 ural.4 ure.4 url.4 urlphy.4 \ + ums.4 umsm.4 umt.4 unix.4 uonerng.4 uow.4 uoaklux.4 uoakrh.4 uoakv.4 \ + upd.4 upgt.4 upl.4 uplcom.4 ural.4 ure.4 url.4 urlphy.4 \ urndis.4 urng.4 urtw.4 urtwn.4 usb.4 uscom.4 uslcom.4 usps.4 \ uthum.4 uticom.4 utpms.4 utwitch.4 utrh.4 uts.4 utvfu.4 uvideo.4 \ uvisor.4 uvscom.4 uwacom.4 \ diff --git a/share/man/man4/uhidev.4 b/share/man/man4/uhidev.4 index eeb5289ec31..7dafba8fa22 100644 --- a/share/man/man4/uhidev.4 +++ b/share/man/man4/uhidev.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: uhidev.4,v 1.9 2016/09/12 08:12:06 mpi Exp $ +.\" $OpenBSD: uhidev.4,v 1.10 2018/08/25 20:31:31 jcs Exp $ .\" $NetBSD: uhidev.4,v 1.2 2001/12/29 03:06:41 augustss Exp $ .\" .\" Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: September 12 2016 $ +.Dd $Mdocdate: August 25 2018 $ .Dt UHIDEV 4 .Os .Sh NAME @@ -42,6 +42,7 @@ .Cd "uhid* at uhidev?" .Cd "ukbd* at uhidev?" .Cd "ums* at uhidev?" +.Cd "umt* at uhidev?" .Cd "uoaklux* at uhidev?" .Cd "uoakrh* at uhidev?" .Cd "uoakv* at uhidev?" @@ -73,6 +74,7 @@ only dispatches data to them based on the report id. .Xr uhid 4 , .Xr ukbd 4 , .Xr ums 4 , +.Xr umt 4 , .Xr uoaklux 4 , .Xr uoakrh 4 , .Xr uoakv 4 , diff --git a/share/man/man4/umt.4 b/share/man/man4/umt.4 new file mode 100644 index 00000000000..7abfe30579c --- /dev/null +++ b/share/man/man4/umt.4 @@ -0,0 +1,47 @@ +.\" $OpenBSD: umt.4,v 1.1 2018/08/25 20:31:31 jcs Exp $ +.\" +.\" Copyright (c) 2016-2018 joshua stein +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: August 25 2018 $ +.Dt UMT 4 +.Os +.Sh NAME +.Nm umt +.Nd USB HID multitouch touchpad devices +.Sh SYNOPSIS +.Cd "umt* at uhidev?" +.Cd "wsmouse* at umt? mux 0" +.Sh DESCRIPTION +The +.Nm +driver provides support for USB HID touchpads conforming to the +Windows Precision Touchpad standard. +Access to these devices is through the +.Xr wscons 4 +driver. +.Sh SEE ALSO +.Xr uhidev 4 , +.Xr ums 4 , +.Xr wsmouse 4 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Ox 6.4 . +.Sh AUTHORS +The +.Nm +driver was written by +.An joshua stein Aq Mt jcs@openbsd.org . diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4 index 0cbecdea2a5..30e6e7f492a 100644 --- a/share/man/man4/usb.4 +++ b/share/man/man4/usb.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: usb.4,v 1.188 2018/08/03 01:50:14 kevlo Exp $ +.\" $OpenBSD: usb.4,v 1.189 2018/08/25 20:31:31 jcs Exp $ .\" $NetBSD: usb.4,v 1.15 1999/07/29 14:20:32 augustss Exp $ .\" .\" Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: August 3 2018 $ +.Dd $Mdocdate: August 25 2018 $ .Dt USB 4 .Os .Sh NAME @@ -248,6 +248,8 @@ Base driver for all Human Interface Devices USB keyboards that follow the boot protocol .It Xr ums 4 USB HID mouse, touchscreen and digitiser devices +.It Xr umt 4 +USB HID multitouch touchpad devices .It Xr uoaklux 4 Toradex OAK USB illuminance sensor .It Xr uoakrh 4 diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index ba12d68d77d..67726159419 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.460 2018/08/22 15:38:46 mpi Exp $ +# $OpenBSD: GENERIC,v 1.461 2018/08/25 20:31:31 jcs Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -257,6 +257,8 @@ wsmouse* at ubcmtp? mux 0 uhidev* at uhub? # Human Interface Devices ums* at uhidev? # USB mouse wsmouse* at ums? mux 0 +umt* at uhidev? # USB multitouch touchpad +wsmouse* at umt? mux 0 uts* at uhub? # USB touchscreen wsmouse* at uts? mux 0 uwacom* at uhidev? # USB Wacom tablet diff --git a/sys/dev/hid/hidmt.c b/sys/dev/hid/hidmt.c index 6638d395d5d..3ca4cc0f97b 100644 --- a/sys/dev/hid/hidmt.c +++ b/sys/dev/hid/hidmt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hidmt.c,v 1.8 2018/08/25 18:32:05 jcs Exp $ */ +/* $OpenBSD: hidmt.c,v 1.9 2018/08/25 20:31:31 jcs Exp $ */ /* * HID multitouch driver for devices conforming to Windows Precision Touchpad * standard @@ -221,7 +221,7 @@ hidmt_setup(struct device *self, struct hidmt *mt, void *desc, int dlen) return 1; } - if (hidmt_set_input_mode(mt, HIDMT_INPUT_MODE_MT)) { + if (hidmt_set_input_mode(mt, HIDMT_INPUT_MODE_MT_TOUCHPAD)) { printf("\n%s: switch to multitouch mode failed\n", self->dv_xname); return 1; diff --git a/sys/dev/hid/hidmtvar.h b/sys/dev/hid/hidmtvar.h index 66d95eda2a2..f99f22a1e49 100644 --- a/sys/dev/hid/hidmtvar.h +++ b/sys/dev/hid/hidmtvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hidmtvar.h,v 1.6 2018/08/25 18:32:05 jcs Exp $ */ +/* $OpenBSD: hidmtvar.h,v 1.7 2018/08/25 20:31:31 jcs Exp $ */ /* * Copyright (c) 2016 joshua stein * @@ -67,7 +67,8 @@ struct hidmt { }; int hidmt_set_input_mode(struct hidmt *, uint16_t); -#define HIDMT_INPUT_MODE_MT 0x3 +#define HIDMT_INPUT_MODE_MT_TOUCHSCREEN 0x2 +#define HIDMT_INPUT_MODE_MT_TOUCHPAD 0x3 void hidmt_attach(struct hidmt *, const struct wsmouse_accessops *); int hidmt_detach(struct hidmt *, int); diff --git a/sys/dev/i2c/imt.c b/sys/dev/i2c/imt.c index debcffc60c5..38169837338 100644 --- a/sys/dev/i2c/imt.c +++ b/sys/dev/i2c/imt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imt.c,v 1.3 2018/08/25 18:32:05 jcs Exp $ */ +/* $OpenBSD: imt.c,v 1.4 2018/08/25 20:31:31 jcs Exp $ */ /* * HID-over-i2c multitouch trackpad driver for devices conforming to * Windows Precision Touchpad standard @@ -218,7 +218,7 @@ imt_enable(void *v) rv = ihidev_open(&sc->sc_hdev); - hidmt_set_input_mode(mt, HIDMT_INPUT_MODE_MT); + hidmt_set_input_mode(mt, HIDMT_INPUT_MODE_MT_TOUCHPAD); return rv; } diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb index 28cb17c3d12..723b8a42915 100644 --- a/sys/dev/usb/files.usb +++ b/sys/dev/usb/files.usb @@ -1,4 +1,4 @@ -# $OpenBSD: files.usb,v 1.135 2018/08/03 01:50:15 kevlo Exp $ +# $OpenBSD: files.usb,v 1.136 2018/08/25 20:31:31 jcs Exp $ # $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $ # # Config file and device description for machine-independent USB code. @@ -87,6 +87,11 @@ device ums: hid, hidms, wsmousedev attach ums at uhidbus file dev/usb/ums.c ums +# HID Multitouch Trackpad +device umt: hid, hidmt, wsmousedev +attach umt at uhidbus +file dev/usb/umt.c umt + # USB Touchscreen device uts: wsmousedev attach uts at uhub diff --git a/sys/dev/usb/umt.c b/sys/dev/usb/umt.c new file mode 100644 index 00000000000..3f6060a0a21 --- /dev/null +++ b/sys/dev/usb/umt.c @@ -0,0 +1,253 @@ +/* $OpenBSD: umt.c,v 1.1 2018/08/25 20:31:31 jcs Exp $ */ +/* + * USB multitouch touchpad driver for devices conforming to + * Windows Precision Touchpad standard + * + * https://msdn.microsoft.com/en-us/library/windows/hardware/dn467314%28v=vs.85%29.aspx + * + * Copyright (c) 2016-2018 joshua stein + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +struct umt_softc { + struct uhidev sc_hdev; + struct hidmt sc_mt; + + int sc_rep_input; + int sc_rep_config; + int sc_rep_cap; +}; + +int umt_enable(void *); +int umt_open(struct uhidev *); +void umt_intr(struct uhidev *, void *, u_int); +void umt_disable(void *); +int umt_ioctl(void *, u_long, caddr_t, int, struct proc *); + +const struct wsmouse_accessops umt_accessops = { + umt_enable, + umt_ioctl, + umt_disable, +}; + +int umt_match(struct device *, void *, void *); +int umt_find_winptp_reports(struct uhidev_softc *, void *, int, + struct umt_softc *); +void umt_attach(struct device *, struct device *, void *); +int umt_hidev_get_report(struct device *, int, int, void *, int); +int umt_hidev_set_report(struct device *, int, int, void *, int); +int umt_detach(struct device *, int); + +struct cfdriver umt_cd = { + NULL, "umt", DV_DULL +}; + +const struct cfattach umt_ca = { + sizeof(struct umt_softc), + umt_match, + umt_attach, + umt_detach +}; + +int +umt_match(struct device *parent, void *match, void *aux) +{ + struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; + int size; + void *desc; + + if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID) { + uhidev_get_report_desc(uha->parent, &desc, &size); + if (umt_find_winptp_reports(uha->parent, desc, size, NULL)) + return (UMATCH_DEVCLASS_DEVSUBCLASS); + } + + return (UMATCH_NONE); +} + +int +umt_find_winptp_reports(struct uhidev_softc *parent, void *desc, int size, + struct umt_softc *sc) +{ + int repid; + int input = 0, conf = 0, cap = 0; + + if (sc != NULL) { + sc->sc_rep_input = -1; + sc->sc_rep_config = -1; + sc->sc_rep_cap = -1; + } + + for (repid = 0; repid < parent->sc_nrepid; repid++) { + if (hid_report_size(desc, size, hid_input, repid) == 0 && + hid_report_size(desc, size, hid_output, repid) == 0 && + hid_report_size(desc, size, hid_feature, repid) == 0) + continue; + + if (hid_is_collection(desc, size, repid, + HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHPAD))) { + input = 1; + if (sc != NULL && sc->sc_rep_input == -1) + sc->sc_rep_input = repid; + } else if (hid_is_collection(desc, size, repid, + HID_USAGE2(HUP_DIGITIZERS, HUD_CONFIG))) { + conf = 1; + if (sc != NULL && sc->sc_rep_config == -1) + sc->sc_rep_config = repid; + } + + /* capabilities report could be anywhere */ + if (hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, + HUD_CONTACT_MAX), repid, hid_feature, NULL, NULL)) { + cap = 1; + if (sc != NULL && sc->sc_rep_cap == -1) + sc->sc_rep_cap = repid; + } + } + + return (conf && input && cap); +} + +void +umt_attach(struct device *parent, struct device *self, void *aux) +{ + struct umt_softc *sc = (struct umt_softc *)self; + struct hidmt *mt = &sc->sc_mt; + struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; + int size; + void *desc; + + sc->sc_hdev.sc_intr = umt_intr; + sc->sc_hdev.sc_parent = uha->parent; + + uhidev_get_report_desc(uha->parent, &desc, &size); + umt_find_winptp_reports(uha->parent, desc, size, sc); + + memset(mt, 0, sizeof(sc->sc_mt)); + + /* assume everything has "natural scrolling" where Y axis is reversed */ + mt->sc_flags = HIDMT_REVY; + + mt->hidev_report_type_conv = uhidev_report_type_conv; + mt->hidev_get_report = umt_hidev_get_report; + mt->hidev_set_report = umt_hidev_set_report; + mt->sc_rep_input = sc->sc_rep_input; + mt->sc_rep_config = sc->sc_rep_config; + mt->sc_rep_cap = sc->sc_rep_cap; + + if (hidmt_setup(self, mt, desc, size) != 0) + return; + + hidmt_attach(mt, &umt_accessops); +} + +int +umt_hidev_get_report(struct device *self, int type, int id, void *data, int len) +{ + struct umt_softc *sc = (struct umt_softc *)self; + int ret; + + ret = uhidev_get_report(sc->sc_hdev.sc_parent, type, id, data, len); + return (ret < len); +} + +int +umt_hidev_set_report(struct device *self, int type, int id, void *data, int len) +{ + struct umt_softc *sc = (struct umt_softc *)self; + int ret; + + ret = uhidev_set_report(sc->sc_hdev.sc_parent, type, id, data, len); + return (ret < len); +} + +int +umt_detach(struct device *self, int flags) +{ + struct umt_softc *sc = (struct umt_softc *)self; + struct hidmt *mt = &sc->sc_mt; + + return hidmt_detach(mt, flags); +} + +void +umt_intr(struct uhidev *dev, void *buf, u_int len) +{ + struct umt_softc *sc = (struct umt_softc *)dev; + struct hidmt *mt = &sc->sc_mt; + + if (!mt->sc_enabled) + return; + + hidmt_input(mt, (uint8_t *)buf, len); +} + +int +umt_enable(void *v) +{ + struct umt_softc *sc = v; + struct hidmt *mt = &sc->sc_mt; + int rv; + + if ((rv = hidmt_enable(mt)) != 0) + return rv; + + rv = uhidev_open(&sc->sc_hdev); + + hidmt_set_input_mode(mt, HIDMT_INPUT_MODE_MT_TOUCHPAD); + + return rv; +} + +void +umt_disable(void *v) +{ + struct umt_softc *sc = v; + struct hidmt *mt = &sc->sc_mt; + + hidmt_disable(mt); + uhidev_close(&sc->sc_hdev); +} + +int +umt_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct umt_softc *sc = v; + struct hidmt *mt = &sc->sc_mt; + int rc; + + rc = uhidev_ioctl(&sc->sc_hdev, cmd, data, flag, p); + if (rc != -1) + return rc; + + return hidmt_ioctl(mt, cmd, data, flag, p); +} -- 2.20.1