uhidev(9): Make uhidev state opaque.

This makes the API simpler and clearer and gives us more latitude to
fix bugs in the state management without breaking the ABI.

XXX kernel ABI change to signature of uhidev_get_report_desc and
uhidev_open, and to struct uhidev_attach_arg, requires bump for
uhidev driver modules
This commit is contained in:
riastradh 2022-03-28 12:44:17 +00:00
parent 043c0ba21a
commit 0b6c2425fd
9 changed files with 207 additions and 234 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $ */ /* $NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $ */
/*- /*-
* Copyright (c) 2011-2014 The NetBSD Foundation, Inc. * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@ -146,7 +146,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_usb.h" #include "opt_usb.h"
@ -301,7 +301,7 @@ static void geyser34_initialize(struct uatp_softc *);
static int geyser34_finalize(struct uatp_softc *); static int geyser34_finalize(struct uatp_softc *);
static void geyser34_deferred_reset(struct uatp_softc *); static void geyser34_deferred_reset(struct uatp_softc *);
static void geyser34_reset_task(void *); static void geyser34_reset_task(void *);
static void uatp_intr(struct uhidev *, void *, unsigned int); static void uatp_intr(void *, void *, unsigned int);
static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *); static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *);
static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *); static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *);
static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *); static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *);
@ -486,7 +486,8 @@ static const struct uatp_knobs default_knobs = {
}; };
struct uatp_softc { struct uatp_softc {
struct uhidev sc_hdev; /* uhidev(9) parent. */ device_t sc_dev;
struct uhidev *sc_hdev; /* uhidev(9) parent. */
struct usbd_device *sc_udev; /* USB device. */ struct usbd_device *sc_udev; /* USB device. */
device_t sc_wsmousedev; /* Attached wsmouse device. */ device_t sc_wsmousedev; /* Attached wsmouse device. */
const struct uatp_parameters *sc_parameters; const struct uatp_parameters *sc_parameters;
@ -691,7 +692,7 @@ find_uatp_descriptor(const struct uhidev_attach_arg *uha)
static device_t static device_t
uatp_dev(const struct uatp_softc *sc) uatp_dev(const struct uatp_softc *sc)
{ {
return sc->sc_hdev.sc_dev; return sc->sc_dev;
} }
static uint8_t * static uint8_t *
@ -931,12 +932,8 @@ uatp_attach(device_t parent, device_t self, void *aux)
int report_size, input_size; int report_size, input_size;
struct wsmousedev_attach_args a; struct wsmousedev_attach_args a;
/* Set up uhidev state. (Why doesn't uhidev do most of this?) */ sc->sc_dev = self;
sc->sc_hdev.sc_dev = self; sc->sc_hdev = uha->parent;
sc->sc_hdev.sc_intr = uatp_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
sc->sc_udev = uha->uiaa->uiaa_device; sc->sc_udev = uha->uiaa->uiaa_device;
/* Identify ourselves to dmesg. */ /* Identify ourselves to dmesg. */
@ -948,7 +945,7 @@ uatp_attach(device_t parent, device_t self, void *aux)
"vendor 0x%04x, product 0x%04x, report id %d\n", "vendor 0x%04x, product 0x%04x, report id %d\n",
(unsigned int)uha->uiaa->uiaa_vendor, (unsigned int)uha->uiaa->uiaa_vendor,
(unsigned int)uha->uiaa->uiaa_product, (unsigned int)uha->uiaa->uiaa_product,
(int)uha->reportid); uha->reportid);
uhidev_get_report_desc(uha->parent, &report_descriptor, &report_size); uhidev_get_report_desc(uha->parent, &report_descriptor, &report_size);
input_size = hid_report_size(report_descriptor, report_size, hid_input, input_size = hid_report_size(report_descriptor, report_size, hid_input,
@ -1251,8 +1248,8 @@ uatp_enable(void *v)
tap_enable(sc); tap_enable(sc);
uatp_clear_position(sc); uatp_clear_position(sc);
DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", &sc->sc_hdev)); DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", sc->sc_hdev));
return uhidev_open(&sc->sc_hdev); return uhidev_open(sc->sc_hdev, &uatp_intr, sc);
} }
static void static void
@ -1270,8 +1267,8 @@ uatp_disable(void *v)
tap_disable(sc); tap_disable(sc);
sc->sc_status &=~ UATP_ENABLED; sc->sc_status &=~ UATP_ENABLED;
DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", &sc->sc_hdev)); DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", sc->sc_hdev));
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
} }
static int static int
@ -1399,15 +1396,15 @@ geyser34_reset_task(void *arg)
/* Interrupt handler */ /* Interrupt handler */
static void static void
uatp_intr(struct uhidev *addr, void *ibuf, unsigned int len) uatp_intr(void *cookie, void *ibuf, unsigned int len)
{ {
struct uatp_softc *sc = (struct uatp_softc *)addr; struct uatp_softc *sc = cookie;
uint8_t *input; uint8_t *input;
int dx, dy, dz, dw; int dx, dy, dz, dw;
uint32_t buttons; uint32_t buttons;
DPRINTF(sc, UATP_DEBUG_INTR, ("softc %p, ibuf %p, len %u\n", DPRINTF(sc, UATP_DEBUG_INTR, ("softc %p, ibuf %p, len %u\n",
addr, ibuf, len)); sc, ibuf, len));
/* /*
* Some devices break packets up into chunks, so we accumulate * Some devices break packets up into chunks, so we accumulate

View File

@ -1,4 +1,4 @@
/* $NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $ */ /* $NetBSD: ucycom.c,v 1.55 2022/03/28 12:44:17 riastradh Exp $ */
/* /*
* Copyright (c) 2005 The NetBSD Foundation, Inc. * Copyright (c) 2005 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.55 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_usb.h" #include "opt_usb.h"
@ -117,7 +117,8 @@ int ucycomdebug = 20;
#define UCYCOM_ORESET 0x08 #define UCYCOM_ORESET 0x08
struct ucycom_softc { struct ucycom_softc {
struct uhidev sc_hdev; device_t sc_dev;
struct uhidev *sc_hdev;
struct usbd_device *sc_udev; struct usbd_device *sc_udev;
struct usb_task sc_task; struct usb_task sc_task;
@ -176,7 +177,7 @@ Static int ucycomparam(struct tty *, struct termios *);
Static void ucycomstart(struct tty *); Static void ucycomstart(struct tty *);
Static void ucycomstarttask(void *); Static void ucycomstarttask(void *);
Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status); Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status);
Static void ucycom_intr(struct uhidev *, void *, u_int); Static void ucycom_intr(void *, void *, u_int);
Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t); Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t);
Static void tiocm_to_ucycom(struct ucycom_softc *, u_long, int); Static void tiocm_to_ucycom(struct ucycom_softc *, u_long, int);
Static int ucycom_to_tiocm(struct ucycom_softc *); Static int ucycom_to_tiocm(struct ucycom_softc *);
@ -222,10 +223,8 @@ ucycom_attach(device_t parent, device_t self, void *aux)
int size, repid; int size, repid;
void *desc; void *desc;
sc->sc_hdev.sc_dev = self; sc->sc_dev = self;
sc->sc_hdev.sc_intr = ucycom_intr; sc->sc_hdev = uha->parent;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
sc->sc_udev = uha->uiaa->uiaa_device; sc->sc_udev = uha->uiaa->uiaa_device;
sc->sc_init_state = UCYCOM_INIT_NONE; sc->sc_init_state = UCYCOM_INIT_NONE;
@ -280,7 +279,7 @@ ucycom_detach(device_t self, int flags)
mutex_spin_exit(&tty_lock); mutex_spin_exit(&tty_lock);
} }
/* Wait for processes to go away. */ /* Wait for processes to go away. */
usb_detach_waitold(sc->sc_hdev.sc_dev); usb_detach_waitold(sc->sc_dev);
splx(s); splx(s);
/* locate the major number */ /* locate the major number */
@ -358,7 +357,7 @@ ucycomopen(dev_t dev, int flag, int mode, struct lwp *l)
return EIO; return EIO;
if (sc->sc_init_state != UCYCOM_INIT_INITED) if (sc->sc_init_state != UCYCOM_INIT_INITED)
return ENXIO; return ENXIO;
if (!device_is_active(sc->sc_hdev.sc_dev)) if (!device_is_active(sc->sc_dev))
return ENXIO; return ENXIO;
tp = sc->sc_tty; tp = sc->sc_tty;
@ -375,7 +374,7 @@ ucycomopen(dev_t dev, int flag, int mode, struct lwp *l)
tp->t_dev = dev; tp->t_dev = dev;
err = uhidev_open(&sc->sc_hdev); err = uhidev_open(sc->sc_hdev, &ucycom_intr, sc);
if (err) { if (err) {
/* Any cleanup? */ /* Any cleanup? */
splx(s); splx(s);
@ -617,7 +616,7 @@ ucycomstarttask(void *cookie)
usbd_status err; usbd_status err;
/* What can we do on error? */ /* What can we do on error? */
err = uhidev_write_async(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0, err = uhidev_write_async(sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0,
USBD_NO_TIMEOUT, ucycomwritecb, sc); USBD_NO_TIMEOUT, ucycomwritecb, sc);
#ifdef UCYCOM_DEBUG #ifdef UCYCOM_DEBUG
@ -942,7 +941,7 @@ ucycom_configure(struct ucycom_softc *sc, uint32_t baud, uint8_t cfg)
report[2] = (baud >> 16) & 0xff; report[2] = (baud >> 16) & 0xff;
report[3] = (baud >> 24) & 0xff; report[3] = (baud >> 24) & 0xff;
report[4] = cfg; report[4] = cfg;
err = uhidev_set_report(&sc->sc_hdev, UHID_FEATURE_REPORT, err = uhidev_set_report(sc->sc_hdev, UHID_FEATURE_REPORT,
report, sc->sc_flen); report, sc->sc_flen);
if (err != 0) { if (err != 0) {
DPRINTF(("%s\n", usbd_errstr(err))); DPRINTF(("%s\n", usbd_errstr(err)));
@ -959,9 +958,9 @@ ucycom_configure(struct ucycom_softc *sc, uint32_t baud, uint8_t cfg)
} }
Static void Static void
ucycom_intr(struct uhidev *addr, void *ibuf, u_int len) ucycom_intr(void *cookie, void *ibuf, u_int len)
{ {
struct ucycom_softc *sc = (struct ucycom_softc *)addr; struct ucycom_softc *sc = cookie;
struct tty *tp = sc->sc_tty; struct tty *tp = sc->sc_tty;
int (*rint)(int , struct tty *) = tp->t_linesw->l_rint; int (*rint)(int , struct tty *) = tp->t_linesw->l_rint;
uint8_t *cp = ibuf; uint8_t *cp = ibuf;
@ -1005,8 +1004,7 @@ ucycom_intr(struct uhidev *addr, void *ibuf, u_int len)
DPRINTFN(7,("ucycom_intr: char=0x%02x\n", *cp)); DPRINTFN(7,("ucycom_intr: char=0x%02x\n", *cp));
if ((*rint)(*cp++, tp) == -1) { if ((*rint)(*cp++, tp) == -1) {
/* XXX what should we do? */ /* XXX what should we do? */
aprint_error_dev(sc->sc_hdev.sc_dev, aprint_error_dev(sc->sc_dev, "lost a character\n");
"lost a character\n");
break; break;
} }
} }
@ -1124,7 +1122,7 @@ ucycom_set_status(struct ucycom_softc *sc)
memset(sc->sc_obuf, 0, sc->sc_olen); memset(sc->sc_obuf, 0, sc->sc_olen);
sc->sc_obuf[0] = sc->sc_mcr; sc->sc_obuf[0] = sc->sc_mcr;
err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen); err = uhidev_write(sc->sc_hdev, sc->sc_obuf, sc->sc_olen);
if (err) { if (err) {
DPRINTF(("ucycom_set_status: err=%d\n", err)); DPRINTF(("ucycom_set_status: err=%d\n", err));
} }
@ -1137,7 +1135,7 @@ ucycom_get_cfg(struct ucycom_softc *sc)
int err, cfg, baud; int err, cfg, baud;
uint8_t report[5]; uint8_t report[5];
err = uhidev_get_report(&sc->sc_hdev, UHID_FEATURE_REPORT, err = uhidev_get_report(sc->sc_hdev, UHID_FEATURE_REPORT,
report, sc->sc_flen); report, sc->sc_flen);
if (err) { if (err) {
DPRINTF(("%s: failed\n", __func__)); DPRINTF(("%s: failed\n", __func__));
@ -1163,7 +1161,7 @@ ucycom_cleanup(struct ucycom_softc *sc)
obuf = sc->sc_obuf; obuf = sc->sc_obuf;
sc->sc_obuf = NULL; sc->sc_obuf = NULL;
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
if (obuf != NULL) if (obuf != NULL)
kmem_free(obuf, sc->sc_olen); kmem_free(obuf, sc->sc_olen);

View File

@ -1,4 +1,4 @@
/* $NetBSD: uhid.c,v 1.122 2022/03/28 12:43:12 riastradh Exp $ */ /* $NetBSD: uhid.c,v 1.123 2022/03/28 12:44:17 riastradh Exp $ */
/* /*
* Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc. * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.122 2022/03/28 12:43:12 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.123 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h" #include "opt_compat_netbsd.h"
@ -85,8 +85,10 @@ int uhiddebug = 0;
#endif #endif
struct uhid_softc { struct uhid_softc {
struct uhidev sc_hdev; device_t sc_dev;
struct uhidev *sc_hdev;
struct usbd_device *sc_udev; struct usbd_device *sc_udev;
uint8_t sc_report_id;
kmutex_t sc_lock; kmutex_t sc_lock;
kcondvar_t sc_cv; kcondvar_t sc_cv;
@ -144,7 +146,7 @@ const struct cdevsw uhid_cdevsw = {
.d_flag = D_OTHER .d_flag = D_OTHER
}; };
static void uhid_intr(struct uhidev *, void *, u_int); static void uhid_intr(void *, void *, u_int);
static int uhid_match(device_t, cfdata_t, void *); static int uhid_match(device_t, cfdata_t, void *);
static void uhid_attach(device_t, device_t, void *); static void uhid_attach(device_t, device_t, void *);
@ -176,13 +178,12 @@ uhid_attach(device_t parent, device_t self, void *aux)
int size, repid; int size, repid;
void *desc; void *desc;
sc->sc_hdev.sc_dev = self; sc->sc_dev = self;
selinit(&sc->sc_rsel); sc->sc_hdev = uha->parent;
sc->sc_hdev.sc_intr = uhid_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
sc->sc_udev = uha->uiaa->uiaa_device; sc->sc_udev = uha->uiaa->uiaa_device;
sc->sc_report_id = uha->reportid;
selinit(&sc->sc_rsel);
uhidev_get_report_desc(uha->parent, &desc, &size); uhidev_get_report_desc(uha->parent, &desc, &size);
repid = uha->reportid; repid = uha->reportid;
@ -232,9 +233,9 @@ uhid_detach(device_t self, int flags)
} }
static void static void
uhid_intr(struct uhidev *addr, void *data, u_int len) uhid_intr(void *cookie, void *data, u_int len)
{ {
struct uhid_softc *sc = (struct uhid_softc *)addr; struct uhid_softc *sc = cookie;
#ifdef UHID_DEBUG #ifdef UHID_DEBUG
if (uhiddebug > 5) { if (uhiddebug > 5) {
@ -306,7 +307,7 @@ uhidopen(dev_t dev, int flag, int mode, struct lwp *l)
mutex_exit(&proc_lock); mutex_exit(&proc_lock);
/* Open the uhidev -- after this point we can get interrupts. */ /* Open the uhidev -- after this point we can get interrupts. */
error = uhidev_open(&sc->sc_hdev); error = uhidev_open(sc->sc_hdev, &uhid_intr, sc);
if (error) if (error)
goto fail1; goto fail1;
@ -354,7 +355,7 @@ uhidcancel(dev_t dev, int flag, int mode, struct lwp *l)
cv_broadcast(&sc->sc_cv); cv_broadcast(&sc->sc_cv);
mutex_exit(&sc->sc_lock); mutex_exit(&sc->sc_lock);
uhidev_stop(&sc->sc_hdev); uhidev_stop(sc->sc_hdev);
return 0; return 0;
} }
@ -379,7 +380,7 @@ uhidclose(dev_t dev, int flag, int mode, struct lwp *l)
mutex_exit(&sc->sc_lock); mutex_exit(&sc->sc_lock);
/* Prevent further interrupts. */ /* Prevent further interrupts. */
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
/* Hang up all select/poll. */ /* Hang up all select/poll. */
selnotify(&sc->sc_rsel, POLLHUP, 0); selnotify(&sc->sc_rsel, POLLHUP, 0);
@ -422,10 +423,10 @@ uhidread(dev_t dev, struct uio *uio, int flag)
DPRINTFN(1, ("uhidread\n")); DPRINTFN(1, ("uhidread\n"));
if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) { if (atomic_load_relaxed(&sc->sc_state) & UHID_IMMED) {
DPRINTFN(1, ("uhidread immed\n")); DPRINTFN(1, ("uhidread immed\n"));
extra = sc->sc_hdev.sc_report_id != 0; extra = sc->sc_report_id != 0;
if (sc->sc_isize + extra > sizeof(buffer)) if (sc->sc_isize + extra > sizeof(buffer))
return ENOBUFS; return ENOBUFS;
err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT,
buffer, sc->sc_isize + extra); buffer, sc->sc_isize + extra);
if (err) if (err)
return EIO; return EIO;
@ -489,7 +490,7 @@ uhidwrite(dev_t dev, struct uio *uio, int flag)
if (uhiddebug > 5) { if (uhiddebug > 5) {
uint32_t i; uint32_t i;
DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_hdev.sc_dev), DPRINTF(("%s: outdata[%d] =", device_xname(sc->sc_dev),
error)); error));
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
DPRINTF((" %02x", sc->sc_obuf[i])); DPRINTF((" %02x", sc->sc_obuf[i]));
@ -498,13 +499,13 @@ uhidwrite(dev_t dev, struct uio *uio, int flag)
#endif #endif
if (!error) { if (!error) {
if (sc->sc_raw) if (sc->sc_raw)
err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, size); err = uhidev_write(sc->sc_hdev, sc->sc_obuf, size);
else else
err = uhidev_set_report(&sc->sc_hdev, err = uhidev_set_report(sc->sc_hdev,
UHID_OUTPUT_REPORT, sc->sc_obuf, size); UHID_OUTPUT_REPORT, sc->sc_obuf, size);
if (err) { if (err) {
DPRINTF(("%s: err = %d\n", DPRINTF(("%s: err = %d\n",
device_xname(sc->sc_hdev.sc_dev), err)); device_xname(sc->sc_dev), err));
error = EIO; error = EIO;
} }
} }
@ -581,7 +582,7 @@ uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
break; break;
case USB_GET_REPORT_DESC: case USB_GET_REPORT_DESC:
uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size); uhidev_get_report_desc(sc->sc_hdev, &desc, &size);
rd = (struct usb_ctl_report_desc *)addr; rd = (struct usb_ctl_report_desc *)addr;
size = uimin(size, sizeof(rd->ucrd_data)); size = uimin(size, sizeof(rd->ucrd_data));
rd->ucrd_size = size; rd->ucrd_size = size;
@ -590,10 +591,10 @@ uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
case USB_SET_IMMED: case USB_SET_IMMED:
if (*(int *)addr) { if (*(int *)addr) {
extra = sc->sc_hdev.sc_report_id != 0; extra = sc->sc_report_id != 0;
if (sc->sc_isize + extra > sizeof(buffer)) if (sc->sc_isize + extra > sizeof(buffer))
return ENOBUFS; return ENOBUFS;
err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT, err = uhidev_get_report(sc->sc_hdev, UHID_INPUT_REPORT,
buffer, sc->sc_isize + extra); buffer, sc->sc_isize + extra);
if (err) if (err)
return EOPNOTSUPP; return EOPNOTSUPP;
@ -618,10 +619,10 @@ uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
default: default:
return EINVAL; return EINVAL;
} }
extra = sc->sc_hdev.sc_report_id != 0; extra = sc->sc_report_id != 0;
if (size + extra > sizeof(re->ucr_data)) if (size + extra > sizeof(re->ucr_data))
return ENOBUFS; return ENOBUFS;
err = uhidev_get_report(&sc->sc_hdev, re->ucr_report, err = uhidev_get_report(sc->sc_hdev, re->ucr_report,
re->ucr_data, size + extra); re->ucr_data, size + extra);
if (extra) if (extra)
memmove(re->ucr_data, re->ucr_data+1, size); memmove(re->ucr_data, re->ucr_data+1, size);
@ -646,14 +647,14 @@ uhidioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
} }
if (size > sizeof(re->ucr_data)) if (size > sizeof(re->ucr_data))
return ENOBUFS; return ENOBUFS;
err = uhidev_set_report(&sc->sc_hdev, re->ucr_report, err = uhidev_set_report(sc->sc_hdev, re->ucr_report,
re->ucr_data, size); re->ucr_data, size);
if (err) if (err)
return EIO; return EIO;
break; break;
case USB_GET_REPORT_ID: case USB_GET_REPORT_ID:
*(int *)addr = sc->sc_hdev.sc_report_id; *(int *)addr = sc->sc_report_id;
break; break;
case USB_GET_DEVICE_DESC: case USB_GET_DEVICE_DESC:

View File

@ -1,4 +1,4 @@
/* $NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $ */ /* $NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $ */
/* /*
* Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_usb.h" #include "opt_usb.h"
@ -88,7 +88,18 @@ struct uhidev_softc {
void *sc_repdesc; void *sc_repdesc;
u_int sc_nrepid; u_int sc_nrepid;
device_t *sc_subdevs; struct uhidev {
struct uhidev_softc *sc_parent;
device_t sc_dev;
void (*sc_intr)(void *, void *, u_int);
void *sc_cookie;
krndsource_t sc_rndsource;
int sc_in_rep_size;
uint8_t sc_report_id;
uint8_t sc_state;
#define UHIDEV_OPEN 0x01 /* device is open */
#define UHIDEV_STOPPED 0x02 /* xfers are stopped */
} *sc_subdevs;
kmutex_t sc_lock; kmutex_t sc_lock;
kcondvar_t sc_cv; kcondvar_t sc_cv;
@ -169,7 +180,6 @@ uhidev_attach(device_t parent, device_t self, void *aux)
usb_endpoint_descriptor_t *ed; usb_endpoint_descriptor_t *ed;
struct uhidev_attach_arg uha; struct uhidev_attach_arg uha;
device_t dev; device_t dev;
struct uhidev *csc;
int maxinpktsize, size, nrepid, repid, repsz; int maxinpktsize, size, nrepid, repid, repsz;
int *repsizes; int *repsizes;
int i; int i;
@ -405,40 +415,35 @@ uhidev_attach(device_t parent, device_t self, void *aux)
DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize)); DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize));
uha.parent = sc;
for (repid = 0; repid < nrepid; repid++) { for (repid = 0; repid < nrepid; repid++) {
struct uhidev *scd = &sc->sc_subdevs[repid];
scd->sc_parent = sc;
scd->sc_report_id = repid;
scd->sc_in_rep_size = repsizes[repid];
DPRINTF(("uhidev_match: try repid=%d\n", repid)); DPRINTF(("uhidev_match: try repid=%d\n", repid));
if (hid_report_size(desc, size, hid_input, repid) == 0 && 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_output, repid) == 0 &&
hid_report_size(desc, size, hid_feature, repid) == 0) { hid_report_size(desc, size, hid_feature, repid) == 0) {
; /* already NULL in sc->sc_subdevs[repid] */ ; /* already NULL in sc->sc_subdevs[repid] */
} else { } else {
uha.parent = scd;
uha.reportid = repid; uha.reportid = repid;
locs[UHIDBUSCF_REPORTID] = repid; locs[UHIDBUSCF_REPORTID] = repid;
dev = config_found(self, &uha, uhidevprint, dev = config_found(self, &uha, uhidevprint,
CFARGS(.submatch = config_stdsubmatch, CFARGS(.submatch = config_stdsubmatch,
.locators = locs)); .locators = locs));
sc->sc_subdevs[repid] = dev; sc->sc_subdevs[repid].sc_dev = dev;
if (dev != NULL) { if (dev == NULL)
csc = device_private(dev); continue;
csc->sc_in_rep_size = repsizes[repid]; /*
#ifdef DIAGNOSTIC * XXXSMP -- could be detached in the middle of
DPRINTF(("uhidev_match: repid=%d dev=%p\n", * sleeping for allocation in rnd_attach_source
repid, dev)); */
if (csc->sc_intr == NULL) { rnd_attach_source(&scd->sc_rndsource,
kmem_free(repsizes, device_xname(dev), RND_TYPE_TTY, RND_FLAG_DEFAULT);
nrepid * sizeof(*repsizes));
aprint_error_dev(self,
"sc_intr == NULL\n");
return;
}
#endif
rnd_attach_source(&csc->rnd_source,
device_xname(dev),
RND_TYPE_TTY,
RND_FLAG_DEFAULT);
}
} }
} }
kmem_free(repsizes, nrepid * sizeof(*repsizes)); kmem_free(repsizes, nrepid * sizeof(*repsizes));
@ -495,19 +500,26 @@ uhidev_childdet(device_t self, device_t child)
struct uhidev_softc *sc = device_private(self); struct uhidev_softc *sc = device_private(self);
for (i = 0; i < sc->sc_nrepid; i++) { for (i = 0; i < sc->sc_nrepid; i++) {
if (sc->sc_subdevs[i] == child) if (sc->sc_subdevs[i].sc_dev == child)
break; break;
} }
KASSERT(i < sc->sc_nrepid); KASSERT(i < sc->sc_nrepid);
sc->sc_subdevs[i] = NULL; sc->sc_subdevs[i].sc_dev = NULL;
/*
* XXXSMP -- could be reattached in the middle of sleeping for
* lock on sources to delete this in rnd_attach_source
*
* (Actually this can't happen right now because there's no
* rescan method, but if there were, it could.)
*/
rnd_detach_source(&sc->sc_subdevs[i].sc_rndsource);
} }
static int static int
uhidev_detach(device_t self, int flags) uhidev_detach(device_t self, int flags)
{ {
struct uhidev_softc *sc = device_private(self); struct uhidev_softc *sc = device_private(self);
int i, rv; int rv;
struct uhidev *csc;
DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags)); DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags));
@ -524,28 +536,12 @@ uhidev_detach(device_t self, int flags)
* DETACH_FORCE and the children will not have the option of * DETACH_FORCE and the children will not have the option of
* refusing detachment. * refusing detachment.
*/ */
for (i = 0; i < sc->sc_nrepid; i++) { rv = config_detach_children(self, flags);
if (sc->sc_subdevs[i] == NULL) if (rv) {
continue; mutex_enter(&sc->sc_lock);
/* sc->sc_dying = 0;
* XXX rnd_detach_source should go in uhidev_childdet, mutex_exit(&sc->sc_lock);
* but the struct krndsource lives in the child's return rv;
* softc, which is gone by the time of childdet. The
* parent uhidev_softc should be changed to allocate
* the struct krndsource, not the child.
*/
csc = device_private(sc->sc_subdevs[i]);
rnd_detach_source(&csc->rnd_source);
rv = config_detach(sc->sc_subdevs[i], flags);
if (rv) {
rnd_attach_source(&csc->rnd_source,
device_xname(sc->sc_dev),
RND_TYPE_TTY, RND_FLAG_DEFAULT);
mutex_enter(&sc->sc_lock);
sc->sc_dying = 0;
mutex_exit(&sc->sc_lock);
return rv;
}
} }
KASSERTMSG(sc->sc_refcnt == 0, KASSERTMSG(sc->sc_refcnt == 0,
@ -579,7 +575,6 @@ static void
uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
{ {
struct uhidev_softc *sc = addr; struct uhidev_softc *sc = addr;
device_t cdev;
struct uhidev *scd; struct uhidev *scd;
u_char *p; u_char *p;
u_int rep; u_int rep;
@ -618,12 +613,9 @@ uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
printf("uhidev_intr: bad repid %d\n", rep); printf("uhidev_intr: bad repid %d\n", rep);
return; return;
} }
cdev = sc->sc_subdevs[rep]; scd = &sc->sc_subdevs[rep];
if (!cdev)
return;
scd = device_private(cdev);
DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n", DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n",
rep, scd, scd ? scd->sc_state : 0)); rep, scd, scd->sc_state));
if (!(atomic_load_acquire(&scd->sc_state) & UHIDEV_OPEN)) if (!(atomic_load_acquire(&scd->sc_state) & UHIDEV_OPEN))
return; return;
#ifdef UHIDEV_DEBUG #ifdef UHIDEV_DEBUG
@ -637,13 +629,15 @@ uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status)
device_xname(sc->sc_dev))); device_xname(sc->sc_dev)));
return; return;
} }
rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf)); rnd_add_uint32(&scd->sc_rndsource, (uintptr_t)(sc->sc_ibuf));
scd->sc_intr(scd, p, cc); scd->sc_intr(scd->sc_cookie, p, cc);
} }
void void
uhidev_get_report_desc(struct uhidev_softc *sc, void **desc, int *size) uhidev_get_report_desc(struct uhidev *scd, void **desc, int *size)
{ {
struct uhidev_softc *sc = scd->sc_parent;
*desc = sc->sc_repdesc; *desc = sc->sc_repdesc;
*size = sc->sc_repdesc_size; *size = sc->sc_repdesc_size;
} }
@ -904,7 +898,8 @@ uhidev_close_pipes(struct uhidev_softc *sc)
} }
int int
uhidev_open(struct uhidev *scd) uhidev_open(struct uhidev *scd, void (*intr)(void *, void *, u_int),
void *cookie)
{ {
struct uhidev_softc *sc = scd->sc_parent; struct uhidev_softc *sc = scd->sc_parent;
int error; int error;
@ -923,6 +918,8 @@ uhidev_open(struct uhidev *scd)
error = EBUSY; error = EBUSY;
goto out; goto out;
} }
scd->sc_intr = intr;
scd->sc_cookie = cookie;
atomic_store_release(&scd->sc_state, scd->sc_state | UHIDEV_OPEN); atomic_store_release(&scd->sc_state, scd->sc_state | UHIDEV_OPEN);
/* Open the pipes which are shared by all report ids. */ /* Open the pipes which are shared by all report ids. */
@ -1067,9 +1064,19 @@ uhidev_close(struct uhidev *scd)
* We must drop the lock while doing this, because * We must drop the lock while doing this, because
* uhidev_write_callback takes the lock in softint context and * uhidev_write_callback takes the lock in softint context and
* it could deadlock with the xcall softint. * it could deadlock with the xcall softint.
*
* It is safe to drop the lock now before zeroing sc_intr and
* sc_cookie because the driver is obligated not to reopen
* until after uhidev_close returns.
*/ */
mutex_exit(&sc->sc_lock); mutex_exit(&sc->sc_lock);
xc_barrier(XC_HIGHPRI); xc_barrier(XC_HIGHPRI);
mutex_enter(&sc->sc_lock);
KASSERT((scd->sc_state & UHIDEV_OPEN) == 0);
scd->sc_intr = NULL;
scd->sc_cookie = NULL;
mutex_exit(&sc->sc_lock);
} }
usbd_status usbd_status

View File

@ -1,4 +1,4 @@
/* $NetBSD: uhidev.h,v 1.25 2022/03/28 12:43:39 riastradh Exp $ */ /* $NetBSD: uhidev.h,v 1.26 2022/03/28 12:44:17 riastradh Exp $ */
/* /*
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -33,34 +33,18 @@
#ifndef _DEV_USB_UHIDEV_H_ #ifndef _DEV_USB_UHIDEV_H_
#define _DEV_USB_UHIDEV_H_ #define _DEV_USB_UHIDEV_H_
#include <sys/device.h>
#include <sys/rndsource.h>
#include <dev/usb/usbdi.h> #include <dev/usb/usbdi.h>
struct uhidev_softc; struct uhidev;
struct uhidev {
device_t sc_dev; /* base device */
struct uhidev_softc *sc_parent;
uByte sc_report_id;
uint8_t sc_state; /* read/written under sc_parent->sc_lock */
#define UHIDEV_OPEN 0x01 /* device is open */
#define UHIDEV_STOPPED 0x02 /* xfers are stopped */
int sc_in_rep_size;
void (*sc_intr)(struct uhidev *, void *, u_int);
krndsource_t rnd_source;
};
struct uhidev_attach_arg { struct uhidev_attach_arg {
struct usbif_attach_arg *uiaa; struct usbif_attach_arg *uiaa;
struct uhidev_softc *parent; struct uhidev *parent;
int reportid; int reportid;
int reportsize;
}; };
void uhidev_get_report_desc(struct uhidev_softc *, void **, int *); void uhidev_get_report_desc(struct uhidev *, void **, int *);
int uhidev_open(struct uhidev *); int uhidev_open(struct uhidev *, void (*)(void *, void *, unsigned), void *);
void uhidev_stop(struct uhidev *); void uhidev_stop(struct uhidev *);
void uhidev_close(struct uhidev *); void uhidev_close(struct uhidev *);
usbd_status uhidev_set_report(struct uhidev *, int, void *, int); usbd_status uhidev_set_report(struct uhidev *, int, void *, int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ukbd.c,v 1.158 2022/03/28 12:43:12 riastradh Exp $ */ /* $NetBSD: ukbd.c,v 1.159 2022/03/28 12:44:17 riastradh Exp $ */
/* /*
* Copyright (c) 1998 The NetBSD Foundation, Inc. * Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.158 2022/03/28 12:43:12 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.159 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_ddb.h" #include "opt_ddb.h"
@ -235,9 +235,11 @@ Static const uint8_t ukbd_trtab[256] = {
#define KEY_ERROR 0x01 #define KEY_ERROR 0x01
struct ukbd_softc { struct ukbd_softc {
struct uhidev sc_hdev; device_t sc_dev;
struct uhidev *sc_hdev;
struct usbd_device *sc_udev; struct usbd_device *sc_udev;
struct usbd_interface *sc_iface; struct usbd_interface *sc_iface;
int sc_report_id;
struct ukbd_data sc_ndata; struct ukbd_data sc_ndata;
struct ukbd_data sc_odata; struct ukbd_data sc_odata;
@ -340,7 +342,7 @@ const struct wskbd_consops ukbd_consops = {
Static const char *ukbd_parse_desc(struct ukbd_softc *); Static const char *ukbd_parse_desc(struct ukbd_softc *);
Static void ukbd_intr(struct uhidev *, void *, u_int); Static void ukbd_intr(void *, void *, u_int);
Static void ukbd_decode(struct ukbd_softc *, struct ukbd_data *); Static void ukbd_decode(struct ukbd_softc *, struct ukbd_data *);
Static void ukbd_delayed_decode(void *); Static void ukbd_delayed_decode(void *);
@ -408,12 +410,11 @@ ukbd_attach(device_t parent, device_t self, void *aux)
const char *parseerr; const char *parseerr;
struct wskbddev_attach_args a; struct wskbddev_attach_args a;
sc->sc_hdev.sc_dev = self; sc->sc_dev = self;
sc->sc_hdev.sc_intr = ukbd_intr; sc->sc_hdev = uha->parent;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
sc->sc_udev = uha->uiaa->uiaa_device; sc->sc_udev = uha->uiaa->uiaa_device;
sc->sc_iface = uha->uiaa->uiaa_iface; sc->sc_iface = uha->uiaa->uiaa_iface;
sc->sc_report_id = uha->reportid;
sc->sc_flags = 0; sc->sc_flags = 0;
aprint_naive("\n"); aprint_naive("\n");
@ -514,7 +515,7 @@ ukbd_enable(void *v, int on)
/* Should only be called to change state */ /* Should only be called to change state */
if ((sc->sc_flags & FLAG_ENABLED) != 0 && on != 0) { if ((sc->sc_flags & FLAG_ENABLED) != 0 && on != 0) {
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
aprint_error_dev(sc->sc_hdev.sc_dev, "bad call on=%d\n", on); aprint_error_dev(sc->sc_dev, "bad call on=%d\n", on);
#endif #endif
return EBUSY; return EBUSY;
} }
@ -522,10 +523,10 @@ ukbd_enable(void *v, int on)
DPRINTF(("%s: sc=%p on=%d\n", __func__, sc, on)); DPRINTF(("%s: sc=%p on=%d\n", __func__, sc, on));
if (on) { if (on) {
sc->sc_flags |= FLAG_ENABLED; sc->sc_flags |= FLAG_ENABLED;
return uhidev_open(&sc->sc_hdev); return uhidev_open(sc->sc_hdev, &ukbd_intr, sc);
} else { } else {
sc->sc_flags &= ~FLAG_ENABLED; sc->sc_flags &= ~FLAG_ENABLED;
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
return 0; return 0;
} }
} }
@ -573,7 +574,7 @@ ukbd_detach(device_t self, int flags)
* XXX console, if there are any other keyboards. * XXX console, if there are any other keyboards.
*/ */
printf("%s: was console keyboard\n", printf("%s: was console keyboard\n",
device_xname(sc->sc_hdev.sc_dev)); device_xname(sc->sc_dev));
wskbd_cndetach(); wskbd_cndetach();
ukbd_is_console = 1; ukbd_is_console = 1;
} }
@ -587,8 +588,8 @@ ukbd_detach(device_t self, int flags)
USB_TASKQ_DRIVER, NULL); USB_TASKQ_DRIVER, NULL);
/* The console keyboard does not get a disable call, so check pipe. */ /* The console keyboard does not get a disable call, so check pipe. */
if (sc->sc_hdev.sc_state & UHIDEV_OPEN) if (sc->sc_flags & FLAG_ENABLED)
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
return rv; return rv;
} }
@ -608,8 +609,7 @@ ukbd_translate_keycodes(struct ukbd_softc *sc, struct ukbd_data *ud,
for (tp = tab; tp->from; tp++) for (tp = tab; tp->from; tp++)
if (tp->from == i) { if (tp->from == i) {
if (tp->to & IS_PMF) { if (tp->to & IS_PMF) {
pmf_event_inject( pmf_event_inject(sc->sc_dev,
sc->sc_hdev.sc_dev,
tp->to & 0xff); tp->to & 0xff);
} else } else
setbit(ud->keys, tp->to); setbit(ud->keys, tp->to);
@ -641,9 +641,9 @@ ukbd_translate_modifier(struct ukbd_softc *sc, uint16_t key)
} }
void void
ukbd_intr(struct uhidev *addr, void *ibuf, u_int len) ukbd_intr(void *cookie, void *ibuf, u_int len)
{ {
struct ukbd_softc *sc = (struct ukbd_softc *)addr; struct ukbd_softc *sc = cookie;
struct ukbd_data *ud = &sc->sc_ndata; struct ukbd_data *ud = &sc->sc_ndata;
int i; int i;
@ -768,7 +768,7 @@ ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
*/ */
if (ukbdtrace) { if (ukbdtrace) {
struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex]; struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
p->unit = device_unit(sc->sc_hdev.sc_dev); p->unit = device_unit(sc->sc_dev);
microtime(&p->tv); microtime(&p->tv);
p->ud = *ud; p->ud = *ud;
if (++ukbdtraceindex >= UKBDTRACESIZE) if (++ukbdtraceindex >= UKBDTRACESIZE)
@ -923,7 +923,7 @@ ukbd_set_leds_task(void *v)
if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1) if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
res |= 1 << sc->sc_capsloc.pos; res |= 1 << sc->sc_capsloc.pos;
uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1); uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
} }
#if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT) #if defined(WSDISPLAY_COMPAT_RAWKBD) && defined(UKBD_REPEAT)
@ -1059,7 +1059,7 @@ ukbd_parse_desc(struct ukbd_softc *sc)
void *desc; void *desc;
int ikey; int ikey;
uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size); uhidev_get_report_desc(sc->sc_hdev, &desc, &size);
ikey = 0; ikey = 0;
sc->sc_nkeycode = 0; sc->sc_nkeycode = 0;
d = hid_start_parse(desc, size, hid_input); d = hid_start_parse(desc, size, hid_input);
@ -1077,7 +1077,7 @@ ukbd_parse_desc(struct ukbd_softc *sc)
if (h.kind != hid_input || (h.flags & HIO_CONST) || if (h.kind != hid_input || (h.flags & HIO_CONST) ||
HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD || HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
h.report_ID != sc->sc_hdev.sc_report_id) h.report_ID != sc->sc_report_id)
continue; continue;
DPRINTF(("%s: ikey=%d usage=%#x flags=%#x pos=%d size=%d " DPRINTF(("%s: ikey=%d usage=%#x flags=%#x pos=%d size=%d "
"cnt=%d\n", __func__, ikey, h.usage, h.flags, h.loc.pos, "cnt=%d\n", __func__, ikey, h.usage, h.flags, h.loc.pos,
@ -1120,13 +1120,13 @@ ukbd_parse_desc(struct ukbd_softc *sc)
hid_end_parse(d); hid_end_parse(d);
hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK), hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL); sc->sc_report_id, hid_output, &sc->sc_numloc, NULL);
hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK), hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL); sc->sc_report_id, hid_output, &sc->sc_capsloc, NULL);
hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK), hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL); sc->sc_report_id, hid_output, &sc->sc_scroloc, NULL);
hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_COMPOSE), hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_COMPOSE),
sc->sc_hdev.sc_report_id, hid_output, &sc->sc_compose, NULL); sc->sc_report_id, hid_output, &sc->sc_compose, NULL);
return NULL; return NULL;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: ums.c,v 1.102 2022/03/28 12:43:12 riastradh Exp $ */ /* $NetBSD: ums.c,v 1.103 2022/03/28 12:44:17 riastradh Exp $ */
/* /*
* Copyright (c) 1998, 2017 The NetBSD Foundation, Inc. * Copyright (c) 1998, 2017 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.102 2022/03/28 12:43:12 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: ums.c,v 1.103 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_usb.h" #include "opt_usb.h"
@ -75,7 +75,7 @@ int umsdebug = 0;
#define UMSUNIT(s) (minor(s)) #define UMSUNIT(s) (minor(s))
struct ums_softc { struct ums_softc {
struct uhidev sc_hdev; struct uhidev *sc_hdev;
struct usbd_device *sc_udev; struct usbd_device *sc_udev;
struct hidms sc_ms; struct hidms sc_ms;
@ -85,7 +85,7 @@ struct ums_softc {
char sc_dying; char sc_dying;
}; };
Static void ums_intr(struct uhidev *, void *, u_int); Static void ums_intr(void *, void *, u_int);
Static int ums_enable(void *); Static int ums_enable(void *);
Static void ums_disable(void *); Static void ums_disable(void *);
@ -146,10 +146,7 @@ ums_attach(device_t parent, device_t self, void *aux)
aprint_naive("\n"); aprint_naive("\n");
sc->sc_hdev.sc_dev = self; sc->sc_hdev = uha->parent;
sc->sc_hdev.sc_intr = ums_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
sc->sc_udev = uha->uiaa->uiaa_device; sc->sc_udev = uha->uiaa->uiaa_device;
quirks = usbd_get_quirks(sc->sc_udev)->uq_flags; quirks = usbd_get_quirks(sc->sc_udev)->uq_flags;
@ -218,7 +215,7 @@ ums_attach(device_t parent, device_t self, void *aux)
while (hid_get_item(d, &item)) { while (hid_get_item(d, &item)) {
if (item.kind != hid_input if (item.kind != hid_input
|| HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
|| item.report_ID != sc->sc_hdev.sc_report_id) || item.report_ID != uha->reportid)
continue; continue;
if (HID_GET_USAGE(item.usage) == HUG_X) { if (HID_GET_USAGE(item.usage) == HUG_X) {
sc->sc_ms.sc_calibcoords.minx = item.logical_minimum; sc->sc_ms.sc_calibcoords.minx = item.logical_minimum;
@ -238,7 +235,7 @@ ums_attach(device_t parent, device_t self, void *aux)
hidms_attach(self, &sc->sc_ms, &ums_accessops); hidms_attach(self, &sc->sc_ms, &ums_accessops);
if (sc->sc_alwayson) { if (sc->sc_alwayson) {
error = uhidev_open(&sc->sc_hdev); error = uhidev_open(sc->sc_hdev, &ums_intr, sc);
if (error != 0) { if (error != 0) {
aprint_error_dev(self, aprint_error_dev(self,
"WARNING: couldn't open always-on device\n"); "WARNING: couldn't open always-on device\n");
@ -279,7 +276,7 @@ ums_detach(device_t self, int flags)
DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags)); DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags));
if (sc->sc_alwayson) if (sc->sc_alwayson)
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
/* No need to do reference counting of ums, wsmouse has all the goo. */ /* No need to do reference counting of ums, wsmouse has all the goo. */
if (sc->sc_ms.hidms_wsmousedev != NULL) if (sc->sc_ms.hidms_wsmousedev != NULL)
@ -291,9 +288,9 @@ ums_detach(device_t self, int flags)
} }
Static void Static void
ums_intr(struct uhidev *addr, void *ibuf, u_int len) ums_intr(void *cookie, void *ibuf, u_int len)
{ {
struct ums_softc *sc = (struct ums_softc *)addr; struct ums_softc *sc = cookie;
if (sc->sc_enabled) if (sc->sc_enabled)
hidms_intr(&sc->sc_ms, ibuf, len); hidms_intr(&sc->sc_ms, ibuf, len);
@ -317,7 +314,7 @@ ums_enable(void *v)
sc->sc_ms.hidms_buttons = 0; sc->sc_ms.hidms_buttons = 0;
if (!sc->sc_alwayson) { if (!sc->sc_alwayson) {
error = uhidev_open(&sc->sc_hdev); error = uhidev_open(sc->sc_hdev, &ums_intr, sc);
if (error) if (error)
sc->sc_enabled = 0; sc->sc_enabled = 0;
} }
@ -341,7 +338,7 @@ ums_disable(void *v)
if (sc->sc_enabled) { if (sc->sc_enabled) {
sc->sc_enabled = 0; sc->sc_enabled = 0;
if (!sc->sc_alwayson) if (!sc->sc_alwayson)
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
} }
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: uthum.c,v 1.22 2022/03/28 12:43:12 riastradh Exp $ */ /* $NetBSD: uthum.c,v 1.23 2022/03/28 12:44:17 riastradh Exp $ */
/* $OpenBSD: uthum.c,v 1.6 2010/01/03 18:43:02 deraadt Exp $ */ /* $OpenBSD: uthum.c,v 1.6 2010/01/03 18:43:02 deraadt Exp $ */
/* /*
@ -22,7 +22,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uthum.c,v 1.22 2022/03/28 12:43:12 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: uthum.c,v 1.23 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_usb.h" #include "opt_usb.h"
@ -74,7 +74,8 @@ static const uint8_t cmd_end[8] =
#define UTHUM_TYPE_TEMPER 2 #define UTHUM_TYPE_TEMPER 2
struct uthum_softc { struct uthum_softc {
struct uhidev sc_hdev; device_t sc_dev;
struct uhidev * sc_hdev;
struct usbd_device * sc_udev; struct usbd_device * sc_udev;
u_char sc_dying; u_char sc_dying;
uint16_t sc_flag; uint16_t sc_flag;
@ -109,7 +110,6 @@ static int uthum_temper_temp(uint8_t, uint8_t);
static int uthum_sht1x_temp(uint8_t, uint8_t); static int uthum_sht1x_temp(uint8_t, uint8_t);
static int uthum_sht1x_rh(unsigned int, int); static int uthum_sht1x_rh(unsigned int, int);
static void uthum_intr(struct uhidev *, void *, u_int);
static void uthum_refresh(struct sysmon_envsys *, envsys_data_t *); static void uthum_refresh(struct sysmon_envsys *, envsys_data_t *);
@ -134,11 +134,9 @@ uthum_attach(device_t parent, device_t self, void *aux)
int size, repid; int size, repid;
void *desc; void *desc;
sc->sc_dev = self;
sc->sc_hdev = uha->parent;
sc->sc_udev = dev; sc->sc_udev = dev;
sc->sc_hdev.sc_dev = self;
sc->sc_hdev.sc_intr = uthum_intr;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
sc->sc_num_sensors = 0; sc->sc_num_sensors = 0;
aprint_normal("\n"); aprint_normal("\n");
@ -149,8 +147,7 @@ uthum_attach(device_t parent, device_t self, void *aux)
sc->sc_olen = hid_report_size(desc, size, hid_output, repid); sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
sc->sc_flen = hid_report_size(desc, size, hid_feature, repid); sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
sc->sc_hdev.sc_dev);
if (sc->sc_flen < 32) { if (sc->sc_flen < 32) {
/* not sensor interface, just attach */ /* not sensor interface, just attach */
@ -230,8 +227,7 @@ uthum_detach(device_t self, int flags)
if (sc->sc_sme != NULL) if (sc->sc_sme != NULL)
sysmon_envsys_unregister(sc->sc_sme); sysmon_envsys_unregister(sc->sc_sme);
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
sc->sc_hdev.sc_dev);
return rv; return rv;
} }
@ -249,12 +245,6 @@ uthum_activate(device_t self, enum devact act)
return 0; return 0;
} }
static void
uthum_intr(struct uhidev *addr, void *ibuf, u_int len)
{
/* do nothing */
}
static int static int
uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf, uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
size_t len, int need_delay) size_t len, int need_delay)
@ -272,24 +262,24 @@ uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
/* issue query */ /* issue query */
memset(cmdbuf, 0, sizeof(cmdbuf)); memset(cmdbuf, 0, sizeof(cmdbuf));
memcpy(cmdbuf, cmd_start, sizeof(cmd_start)); memcpy(cmdbuf, cmd_start, sizeof(cmd_start));
if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
cmdbuf, olen)) cmdbuf, olen))
return EIO; return EIO;
memset(cmdbuf, 0, sizeof(cmdbuf)); memset(cmdbuf, 0, sizeof(cmdbuf));
cmdbuf[0] = target_cmd; cmdbuf[0] = target_cmd;
if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
cmdbuf, olen)) cmdbuf, olen))
return EIO; return EIO;
memset(cmdbuf, 0, sizeof(cmdbuf)); memset(cmdbuf, 0, sizeof(cmdbuf));
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
cmdbuf, olen)) cmdbuf, olen))
return EIO; return EIO;
} }
memcpy(cmdbuf, cmd_end, sizeof(cmd_end)); memcpy(cmdbuf, cmd_end, sizeof(cmd_end));
if (uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT, if (uhidev_set_report(sc->sc_hdev, UHID_OUTPUT_REPORT,
cmdbuf, olen)) cmdbuf, olen))
return EIO; return EIO;
@ -299,7 +289,7 @@ uthum_read_data(struct uthum_softc *sc, uint8_t target_cmd, uint8_t *buf,
/* get answer */ /* get answer */
flen = uimin(sc->sc_flen, sizeof(report)); flen = uimin(sc->sc_flen, sizeof(report));
if (uhidev_get_report(&sc->sc_hdev, UHID_FEATURE_REPORT, if (uhidev_get_report(sc->sc_hdev, UHID_FEATURE_REPORT,
report, flen)) report, flen))
return EIO; return EIO;
memcpy(buf, report, len); memcpy(buf, report, len);

View File

@ -1,4 +1,4 @@
/* $NetBSD: uts.c,v 1.14 2021/08/07 16:19:17 thorpej Exp $ */ /* $NetBSD: uts.c,v 1.15 2022/03/28 12:44:17 riastradh Exp $ */
/* /*
* Copyright (c) 2012 The NetBSD Foundation, Inc. * Copyright (c) 2012 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.14 2021/08/07 16:19:17 thorpej Exp $"); __KERNEL_RCSID(0, "$NetBSD: uts.c,v 1.15 2022/03/28 12:44:17 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "opt_usb.h" #include "opt_usb.h"
@ -72,7 +72,8 @@ int utsdebug = 0;
struct uts_softc { struct uts_softc {
struct uhidev sc_hdev; device_t sc_dev;
struct uhidev *sc_hdev;
struct hid_location sc_loc_x, sc_loc_y, sc_loc_z; struct hid_location sc_loc_x, sc_loc_y, sc_loc_z;
struct hid_location sc_loc_btn; struct hid_location sc_loc_btn;
@ -92,7 +93,7 @@ struct uts_softc {
#define TSCREEN_FLAGS_MASK (HIO_CONST|HIO_RELATIVE) #define TSCREEN_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
Static void uts_intr(struct uhidev *, void *, u_int); Static void uts_intr(void *, void *, u_int);
Static int uts_enable(void *); Static int uts_enable(void *);
Static void uts_disable(void *); Static void uts_disable(void *);
@ -146,10 +147,8 @@ uts_attach(device_t parent, device_t self, void *aux)
aprint_normal("\n"); aprint_normal("\n");
sc->sc_hdev.sc_dev = self; sc->sc_dev = self;
sc->sc_hdev.sc_intr = uts_intr; sc->sc_hdev = uha->parent;
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
uhidev_get_report_desc(uha->parent, &desc, &size); uhidev_get_report_desc(uha->parent, &desc, &size);
@ -159,7 +158,7 @@ uts_attach(device_t parent, device_t self, void *aux)
/* requires HID usage Generic_Desktop:X */ /* requires HID usage Generic_Desktop:X */
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
uha->reportid, hid_input, &sc->sc_loc_x, &flags)) { uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
aprint_error_dev(sc->sc_hdev.sc_dev, aprint_error_dev(sc->sc_dev,
"touchscreen has no X report\n"); "touchscreen has no X report\n");
return; return;
} }
@ -170,7 +169,7 @@ uts_attach(device_t parent, device_t self, void *aux)
case HIO_RELATIVE: case HIO_RELATIVE:
break; break;
default: default:
aprint_error_dev(sc->sc_hdev.sc_dev, aprint_error_dev(sc->sc_dev,
"X report 0x%04x not supported\n", flags); "X report 0x%04x not supported\n", flags);
return; return;
} }
@ -178,7 +177,7 @@ uts_attach(device_t parent, device_t self, void *aux)
/* requires HID usage Generic_Desktop:Y */ /* requires HID usage Generic_Desktop:Y */
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
uha->reportid, hid_input, &sc->sc_loc_y, &flags)) { uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
aprint_error_dev(sc->sc_hdev.sc_dev, aprint_error_dev(sc->sc_dev,
"touchscreen has no Y report\n"); "touchscreen has no Y report\n");
return; return;
} }
@ -189,15 +188,15 @@ uts_attach(device_t parent, device_t self, void *aux)
case HIO_RELATIVE: case HIO_RELATIVE:
break; break;
default: default:
aprint_error_dev(sc->sc_hdev.sc_dev, aprint_error_dev(sc->sc_dev,
"Y report 0x%04x not supported\n", flags); "Y report 0x%04x not supported\n", flags);
return; return;
} }
/* requires HID usage Digitizer:Tip_Switch */ /* requires HID usage Digitizer:Tip_Switch */
if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH), if (!hid_locate(desc, size, HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH),
uha->reportid, hid_input, &sc->sc_loc_btn, 0)) { uha->reportid, hid_input, &sc->sc_loc_btn, 0)) {
aprint_error_dev(sc->sc_hdev.sc_dev, aprint_error_dev(sc->sc_dev,
"touchscreen has no tip switch report\n"); "touchscreen has no tip switch report\n");
return; return;
} }
@ -211,10 +210,10 @@ uts_attach(device_t parent, device_t self, void *aux)
* ELAN touchscreens error out here but still return * ELAN touchscreens error out here but still return
* valid data * valid data
*/ */
aprint_debug_dev(sc->sc_hdev.sc_dev, aprint_debug_dev(sc->sc_dev,
"ELAN touchscreen found, working around bug.\n"); "ELAN touchscreen found, working around bug.\n");
} else { } else {
aprint_error_dev(sc->sc_hdev.sc_dev, aprint_error_dev(sc->sc_dev,
"touchscreen has no range report\n"); "touchscreen has no range report\n");
return; return;
} }
@ -247,7 +246,7 @@ uts_attach(device_t parent, device_t self, void *aux)
while (hid_get_item(d, &item)) { while (hid_get_item(d, &item)) {
if (item.kind != hid_input if (item.kind != hid_input
|| HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP || HID_GET_USAGE_PAGE(item.usage) != HUP_GENERIC_DESKTOP
|| item.report_ID != sc->sc_hdev.sc_report_id) || item.report_ID != uha->reportid)
continue; continue;
if (HID_GET_USAGE(item.usage) == HUG_X) { if (HID_GET_USAGE(item.usage) == HUG_X) {
sc->sc_calibcoords.minx = item.logical_minimum; sc->sc_calibcoords.minx = item.logical_minimum;
@ -322,7 +321,7 @@ uts_enable(void *v)
sc->sc_enabled = 1; sc->sc_enabled = 1;
sc->sc_buttons = 0; sc->sc_buttons = 0;
return uhidev_open(&sc->sc_hdev); return uhidev_open(sc->sc_hdev, &uts_intr, sc);
} }
Static void Static void
@ -339,7 +338,7 @@ uts_disable(void *v)
#endif #endif
sc->sc_enabled = 0; sc->sc_enabled = 0;
uhidev_close(&sc->sc_hdev); uhidev_close(sc->sc_hdev);
} }
Static int Static int
@ -363,9 +362,9 @@ uts_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
} }
Static void Static void
uts_intr(struct uhidev *addr, void *ibuf, u_int len) uts_intr(void *cookie, void *ibuf, u_int len)
{ {
struct uts_softc *sc = (struct uts_softc *)addr; struct uts_softc *sc = cookie;
int dx, dy, dz; int dx, dy, dz;
uint32_t buttons = 0; uint32_t buttons = 0;
int flags, s; int flags, s;