Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F97301150
D39373.id119831.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D39373.id119831.diff
View Options
diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h
--- a/sys/dev/usb/usb_dev.h
+++ b/sys/dev/usb/usb_dev.h
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -110,13 +110,15 @@
struct selinfo selinfo;
struct cv cv_io;
struct cv cv_drain;
+ struct sx fs_fastpath_lock;
struct usb_fifo_methods *methods;
struct usb_symlink *symlink[2];/* our symlinks */
struct proc *async_p; /* process that wants SIGIO */
struct usb_fs_endpoint *fs_ep_ptr;
struct usb_device *udev;
+#define USB_FS_XFER_MAX 126
struct usb_xfer *xfer[2];
- struct usb_xfer **fs_xfer;
+ struct usb_xfer *fs_xfer[USB_FS_XFER_MAX];
struct mtx *priv_mtx; /* client data */
/* set if FIFO is opened by a FILE: */
struct usb_cdev_privdata *curr_cpd;
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2006-2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2006-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -386,6 +386,7 @@
f = malloc(sizeof(*f), M_USBDEV, M_WAITOK | M_ZERO);
cv_init(&f->cv_io, "FIFO-IO");
cv_init(&f->cv_drain, "FIFO-DRAIN");
+ sx_init(&f->fs_fastpath_lock, "FIFO-FP");
f->priv_mtx = mtx;
f->refcount = 1;
knlist_init_mtx(&f->selinfo.si_note, mtx);
@@ -626,6 +627,7 @@
cv_destroy(&f->cv_io);
cv_destroy(&f->cv_drain);
+ sx_destroy(&f->fs_fastpath_lock);
knlist_clear(&f->selinfo.si_note, 0);
seldrain(&f->selinfo);
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008-2020 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -2829,7 +2829,7 @@
continue;
}
if ((f->dev_ep_index == 0) &&
- (f->fs_xfer == NULL)) {
+ (f->fs_ep_max == 0)) {
/* no need to free this FIFO */
continue;
}
@@ -2837,7 +2837,7 @@
if ((f->methods == &usb_ugen_methods) &&
(f->dev_ep_index == 0) &&
(!(flag & USB_UNCFG_FLAG_FREE_EP0)) &&
- (f->fs_xfer == NULL)) {
+ (f->fs_ep_max == 0)) {
/* no need to free this FIFO */
continue;
}
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008-2022 Hans Petter Selasky
+ * Copyright (c) 2008-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -120,6 +120,7 @@
static uint8_t ugen_fs_get_complete(struct usb_fifo *, uint8_t *);
static int ugen_fs_uninit(struct usb_fifo *f);
static int ugen_fs_copyin(struct usb_fifo *, uint8_t, struct usb_fs_endpoint*);
+static uint8_t ugen_fifo_in_use(struct usb_fifo *, int fflags);
/* structures */
@@ -959,22 +960,231 @@
return (0);
}
+static int
+ugen_fs_init(struct usb_fifo *f,
+ struct usb_fs_endpoint *fs_ep_ptr, usb_size_t fs_ep_sz,
+ int fflags, uint8_t ep_index_max)
+{
+ int error;
+
+ /* verify input parameters */
+ if (fs_ep_ptr == NULL || ep_index_max > USB_FS_XFER_MAX)
+ return (EINVAL);
+
+ if (f->fs_ep_max != 0)
+ return (EBUSY);
+
+ if (f->dev_ep_index != 0 || ep_index_max == 0)
+ return (EINVAL);
+
+ if (ugen_fifo_in_use(f, fflags))
+ return (EBUSY);
+
+ error = usb_fifo_alloc_buffer(f, 1, ep_index_max);
+ if (error == 0) {
+ mtx_lock(f->priv_mtx);
+ f->fs_ep_max = ep_index_max;
+ f->fs_ep_ptr = fs_ep_ptr;
+ f->fs_ep_sz = fs_ep_sz;
+ mtx_unlock(f->priv_mtx);
+ }
+ return (error);
+}
+
int
ugen_fs_uninit(struct usb_fifo *f)
{
- if (f->fs_xfer == NULL) {
+ if (f->fs_ep_max == 0)
return (EINVAL);
- }
- usbd_transfer_unsetup(f->fs_xfer, f->fs_ep_max);
- free(f->fs_xfer, M_USB);
- f->fs_xfer = NULL;
+
+ /*
+ * Prevent calls into the fast-path code, by setting fs_ep_max
+ * to zero:
+ */
+ sx_xlock(&f->fs_fastpath_lock);
+ mtx_lock(f->priv_mtx);
f->fs_ep_max = 0;
+ mtx_unlock(f->priv_mtx);
+ sx_xunlock(&f->fs_fastpath_lock);
+
+ usbd_transfer_unsetup(f->fs_xfer, USB_FS_XFER_MAX);
+
+ mtx_lock(f->priv_mtx);
f->fs_ep_ptr = NULL;
f->flag_iscomplete = 0;
+ mtx_unlock(f->priv_mtx);
+
usb_fifo_free_buffer(f);
return (0);
}
+static int
+usb_fs_open(struct usb_fifo *f, struct usb_fs_open *popen,
+ int fflags, usb_stream_t stream_id)
+{
+ struct usb_config usb_config[1] = {};
+ struct usb_endpoint *ep;
+ struct usb_endpoint_descriptor *ed;
+ uint8_t iface_index;
+ uint8_t pre_scale;
+ uint8_t isread;
+ int error;
+
+ if (popen->ep_index >= f->fs_ep_max)
+ return (EINVAL);
+
+ if (f->fs_xfer[popen->ep_index] != NULL)
+ return (EBUSY);
+
+ if (popen->max_bufsize > USB_FS_MAX_BUFSIZE)
+ popen->max_bufsize = USB_FS_MAX_BUFSIZE;
+
+ if (popen->max_frames & USB_FS_MAX_FRAMES_PRE_SCALE) {
+ pre_scale = 1;
+ popen->max_frames &= ~USB_FS_MAX_FRAMES_PRE_SCALE;
+ } else {
+ pre_scale = 0;
+ }
+
+ if (popen->max_frames > USB_FS_MAX_FRAMES)
+ popen->max_frames = USB_FS_MAX_FRAMES;
+
+ if (popen->max_frames == 0)
+ return (EINVAL);
+
+ ep = usbd_get_ep_by_addr(f->udev, popen->ep_no);
+ if (ep == NULL)
+ return (EINVAL);
+
+ ed = ep->edesc;
+ if (ed == NULL)
+ return (ENXIO);
+
+ iface_index = ep->iface_index;
+
+ usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
+ usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
+ usb_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
+ usb_config[0].interval = USB_DEFAULT_INTERVAL;
+ usb_config[0].flags.proxy_buffer = 1;
+ if (pre_scale != 0)
+ usb_config[0].flags.pre_scale_frames = 1;
+
+ usb_config[0].callback = &ugen_ctrl_fs_callback;
+ usb_config[0].timeout = 0; /* no timeout */
+ usb_config[0].frames = popen->max_frames;
+ usb_config[0].bufsize = popen->max_bufsize;
+ usb_config[0].usb_mode = USB_MODE_DUAL; /* both modes */
+ usb_config[0].stream_id = stream_id;
+
+ if (usb_config[0].type == UE_CONTROL) {
+ if (f->udev->flags.usb_mode != USB_MODE_HOST)
+ return (EINVAL);
+ } else {
+ isread = ((usb_config[0].endpoint &
+ (UE_DIR_IN | UE_DIR_OUT)) == UE_DIR_IN);
+
+ if (f->udev->flags.usb_mode != USB_MODE_HOST)
+ isread = !isread;
+
+ /* check permissions */
+ if (isread) {
+ if (!(fflags & FREAD))
+ return (EPERM);
+ } else {
+ if (!(fflags & FWRITE))
+ return (EPERM);
+ }
+ }
+ error = usbd_transfer_setup(f->udev, &iface_index,
+ f->fs_xfer + popen->ep_index, usb_config, 1,
+ f, f->priv_mtx);
+ if (error == 0) {
+ /* update maximums */
+ popen->max_packet_length =
+ f->fs_xfer[popen->ep_index]->max_frame_size;
+ popen->max_bufsize =
+ f->fs_xfer[popen->ep_index]->max_data_length;
+ /* update number of frames */
+ popen->max_frames =
+ f->fs_xfer[popen->ep_index]->nframes;
+ /* store index of endpoint */
+ f->fs_xfer[popen->ep_index]->priv_fifo =
+ ((uint8_t *)0) + popen->ep_index;
+ } else {
+ error = ENOMEM;
+ }
+ return (error);
+}
+
+static int
+usb_fs_close(struct usb_fifo *f, struct usb_fs_close *pclose)
+{
+ struct usb_xfer *xfer;
+
+ if (pclose->ep_index >= f->fs_ep_max)
+ return (EINVAL);
+
+ /*
+ * Prevent calls into the fast-path code, by setting the
+ * fs_xfer[] in question to NULL:
+ */
+ sx_xlock(&f->fs_fastpath_lock);
+ mtx_lock(f->priv_mtx);
+ xfer = f->fs_xfer[pclose->ep_index];
+ f->fs_xfer[pclose->ep_index] = NULL;
+ mtx_unlock(f->priv_mtx);
+ sx_xunlock(&f->fs_fastpath_lock);
+
+ if (xfer == NULL)
+ return (EINVAL);
+
+ usbd_transfer_unsetup(&xfer, 1);
+ return (0);
+}
+
+static int
+usb_fs_clear_stall_sync(struct usb_fifo *f, struct usb_fs_clear_stall_sync *pstall)
+{
+ struct usb_device_request req;
+ struct usb_endpoint *ep;
+ int error;
+
+ if (pstall->ep_index >= f->fs_ep_max)
+ return (EINVAL);
+
+ if (f->fs_xfer[pstall->ep_index] == NULL)
+ return (EINVAL);
+
+ if (f->udev->flags.usb_mode != USB_MODE_HOST)
+ return (EINVAL);
+
+ mtx_lock(f->priv_mtx);
+ error = usbd_transfer_pending(f->fs_xfer[pstall->ep_index]);
+ mtx_unlock(f->priv_mtx);
+
+ if (error)
+ return (EBUSY);
+
+ ep = f->fs_xfer[pstall->ep_index]->endpoint;
+
+ /* setup a clear-stall packet */
+ req.bmRequestType = UT_WRITE_ENDPOINT;
+ req.bRequest = UR_CLEAR_FEATURE;
+ USETW(req.wValue, UF_ENDPOINT_HALT);
+ req.wIndex[0] = ep->edesc->bEndpointAddress;
+ req.wIndex[1] = 0;
+ USETW(req.wLength, 0);
+
+ error = usbd_do_request(f->udev, NULL, &req, NULL);
+ if (error == 0) {
+ usbd_clear_data_toggle(f->udev, ep);
+ } else {
+ error = ENXIO;
+ }
+ return (error);
+}
+
static uint8_t
ugen_fs_get_complete(struct usb_fifo *f, uint8_t *pindex)
{
@@ -1066,14 +1276,16 @@
int error;
uint8_t isread;
+ mtx_lock(f->priv_mtx);
if (ep_index >= f->fs_ep_max) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
}
xfer = f->fs_xfer[ep_index];
if (xfer == NULL) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
}
- mtx_lock(f->priv_mtx);
if (usbd_transfer_pending(xfer)) {
mtx_unlock(f->priv_mtx);
return (EBUSY); /* should not happen */
@@ -1346,14 +1558,16 @@
int error;
uint8_t isread;
- if (ep_index >= f->fs_ep_max)
+ mtx_lock(f->priv_mtx);
+ if (ep_index >= f->fs_ep_max) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
-
+ }
xfer = f->fs_xfer[ep_index];
- if (xfer == NULL)
+ if (xfer == NULL) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
-
- mtx_lock(f->priv_mtx);
+ }
if (!xfer->flags_int.transferring &&
!xfer->flags_int.started) {
mtx_unlock(f->priv_mtx);
@@ -1488,26 +1702,15 @@
static int
ugen_ioctl(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
{
- struct usb_config usb_config[1];
- struct usb_device_request req;
union {
struct usb_fs_complete *pcomp;
struct usb_fs_start *pstart;
struct usb_fs_stop *pstop;
- struct usb_fs_open *popen;
- struct usb_fs_open_stream *popen_stream;
- struct usb_fs_close *pclose;
- struct usb_fs_clear_stall_sync *pstall;
void *addr;
} u;
- struct usb_endpoint *ep;
- struct usb_endpoint_descriptor *ed;
struct usb_xfer *xfer;
- int error = 0;
- uint8_t iface_index;
- uint8_t isread;
+ int error;
uint8_t ep_index;
- uint8_t pre_scale;
u.addr = addr;
@@ -1515,202 +1718,58 @@
switch (cmd) {
case USB_FS_COMPLETE:
+ sx_slock(&f->fs_fastpath_lock);
mtx_lock(f->priv_mtx);
error = ugen_fs_get_complete(f, &ep_index);
mtx_unlock(f->priv_mtx);
- if (error) {
+ if (error != 0) {
error = EBUSY;
- break;
+ } else {
+ u.pcomp->ep_index = ep_index;
+ error = ugen_fs_copy_out(f, u.pcomp->ep_index);
}
- u.pcomp->ep_index = ep_index;
- error = ugen_fs_copy_out(f, u.pcomp->ep_index);
+ sx_sunlock(&f->fs_fastpath_lock);
break;
case USB_FS_START:
+ sx_slock(&f->fs_fastpath_lock);
error = ugen_fs_copy_in(f, u.pstart->ep_index);
- if (error)
- break;
- mtx_lock(f->priv_mtx);
- xfer = f->fs_xfer[u.pstart->ep_index];
- usbd_transfer_start(xfer);
- mtx_unlock(f->priv_mtx);
+ if (error == 0) {
+ mtx_lock(f->priv_mtx);
+ xfer = f->fs_xfer[u.pstart->ep_index];
+ usbd_transfer_start(xfer);
+ mtx_unlock(f->priv_mtx);
+ }
+ sx_sunlock(&f->fs_fastpath_lock);
break;
case USB_FS_STOP:
- if (u.pstop->ep_index >= f->fs_ep_max) {
- error = EINVAL;
- break;
- }
+ sx_slock(&f->fs_fastpath_lock);
mtx_lock(f->priv_mtx);
- xfer = f->fs_xfer[u.pstart->ep_index];
- if (usbd_transfer_pending(xfer)) {
- usbd_transfer_stop(xfer);
-
- /*
- * Check if the USB transfer was stopped
- * before it was even started and fake a
- * cancel event.
- */
- if (!xfer->flags_int.transferring &&
- !xfer->flags_int.started) {
- DPRINTF("Issuing fake completion event\n");
- ugen_fs_set_complete(xfer->priv_sc,
- USB_P2U(xfer->priv_fifo));
- }
- }
- mtx_unlock(f->priv_mtx);
- break;
-
- case USB_FS_OPEN:
- case USB_FS_OPEN_STREAM:
- if (u.popen->ep_index >= f->fs_ep_max) {
- error = EINVAL;
- break;
- }
- if (f->fs_xfer[u.popen->ep_index] != NULL) {
- error = EBUSY;
- break;
- }
- if (u.popen->max_bufsize > USB_FS_MAX_BUFSIZE) {
- u.popen->max_bufsize = USB_FS_MAX_BUFSIZE;
- }
- if (u.popen->max_frames & USB_FS_MAX_FRAMES_PRE_SCALE) {
- pre_scale = 1;
- u.popen->max_frames &= ~USB_FS_MAX_FRAMES_PRE_SCALE;
- } else {
- pre_scale = 0;
- }
- if (u.popen->max_frames > USB_FS_MAX_FRAMES) {
- u.popen->max_frames = USB_FS_MAX_FRAMES;
- break;
- }
- if (u.popen->max_frames == 0) {
- error = EINVAL;
- break;
- }
- ep = usbd_get_ep_by_addr(f->udev, u.popen->ep_no);
- if (ep == NULL) {
+ if (u.pstop->ep_index >= f->fs_ep_max) {
error = EINVAL;
- break;
- }
- ed = ep->edesc;
- if (ed == NULL) {
- error = ENXIO;
- break;
- }
- iface_index = ep->iface_index;
-
- memset(usb_config, 0, sizeof(usb_config));
-
- usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
- usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
- usb_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
- usb_config[0].interval = USB_DEFAULT_INTERVAL;
- usb_config[0].flags.proxy_buffer = 1;
- if (pre_scale != 0)
- usb_config[0].flags.pre_scale_frames = 1;
- usb_config[0].callback = &ugen_ctrl_fs_callback;
- usb_config[0].timeout = 0; /* no timeout */
- usb_config[0].frames = u.popen->max_frames;
- usb_config[0].bufsize = u.popen->max_bufsize;
- usb_config[0].usb_mode = USB_MODE_DUAL; /* both modes */
- if (cmd == USB_FS_OPEN_STREAM)
- usb_config[0].stream_id = u.popen_stream->stream_id;
-
- if (usb_config[0].type == UE_CONTROL) {
- if (f->udev->flags.usb_mode != USB_MODE_HOST) {
- error = EINVAL;
- break;
- }
} else {
- isread = ((usb_config[0].endpoint &
- (UE_DIR_IN | UE_DIR_OUT)) == UE_DIR_IN);
+ error = 0;
+ xfer = f->fs_xfer[u.pstart->ep_index];
+ if (usbd_transfer_pending(xfer)) {
+ usbd_transfer_stop(xfer);
- if (f->udev->flags.usb_mode != USB_MODE_HOST) {
- isread = !isread;
- }
- /* check permissions */
- if (isread) {
- if (!(fflags & FREAD)) {
- error = EPERM;
- break;
- }
- } else {
- if (!(fflags & FWRITE)) {
- error = EPERM;
- break;
+ /*
+ * Check if the USB transfer was
+ * stopped before it was even started
+ * and fake a cancel event.
+ */
+ if (!xfer->flags_int.transferring &&
+ !xfer->flags_int.started) {
+ DPRINTF("Issuing fake completion event\n");
+ ugen_fs_set_complete(xfer->priv_sc,
+ USB_P2U(xfer->priv_fifo));
}
}
}
- error = usbd_transfer_setup(f->udev, &iface_index,
- f->fs_xfer + u.popen->ep_index, usb_config, 1,
- f, f->priv_mtx);
- if (error == 0) {
- /* update maximums */
- u.popen->max_packet_length =
- f->fs_xfer[u.popen->ep_index]->max_frame_size;
- u.popen->max_bufsize =
- f->fs_xfer[u.popen->ep_index]->max_data_length;
- /* update number of frames */
- u.popen->max_frames =
- f->fs_xfer[u.popen->ep_index]->nframes;
- /* store index of endpoint */
- f->fs_xfer[u.popen->ep_index]->priv_fifo =
- ((uint8_t *)0) + u.popen->ep_index;
- } else {
- error = ENOMEM;
- }
- break;
-
- case USB_FS_CLOSE:
- if (u.pclose->ep_index >= f->fs_ep_max) {
- error = EINVAL;
- break;
- }
- if (f->fs_xfer[u.pclose->ep_index] == NULL) {
- error = EINVAL;
- break;
- }
- usbd_transfer_unsetup(f->fs_xfer + u.pclose->ep_index, 1);
- break;
-
- case USB_FS_CLEAR_STALL_SYNC:
- if (u.pstall->ep_index >= f->fs_ep_max) {
- error = EINVAL;
- break;
- }
- if (f->fs_xfer[u.pstall->ep_index] == NULL) {
- error = EINVAL;
- break;
- }
- if (f->udev->flags.usb_mode != USB_MODE_HOST) {
- error = EINVAL;
- break;
- }
- mtx_lock(f->priv_mtx);
- error = usbd_transfer_pending(f->fs_xfer[u.pstall->ep_index]);
mtx_unlock(f->priv_mtx);
-
- if (error) {
- return (EBUSY);
- }
- ep = f->fs_xfer[u.pstall->ep_index]->endpoint;
-
- /* setup a clear-stall packet */
- req.bmRequestType = UT_WRITE_ENDPOINT;
- req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_HALT);
- req.wIndex[0] = ep->edesc->bEndpointAddress;
- req.wIndex[1] = 0;
- USETW(req.wLength, 0);
-
- error = usbd_do_request(f->udev, NULL, &req, NULL);
- if (error == 0) {
- usbd_clear_data_toggle(f->udev, ep);
- } else {
- error = ENXIO;
- }
+ sx_sunlock(&f->fs_fastpath_lock);
break;
default:
@@ -2161,9 +2220,6 @@
static int
ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags)
{
-#ifdef COMPAT_FREEBSD32
- struct usb_fs_init local_pinit;
-#endif
union {
struct usb_interface_descriptor *idesc;
struct usb_alt_interface *ai;
@@ -2175,6 +2231,10 @@
struct usb_fs_init32 *pinit32;
#endif
struct usb_fs_uninit *puninit;
+ struct usb_fs_open *popen;
+ struct usb_fs_open_stream *popen_stream;
+ struct usb_fs_close *pclose;
+ struct usb_fs_clear_stall_sync *pstall;
struct usb_device_port_path *dpp;
uint32_t *ptime;
void *addr;
@@ -2183,7 +2243,6 @@
struct usb_device_descriptor *dtemp;
struct usb_config_descriptor *ctemp;
struct usb_interface *iface;
- size_t usb_fs_endpoint_sz = sizeof(struct usb_fs_endpoint);
int error = 0;
uint8_t n;
@@ -2191,18 +2250,6 @@
DPRINTFN(6, "cmd=0x%08lx\n", cmd);
-#ifdef COMPAT_FREEBSD32
- switch (cmd) {
- case USB_FS_INIT32:
- PTRIN_CP(*u.pinit32, local_pinit, pEndpoints);
- CP(*u.pinit32, local_pinit, ep_index_max);
- u.addr = &local_pinit;
- cmd = _IOC_NEWTYPE(USB_FS_INIT, struct usb_fs_init);
- usb_fs_endpoint_sz = sizeof(struct usb_fs_endpoint32);
- break;
- }
-#endif
-
switch (cmd) {
case USB_DISCOVER:
usb_needs_explore_all();
@@ -2397,42 +2444,17 @@
break;
case USB_FS_INIT:
- /* verify input parameters */
- if (u.pinit->pEndpoints == NULL) {
- error = EINVAL;
- break;
- }
- if (u.pinit->ep_index_max > 127) {
- error = EINVAL;
- break;
- }
- if (u.pinit->ep_index_max == 0) {
- error = EINVAL;
- break;
- }
- if (f->fs_xfer != NULL) {
- error = EBUSY;
- break;
- }
- if (f->dev_ep_index != 0) {
- error = EINVAL;
- break;
- }
- if (ugen_fifo_in_use(f, fflags)) {
- error = EBUSY;
- break;
- }
- error = usb_fifo_alloc_buffer(f, 1, u.pinit->ep_index_max);
- if (error) {
- break;
- }
- f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) *
- u.pinit->ep_index_max, M_USB, M_WAITOK | M_ZERO);
- f->fs_ep_max = u.pinit->ep_index_max;
- f->fs_ep_ptr = u.pinit->pEndpoints;
- f->fs_ep_sz = usb_fs_endpoint_sz;
+ error = ugen_fs_init(f, u.pinit->pEndpoints,
+ sizeof(struct usb_fs_endpoint), fflags,
+ u.pinit->ep_index_max);
break;
-
+#ifdef COMPAT_FREEBSD32
+ case USB_FS_INIT32:
+ error = ugen_fs_init(f, PTRIN(u.pinit32->pEndpoints),
+ sizeof(struct usb_fs_endpoint32), fflags,
+ u.pinit32->ep_index_max);
+ break;
+#endif
case USB_FS_UNINIT:
if (u.puninit->dummy != 0) {
error = EINVAL;
@@ -2441,6 +2463,20 @@
error = ugen_fs_uninit(f);
break;
+ case USB_FS_OPEN:
+ case USB_FS_OPEN_STREAM:
+ error = usb_fs_open(f, u.popen, fflags,
+ (cmd == USB_FS_OPEN_STREAM) ? u.popen_stream->stream_id : 0);
+ break;
+
+ case USB_FS_CLOSE:
+ error = usb_fs_close(f, u.pclose);
+ break;
+
+ case USB_FS_CLEAR_STALL_SYNC:
+ error = usb_fs_clear_stall_sync(f, u.pstall);
+ break;
+
default:
mtx_lock(f->priv_mtx);
error = ugen_iface_ioctl(f, cmd, addr, fflags);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Sep 29, 1:36 PM (3 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
13131483
Default Alt Text
D39373.id119831.diff (19 KB)
Attached To
Mode
D39373: usb(4): Separate the fast path and the slow path to avoid races and use-after-free for the USB FS interface
Attached
Detach File
Event Timeline
Log In to Comment