summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Binkert <nate@cvs.openbsd.org>2002-07-09 17:50:15 +0000
committerNathan Binkert <nate@cvs.openbsd.org>2002-07-09 17:50:15 +0000
commit2621c6ba13ef1435846b92dbb93788c7ef4a07ea (patch)
treeabc9c56fdd884cf4dc4a6731550208649a4300ec
parentdcb90d88f68f79bfaa157bf8c7b53d98d7f8bcce (diff)
sync with NetBSD
-rw-r--r--sys/dev/usb/ugen.c165
1 files changed, 90 insertions, 75 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 2a393c3f1df..16e11e3abe0 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ugen.c,v 1.21 2002/07/09 17:41:02 nate Exp $ */
-/* $NetBSD: ugen.c,v 1.49 2001/10/24 22:31:04 augustss Exp $ */
+/* $OpenBSD: ugen.c,v 1.22 2002/07/09 17:50:14 nate Exp $ */
+/* $NetBSD: ugen.c,v 1.58 2002/02/20 20:30:12 christos Exp $ */
/* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
/*
@@ -20,8 +20,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
@@ -150,16 +150,16 @@ Static struct cdevsw ugen_cdevsw = {
};
#endif
-Static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr,
+Static void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr,
usbd_status status);
Static void ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
usbd_status status);
Static int ugen_do_read(struct ugen_softc *, int, struct uio *, int);
Static int ugen_do_write(struct ugen_softc *, int, struct uio *, int);
-Static int ugen_do_ioctl(struct ugen_softc *, int, u_long,
- caddr_t, int, struct proc *);
+Static int ugen_do_ioctl(struct ugen_softc *, int, u_long,
+ caddr_t, int, usb_proc_ptr);
Static int ugen_set_config(struct ugen_softc *sc, int configno);
-Static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc,
+Static usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc,
int index, int *lenp);
Static usbd_status ugen_set_interface(struct ugen_softc *, int, int);
Static int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx);
@@ -201,7 +201,7 @@ USB_ATTACH(ugen)
/* First set configuration index 0, the default one for ugen. */
err = usbd_set_config_index(udev, 0, 0);
if (err) {
- printf("%s: setting configuration index 0 failed\n",
+ printf("%s: setting configuration index 0 failed\n",
USBDEVNAME(sc->sc_dev));
sc->sc_dying = 1;
USB_ATTACH_ERROR_RETURN;
@@ -211,7 +211,7 @@ USB_ATTACH(ugen)
/* Set up all the local state for this configuration. */
err = ugen_set_config(sc, conf);
if (err) {
- printf("%s: setting configuration %d failed\n",
+ printf("%s: setting configuration %d failed\n",
USBDEVNAME(sc->sc_dev), conf);
sc->sc_dying = 1;
USB_ATTACH_ERROR_RETURN;
@@ -247,6 +247,19 @@ ugen_set_config(struct ugen_softc *sc, int configno)
DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
USBDEVNAME(sc->sc_dev), configno, sc));
+
+ /*
+ * We start at 1, not 0, because we don't care whether the
+ * control endpoint is open or not. It is always present.
+ */
+ for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++)
+ if (sc->sc_is_open[endptno]) {
+ DPRINTFN(1,
+ ("ugen_set_config: %s - endpoint %d is open\n",
+ USBDEVNAME(sc->sc_dev), endptno));
+ return (USBD_IN_USE);
+ }
+
/* Avoid setting the current value. */
if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
err = usbd_set_config_no(dev, configno, 1);
@@ -272,7 +285,7 @@ ugen_set_config(struct ugen_softc *sc, int configno)
dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
- "(%d,%d), sce=%p\n",
+ "(%d,%d), sce=%p\n",
endptno, endpt, UE_GET_ADDR(endpt),
UE_GET_DIR(endpt), sce));
sce->sc = sc;
@@ -284,7 +297,7 @@ ugen_set_config(struct ugen_softc *sc, int configno)
}
int
-ugenopen(dev_t dev, int flag, int mode, struct proc *p)
+ugenopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
{
struct ugen_softc *sc;
int unit = UGENUNIT(dev);
@@ -299,7 +312,7 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
USB_GET_SC_OPEN(ugen, unit, sc);
- DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
+ DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
flag, mode, unit, endpt));
if (sc == NULL || sc->sc_dying)
@@ -330,7 +343,7 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
sce = &sc->sc_endpoints[endpt][dir];
sce->state = 0;
sce->timeout = USBD_NO_TIMEOUT;
- DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
+ DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
sc, endpt, dir, sce));
edesc = sce->edesc;
switch (edesc->bmAttributes & UE_XFERTYPE) {
@@ -339,14 +352,14 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
if (isize == 0) /* shouldn't happen */
return (EINVAL);
sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
- DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
+ DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
endpt, isize));
- if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
- return (ENOMEM);
- err = usbd_open_pipe_intr(sce->iface,
- edesc->bEndpointAddress,
- USBD_SHORT_XFER_OK, &sce->pipeh, sce,
- sce->ibuf, isize, ugenintr,
+ if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
+ return (ENOMEM);
+ err = usbd_open_pipe_intr(sce->iface,
+ edesc->bEndpointAddress,
+ USBD_SHORT_XFER_OK, &sce->pipeh, sce,
+ sce->ibuf, isize, ugenintr,
USBD_DEFAULT_INTERVAL);
if (err) {
free(sce->ibuf, M_USBDEV);
@@ -356,7 +369,7 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
DPRINTFN(5, ("ugenopen: interrupt open done\n"));
break;
case UE_BULK:
- err = usbd_open_pipe(sce->iface,
+ err = usbd_open_pipe(sce->iface,
edesc->bEndpointAddress, 0, &sce->pipeh);
if (err)
return (EIO);
@@ -371,7 +384,7 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
M_USBDEV, M_WAITOK);
sce->cur = sce->fill = sce->ibuf;
sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
- DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
+ DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
endpt, isize));
err = usbd_open_pipe(sce->iface,
edesc->bEndpointAddress, 0, &sce->pipeh);
@@ -408,6 +421,7 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
usbd_free_xfer(sce->isoreqs[i].xfer);
return (ENOMEM);
case UE_CONTROL:
+ sce->timeout = USBD_DEFAULT_TIMEOUT;
return (EINVAL);
}
}
@@ -416,7 +430,7 @@ ugenopen(dev_t dev, int flag, int mode, struct proc *p)
}
int
-ugenclose(dev_t dev, int flag, int mode, struct proc *p)
+ugenclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
{
int endpt = UGENENDPOINT(dev);
struct ugen_softc *sc;
@@ -448,31 +462,30 @@ ugenclose(dev_t dev, int flag, int mode, struct proc *p)
sce = &sc->sc_endpoints[endpt][dir];
if (sce == NULL || sce->pipeh == NULL)
continue;
- DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
+ DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
endpt, dir, sce));
usbd_abort_pipe(sce->pipeh);
usbd_close_pipe(sce->pipeh);
sce->pipeh = NULL;
- switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
- case UE_INTERRUPT:
- ndflush(&sce->q, sce->q.c_cc);
- clfree(&sce->q);
- break;
- case UE_ISOCHRONOUS:
- for (i = 0; i < UGEN_NISOREQS; ++i)
- usbd_free_xfer(sce->isoreqs[i].xfer);
-
- default:
- break;
+ switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_INTERRUPT:
+ ndflush(&sce->q, sce->q.c_cc);
+ clfree(&sce->q);
+ break;
+ case UE_ISOCHRONOUS:
+ for (i = 0; i < UGEN_NISOREQS; ++i)
+ usbd_free_xfer(sce->isoreqs[i].xfer);
+
+ default:
+ break;
}
if (sce->ibuf != NULL) {
free(sce->ibuf, M_USBDEV);
sce->ibuf = NULL;
clfree(&sce->q);
-
}
}
sc->sc_is_open[endpt] = 0;
@@ -558,8 +571,8 @@ ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
tn = n;
err = usbd_bulk_transfer(
xfer, sce->pipeh,
- sce->state & UGEN_SHORT_OK ?
- USBD_SHORT_XFER_OK : 0,
+ sce->state & UGEN_SHORT_OK ?
+ USBD_SHORT_XFER_OK : 0,
sce->timeout, buf, &tn, "ugenrb");
if (err) {
if (err == USBD_INTERRUPTED)
@@ -677,7 +690,7 @@ ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
if (error)
break;
DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
- err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
+ err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
sce->timeout, buf, &n,"ugenwb");
if (err) {
if (err == USBD_INTERRUPTED)
@@ -798,14 +811,15 @@ ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
if (status != USBD_NORMAL_COMPLETION) {
DPRINTF(("ugenintr: status=%d\n", status));
- usbd_clear_endpoint_stall_async(sce->pipeh);
+ if (status == USBD_STALLED)
+ usbd_clear_endpoint_stall_async(sce->pipeh);
return;
}
usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
ibuf = sce->ibuf;
- DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
+ DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
xfer, status, count));
DPRINTFN(5, (" data = %02x %02x %02x\n",
ibuf[0], ibuf[1], ibuf[2]));
@@ -821,7 +835,7 @@ ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
}
Static void
-ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
+ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
usbd_status status)
{
struct isoreq *req = addr;
@@ -959,7 +973,8 @@ ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp)
if (lenp)
*lenp = len;
cdesc = malloc(len, M_TEMP, M_WAITOK);
- err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc,len);
+ err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc,
+ len);
if (err) {
free(cdesc, M_TEMP);
return (0);
@@ -982,7 +997,7 @@ ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx)
Static int
ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
- caddr_t addr, int flag, struct proc *p)
+ caddr_t addr, int flag, usb_proc_ptr p)
{
struct ugen_endpoint *sce;
usbd_status err;
@@ -1006,18 +1021,12 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
/* All handled in the upper FS layer. */
return (0);
case USB_SET_SHORT_XFER:
- /* This flag only affects read */
if (endpt == USB_CONTROL_ENDPOINT)
return (EINVAL);
+ /* This flag only affects read */
sce = &sc->sc_endpoints[endpt][IN];
- if (sce == NULL)
+ if (sce == NULL || sce->pipeh == NULL)
return (EINVAL);
-#ifdef DIAGNOSTIC
- if (sce->pipeh == NULL) {
- printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
- return (EIO);
- }
-#endif
if (*(int *)addr)
sce->state |= UGEN_SHORT_OK;
else
@@ -1025,14 +1034,12 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
return (0);
case USB_SET_TIMEOUT:
sce = &sc->sc_endpoints[endpt][IN];
- if (sce == NULL)
+ if (sce == NULL
+ /* XXX this shouldn't happen, but the distinction between
+ input and output pipes isn't clear enough.
+ || sce->pipeh == NULL */
+ )
return (EINVAL);
-#ifdef DIAGNOSTIC
- if (sce->pipeh == NULL) {
- printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n");
- return (EIO);
- }
-#endif
sce->timeout = *(int *)addr;
return (0);
default:
@@ -1058,12 +1065,18 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
if (!(flag & FWRITE))
return (EPERM);
err = ugen_set_config(sc, *(int *)addr);
- if (err)
+ switch (err) {
+ case USBD_NORMAL_COMPLETION:
+ break;
+ case USBD_IN_USE:
+ return (EBUSY);
+ default:
return (EIO);
+ }
break;
case USB_GET_ALTINTERFACE:
ai = (struct usb_alt_interface *)addr;
- err = usbd_device2interface_handle(sc->sc_udev,
+ err = usbd_device2interface_handle(sc->sc_udev,
ai->uai_interface_index, &iface);
if (err)
return (EINVAL);
@@ -1076,11 +1089,12 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
if (!(flag & FWRITE))
return (EPERM);
ai = (struct usb_alt_interface *)addr;
- err = usbd_device2interface_handle(sc->sc_udev,
+ err = usbd_device2interface_handle(sc->sc_udev,
ai->uai_interface_index, &iface);
if (err)
return (EINVAL);
- err = ugen_set_interface(sc, ai->uai_interface_index, ai->uai_alt_no);
+ err = ugen_set_interface(sc, ai->uai_interface_index,
+ ai->uai_alt_no);
if (err)
return (EINVAL);
break;
@@ -1094,7 +1108,8 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
free(cdesc, M_TEMP);
return (EINVAL);
}
- ai->uai_alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber);
+ ai->uai_alt_no = usbd_get_no_alts(cdesc,
+ idesc->bInterfaceNumber);
free(cdesc, M_TEMP);
break;
case USB_GET_DEVICE_DESC:
@@ -1137,7 +1152,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
alt = ugen_get_alt_index(sc, ed->ued_interface_index);
else
alt = ed->ued_alt_index;
- edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
+ edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
alt, ed->ued_endpoint_index);
if (edesc == NULL) {
free(cdesc, M_TEMP);
@@ -1172,7 +1187,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
}
case USB_GET_STRING_DESC:
si = (struct usb_string_desc *)addr;
- err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
+ err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
si->usd_language_id, &si->usd_desc);
if (err)
return (EINVAL);
@@ -1209,7 +1224,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
uio.uio_offset = 0;
uio.uio_segflg = UIO_USERSPACE;
uio.uio_rw =
- ur->ucr_request.bmRequestType & UT_READ ?
+ ur->ucr_request.bmRequestType & UT_READ ?
UIO_READ : UIO_WRITE;
uio.uio_procp = p;
ptr = malloc(len, M_TEMP, M_WAITOK);
@@ -1219,9 +1234,9 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
goto ret;
}
}
- err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
- ptr, ur->ucr_flags, &ur->ucr_actlen,
- USBD_DEFAULT_TIMEOUT);
+ sce = &sc->sc_endpoints[endpt][IN];
+ err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
+ ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
if (err) {
error = EIO;
goto ret;
@@ -1249,7 +1264,7 @@ ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
}
int
-ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
+ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
{
int endpt = UGENENDPOINT(dev);
struct ugen_softc *sc;
@@ -1265,7 +1280,7 @@ ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
}
int
-ugenpoll(dev_t dev, int events, struct proc *p)
+ugenpoll(dev_t dev, int events, usb_proc_ptr p)
{
struct ugen_softc *sc;
struct ugen_endpoint *sce;
@@ -1310,12 +1325,12 @@ ugenpoll(dev_t dev, int events, struct proc *p)
}
break;
case UE_BULK:
- /*
+ /*
* We have no easy way of determining if a read will
* yield any data or a write will happen.
* Pretend they will.
*/
- revents |= events &
+ revents |= events &
(POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
break;
default: