tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
uhidev(9) improvements
The attached patch series partially fixes a bug in the uhidev(9) API
(uhidev_stop didn't do anything at all; now it is merely racy).
But more importantly, the patch series makes struct uhidev_softc
opaque, so the uhidev(9) API can have a more stable ABI. This will
give us better latitude to fix this race -- and potentially others --
later on and pull them up to netbsd-10 after it branches.
I have tested uhid(4) and ukbd(4). I haven't tested ucycom(4), which
uses uhidev(9) in a way that nothing else does -- to do async xfers on
the output pipe. Can anyone review and/or test ucycom(4)?
From 7aa6050cfb88fbe8b42cf339fd42657b94ff5741 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Wed, 19 Jan 2022 14:43:11 +0000
Subject: [PATCH 1/4] uhidev(9): Partially fix uhidev_write aborting.
In my previous change, I intended to make uhidev_stop abort any
pending write -- but I forgot to initialize sc->sc_writereportid, so
it never did anything.
This changes the API and ABI of uhidev_write so it takes the struct
uhidev pointer, rather than the struct uhidev_softc pointer; this way
uhidev_write knows what the report id of the client is, so it can
arrange to have uhidev_stop abort only this one.
XXX Except it still doesn't actually work because we do this
unlocked, ugh, so the write might complete before we abort anything.
---
sys/dev/usb/ucycom.c | 2 +-
sys/dev/usb/uhid.c | 3 +--
sys/dev/usb/uhidev.c | 10 ++++++++--
sys/dev/usb/uhidev.h | 2 +-
4 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/sys/dev/usb/ucycom.c b/sys/dev/usb/ucycom.c
index bb6046ae1a12..5191d234a52c 100644
--- a/sys/dev/usb/ucycom.c
+++ b/sys/dev/usb/ucycom.c
@@ -1105,7 +1105,7 @@ ucycom_set_status(struct ucycom_softc *sc)
memset(sc->sc_obuf, 0, sc->sc_olen);
sc->sc_obuf[0] = sc->sc_mcr;
- err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, sc->sc_olen);
+ err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen);
if (err) {
DPRINTF(("ucycom_set_status: err=%d\n", err));
}
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index 46769dc0353a..66ab1a74b3c1 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -581,8 +581,7 @@ uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
#endif
if (!error) {
if (sc->sc_raw)
- err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf,
- size);
+ err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, size);
else
err = uhidev_set_report(&sc->sc_hdev,
UHID_OUTPUT_REPORT, sc->sc_obuf, size);
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index b0c03092c77a..1a530cd76412 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -901,7 +901,7 @@ uhidev_stop(struct uhidev *scd)
abort = true;
mutex_exit(&sc->sc_lock);
- if (abort && sc->sc_opipe)
+ if (abort && sc->sc_opipe) /* XXX sc_opipe might go away */
usbd_abort_pipe(sc->sc_opipe);
}
@@ -961,8 +961,9 @@ uhidev_get_report(struct uhidev *scd, int type, void *data, int len)
}
usbd_status
-uhidev_write(struct uhidev_softc *sc, void *data, int len)
+uhidev_write(struct uhidev *scd, void *data, int len)
{
+ struct uhidev_softc *sc = scd->sc_parent;
usbd_status err;
DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len));
@@ -985,6 +986,7 @@ uhidev_write(struct uhidev_softc *sc, void *data, int len)
}
}
sc->sc_writelock = curlwp;
+ sc->sc_writereportid = scd->sc_report_id;
mutex_exit(&sc->sc_lock);
#ifdef UHIDEV_DEBUG
@@ -1006,6 +1008,10 @@ uhidev_write(struct uhidev_softc *sc, void *data, int len)
KASSERT(sc->sc_refcnt);
KASSERTMSG(sc->sc_writelock == curlwp, "%s: migrated from %p to %p",
device_xname(sc->sc_dev), curlwp, sc->sc_writelock);
+ KASSERTMSG(sc->sc_writereportid == scd->sc_report_id,
+ "%s: changed write report ids from %d to %d",
+ device_xname(sc->sc_dev), scd->sc_report_id, sc->sc_writereportid);
+ sc->sc_writereportid = -1;
sc->sc_writelock = NULL;
cv_broadcast(&sc->sc_cv);
out: mutex_exit(&sc->sc_lock);
diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h
index 83c0a357744e..447780987af8 100644
--- a/sys/dev/usb/uhidev.h
+++ b/sys/dev/usb/uhidev.h
@@ -97,7 +97,7 @@ void uhidev_stop(struct uhidev *);
void uhidev_close(struct uhidev *);
usbd_status uhidev_set_report(struct uhidev *, int, void *, int);
usbd_status uhidev_get_report(struct uhidev *, int, void *, int);
-usbd_status uhidev_write(struct uhidev_softc *, void *, int);
+usbd_status uhidev_write(struct uhidev *, void *, int);
#define UHIDEV_OSIZE 64
From 6627dba911522e91e7b7848ff570a5229f0b9176 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Tue, 25 Jan 2022 00:37:14 +0000
Subject: [PATCH 2/4] uhidev(9): New uhidev_write_async.
Like uhidev_write but issues the transfer asynchronously with a
callback.
Use it in ucycom(4).
---
sys/dev/usb/ucycom.c | 7 ++---
sys/dev/usb/uhidev.c | 67 ++++++++++++++++++++++++++++++++++++++++++++
sys/dev/usb/uhidev.h | 4 +++
3 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/sys/dev/usb/ucycom.c b/sys/dev/usb/ucycom.c
index 5191d234a52c..242ac817fda5 100644
--- a/sys/dev/usb/ucycom.c
+++ b/sys/dev/usb/ucycom.c
@@ -592,11 +592,9 @@ ucycomstart(struct tty *tp)
}
#endif
DPRINTFN(4,("ucycomstart: %d chars\n", len));
- usbd_setup_xfer(sc->sc_hdev.sc_parent->sc_oxfer, sc, sc->sc_obuf,
- sc->sc_olen, 0, USBD_NO_TIMEOUT, ucycomwritecb);
-
/* What can we do on error? */
- err = usbd_transfer(sc->sc_hdev.sc_parent->sc_oxfer);
+ err = uhidev_write_async(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0,
+ USBD_NO_TIMEOUT, ucycomwritecb, sc);
#ifdef UCYCOM_DEBUG
if (err != USBD_IN_PROGRESS)
@@ -621,7 +619,6 @@ ucycomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
if (status) {
DPRINTF(("ucycomwritecb: status=%d\n", status));
- usbd_clear_endpoint_stall(sc->sc_hdev.sc_parent->sc_opipe);
/* XXX we should restart after some delay. */
goto error;
}
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index 1a530cd76412..d1a2909c5b59 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -1017,3 +1017,70 @@ uhidev_write(struct uhidev *scd, void *data, int len)
out: mutex_exit(&sc->sc_lock);
return err;
}
+
+static void
+uhidev_write_callback(struct usbd_xfer *xfer, void *cookie, usbd_status err)
+{
+ struct uhidev_softc *sc = cookie;
+ usbd_callback writecallback;
+ void *writecookie;
+
+ if (err)
+ usbd_clear_endpoint_stall(sc->sc_opipe);
+
+ mutex_enter(&sc->sc_lock);
+ KASSERT(sc->sc_writelock == (void *)1);
+ writecallback = sc->sc_writecallback;
+ writecookie = sc->sc_writecookie;
+ sc->sc_writereportid = -1;
+ sc->sc_writelock = NULL;
+ sc->sc_writecallback = NULL;
+ sc->sc_writecookie = NULL;
+ cv_broadcast(&sc->sc_cv);
+ mutex_exit(&sc->sc_lock);
+
+ (*writecallback)(xfer, writecookie, err);
+}
+
+usbd_status
+uhidev_write_async(struct uhidev *scd, void *data, int len, int flags,
+ int timo, usbd_callback writecallback, void *writecookie)
+{
+ struct uhidev_softc *sc = scd->sc_parent;
+ usbd_status err;
+
+ DPRINTF(("%s: data=%p, len=%d\n", __func__, data, len));
+
+ if (sc->sc_opipe == NULL)
+ return USBD_INVAL;
+
+ mutex_enter(&sc->sc_lock);
+ KASSERT(sc->sc_refcnt);
+ if (sc->sc_dying) {
+ err = USBD_IOERROR;
+ goto out;
+ }
+ if (sc->sc_writelock != NULL) {
+ err = USBD_IN_USE;
+ goto out;
+ }
+ sc->sc_writelock = (void *)1; /* XXX no lwp to attribute async xfer */
+ sc->sc_writereportid = scd->sc_report_id;
+ sc->sc_writecallback = writecallback;
+ sc->sc_writecookie = writecookie;
+ usbd_setup_xfer(sc->sc_oxfer, sc, data, len, flags, timo,
+ uhidev_write_callback);
+ err = usbd_transfer(sc->sc_oxfer);
+ switch (err) {
+ case USBD_IN_PROGRESS:
+ break;
+ case USBD_NORMAL_COMPLETION:
+ panic("unexpected normal completion of async xfer under lock");
+ default: /* error */
+ sc->sc_writelock = NULL;
+ sc->sc_writereportid = -1;
+ cv_broadcast(&sc->sc_cv);
+ }
+out: mutex_exit(&sc->sc_lock);
+ return err;
+}
diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h
index 447780987af8..0b19e9015fcd 100644
--- a/sys/dev/usb/uhidev.h
+++ b/sys/dev/usb/uhidev.h
@@ -68,6 +68,8 @@ struct uhidev_softc {
struct usbd_pipe *sc_ipipe; /* input interrupt pipe */
struct usbd_pipe *sc_opipe; /* output interrupt pipe */
struct usbd_xfer *sc_oxfer; /* write request */
+ usbd_callback sc_writecallback; /* async write request callback */
+ void *sc_writecookie;
u_int sc_flags;
#define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */
@@ -98,6 +100,8 @@ void uhidev_close(struct uhidev *);
usbd_status uhidev_set_report(struct uhidev *, int, void *, int);
usbd_status uhidev_get_report(struct uhidev *, int, void *, int);
usbd_status uhidev_write(struct uhidev *, void *, int);
+usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int,
+ usbd_callback, void *);
#define UHIDEV_OSIZE 64
From 2f5f3af6a339aace77590048f159cfb93fca70a8 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Wed, 19 Jan 2022 17:18:13 +0000
Subject: [PATCH 3/4] uhidev(9): Get the device and interface through attach
args.
This way uhidev drivers don't need access to uhidev_softc itself for
it.
---
sys/arch/macppc/dev/pbms.c | 7 +++++--
sys/dev/usb/uatp.c | 14 ++++++++------
sys/dev/usb/uhid.c | 11 +++++++----
sys/dev/usb/ukbd.c | 15 ++++++++++-----
sys/dev/usb/ums.c | 4 +++-
sys/dev/usb/uthum.c | 2 +-
6 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/sys/arch/macppc/dev/pbms.c b/sys/arch/macppc/dev/pbms.c
index a1bfb88516cb..edc2213c619c 100644
--- a/sys/arch/macppc/dev/pbms.c
+++ b/sys/arch/macppc/dev/pbms.c
@@ -307,7 +307,8 @@ pbms_match(device_t parent, cfdata_t match, void *aux)
* we expect.
*/
if (uha->uiaa->uiaa_proto == UIPROTO_MOUSE &&
- (udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) {
+ ((udd = usbd_get_device_descriptor(uha->uiaa->uiaa_device))
+ != NULL)) {
vendor = UGETW(udd->idVendor);
product = UGETW(udd->idProduct);
for (i = 0; i < PBMS_NUM_DEVICES; i++) {
@@ -329,6 +330,7 @@ pbms_attach(device_t parent, device_t self, void *aux)
struct uhidev_attach_arg *uha = aux;
struct pbms_dev *pd;
struct pbms_softc *sc = device_private(self);
+ struct usbd_device *udev;
usb_device_descriptor_t *udd;
int i;
uint16_t vendor, product;
@@ -341,7 +343,8 @@ pbms_attach(device_t parent, device_t self, void *aux)
sc->sc_datalen = PBMS_DATA_LEN;
/* Fill in device-specific parameters. */
- if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) {
+ udev = uha->uiaa->uiaa_udevice;
+ if ((udd = usbd_get_device_descriptor(udev)) != NULL) {
product = UGETW(udd->idProduct);
vendor = UGETW(udd->idVendor);
for (i = 0; i < PBMS_NUM_DEVICES; i++) {
diff --git a/sys/dev/usb/uatp.c b/sys/dev/usb/uatp.c
index a94e755f1ed2..d0a564eca616 100644
--- a/sys/dev/usb/uatp.c
+++ b/sys/dev/usb/uatp.c
@@ -486,7 +486,8 @@ static const struct uatp_knobs default_knobs = {
};
struct uatp_softc {
- struct uhidev sc_hdev; /* USB parent. */
+ struct uhidev sc_hdev; /* uhidev(9) parent. */
+ struct usbd_device *sc_udev; /* USB device. */
device_t sc_wsmousedev; /* Attached wsmouse device. */
const struct uatp_parameters *sc_parameters;
struct uatp_knobs sc_knobs;
@@ -936,6 +937,8 @@ uatp_attach(device_t parent, device_t self, void *aux)
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
+ sc->sc_udev = uha->uiaa->uiaa_device;
+
/* Identify ourselves to dmesg. */
uatp_descriptor = find_uatp_descriptor(uha);
KASSERT(uatp_descriptor != NULL);
@@ -1296,7 +1299,7 @@ uatp_ioctl(void *v, unsigned long cmd, void *data, int flag, struct lwp *p)
static void
geyser34_enable_raw_mode(struct uatp_softc *sc)
{
- struct usbd_device *udev = sc->sc_hdev.sc_parent->sc_udev;
+ struct usbd_device *udev = sc->sc_udev;
usb_device_request_t req;
usbd_status status;
uint8_t report[GEYSER34_MODE_PACKET_SIZE];
@@ -1368,8 +1371,8 @@ geyser34_finalize(struct uatp_softc *sc)
{
DPRINTF(sc, UATP_DEBUG_MISC, ("finalizing\n"));
- usb_rem_task_wait(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_reset_task,
- USB_TASKQ_DRIVER, NULL);
+ usb_rem_task_wait(sc->sc_udev, &sc->sc_reset_task, USB_TASKQ_DRIVER,
+ NULL);
return 0;
}
@@ -1379,8 +1382,7 @@ geyser34_deferred_reset(struct uatp_softc *sc)
{
DPRINTF(sc, UATP_DEBUG_RESET, ("deferring reset\n"));
- usb_add_task(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_reset_task,
- USB_TASKQ_DRIVER);
+ usb_add_task(sc->sc_udev, &sc->sc_reset_task, USB_TASKQ_DRIVER);
}
static void
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index 66ab1a74b3c1..3d2841a1867d 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -86,6 +86,7 @@ int uhiddebug = 0;
struct uhid_softc {
struct uhidev sc_hdev;
+ struct usbd_device *sc_udev;
kmutex_t sc_lock;
kcondvar_t sc_cv;
@@ -182,6 +183,8 @@ uhid_attach(device_t parent, device_t self, void *aux)
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
+ sc->sc_udev = uha->uiaa->uiaa_device;
+
uhidev_get_report_desc(uha->parent, &desc, &size);
repid = uha->reportid;
sc->sc_isize = hid_report_size(desc, size, hid_input, repid);
@@ -755,16 +758,16 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, void *addr,
case USB_GET_DEVICE_DESC:
*(usb_device_descriptor_t *)addr =
- *usbd_get_device_descriptor(sc->sc_hdev.sc_parent->sc_udev);
+ *usbd_get_device_descriptor(sc->sc_udev);
break;
case USB_GET_DEVICEINFO:
- usbd_fill_deviceinfo(sc->sc_hdev.sc_parent->sc_udev,
+ usbd_fill_deviceinfo(sc->sc_udev,
(struct usb_device_info *)addr, 0);
break;
case USB_GET_DEVICEINFO_OLD:
MODULE_HOOK_CALL(usb_subr_fill_30_hook,
- (sc->sc_hdev.sc_parent->sc_udev,
+ (sc->sc_udev,
(struct usb_device_info_old *)addr, 0,
usbd_devinfo_vp, usbd_printBCD),
enosys(), err);
@@ -774,7 +777,7 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, void *addr,
case USB_GET_STRING_DESC:
{
struct usb_string_desc *si = (struct usb_string_desc *)addr;
- err = usbd_get_string_desc(sc->sc_hdev.sc_parent->sc_udev,
+ err = usbd_get_string_desc(sc->sc_udev,
si->usd_string_index,
si->usd_language_id, &si->usd_desc, &size);
if (err)
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
index 14df4d53730e..4b96e831c8b5 100644
--- a/sys/dev/usb/ukbd.c
+++ b/sys/dev/usb/ukbd.c
@@ -236,6 +236,8 @@ Static const uint8_t ukbd_trtab[256] = {
struct ukbd_softc {
struct uhidev sc_hdev;
+ struct usbd_device *sc_udev;
+ struct usbd_interface *sc_iface;
struct ukbd_data sc_ndata;
struct ukbd_data sc_odata;
@@ -410,6 +412,8 @@ ukbd_attach(device_t parent, device_t self, void *aux)
sc->sc_hdev.sc_intr = ukbd_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_iface = uha->uiaa->uiaa_iface;
sc->sc_flags = 0;
aprint_naive("\n");
@@ -427,7 +431,7 @@ ukbd_attach(device_t parent, device_t self, void *aux)
}
/* Quirks */
- qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
+ qflags = usbd_get_quirks(sc->sc_udev)->uq_flags;
if (qflags & UQ_SPUR_BUT_UP)
sc->sc_flags |= FLAG_DEBOUNCE;
if (qflags & UQ_APPLE_ISO)
@@ -579,7 +583,7 @@ ukbd_detach(device_t self, int flags)
callout_halt(&sc->sc_delay, NULL);
callout_halt(&sc->sc_ledreset, NULL);
- usb_rem_task_wait(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_ledtask,
+ usb_rem_task_wait(sc->sc_udev, &sc->sc_ledtask,
USB_TASKQ_DRIVER, NULL);
/* The console keyboard does not get a disable call, so check pipe. */
@@ -885,7 +889,7 @@ void
ukbd_set_leds(void *v, int leds)
{
struct ukbd_softc *sc = v;
- struct usbd_device *udev = sc->sc_hdev.sc_parent->sc_udev;
+ struct usbd_device *udev = sc->sc_udev;
DPRINTF(("%s: sc=%p leds=%d, sc_leds=%d\n", __func__,
sc, leds, sc->sc_leds));
@@ -995,7 +999,7 @@ ukbd_cngetc(void *v, u_int *type, int *data)
DPRINTFN(0,("%s: enter\n", __func__));
sc->sc_flags |= FLAG_POLLING;
if (sc->sc_npollchar <= 0)
- usbd_dopoll(sc->sc_hdev.sc_parent->sc_iface);
+ usbd_dopoll(sc->sc_iface);
sc->sc_flags &= ~FLAG_POLLING;
if (sc->sc_npollchar > 0) {
c = sc->sc_pollchars[0];
@@ -1021,7 +1025,8 @@ ukbd_cnpollc(void *v, int on)
DPRINTFN(2,("%s: sc=%p on=%d\n", __func__, v, on));
- usbd_interface2device_handle(sc->sc_hdev.sc_parent->sc_iface, &dev);
+ /* XXX Can this just use sc->sc_udev, or am I mistaken? */
+ usbd_interface2device_handle(sc->sc_iface, &dev);
if (on) {
sc->sc_spl = splusb();
pollenter++;
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index 0f49020b7e9e..a445cc9cfc3c 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -76,6 +76,7 @@ int umsdebug = 0;
struct ums_softc {
struct uhidev sc_hdev;
+ struct usbd_device *sc_udev;
struct hidms sc_ms;
bool sc_alwayson;
@@ -149,8 +150,9 @@ ums_attach(device_t parent, device_t self, void *aux)
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;
- quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
+ quirks = usbd_get_quirks(sc->sc_udev)->uq_flags;
if (quirks & UQ_MS_REVZ)
sc->sc_ms.flags |= HIDMS_REVZ;
if (quirks & UQ_SPUR_BUT_UP)
diff --git a/sys/dev/usb/uthum.c b/sys/dev/usb/uthum.c
index 924a6586ad21..e2fbd70584e0 100644
--- a/sys/dev/usb/uthum.c
+++ b/sys/dev/usb/uthum.c
@@ -130,7 +130,7 @@ uthum_attach(device_t parent, device_t self, void *aux)
{
struct uthum_softc *sc = device_private(self);
struct uhidev_attach_arg *uha = aux;
- struct usbd_device *dev = uha->parent->sc_udev;
+ struct usbd_device *dev = uha->uiaa->uiaa_device;
int size, repid;
void *desc;
From 7536a756168f47c5afdb8ec41ac73cc291297823 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Tue, 25 Jan 2022 00:43:58 +0000
Subject: [PATCH 4/4] uhidev(9): Move struct uhidev_softc into uhidev.c.
No longer part of any ABI for uhidev modules.
---
sys/dev/usb/uhidev.c | 40 ++++++++++++++++++++++++++++++++++++++++
sys/dev/usb/uhidev.h | 40 ----------------------------------------
2 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index d1a2909c5b59..cb7130c1dfde 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -74,6 +74,46 @@ __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.81 2021/08/07 16:19:17 thorpej Exp $");
#include "locators.h"
+struct uhidev_softc {
+ device_t sc_dev; /* base device */
+ struct usbd_device *sc_udev;
+ struct usbd_interface *sc_iface; /* interface */
+ int sc_iep_addr;
+ int sc_oep_addr;
+ u_int sc_isize;
+
+ int sc_repdesc_size;
+ void *sc_repdesc;
+
+ u_int sc_nrepid;
+ device_t *sc_subdevs;
+
+ kmutex_t sc_lock;
+ kcondvar_t sc_cv;
+
+ /* Read/written under sc_lock. */
+ struct lwp *sc_writelock;
+ struct lwp *sc_configlock;
+ int sc_refcnt;
+ int sc_writereportid;
+ u_char sc_dying;
+
+ /*
+ * - Read under sc_lock, provided sc_refcnt > 0.
+ * - Written under sc_configlock only when transitioning to and
+ * from sc_refcnt = 0.
+ */
+ u_char *sc_ibuf;
+ struct usbd_pipe *sc_ipipe; /* input interrupt pipe */
+ struct usbd_pipe *sc_opipe; /* output interrupt pipe */
+ struct usbd_xfer *sc_oxfer; /* write request */
+ usbd_callback sc_writecallback; /* async write request callback */
+ void *sc_writecookie;
+
+ u_int sc_flags;
+#define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */
+};
+
#ifdef UHIDEV_DEBUG
#define DPRINTF(x) if (uhidevdebug) printf x
#define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x
diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h
index 0b19e9015fcd..b75f6f6f74c1 100644
--- a/sys/dev/usb/uhidev.h
+++ b/sys/dev/usb/uhidev.h
@@ -35,46 +35,6 @@
#include <sys/rndsource.h>
-struct uhidev_softc {
- device_t sc_dev; /* base device */
- struct usbd_device *sc_udev;
- struct usbd_interface *sc_iface; /* interface */
- int sc_iep_addr;
- int sc_oep_addr;
- u_int sc_isize;
-
- int sc_repdesc_size;
- void *sc_repdesc;
-
- u_int sc_nrepid;
- device_t *sc_subdevs;
-
- kmutex_t sc_lock;
- kcondvar_t sc_cv;
-
- /* Read/written under sc_lock. */
- struct lwp *sc_writelock;
- struct lwp *sc_configlock;
- int sc_refcnt;
- int sc_writereportid;
- u_char sc_dying;
-
- /*
- * - Read under sc_lock, provided sc_refcnt > 0.
- * - Written under sc_configlock only when transitioning to and
- * from sc_refcnt = 0.
- */
- u_char *sc_ibuf;
- struct usbd_pipe *sc_ipipe; /* input interrupt pipe */
- struct usbd_pipe *sc_opipe; /* output interrupt pipe */
- struct usbd_xfer *sc_oxfer; /* write request */
- usbd_callback sc_writecallback; /* async write request callback */
- void *sc_writecookie;
-
- u_int sc_flags;
-#define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */
-};
-
struct uhidev {
device_t sc_dev; /* base device */
struct uhidev_softc *sc_parent;
diff --git a/sys/arch/macppc/dev/pbms.c b/sys/arch/macppc/dev/pbms.c
index a1bfb88516cb..edc2213c619c 100644
--- a/sys/arch/macppc/dev/pbms.c
+++ b/sys/arch/macppc/dev/pbms.c
@@ -307,7 +307,8 @@ pbms_match(device_t parent, cfdata_t match, void *aux)
* we expect.
*/
if (uha->uiaa->uiaa_proto == UIPROTO_MOUSE &&
- (udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) {
+ ((udd = usbd_get_device_descriptor(uha->uiaa->uiaa_device))
+ != NULL)) {
vendor = UGETW(udd->idVendor);
product = UGETW(udd->idProduct);
for (i = 0; i < PBMS_NUM_DEVICES; i++) {
@@ -329,6 +330,7 @@ pbms_attach(device_t parent, device_t self, void *aux)
struct uhidev_attach_arg *uha = aux;
struct pbms_dev *pd;
struct pbms_softc *sc = device_private(self);
+ struct usbd_device *udev;
usb_device_descriptor_t *udd;
int i;
uint16_t vendor, product;
@@ -341,7 +343,8 @@ pbms_attach(device_t parent, device_t self, void *aux)
sc->sc_datalen = PBMS_DATA_LEN;
/* Fill in device-specific parameters. */
- if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) {
+ udev = uha->uiaa->uiaa_udevice;
+ if ((udd = usbd_get_device_descriptor(udev)) != NULL) {
product = UGETW(udd->idProduct);
vendor = UGETW(udd->idVendor);
for (i = 0; i < PBMS_NUM_DEVICES; i++) {
diff --git a/sys/dev/usb/uatp.c b/sys/dev/usb/uatp.c
index a94e755f1ed2..d0a564eca616 100644
--- a/sys/dev/usb/uatp.c
+++ b/sys/dev/usb/uatp.c
@@ -486,7 +486,8 @@ static const struct uatp_knobs default_knobs = {
};
struct uatp_softc {
- struct uhidev sc_hdev; /* USB parent. */
+ struct uhidev sc_hdev; /* uhidev(9) parent. */
+ struct usbd_device *sc_udev; /* USB device. */
device_t sc_wsmousedev; /* Attached wsmouse device. */
const struct uatp_parameters *sc_parameters;
struct uatp_knobs sc_knobs;
@@ -936,6 +937,8 @@ uatp_attach(device_t parent, device_t self, void *aux)
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
+ sc->sc_udev = uha->uiaa->uiaa_device;
+
/* Identify ourselves to dmesg. */
uatp_descriptor = find_uatp_descriptor(uha);
KASSERT(uatp_descriptor != NULL);
@@ -1296,7 +1299,7 @@ uatp_ioctl(void *v, unsigned long cmd, void *data, int flag, struct lwp *p)
static void
geyser34_enable_raw_mode(struct uatp_softc *sc)
{
- struct usbd_device *udev = sc->sc_hdev.sc_parent->sc_udev;
+ struct usbd_device *udev = sc->sc_udev;
usb_device_request_t req;
usbd_status status;
uint8_t report[GEYSER34_MODE_PACKET_SIZE];
@@ -1368,8 +1371,8 @@ geyser34_finalize(struct uatp_softc *sc)
{
DPRINTF(sc, UATP_DEBUG_MISC, ("finalizing\n"));
- usb_rem_task_wait(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_reset_task,
- USB_TASKQ_DRIVER, NULL);
+ usb_rem_task_wait(sc->sc_udev, &sc->sc_reset_task, USB_TASKQ_DRIVER,
+ NULL);
return 0;
}
@@ -1379,8 +1382,7 @@ geyser34_deferred_reset(struct uatp_softc *sc)
{
DPRINTF(sc, UATP_DEBUG_RESET, ("deferring reset\n"));
- usb_add_task(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_reset_task,
- USB_TASKQ_DRIVER);
+ usb_add_task(sc->sc_udev, &sc->sc_reset_task, USB_TASKQ_DRIVER);
}
static void
diff --git a/sys/dev/usb/ucycom.c b/sys/dev/usb/ucycom.c
index bb6046ae1a12..242ac817fda5 100644
--- a/sys/dev/usb/ucycom.c
+++ b/sys/dev/usb/ucycom.c
@@ -592,11 +592,9 @@ ucycomstart(struct tty *tp)
}
#endif
DPRINTFN(4,("ucycomstart: %d chars\n", len));
- usbd_setup_xfer(sc->sc_hdev.sc_parent->sc_oxfer, sc, sc->sc_obuf,
- sc->sc_olen, 0, USBD_NO_TIMEOUT, ucycomwritecb);
-
/* What can we do on error? */
- err = usbd_transfer(sc->sc_hdev.sc_parent->sc_oxfer);
+ err = uhidev_write_async(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0,
+ USBD_NO_TIMEOUT, ucycomwritecb, sc);
#ifdef UCYCOM_DEBUG
if (err != USBD_IN_PROGRESS)
@@ -621,7 +619,6 @@ ucycomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
if (status) {
DPRINTF(("ucycomwritecb: status=%d\n", status));
- usbd_clear_endpoint_stall(sc->sc_hdev.sc_parent->sc_opipe);
/* XXX we should restart after some delay. */
goto error;
}
@@ -1105,7 +1102,7 @@ ucycom_set_status(struct ucycom_softc *sc)
memset(sc->sc_obuf, 0, sc->sc_olen);
sc->sc_obuf[0] = sc->sc_mcr;
- err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, sc->sc_olen);
+ err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen);
if (err) {
DPRINTF(("ucycom_set_status: err=%d\n", err));
}
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index 46769dc0353a..3d2841a1867d 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -86,6 +86,7 @@ int uhiddebug = 0;
struct uhid_softc {
struct uhidev sc_hdev;
+ struct usbd_device *sc_udev;
kmutex_t sc_lock;
kcondvar_t sc_cv;
@@ -182,6 +183,8 @@ uhid_attach(device_t parent, device_t self, void *aux)
sc->sc_hdev.sc_parent = uha->parent;
sc->sc_hdev.sc_report_id = uha->reportid;
+ sc->sc_udev = uha->uiaa->uiaa_device;
+
uhidev_get_report_desc(uha->parent, &desc, &size);
repid = uha->reportid;
sc->sc_isize = hid_report_size(desc, size, hid_input, repid);
@@ -581,8 +584,7 @@ uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
#endif
if (!error) {
if (sc->sc_raw)
- err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf,
- size);
+ err = uhidev_write(&sc->sc_hdev, sc->sc_obuf, size);
else
err = uhidev_set_report(&sc->sc_hdev,
UHID_OUTPUT_REPORT, sc->sc_obuf, size);
@@ -756,16 +758,16 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, void *addr,
case USB_GET_DEVICE_DESC:
*(usb_device_descriptor_t *)addr =
- *usbd_get_device_descriptor(sc->sc_hdev.sc_parent->sc_udev);
+ *usbd_get_device_descriptor(sc->sc_udev);
break;
case USB_GET_DEVICEINFO:
- usbd_fill_deviceinfo(sc->sc_hdev.sc_parent->sc_udev,
+ usbd_fill_deviceinfo(sc->sc_udev,
(struct usb_device_info *)addr, 0);
break;
case USB_GET_DEVICEINFO_OLD:
MODULE_HOOK_CALL(usb_subr_fill_30_hook,
- (sc->sc_hdev.sc_parent->sc_udev,
+ (sc->sc_udev,
(struct usb_device_info_old *)addr, 0,
usbd_devinfo_vp, usbd_printBCD),
enosys(), err);
@@ -775,7 +777,7 @@ uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, void *addr,
case USB_GET_STRING_DESC:
{
struct usb_string_desc *si = (struct usb_string_desc *)addr;
- err = usbd_get_string_desc(sc->sc_hdev.sc_parent->sc_udev,
+ err = usbd_get_string_desc(sc->sc_udev,
si->usd_string_index,
si->usd_language_id, &si->usd_desc, &size);
if (err)
diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index b0c03092c77a..cb7130c1dfde 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -74,6 +74,46 @@ __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.81 2021/08/07 16:19:17 thorpej Exp $");
#include "locators.h"
+struct uhidev_softc {
+ device_t sc_dev; /* base device */
+ struct usbd_device *sc_udev;
+ struct usbd_interface *sc_iface; /* interface */
+ int sc_iep_addr;
+ int sc_oep_addr;
+ u_int sc_isize;
+
+ int sc_repdesc_size;
+ void *sc_repdesc;
+
+ u_int sc_nrepid;
+ device_t *sc_subdevs;
+
+ kmutex_t sc_lock;
+ kcondvar_t sc_cv;
+
+ /* Read/written under sc_lock. */
+ struct lwp *sc_writelock;
+ struct lwp *sc_configlock;
+ int sc_refcnt;
+ int sc_writereportid;
+ u_char sc_dying;
+
+ /*
+ * - Read under sc_lock, provided sc_refcnt > 0.
+ * - Written under sc_configlock only when transitioning to and
+ * from sc_refcnt = 0.
+ */
+ u_char *sc_ibuf;
+ struct usbd_pipe *sc_ipipe; /* input interrupt pipe */
+ struct usbd_pipe *sc_opipe; /* output interrupt pipe */
+ struct usbd_xfer *sc_oxfer; /* write request */
+ usbd_callback sc_writecallback; /* async write request callback */
+ void *sc_writecookie;
+
+ u_int sc_flags;
+#define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */
+};
+
#ifdef UHIDEV_DEBUG
#define DPRINTF(x) if (uhidevdebug) printf x
#define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x
@@ -901,7 +941,7 @@ uhidev_stop(struct uhidev *scd)
abort = true;
mutex_exit(&sc->sc_lock);
- if (abort && sc->sc_opipe)
+ if (abort && sc->sc_opipe) /* XXX sc_opipe might go away */
usbd_abort_pipe(sc->sc_opipe);
}
@@ -961,8 +1001,9 @@ uhidev_get_report(struct uhidev *scd, int type, void *data, int len)
}
usbd_status
-uhidev_write(struct uhidev_softc *sc, void *data, int len)
+uhidev_write(struct uhidev *scd, void *data, int len)
{
+ struct uhidev_softc *sc = scd->sc_parent;
usbd_status err;
DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len));
@@ -985,6 +1026,7 @@ uhidev_write(struct uhidev_softc *sc, void *data, int len)
}
}
sc->sc_writelock = curlwp;
+ sc->sc_writereportid = scd->sc_report_id;
mutex_exit(&sc->sc_lock);
#ifdef UHIDEV_DEBUG
@@ -1006,8 +1048,79 @@ uhidev_write(struct uhidev_softc *sc, void *data, int len)
KASSERT(sc->sc_refcnt);
KASSERTMSG(sc->sc_writelock == curlwp, "%s: migrated from %p to %p",
device_xname(sc->sc_dev), curlwp, sc->sc_writelock);
+ KASSERTMSG(sc->sc_writereportid == scd->sc_report_id,
+ "%s: changed write report ids from %d to %d",
+ device_xname(sc->sc_dev), scd->sc_report_id, sc->sc_writereportid);
+ sc->sc_writereportid = -1;
sc->sc_writelock = NULL;
cv_broadcast(&sc->sc_cv);
out: mutex_exit(&sc->sc_lock);
return err;
}
+
+static void
+uhidev_write_callback(struct usbd_xfer *xfer, void *cookie, usbd_status err)
+{
+ struct uhidev_softc *sc = cookie;
+ usbd_callback writecallback;
+ void *writecookie;
+
+ if (err)
+ usbd_clear_endpoint_stall(sc->sc_opipe);
+
+ mutex_enter(&sc->sc_lock);
+ KASSERT(sc->sc_writelock == (void *)1);
+ writecallback = sc->sc_writecallback;
+ writecookie = sc->sc_writecookie;
+ sc->sc_writereportid = -1;
+ sc->sc_writelock = NULL;
+ sc->sc_writecallback = NULL;
+ sc->sc_writecookie = NULL;
+ cv_broadcast(&sc->sc_cv);
+ mutex_exit(&sc->sc_lock);
+
+ (*writecallback)(xfer, writecookie, err);
+}
+
+usbd_status
+uhidev_write_async(struct uhidev *scd, void *data, int len, int flags,
+ int timo, usbd_callback writecallback, void *writecookie)
+{
+ struct uhidev_softc *sc = scd->sc_parent;
+ usbd_status err;
+
+ DPRINTF(("%s: data=%p, len=%d\n", __func__, data, len));
+
+ if (sc->sc_opipe == NULL)
+ return USBD_INVAL;
+
+ mutex_enter(&sc->sc_lock);
+ KASSERT(sc->sc_refcnt);
+ if (sc->sc_dying) {
+ err = USBD_IOERROR;
+ goto out;
+ }
+ if (sc->sc_writelock != NULL) {
+ err = USBD_IN_USE;
+ goto out;
+ }
+ sc->sc_writelock = (void *)1; /* XXX no lwp to attribute async xfer */
+ sc->sc_writereportid = scd->sc_report_id;
+ sc->sc_writecallback = writecallback;
+ sc->sc_writecookie = writecookie;
+ usbd_setup_xfer(sc->sc_oxfer, sc, data, len, flags, timo,
+ uhidev_write_callback);
+ err = usbd_transfer(sc->sc_oxfer);
+ switch (err) {
+ case USBD_IN_PROGRESS:
+ break;
+ case USBD_NORMAL_COMPLETION:
+ panic("unexpected normal completion of async xfer under lock");
+ default: /* error */
+ sc->sc_writelock = NULL;
+ sc->sc_writereportid = -1;
+ cv_broadcast(&sc->sc_cv);
+ }
+out: mutex_exit(&sc->sc_lock);
+ return err;
+}
diff --git a/sys/dev/usb/uhidev.h b/sys/dev/usb/uhidev.h
index 83c0a357744e..b75f6f6f74c1 100644
--- a/sys/dev/usb/uhidev.h
+++ b/sys/dev/usb/uhidev.h
@@ -35,44 +35,6 @@
#include <sys/rndsource.h>
-struct uhidev_softc {
- device_t sc_dev; /* base device */
- struct usbd_device *sc_udev;
- struct usbd_interface *sc_iface; /* interface */
- int sc_iep_addr;
- int sc_oep_addr;
- u_int sc_isize;
-
- int sc_repdesc_size;
- void *sc_repdesc;
-
- u_int sc_nrepid;
- device_t *sc_subdevs;
-
- kmutex_t sc_lock;
- kcondvar_t sc_cv;
-
- /* Read/written under sc_lock. */
- struct lwp *sc_writelock;
- struct lwp *sc_configlock;
- int sc_refcnt;
- int sc_writereportid;
- u_char sc_dying;
-
- /*
- * - Read under sc_lock, provided sc_refcnt > 0.
- * - Written under sc_configlock only when transitioning to and
- * from sc_refcnt = 0.
- */
- u_char *sc_ibuf;
- struct usbd_pipe *sc_ipipe; /* input interrupt pipe */
- struct usbd_pipe *sc_opipe; /* output interrupt pipe */
- struct usbd_xfer *sc_oxfer; /* write request */
-
- u_int sc_flags;
-#define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */
-};
-
struct uhidev {
device_t sc_dev; /* base device */
struct uhidev_softc *sc_parent;
@@ -97,7 +59,9 @@ void uhidev_stop(struct uhidev *);
void uhidev_close(struct uhidev *);
usbd_status uhidev_set_report(struct uhidev *, int, void *, int);
usbd_status uhidev_get_report(struct uhidev *, int, void *, int);
-usbd_status uhidev_write(struct uhidev_softc *, void *, int);
+usbd_status uhidev_write(struct uhidev *, void *, int);
+usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int,
+ usbd_callback, void *);
#define UHIDEV_OSIZE 64
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
index 14df4d53730e..4b96e831c8b5 100644
--- a/sys/dev/usb/ukbd.c
+++ b/sys/dev/usb/ukbd.c
@@ -236,6 +236,8 @@ Static const uint8_t ukbd_trtab[256] = {
struct ukbd_softc {
struct uhidev sc_hdev;
+ struct usbd_device *sc_udev;
+ struct usbd_interface *sc_iface;
struct ukbd_data sc_ndata;
struct ukbd_data sc_odata;
@@ -410,6 +412,8 @@ ukbd_attach(device_t parent, device_t self, void *aux)
sc->sc_hdev.sc_intr = ukbd_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_iface = uha->uiaa->uiaa_iface;
sc->sc_flags = 0;
aprint_naive("\n");
@@ -427,7 +431,7 @@ ukbd_attach(device_t parent, device_t self, void *aux)
}
/* Quirks */
- qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
+ qflags = usbd_get_quirks(sc->sc_udev)->uq_flags;
if (qflags & UQ_SPUR_BUT_UP)
sc->sc_flags |= FLAG_DEBOUNCE;
if (qflags & UQ_APPLE_ISO)
@@ -579,7 +583,7 @@ ukbd_detach(device_t self, int flags)
callout_halt(&sc->sc_delay, NULL);
callout_halt(&sc->sc_ledreset, NULL);
- usb_rem_task_wait(sc->sc_hdev.sc_parent->sc_udev, &sc->sc_ledtask,
+ usb_rem_task_wait(sc->sc_udev, &sc->sc_ledtask,
USB_TASKQ_DRIVER, NULL);
/* The console keyboard does not get a disable call, so check pipe. */
@@ -885,7 +889,7 @@ void
ukbd_set_leds(void *v, int leds)
{
struct ukbd_softc *sc = v;
- struct usbd_device *udev = sc->sc_hdev.sc_parent->sc_udev;
+ struct usbd_device *udev = sc->sc_udev;
DPRINTF(("%s: sc=%p leds=%d, sc_leds=%d\n", __func__,
sc, leds, sc->sc_leds));
@@ -995,7 +999,7 @@ ukbd_cngetc(void *v, u_int *type, int *data)
DPRINTFN(0,("%s: enter\n", __func__));
sc->sc_flags |= FLAG_POLLING;
if (sc->sc_npollchar <= 0)
- usbd_dopoll(sc->sc_hdev.sc_parent->sc_iface);
+ usbd_dopoll(sc->sc_iface);
sc->sc_flags &= ~FLAG_POLLING;
if (sc->sc_npollchar > 0) {
c = sc->sc_pollchars[0];
@@ -1021,7 +1025,8 @@ ukbd_cnpollc(void *v, int on)
DPRINTFN(2,("%s: sc=%p on=%d\n", __func__, v, on));
- usbd_interface2device_handle(sc->sc_hdev.sc_parent->sc_iface, &dev);
+ /* XXX Can this just use sc->sc_udev, or am I mistaken? */
+ usbd_interface2device_handle(sc->sc_iface, &dev);
if (on) {
sc->sc_spl = splusb();
pollenter++;
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index 0f49020b7e9e..a445cc9cfc3c 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -76,6 +76,7 @@ int umsdebug = 0;
struct ums_softc {
struct uhidev sc_hdev;
+ struct usbd_device *sc_udev;
struct hidms sc_ms;
bool sc_alwayson;
@@ -149,8 +150,9 @@ ums_attach(device_t parent, device_t self, void *aux)
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;
- quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
+ quirks = usbd_get_quirks(sc->sc_udev)->uq_flags;
if (quirks & UQ_MS_REVZ)
sc->sc_ms.flags |= HIDMS_REVZ;
if (quirks & UQ_SPUR_BUT_UP)
diff --git a/sys/dev/usb/uthum.c b/sys/dev/usb/uthum.c
index 924a6586ad21..e2fbd70584e0 100644
--- a/sys/dev/usb/uthum.c
+++ b/sys/dev/usb/uthum.c
@@ -130,7 +130,7 @@ uthum_attach(device_t parent, device_t self, void *aux)
{
struct uthum_softc *sc = device_private(self);
struct uhidev_attach_arg *uha = aux;
- struct usbd_device *dev = uha->parent->sc_udev;
+ struct usbd_device *dev = uha->uiaa->uiaa_device;
int size, repid;
void *desc;
Home |
Main Index |
Thread Index |
Old Index