USB_SET_REPORT ioctls in ukbd and ums.
This allows usbhidctl to be used on these devices e.g. to dump the report
descriptor of troublesome models.
ok deraadt@
-/* $OpenBSD: uhid.c,v 1.48 2010/07/26 01:56:27 guenther Exp $ */
+/* $OpenBSD: uhid.c,v 1.49 2010/08/02 23:17:34 miod Exp $ */
/* $NetBSD: uhid.c,v 1.57 2003/03/11 16:44:00 augustss Exp $ */
/*
struct uhid_softc {
struct uhidev sc_hdev;
- int sc_isize;
- int sc_osize;
- int sc_fsize;
-
u_char *sc_obuf;
struct clist sc_q;
uhidev_get_report_desc(uha->parent, &desc, &size);
repid = uha->reportid;
- sc->sc_isize = hid_report_size(desc, size, hid_input, repid);
- sc->sc_osize = hid_report_size(desc, size, hid_output, repid);
- sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid);
+ sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
+ sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
+ sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
printf(": input=%d, output=%d, feature=%d\n",
- sc->sc_isize, sc->sc_osize, sc->sc_fsize);
+ sc->sc_hdev.sc_isize, sc->sc_hdev.sc_osize, sc->sc_hdev.sc_fsize);
}
int
clalloc(&sc->sc_q, UHID_BSIZE, 0);
- sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
+ sc->sc_obuf = malloc(sc->sc_hdev.sc_osize, M_USBDEV, M_WAITOK);
sc->sc_state &= ~UHID_IMMED;
sc->sc_async = NULL;
DPRINTFN(1, ("uhidread immed\n"));
extra = sc->sc_hdev.sc_report_id != 0;
err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
- buffer, sc->sc_isize + extra);
+ buffer, sc->sc_hdev.sc_isize + extra);
if (err)
return (EIO);
- return (uiomove(buffer+extra, sc->sc_isize, uio));
+ return (uiomove(buffer+extra, sc->sc_hdev.sc_isize, uio));
}
s = splusb();
if (sc->sc_dying)
return (EIO);
- size = sc->sc_osize;
+ size = sc->sc_hdev.sc_osize;
error = 0;
if (uio->uio_resid != size)
return (EINVAL);
uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr,
int flag, struct proc *p)
{
- struct usb_ctl_report_desc *rd;
- struct usb_ctl_report *re;
u_char buffer[UHID_CHUNK];
int size, extra;
usbd_status err;
- void *desc;
+ int rc;
DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
return (EPERM);
break;
- case USB_GET_REPORT_DESC:
- uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
- rd = (struct usb_ctl_report_desc *)addr;
- size = min(size, sizeof rd->ucrd_data);
- rd->ucrd_size = size;
- memcpy(rd->ucrd_data, desc, size);
- break;
-
case USB_SET_IMMED:
if (*(int *)addr) {
extra = sc->sc_hdev.sc_report_id != 0;
err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
- buffer, sc->sc_isize + extra);
+ buffer, sc->sc_hdev.sc_isize + extra);
if (err)
return (EOPNOTSUPP);
sc->sc_state &= ~UHID_IMMED;
break;
- case USB_GET_REPORT:
- re = (struct usb_ctl_report *)addr;
- switch (re->ucr_report) {
- case UHID_INPUT_REPORT:
- size = sc->sc_isize;
- break;
- case UHID_OUTPUT_REPORT:
- size = sc->sc_osize;
- break;
- case UHID_FEATURE_REPORT:
- size = sc->sc_fsize;
- break;
- default:
- return (EINVAL);
- }
- extra = sc->sc_hdev.sc_report_id != 0;
- err = uhidev_get_report(&sc->sc_hdev, re->ucr_report,
- re->ucr_data, size + extra);
- if (extra)
- memcpy(re->ucr_data, re->ucr_data+1, size);
- if (err)
- return (EIO);
- break;
-
- case USB_SET_REPORT:
- re = (struct usb_ctl_report *)addr;
- switch (re->ucr_report) {
- case UHID_INPUT_REPORT:
- size = sc->sc_isize;
- break;
- case UHID_OUTPUT_REPORT:
- size = sc->sc_osize;
- break;
- case UHID_FEATURE_REPORT:
- size = sc->sc_fsize;
- break;
- default:
- return (EINVAL);
- }
- err = uhidev_set_report(&sc->sc_hdev, re->ucr_report,
- re->ucr_data, size);
- if (err)
- return (EIO);
- break;
-
- case USB_GET_REPORT_ID:
- *(int *)addr = sc->sc_hdev.sc_report_id;
- break;
-
case USB_GET_DEVICEINFO:
usbd_fill_deviceinfo(sc->sc_hdev.sc_parent->sc_udev,
(struct usb_device_info *)addr, 1);
break;
}
+ case USB_GET_REPORT_DESC:
+ case USB_GET_REPORT:
+ case USB_SET_REPORT:
+ case USB_GET_REPORT_ID:
default:
- return (EINVAL);
+ rc = uhidev_ioctl(&sc->sc_hdev, cmd, addr, flag, p);
+ if (rc == -1)
+ rc = EINVAL;
+ return rc;
}
return (0);
}
-/* $OpenBSD: uhidev.c,v 1.37 2009/11/23 19:26:54 yuo Exp $ */
+/* $OpenBSD: uhidev.c,v 1.38 2010/08/02 23:17:34 miod Exp $ */
/* $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $ */
/*
return usbd_intr_transfer(sc->sc_owxfer, sc->sc_opipe, 0,
USBD_NO_TIMEOUT, data, &len, "uhidevwi");
}
+
+int
+uhidev_ioctl(struct uhidev *sc, u_long cmd, caddr_t addr, int flag,
+ struct proc *p)
+{
+ struct usb_ctl_report_desc *rd;
+ struct usb_ctl_report *re;
+ int size, extra;
+ usbd_status err;
+ void *desc;
+
+ switch (cmd) {
+ case USB_GET_REPORT_DESC:
+ uhidev_get_report_desc(sc->sc_parent, &desc, &size);
+ rd = (struct usb_ctl_report_desc *)addr;
+ size = min(size, sizeof rd->ucrd_data);
+ rd->ucrd_size = size;
+ memcpy(rd->ucrd_data, desc, size);
+ break;
+ case USB_GET_REPORT:
+ re = (struct usb_ctl_report *)addr;
+ switch (re->ucr_report) {
+ case UHID_INPUT_REPORT:
+ size = sc->sc_isize;
+ break;
+ case UHID_OUTPUT_REPORT:
+ size = sc->sc_osize;
+ break;
+ case UHID_FEATURE_REPORT:
+ size = sc->sc_fsize;
+ break;
+ default:
+ return EINVAL;
+ }
+ extra = sc->sc_report_id != 0;
+ err = uhidev_get_report(sc, re->ucr_report, re->ucr_data,
+ size + extra);
+ if (extra)
+ memcpy(re->ucr_data, re->ucr_data + 1, size);
+ if (err)
+ return EIO;
+ break;
+ case USB_SET_REPORT:
+ re = (struct usb_ctl_report *)addr;
+ switch (re->ucr_report) {
+ case UHID_INPUT_REPORT:
+ size = sc->sc_isize;
+ break;
+ case UHID_OUTPUT_REPORT:
+ size = sc->sc_osize;
+ break;
+ case UHID_FEATURE_REPORT:
+ size = sc->sc_fsize;
+ break;
+ default:
+ return EINVAL;
+ }
+ err = uhidev_set_report(sc, re->ucr_report, re->ucr_data, size);
+ if (err)
+ return EIO;
+ break;
+ case USB_GET_REPORT_ID:
+ *(int *)addr = sc->sc_report_id;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
-/* $OpenBSD: uhidev.h,v 1.10 2008/06/26 05:42:18 ray Exp $ */
+/* $OpenBSD: uhidev.h,v 1.11 2010/08/02 23:17:34 miod Exp $ */
/* $NetBSD: uhidev.h,v 1.3 2002/10/08 09:56:17 dan Exp $ */
/*
int sc_in_rep_size;
#define UHIDEV_OPEN 0x01 /* device is open */
void (*sc_intr)(struct uhidev *, void *, u_int);
+
+ int sc_isize;
+ int sc_osize;
+ int sc_fsize;
};
struct uhidev_attach_arg {
void uhidev_get_report_desc(struct uhidev_softc *, void **, int *);
int uhidev_open(struct uhidev *);
void uhidev_close(struct uhidev *);
+int uhidev_ioctl(struct uhidev *, u_long, caddr_t, int, struct proc *);
usbd_status uhidev_set_report(struct uhidev *scd, int type, void *data,int len);
void uhidev_set_report_async(struct uhidev *scd, int type, void *data, int len);
usbd_status uhidev_get_report(struct uhidev *scd, int type, void *data,int len);
-/* $OpenBSD: ukbd.c,v 1.52 2010/07/31 16:04:50 miod Exp $ */
+/* $OpenBSD: ukbd.c,v 1.53 2010/08/02 23:17:34 miod Exp $ */
/* $NetBSD: ukbd.c,v 1.85 2003/03/11 16:44:00 augustss Exp $ */
/*
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
usb_hid_descriptor_t *hid;
u_int32_t qflags;
- int dlen;
+ int dlen, repid;
void *desc;
kbd_t layout = (kbd_t)-1;
sc->sc_hdev.sc_report_id = uha->reportid;
uhidev_get_report_desc(uha->parent, &desc, &dlen);
+ repid = uha->reportid;
+ sc->sc_hdev.sc_isize = hid_report_size(desc, dlen, hid_input, repid);
+ sc->sc_hdev.sc_osize = hid_report_size(desc, dlen, hid_output, repid);
+ sc->sc_hdev.sc_fsize = hid_report_size(desc, dlen, hid_feature, repid);
+
qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
- if (hidkbd_attach(self, kbd, 1, qflags, uha->reportid, desc, dlen) != 0)
+ if (hidkbd_attach(self, kbd, 1, qflags, repid, desc, dlen) != 0)
return;
if (uha->uaa->vendor == USB_VENDOR_TOPRE &&
{
struct ukbd_softc *sc = v;
struct hidkbd *kbd = &sc->sc_kbd;
+ int rc;
switch (cmd) {
case WSKBDIO_GTYPE:
ukbd_set_leds(v, *(int *)data);
return (0);
default:
- return hidkbd_ioctl(kbd, cmd, data, flag, p);
+ rc = uhidev_ioctl(&sc->sc_hdev, cmd, data, flag, p);
+ if (rc != -1)
+ return rc;
+ else
+ return hidkbd_ioctl(kbd, cmd, data, flag, p);
}
}
-/* $OpenBSD: ums.c,v 1.32 2010/07/31 16:04:50 miod Exp $ */
+/* $OpenBSD: ums.c,v 1.33 2010/08/02 23:17:34 miod Exp $ */
/* $NetBSD: ums.c,v 1.60 2003/03/11 16:44:00 augustss Exp $ */
/*
struct hidms *ms = &sc->sc_ms;
struct usb_attach_arg *uaa = aux;
struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
- int size;
+ int size, repid;
void *desc;
u_int32_t quirks;
quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
uhidev_get_report_desc(uha->parent, &desc, &size);
+ repid = uha->reportid;
+ sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
+ sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
+ sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
if (hidms_setup(self, ms, quirks, uha->reportid, desc, size) != 0)
return;
{
struct ums_softc *sc = v;
struct hidms *ms = &sc->sc_ms;
+ int rc;
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_USB;
return 0;
default:
- return hidms_ioctl(ms, cmd, data, flag, p);
+ rc = uhidev_ioctl(&sc->sc_hdev, cmd, data, flag, p);
+ if (rc != -1)
+ return rc;
+ else
+ return hidms_ioctl(ms, cmd, data, flag, p);
}
}
-.\" $OpenBSD: usbhidctl.1,v 1.12 2008/10/16 18:37:19 jakemsr Exp $
+.\" $OpenBSD: usbhidctl.1,v 1.13 2010/08/02 23:17:36 miod Exp $
.\" $NetBSD: usbhidctl.1,v 1.14 2001/12/28 17:49:32 augustss Exp $
.\"
.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: October 16 2008 $
+.Dd $Mdocdate: August 2 2010 $
.Dt USBHIDCTL 1
.Os
.Sh NAME
.Qq button 2
item would usually just be referred to on the command line as:
.Pp
-.Dl $ usbhidctl -f /dev/mouse Mouse.Pointer.Button_2
+.Dl $ usbhidctl -f /dev/wsmouse0 Mouse.Pointer.Button_2
.Pp
Items can also be named by referring to parts of the item name with the
numeric representation of the native HID usage identifiers.
.Qq button 2
item:
.Pp
-.Dl $ usbhidctl -f /dev/mouse 1:Mouse.1:Pointer.Button:2
+.Dl $ usbhidctl -f /dev/wsmouse0 1:Mouse.1:Pointer.Button:2
.Pp
Devices with human interface outputs can be manipulated with the
.Fl w
collection.
The following can be used to switch this LED off:
.Pp
-.Dl $ usbhidctl -f /dev/mouse -w Mouse.0xffff:2=0
+.Dl $ usbhidctl -f /dev/wsmouse0 -w Mouse.0xffff:2=0
.Sh SEE ALSO
.Xr usbhidaction 1 ,
.Xr usbhid 3 ,