summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>1999-01-07 23:07:57 +0000
committern_hibma <n_hibma@FreeBSD.org>1999-01-07 23:07:57 +0000
commitf85edabd28f8c9ebaeed20a6bdb7ddef1ff1c098 (patch)
treec8f677155dd2322c9b2477c85e8f2959ef963429 /sys
parentb118bd4907acdfd7a8cb3f83f50f0219e395b4a3 (diff)
downloadFreeBSD-src-f85edabd28f8c9ebaeed20a6bdb7ddef1ff1c098.zip
FreeBSD-src-f85edabd28f8c9ebaeed20a6bdb7ddef1ff1c098.tar.gz
Major synchronisation with NetBSD USB code
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/hid.c18
-rw-r--r--sys/dev/usb/hid.h7
-rw-r--r--sys/dev/usb/ohci.c510
-rw-r--r--sys/dev/usb/ohcireg.h5
-rw-r--r--sys/dev/usb/ohcivar.h10
-rw-r--r--sys/dev/usb/ucom.c88
-rw-r--r--sys/dev/usb/ugen.c980
-rw-r--r--sys/dev/usb/uhci.c602
-rw-r--r--sys/dev/usb/uhcireg.h20
-rw-r--r--sys/dev/usb/uhcivar.h17
-rw-r--r--sys/dev/usb/uhid.c229
-rw-r--r--sys/dev/usb/uhub.c355
-rw-r--r--sys/dev/usb/ukbd.c268
-rw-r--r--sys/dev/usb/ulpt.c177
-rw-r--r--sys/dev/usb/umodem.c96
-rw-r--r--sys/dev/usb/ums.c244
-rw-r--r--sys/dev/usb/usb.c303
-rw-r--r--sys/dev/usb/usb.h185
-rw-r--r--sys/dev/usb/usb_if.m30
-rw-r--r--sys/dev/usb/usb_mem.h12
-rw-r--r--sys/dev/usb/usb_port.h219
-rw-r--r--sys/dev/usb/usb_quirks.c20
-rw-r--r--sys/dev/usb/usb_quirks.h12
-rw-r--r--sys/dev/usb/usb_subr.c605
-rw-r--r--sys/dev/usb/usbdevs.h48
-rw-r--r--sys/dev/usb/usbdevs_data.h164
-rw-r--r--sys/dev/usb/usbdi.c350
-rw-r--r--sys/dev/usb/usbdi.h49
-rw-r--r--sys/dev/usb/usbdi_util.c111
-rw-r--r--sys/dev/usb/usbdi_util.h23
-rw-r--r--sys/dev/usb/usbdivar.h80
-rw-r--r--sys/dev/usb/usbhid.h7
32 files changed, 3790 insertions, 2054 deletions
diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c
index a96da40..b03f749 100644
--- a/sys/dev/usb/hid.c
+++ b/sys/dev/usb/hid.c
@@ -1,12 +1,13 @@
-/* $NetBSD: hid.c,v 1.2 1998/07/24 20:57:46 augustss Exp $ */
-/* FreeBSD $Id: hid.c,v 1.2 1998/12/14 09:32:23 n_hibma Exp $ */
+/* $NetBSD: hid.c,v 1.5 1998/12/26 12:53:00 augustss Exp $ */
+/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,12 +38,13 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__FreeBSD__)
+#include <sys/bus.h>
+#endif
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
@@ -442,8 +444,8 @@ hid_get_data(buf, loc)
hsize = 32 - hsize;
/* Sign extend */
data = ((int32_t)data << hsize) >> hsize;
- DPRINTFN(10, ("hid_get_data: loc %d/%d = %lu\n",
- loc->pos, loc->size, (long)data));
+ DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n",
+ loc->pos, loc->size, (long)data));
return (data);
}
diff --git a/sys/dev/usb/hid.h b/sys/dev/usb/hid.h
index 2657cc0..0529701 100644
--- a/sys/dev/usb/hid.h
+++ b/sys/dev/usb/hid.h
@@ -1,12 +1,13 @@
-/* $NetBSD: hid.h,v 1.2 1998/07/24 20:57:46 augustss Exp $ */
+/* $NetBSD: hid.h,v 1.3 1998/11/25 22:32:04 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 90f638a..aa21238 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,5 +1,5 @@
-/* $NetBSD: ohci.c,v 1.12 1998/11/30 21:39:20 augustss Exp $ */
-/* FreeBSD $Id: ohci.c,v 1.4 1998/12/14 09:32:23 n_hibma Exp $ */
+/* $NetBSD: ohci.c,v 1.21 1999/01/01 15:15:33 augustss Exp $ */
+/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -45,8 +45,6 @@
* USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -62,6 +60,7 @@
#include <sys/select.h>
#include <machine/bus.h>
+#include <machine/endian.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -74,12 +73,21 @@
#if defined(__FreeBSD__)
#include <machine/clock.h>
-#include "dev/usb/queue.addendum.h"
#define delay(d) DELAY(d)
#endif
+/*
+ * The OHCI controller is little endian, so on big endian machines
+ * the data strored in memory needs to be swapped.
+ */
+#if BYTE_ORDER == BIG_ENDIAN
+#define LE(x) (bswap32(x))
+#else
+#define LE(x) (x)
+#endif
+
struct ohci_pipe;
ohci_soft_ed_t *ohci_alloc_sed __P((ohci_softc_t *));
@@ -93,6 +101,7 @@ void ohci_poll __P((struct usbd_bus *));
void ohci_waitintr __P((ohci_softc_t *, usbd_request_handle));
void ohci_rhsc __P((ohci_softc_t *, usbd_request_handle));
void ohci_process_done __P((ohci_softc_t *, ohci_physaddr_t));
+void ohci_ii_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_ctrl_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_intr_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_bulk_done __P((ohci_softc_t *, usbd_request_handle));
@@ -105,22 +114,27 @@ void ohci_hash_rem_td __P((ohci_softc_t *, ohci_soft_td_t *));
ohci_soft_td_t *ohci_hash_find_td __P((ohci_softc_t *, ohci_physaddr_t));
usbd_status ohci_root_ctrl_transfer __P((usbd_request_handle));
+usbd_status ohci_root_ctrl_start __P((usbd_request_handle));
void ohci_root_ctrl_abort __P((usbd_request_handle));
void ohci_root_ctrl_close __P((usbd_pipe_handle));
usbd_status ohci_root_intr_transfer __P((usbd_request_handle));
+usbd_status ohci_root_intr_start __P((usbd_request_handle));
void ohci_root_intr_abort __P((usbd_request_handle));
void ohci_root_intr_close __P((usbd_pipe_handle));
usbd_status ohci_device_ctrl_transfer __P((usbd_request_handle));
+usbd_status ohci_device_ctrl_start __P((usbd_request_handle));
void ohci_device_ctrl_abort __P((usbd_request_handle));
void ohci_device_ctrl_close __P((usbd_pipe_handle));
usbd_status ohci_device_bulk_transfer __P((usbd_request_handle));
+usbd_status ohci_device_bulk_start __P((usbd_request_handle));
void ohci_device_bulk_abort __P((usbd_request_handle));
void ohci_device_bulk_close __P((usbd_pipe_handle));
usbd_status ohci_device_intr_transfer __P((usbd_request_handle));
+usbd_status ohci_device_intr_start __P((usbd_request_handle));
void ohci_device_intr_abort __P((usbd_request_handle));
void ohci_device_intr_close __P((usbd_pipe_handle));
usbd_status ohci_device_setintr __P((ohci_softc_t *sc,
@@ -187,6 +201,7 @@ struct ohci_pipe {
struct usbd_methods ohci_root_ctrl_methods = {
ohci_root_ctrl_transfer,
+ ohci_root_ctrl_start,
ohci_root_ctrl_abort,
ohci_root_ctrl_close,
0,
@@ -194,6 +209,7 @@ struct usbd_methods ohci_root_ctrl_methods = {
struct usbd_methods ohci_root_intr_methods = {
ohci_root_intr_transfer,
+ ohci_root_intr_start,
ohci_root_intr_abort,
ohci_root_intr_close,
0,
@@ -201,6 +217,7 @@ struct usbd_methods ohci_root_intr_methods = {
struct usbd_methods ohci_device_ctrl_methods = {
ohci_device_ctrl_transfer,
+ ohci_device_ctrl_start,
ohci_device_ctrl_abort,
ohci_device_ctrl_close,
0,
@@ -208,12 +225,14 @@ struct usbd_methods ohci_device_ctrl_methods = {
struct usbd_methods ohci_device_intr_methods = {
ohci_device_intr_transfer,
+ ohci_device_intr_start,
ohci_device_intr_abort,
ohci_device_intr_close,
};
struct usbd_methods ohci_device_bulk_methods = {
ohci_device_bulk_transfer,
+ ohci_device_bulk_start,
ohci_device_bulk_abort,
ohci_device_bulk_close,
0,
@@ -323,11 +342,12 @@ ohci_init(sc)
DPRINTF(("ohci_init: start\n"));
rev = OREAD4(sc, OHCI_REVISION);
- DEVICE_MSG(sc->sc_bus.bdev, ("OHCI version %d.%d%s\n",
+ printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev),
OHCI_REV_HI(rev), OHCI_REV_LO(rev),
- OHCI_REV_LEGACY(rev) ? ", legacy support" : ""));
+ OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
- DEVICE_MSG(sc->sc_bus.bdev, ("unsupported OHCI revision\n"));
+ printf("%s: unsupported OHCI revision\n",
+ USBDEVNAME(sc->sc_bus.bdev));
return (USBD_INVAL);
}
@@ -349,13 +369,13 @@ ohci_init(sc)
r = USBD_NOMEM;
goto bad1;
}
- sc->sc_ctrl_head->ed->ed_flags |= OHCI_ED_SKIP;
+ sc->sc_ctrl_head->ed->ed_flags |= LE(OHCI_ED_SKIP);
sc->sc_bulk_head = ohci_alloc_sed(sc);
if (!sc->sc_bulk_head) {
r = USBD_NOMEM;
goto bad2;
}
- sc->sc_bulk_head->ed->ed_flags |= OHCI_ED_SKIP;
+ sc->sc_bulk_head->ed->ed_flags |= LE(OHCI_ED_SKIP);
/* Allocate all the dummy EDs that make up the interrupt tree. */
for (i = 0; i < OHCI_NO_EDS; i++) {
@@ -368,11 +388,11 @@ ohci_init(sc)
}
/* All ED fields are set to 0. */
sc->sc_eds[i] = sed;
- sed->ed->ed_flags |= OHCI_ED_SKIP;
+ sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
if (i != 0) {
psed = sc->sc_eds[(i-1) / 2];
sed->next = psed;
- sed->ed->ed_nexted = psed->physaddr;
+ sed->ed->ed_nexted = LE(psed->physaddr);
}
}
/*
@@ -381,7 +401,7 @@ ohci_init(sc)
*/
for (i = 0; i < OHCI_NO_INTRS; i++)
sc->sc_hcca->hcca_interrupt_table[revbits[i]] =
- sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr;
+ LE(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr);
/* Determine in what context we are running. */
ctl = OREAD4(sc, OHCI_CONTROL);
@@ -395,8 +415,8 @@ ohci_init(sc)
ctl = OREAD4(sc, OHCI_CONTROL);
}
if ((ctl & OHCI_IR) == 0) {
- DEVICE_MSG(sc->sc_bus.bdev,
- ("SMM does not respond, resetting\n"));
+ printf("%s: SMM does not respond, resetting\n",
+ USBDEVNAME(sc->sc_bus.bdev));
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
goto reset;
}
@@ -411,9 +431,17 @@ ohci_init(sc)
DPRINTF(("ohci_init: cold started\n"));
reset:
/* Controller was cold started. */
- delay(USB_RESET_DELAY * 1000);
+ delay(USB_BUS_RESET_DELAY * 1000);
}
+ /*
+ * This reset should not be necessary according to the OHCI spec, but
+ * without it some controllers do not start.
+ */
+ DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev)));
+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
+ delay(USB_BUS_RESET_DELAY * 1000);
+
/* We now own the host controller and the bus has been reset. */
ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL));
@@ -426,7 +454,7 @@ ohci_init(sc)
break;
}
if (hcr) {
- DEVICE_MSG(sc->sc_bus.bdev, ("reset timeout\n"));
+ printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
r = USBD_IOERROR;
goto bad3;
}
@@ -465,9 +493,6 @@ ohci_init(sc)
OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
- DEVICE_MSG(sc->sc_bus.bdev, ("%d downstream port%s\n",
- sc->sc_noport,
- sc->sc_noport != 1 ? "s" : ""));
#ifdef USB_DEBUG
if (ohcidebug > 5)
@@ -530,8 +555,8 @@ ohci_dumpregs(sc)
OREAD4(sc, OHCI_RH_PORT_STATUS(1)),
OREAD4(sc, OHCI_RH_PORT_STATUS(2)));
printf(" HCCA: frame_number=0x%04x done_head=0x%08x\n",
- sc->sc_hcca->hcca_frame_number,
- sc->sc_hcca->hcca_done_head);
+ LE(sc->sc_hcca->hcca_frame_number),
+ LE(sc->sc_hcca->hcca_done_head));
}
#endif
@@ -543,13 +568,15 @@ ohci_intr(p)
u_int32_t intrs, eintrs;
ohci_physaddr_t done;
- /* if attach is failed we get a NULL pointer here
- * XXX should be removed when pci_unmap_int is implemented
- */
- if ((sc == NULL) || (sc->sc_hcca == NULL))
+ /* In case the interrupt occurs before initialization has completed. */
+ if (sc == NULL || sc->sc_hcca == NULL) { /* NWH added sc==0 */
+#ifdef DIAGNOSTIC
+ printf("ohci_intr: sc->sc_hcca == NULL\n");
+#endif
return (0);
+ }
- done = sc->sc_hcca->hcca_done_head;
+ done = LE(sc->sc_hcca->hcca_done_head);
if (done != 0) {
intrs = OHCI_WDH;
if (done & OHCI_DONE_INTRS)
@@ -570,7 +597,7 @@ ohci_intr(p)
(u_int)eintrs));
if (eintrs & OHCI_SO) {
- DEVICE_MSG(sc->sc_bus.bdev, ("scheduling overrun\n"));
+ printf("%s: scheduling overrun\n",USBDEVNAME(sc->sc_bus.bdev));
/* XXX do what */
intrs &= ~OHCI_SO;
}
@@ -583,8 +610,8 @@ ohci_intr(p)
/* XXX process resume detect */
}
if (eintrs & OHCI_UE) {
- DEVICE_MSG(sc->sc_bus.bdev,
- ("unrecoverable error, controller halted\n"));
+ printf("%s: unrecoverable error, controller halted\n",
+ USBDEVNAME(sc->sc_bus.bdev));
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
/* XXX what else */
}
@@ -621,6 +648,24 @@ ohci_rhsc_able(sc, on)
}
}
+#ifdef USB_DEBUG
+char *ohci_cc_strs[] = {
+ "NO_ERROR",
+ "CRC",
+ "BIT_STUFFING",
+ "DATA_TOGGLE_MISMATCH",
+ "STALL",
+ "DEVICE_NOT_RESPONDING",
+ "PID_CHECK_FAILURE",
+ "UNEXPECTED_PID",
+ "DATA_OVERRUN",
+ "DATA_UNDERRUN",
+ "BUFFER_OVERRUN",
+ "BUFFER_UNDERRUN",
+ "NOT_ACCESSED",
+};
+#endif
+
void
ohci_process_done(sc, done)
ohci_softc_t *sc;
@@ -633,7 +678,7 @@ ohci_process_done(sc, done)
DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done));
/* Reverse the done list. */
- for (sdone = 0; done; done = std->td->td_nexttd) {
+ for (sdone = 0; done; done = LE(std->td->td_nexttd)) {
std = ohci_hash_find_td(sc, done);
std->dnext = sdone;
sdone = std;
@@ -649,38 +694,40 @@ ohci_process_done(sc, done)
for (std = sdone; std; std = std->dnext) {
reqh = std->reqh;
DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p\n",std,reqh));
- cc = OHCI_TD_GET_CC(std->td->td_flags);
+ cc = OHCI_TD_GET_CC(LE(std->td->td_flags));
if (cc == OHCI_CC_NO_ERROR) {
if (std->td->td_cbp == 0)
len = std->len;
else
- len = std->td->td_be - std->td->td_cbp + 1;
- reqh->actlen += len;
- if (reqh->hcpriv == std) {
- switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- ohci_ctrl_done(sc, reqh);
- break;
- case UE_INTERRUPT:
- ohci_intr_done(sc, reqh);
- break;
- case UE_BULK:
- ohci_bulk_done(sc, reqh);
- break;
- case UE_ISOCHRONOUS:
- printf("ohci_process_done: ISO done?\n");
- break;
+ len = LE(std->td->td_be) -
+ LE(std->td->td_cbp) + 1;
+ /*
+ * Only do a callback on the last stage of a transfer.
+ * Others have hcpriv = 0.
+ */
+ if ((reqh->pipe->endpoint->edesc->bmAttributes &
+ UE_XFERTYPE) == UE_CONTROL) {
+ /* For a control transfer the length is in
+ * the xfer stage */
+ if (reqh->hcpriv == std) {
+ reqh->status = USBD_NORMAL_COMPLETION;
+ ohci_ii_done(sc, reqh);
+ } else
+ reqh->actlen = len;
+ } else {
+ if (reqh->hcpriv == std) {
+ reqh->actlen = len;
+ reqh->status = USBD_NORMAL_COMPLETION;
+ ohci_ii_done(sc, reqh);
}
- /* And finally execute callback. */
- reqh->status = USBD_NORMAL_COMPLETION;
- reqh->xfercb(reqh);
}
} else {
ohci_soft_td_t *p, *n;
struct ohci_pipe *opipe =
(struct ohci_pipe *)reqh->pipe;
- DPRINTFN(-1,("ohci_process_done: error cc=%d\n",
- OHCI_TD_GET_CC(std->td->td_flags)));
+ DPRINTFN(-1,("ohci_process_done: error cc=%d (%s)\n",
+ OHCI_TD_GET_CC(LE(std->td->td_flags)),
+ ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td->td_flags))]));
/*
* Endpoint is halted. First unlink all the TDs
* belonging to the failed transfer, and then restart
@@ -691,14 +738,15 @@ ohci_process_done(sc, done)
ohci_hash_rem_td(sc, p);
ohci_free_std(sc, p);
}
- opipe->sed->ed->ed_headp = p->physaddr;/* clear halt */
+ /* clear halt */
+ opipe->sed->ed->ed_headp = LE(p->physaddr);
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (cc == OHCI_CC_STALL)
reqh->status = USBD_STALLED;
else
reqh->status = USBD_IOERROR;
- reqh->xfercb(reqh);
+ ohci_ii_done(sc, reqh);
}
ohci_hash_rem_td(sc, std);
ohci_free_std(sc, std);
@@ -706,6 +754,33 @@ ohci_process_done(sc, done)
}
void
+ohci_ii_done(sc, reqh)
+ ohci_softc_t *sc;
+ usbd_request_handle reqh;
+{
+ switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_CONTROL:
+ ohci_ctrl_done(sc, reqh);
+ usb_start_next(reqh->pipe);
+ break;
+ case UE_INTERRUPT:
+ ohci_intr_done(sc, reqh);
+ break;
+ case UE_BULK:
+ ohci_bulk_done(sc, reqh);
+ usb_start_next(reqh->pipe);
+ break;
+ case UE_ISOCHRONOUS:
+ printf("ohci_process_done: ISO done?\n");
+ usb_start_next(reqh->pipe);
+ break;
+ }
+
+ /* And finally execute callback. */
+ reqh->xfercb(reqh);
+}
+
+void
ohci_ctrl_done(sc, reqh)
ohci_softc_t *sc;
usbd_request_handle reqh;
@@ -727,11 +802,7 @@ ohci_ctrl_done(sc, reqh)
memcpy(reqh->buffer, KERNADDR(dma), len);
usb_freemem(sc->sc_dmatag, dma);
}
-#if defined(__NetBSD__)
- untimeout(ohci_timeout, reqh);
-#elif defined(__FreeBSD__)
- untimeout(ohci_timeout, reqh, reqh->timo_handle);
-#endif
+ usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
}
void
@@ -760,23 +831,24 @@ ohci_intr_done(sc, reqh)
}
tail->reqh = 0;
- xfer->td->td_flags = OHCI_TD_IN | OHCI_TD_NOCC |
- OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY;
- xfer->td->td_cbp = DMAADDR(dma);
+ xfer->td->td_flags = LE(
+ OHCI_TD_IN | OHCI_TD_NOCC |
+ OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
+ if (reqh->flags & USBD_SHORT_XFER_OK)
+ xfer->td->td_flags |= LE(OHCI_TD_R);
+ xfer->td->td_cbp = LE(DMAADDR(dma));
xfer->nexttd = tail;
- xfer->td->td_nexttd = tail->physaddr;
- xfer->td->td_be = xfer->td->td_cbp + reqh->length - 1;
+ xfer->td->td_nexttd = LE(tail->physaddr);
+ xfer->td->td_be = LE(LE(xfer->td->td_cbp) + reqh->length - 1);
xfer->len = reqh->length;
xfer->reqh = reqh;
- reqh->actlen = 0;
- reqh->hcpriv = xfer;
-
ohci_hash_add_td(sc, xfer);
- sed->ed->ed_tailp = tail->physaddr;
+ sed->ed->ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
} else {
usb_freemem(sc->sc_dmatag, dma);
+ usb_start_next(reqh->pipe);
}
}
@@ -796,11 +868,7 @@ ohci_bulk_done(sc, reqh)
if (reqh->request.bmRequestType & UT_READ)
memcpy(reqh->buffer, KERNADDR(dma), reqh->actlen);
usb_freemem(sc->sc_dmatag, dma);
-#if defined(__NetBSD__)
- untimeout(ohci_timeout, reqh);
-#elif defined(__FreeBSD__)
- untimeout(ohci_timeout, reqh, reqh->timo_handle);
-#endif
+ usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
}
void
@@ -841,6 +909,7 @@ ohci_rhsc(sc, reqh)
if (reqh->pipe->intrreqh != reqh) {
sc->sc_intrreqh = 0;
usb_freemem(sc->sc_dmatag, &opipe->u.intr.datadma);
+ usb_start_next(reqh->pipe);
}
}
@@ -860,7 +929,7 @@ ohci_waitintr(sc, reqh)
reqh->status = USBD_IN_PROGRESS;
for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
- delay(1000);
+ usb_delay_ms(&sc->sc_bus, 1);
intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs;
DPRINTFN(10,("ohci_waitintr: 0x%04x\n", intrs));
#ifdef USB_DEBUG
@@ -873,9 +942,12 @@ ohci_waitintr(sc, reqh)
return;
}
}
+
+ /* Timeout */
DPRINTF(("ohci_waitintr: timeout\n"));
reqh->status = USBD_TIMEOUT;
- reqh->xfercb(reqh);
+ ohci_ii_done(sc, reqh);
+ /* XXX should free TD */
}
void
@@ -908,7 +980,8 @@ ohci_device_request(reqh)
isread = req->bmRequestType & UT_READ;
len = UGETW(req->wLength);
- DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
+ DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, "
+ "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
req->bmRequestType, req->bRequest, UGETW(req->wValue),
UGETW(req->wIndex), len, addr,
opipe->pipe.endpoint->edesc->bEndpointAddress));
@@ -932,10 +1005,10 @@ ohci_device_request(reqh)
/* Update device address and length since they may have changed. */
/* XXX This only needs to be done once, but it's too early in open. */
- sed->ed->ed_flags =
- (sed->ed->ed_flags & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
- OHCI_ED_SET_FA(addr) |
- OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize));
+ sed->ed->ed_flags = LE(
+ (LE(sed->ed->ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
+ OHCI_ED_SET_FA(addr) |
+ OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
/* Set up data transaction */
if (len != 0) {
@@ -947,13 +1020,14 @@ ohci_device_request(reqh)
r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
if (r != USBD_NORMAL_COMPLETION)
goto bad4;
- xfer->td->td_flags =
+ xfer->td->td_flags = LE(
(isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR;
- xfer->td->td_cbp = DMAADDR(dmap);
+ OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR |
+ (reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
+ xfer->td->td_cbp = LE(DMAADDR(dmap));
xfer->nexttd = stat;
- xfer->td->td_nexttd = stat->physaddr;
- xfer->td->td_be = xfer->td->td_cbp + len - 1;
+ xfer->td->td_nexttd = LE(stat->physaddr);
+ xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
xfer->len = len;
xfer->reqh = reqh;
@@ -965,26 +1039,25 @@ ohci_device_request(reqh)
if (!isread && len != 0)
memcpy(KERNADDR(dmap), reqh->buffer, len);
- setup->td->td_flags = OHCI_TD_SETUP | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR;
- setup->td->td_cbp = DMAADDR(&opipe->u.ctl.reqdma);
+ setup->td->td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC |
+ OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
+ setup->td->td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma));
setup->nexttd = next;
- setup->td->td_nexttd = next->physaddr;
- setup->td->td_be = setup->td->td_cbp + sizeof *req - 1;
+ setup->td->td_nexttd = LE(next->physaddr);
+ setup->td->td_be = LE(LE(setup->td->td_cbp) + sizeof *req - 1);
setup->len = 0; /* XXX The number of byte we count */
setup->reqh = reqh;
- stat->td->td_flags =
+ stat->td->td_flags = LE(
(isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1);
+ OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
stat->td->td_cbp = 0;
stat->nexttd = tail;
- stat->td->td_nexttd = tail->physaddr;
+ stat->td->td_nexttd = LE(tail->physaddr);
stat->td->td_be = 0;
stat->len = 0;
stat->reqh = reqh;
- reqh->actlen = 0;
reqh->hcpriv = stat;
#if USB_DEBUG
@@ -1001,17 +1074,12 @@ ohci_device_request(reqh)
if (len != 0)
ohci_hash_add_td(sc, xfer);
ohci_hash_add_td(sc, stat);
- sed->ed->ed_tailp = tail->physaddr;
+ sed->ed->ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (reqh->timeout && !sc->sc_bus.use_polling) {
-#if defined(__NetBSD__)
- timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout));
-#elif defined(__FreeBSD__)
- callout_handle_init(&reqh->timo_handle);
- reqh->timo_handle = timeout(ohci_timeout, reqh,
- MS_TO_TICKS(reqh->timeout));
-#endif
+ usb_timeout(ohci_timeout, reqh,
+ MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
}
splx(s);
@@ -1048,7 +1116,7 @@ ohci_add_ed(sed, head)
sed->next = head->next;
sed->ed->ed_nexted = head->ed->ed_nexted;
head->next = sed;
- head->ed->ed_nexted = sed->physaddr;
+ head->ed->ed_nexted = LE(sed->physaddr);
}
/*
@@ -1146,31 +1214,33 @@ void
ohci_dump_td(std)
ohci_soft_td_t *std;
{
- printf("TD(%p) at %08lx: %b delay=%d ec=%d cc=%d\ncbp=0x%08lx nexttd=0x%08lx be=0x%08lx\n",
+ printf("TD(%p) at %08lx: %b delay=%d ec=%d cc=%d\ncbp=0x%08lx "
+ "nexttd=0x%08lx be=0x%08lx\n",
std, (u_long)std->physaddr,
- (u_long)std->td->td_flags,
+ (u_long)LE(std->td->td_flags),
"\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
- OHCI_TD_GET_DI(std->td->td_flags),
- OHCI_TD_GET_EC(std->td->td_flags),
- OHCI_TD_GET_CC(std->td->td_flags),
- (u_long)std->td->td_cbp,
- (u_long)std->td->td_nexttd, (u_long)std->td->td_be);
+ OHCI_TD_GET_DI(LE(std->td->td_flags)),
+ OHCI_TD_GET_EC(LE(std->td->td_flags)),
+ OHCI_TD_GET_CC(LE(std->td->td_flags)),
+ (u_long)LE(std->td->td_cbp),
+ (u_long)LE(std->td->td_nexttd), (u_long)LE(std->td->td_be));
}
void
ohci_dump_ed(sed)
ohci_soft_ed_t *sed;
{
- printf("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx headp=%b nexted=0x%08lx\n",
+ printf("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
+ "headp=%b nexted=0x%08lx\n",
sed, (u_long)sed->physaddr,
- OHCI_ED_GET_FA(sed->ed->ed_flags),
- OHCI_ED_GET_EN(sed->ed->ed_flags),
- OHCI_ED_GET_MAXP(sed->ed->ed_flags),
- (u_long)sed->ed->ed_flags,
+ OHCI_ED_GET_FA(LE(sed->ed->ed_flags)),
+ OHCI_ED_GET_EN(LE(sed->ed->ed_flags)),
+ OHCI_ED_GET_MAXP(LE(sed->ed->ed_flags)),
+ (u_long)LE(sed->ed->ed_flags),
"\20\14OUT\15IN\16LOWSPEED\17SKIP\18ISO",
- (u_long)sed->ed->ed_tailp,
- (u_long)sed->ed->ed_headp, "\20\1HALT\2CARRY",
- (u_long)sed->ed->ed_nexted);
+ (u_long)LE(sed->ed->ed_tailp),
+ (u_long)LE(sed->ed->ed_headp), "\20\1HALT\2CARRY",
+ (u_long)LE(sed->ed->ed_nexted));
}
#endif
@@ -1210,15 +1280,15 @@ ohci_open(pipe)
goto bad1;
opipe->sed = sed;
opipe->tail = std;
- sed->ed->ed_flags =
+ sed->ed->ed_flags = LE(
OHCI_ED_SET_FA(addr) |
OHCI_ED_SET_EN(ed->bEndpointAddress) |
OHCI_ED_DIR_TD |
(dev->lowspeed ? OHCI_ED_SPEED : 0) |
((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ?
OHCI_ED_FORMAT_ISO : OHCI_ED_FORMAT_GEN) |
- OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize));
- sed->ed->ed_headp = sed->ed->ed_tailp = std->physaddr;
+ OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)));
+ sed->ed->ed_headp = sed->ed->ed_tailp = LE(std->physaddr);
switch (ed->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
@@ -1315,7 +1385,6 @@ usb_hub_descriptor_t ohci_hubd = {
0,
0,
{0},
- {0},
};
int
@@ -1345,6 +1414,22 @@ usbd_status
ohci_root_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (ohci_root_ctrl_start(reqh));
+}
+
+usbd_status
+ohci_root_ctrl_start(reqh)
+ usbd_request_handle reqh;
+{
ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus;
usb_device_request_t *req;
void *buf;
@@ -1373,7 +1458,7 @@ ohci_root_ctrl_transfer(reqh)
case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
/*
- * DEVICE_REMOTE_WAKEUP and ENDPOINT_STALL are no-ops
+ * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
* for the integrated root hub.
*/
break;
@@ -1479,7 +1564,8 @@ ohci_root_ctrl_transfer(reqh)
case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
break;
case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
- DPRINTFN(8, ("ohci_root_ctrl_control: UR_CLEAR_PORT_FEATURE port=%d feature=%d\n",
+ DPRINTFN(8, ("ohci_root_ctrl_control: UR_CLEAR_PORT_FEATURE "
+ "port=%d feature=%d\n",
index, value));
if (index < 1 || index > sc->sc_noport) {
r = USBD_IOERROR;
@@ -1537,24 +1623,16 @@ ohci_root_ctrl_transfer(reqh)
v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
hubd = ohci_hubd;
hubd.bNbrPorts = sc->sc_noport;
- USETW(hubd.bHubCharacteristics,
+ USETW(hubd.wHubCharacteristics,
(v & OHCI_NPS ? UHD_PWR_NO_SWITCH :
v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL)
/* XXX overcurrent */
);
hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v);
v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B);
- if (sc->sc_noport < 8) {
- hubd.DeviceRemovable[0] = (u_int8_t)v;
- hubd.PortPowerCtrlMask[0] = (u_int8_t)(v >> 16);
- hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE;
- } else {
- hubd.DeviceRemovable[0] = (u_int8_t)v;
- hubd.DeviceRemovable[1] = (u_int8_t)(v>>8);
- hubd.PortPowerCtrlMask[1] = (u_int8_t)(v >> 16);
- hubd.PortPowerCtrlMask[2] = (u_int8_t)(v >> 24);
- hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + 2;
- }
+ for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8)
+ hubd.DeviceRemovable[i++] = (u_int8_t)v;
+ hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i;
l = min(len, hubd.bDescLength);
totlen = l;
memcpy(buf, &hubd, l);
@@ -1606,10 +1684,11 @@ ohci_root_ctrl_transfer(reqh)
OWRITE4(sc, port, UPS_SUSPEND);
break;
case UHF_PORT_RESET:
- DPRINTFN(5,("ohci_root_ctrl_transfer: reset port %d\n", index));
+ DPRINTFN(5,("ohci_root_ctrl_transfer: reset port %d\n",
+ index));
OWRITE4(sc, port, UPS_RESET);
for (i = 0; i < 10; i++) {
- usbd_delay_ms(&sc->sc_bus, 10);
+ usb_delay_ms(&sc->sc_bus, 10);
if ((OREAD4(sc, port) & UPS_RESET) == 0)
break;
}
@@ -1617,7 +1696,8 @@ ohci_root_ctrl_transfer(reqh)
index, OREAD4(sc, port)));
break;
case UHF_PORT_POWER:
- DPRINTFN(2,("ohci_root_ctrl_transfer: set port power %d\n", index));
+ DPRINTFN(2,("ohci_root_ctrl_transfer: set port power "
+ "%d\n", index));
OWRITE4(sc, port, UPS_PORT_POWER);
break;
default:
@@ -1634,6 +1714,7 @@ ohci_root_ctrl_transfer(reqh)
ret:
reqh->status = r;
reqh->xfercb(reqh);
+ usb_start_next(reqh->pipe);
return (USBD_IN_PROGRESS);
}
@@ -1657,6 +1738,22 @@ usbd_status
ohci_root_intr_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (ohci_root_intr_start(reqh));
+}
+
+usbd_status
+ohci_root_intr_start(reqh)
+ usbd_request_handle reqh;
+{
usbd_pipe_handle pipe = reqh->pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
struct ohci_pipe *upipe = (struct ohci_pipe *)pipe;
@@ -1702,6 +1799,22 @@ usbd_status
ohci_device_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (ohci_device_ctrl_start(reqh));
+}
+
+usbd_status
+ohci_device_ctrl_start(reqh)
+ usbd_request_handle reqh;
+{
ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus;
usbd_status r;
@@ -1726,7 +1839,7 @@ ohci_device_ctrl_abort(reqh)
usbd_request_handle reqh;
{
/* XXX inactivate */
- usbd_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is finished */
+ usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is donw */
/* XXX call done */
}
@@ -1741,9 +1854,9 @@ ohci_device_ctrl_close(pipe)
int s;
s = splusb();
- sed->ed->ed_flags |= OHCI_ED_SKIP;
- if ((sed->ed->ed_tailp & OHCI_TAILMASK) != sed->ed->ed_headp)
- usbd_delay_ms(&sc->sc_bus, 2);
+ sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
+ if ((LE(sed->ed->ed_tailp) & OHCI_TAILMASK) != LE(sed->ed->ed_headp))
+ usb_delay_ms(&sc->sc_bus, 2);
ohci_rem_ed(sed, sc->sc_ctrl_head);
splx(s);
ohci_free_std(sc, opipe->tail);
@@ -1757,6 +1870,22 @@ usbd_status
ohci_device_bulk_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (ohci_device_bulk_start(reqh));
+}
+
+usbd_status
+ohci_device_bulk_start(reqh)
+ usbd_request_handle reqh;
+{
struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
@@ -1792,23 +1921,23 @@ ohci_device_bulk_transfer(reqh)
tail->reqh = 0;
/* Update device address */
- sed->ed->ed_flags =
- (sed->ed->ed_flags & ~OHCI_ED_ADDRMASK) |
- OHCI_ED_SET_FA(addr);
+ sed->ed->ed_flags = LE(
+ (LE(sed->ed->ed_flags) & ~OHCI_ED_ADDRMASK) |
+ OHCI_ED_SET_FA(addr));
/* Set up data transaction */
xfer = opipe->tail;
- xfer->td->td_flags =
+ xfer->td->td_flags = LE(
(isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
- OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY;
- xfer->td->td_cbp = DMAADDR(dmap);
+ OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY |
+ (reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
+ xfer->td->td_cbp = LE(DMAADDR(dmap));
xfer->nexttd = tail;
- xfer->td->td_nexttd = tail->physaddr;
- xfer->td->td_be = xfer->td->td_cbp + len - 1;
+ xfer->td->td_nexttd = LE(tail->physaddr);
+ xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
xfer->len = len;
xfer->reqh = reqh;
- reqh->actlen = 0;
reqh->hcpriv = xfer;
if (!isread)
@@ -1817,17 +1946,12 @@ ohci_device_bulk_transfer(reqh)
/* Insert ED in schedule */
s = splusb();
ohci_hash_add_td(sc, xfer);
- sed->ed->ed_tailp = tail->physaddr;
+ sed->ed->ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
if (reqh->timeout && !sc->sc_bus.use_polling) {
-#if defined(__NetBSD__)
- timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout));
-#elif defined(__FreeBSD__)
- callout_handle_init(&reqh->timo_handle);
- reqh->timo_handle = timeout(ohci_timeout, reqh,
- MS_TO_TICKS(reqh->timeout));
-#endif
+ usb_timeout(ohci_timeout, reqh,
+ MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
}
splx(s);
@@ -1845,12 +1969,12 @@ ohci_device_bulk_abort(reqh)
usbd_request_handle reqh;
{
#if 0
- sed->ed->ed_flags |= OHCI_ED_SKIP;
- if ((sed->ed->ed_tailp & OHCI_TAILMASK) != sed->ed->ed_headp)
- usbd_delay_ms(reqh->pipe->device->bus, 2);
+ sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
+ if ((LE(sed->ed->ed_tailp) & OHCI_TAILMASK) != LE(sed->ed->ed_headp))
+ usb_delay_ms(reqh->pipe->device->bus, 2);
#endif
/* XXX inactivate */
- usbd_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is finished */
+ usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is done */
/* XXX call done */
}
@@ -1878,6 +2002,22 @@ usbd_status
ohci_device_intr_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (ohci_device_intr_start(reqh));
+}
+
+usbd_status
+ohci_device_intr_start(reqh)
+ usbd_request_handle reqh;
+{
struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
@@ -1888,7 +2028,8 @@ ohci_device_intr_transfer(reqh)
int len;
int s;
- DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p buf=%p len=%d flags=%d priv=%p\n",
+ DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p buf=%p len=%d "
+ "flags=%d priv=%p\n",
reqh, reqh->buffer, reqh->length, reqh->flags, reqh->priv));
if (reqh->isreq)
@@ -1911,16 +2052,18 @@ ohci_device_intr_transfer(reqh)
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
- xfer->td->td_flags = OHCI_TD_IN | OHCI_TD_NOCC |
- OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY;
- xfer->td->td_cbp = DMAADDR(dmap);
+ xfer->td->td_flags = LE(
+ OHCI_TD_IN | OHCI_TD_NOCC |
+ OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
+ if (reqh->flags & USBD_SHORT_XFER_OK)
+ xfer->td->td_flags |= LE(OHCI_TD_R);
+ xfer->td->td_cbp = LE(DMAADDR(dmap));
xfer->nexttd = tail;
- xfer->td->td_nexttd = tail->physaddr;
- xfer->td->td_be = xfer->td->td_cbp + len - 1;
+ xfer->td->td_nexttd = LE(tail->physaddr);
+ xfer->td->td_be = LE(LE(xfer->td->td_cbp) + len - 1);
xfer->len = len;
xfer->reqh = reqh;
- reqh->actlen = 0;
reqh->hcpriv = xfer;
#if USB_DEBUG
@@ -1934,20 +2077,15 @@ ohci_device_intr_transfer(reqh)
/* Insert ED in schedule */
s = splusb();
ohci_hash_add_td(sc, xfer);
- sed->ed->ed_tailp = tail->physaddr;
+ sed->ed->ed_tailp = LE(tail->physaddr);
opipe->tail = tail;
#if 0
if (reqh->timeout && !sc->sc_bus.use_polling) {
-#if defined(__NetBSD__)
- timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout));
-#elif defined(__FreeBSD__)
- callout_handle_init(&reqh->timo_handle);
- reqh->timo_handle = timeout(ohci_timeout, reqh,
- MS_TO_TICKS(reqh->timeout));
-#endif
+ usb_timeout(ohci_timeout, reqh,
+ MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
}
#endif
- sed->ed->ed_flags &= ~OHCI_ED_SKIP;
+ sed->ed->ed_flags &= LE(~OHCI_ED_SKIP);
splx(s);
#ifdef USB_DEBUG
@@ -1974,7 +2112,7 @@ ohci_device_intr_abort(reqh)
usbd_request_handle reqh;
{
/* XXX inactivate */
- usbd_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is finished */
+ usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is done */
if (reqh->pipe->intrreqh == reqh) {
DPRINTF(("ohci_device_intr_abort: remove\n"));
reqh->pipe->intrreqh = 0;
@@ -1998,9 +2136,9 @@ ohci_device_intr_close(pipe)
DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n",
pipe, nslots, pos));
s = splusb();
- sed->ed->ed_flags |= OHCI_ED_SKIP;
- if ((sed->ed->ed_tailp & OHCI_TAILMASK) != sed->ed->ed_headp)
- usbd_delay_ms(&sc->sc_bus, 2);
+ sed->ed->ed_flags |= LE(OHCI_ED_SKIP);
+ if ((sed->ed->ed_tailp & LE(OHCI_TAILMASK)) != sed->ed->ed_headp)
+ usb_delay_ms(&sc->sc_bus, 2);
for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
;
@@ -2071,7 +2209,7 @@ ohci_device_setintr(sc, opipe, ival)
sed->next = hsed->next;
sed->ed->ed_nexted = hsed->ed->ed_nexted;
hsed->next = sed;
- hsed->ed->ed_nexted = sed->physaddr;
+ hsed->ed->ed_nexted = LE(sed->physaddr);
splx(s);
for (j = 0; j < nslots; j++)
diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h
index a3a7a3c..bd44e8b 100644
--- a/sys/dev/usb/ohcireg.h
+++ b/sys/dev/usb/ohcireg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ohcireg.h,v 1.6 1998/11/25 22:32:04 augustss Exp $ */
+/* $NetBSD: ohcireg.h,v 1.7 1998/12/10 23:16:47 augustss Exp $ */
/* FreeBSD $Id$ */
/*
@@ -121,7 +121,8 @@
#define OHCI_RH_PORT_STATUS(n) (0x50 + (n)*4) /* 1 based indexing */
#define OHCI_LES (OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE)
-#define OHCI_ALL_INTRS (OHCI_SO | OHCI_WDH | OHCI_SF | OHCI_RD | OHCI_UE | OHCI_FNO | OHCI_RHSC | OHCI_OC)
+#define OHCI_ALL_INTRS (OHCI_SO | OHCI_WDH | OHCI_SF | OHCI_RD | OHCI_UE | \
+ OHCI_FNO | OHCI_RHSC | OHCI_OC)
#define OHCI_NORMAL_INTRS (OHCI_SO | OHCI_WDH | OHCI_RD | OHCI_UE | OHCI_RHSC)
#define OHCI_FSMPS(i) (((i-210)*6/7) << 16)
diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h
index 7edbad4..db8631f 100644
--- a/sys/dev/usb/ohcivar.h
+++ b/sys/dev/usb/ohcivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ohcivar.h,v 1.3 1998/11/25 22:32:04 augustss Exp $ */
+/* $NetBSD: ohcivar.h,v 1.4 1998/12/26 12:53:01 augustss Exp $ */
/* FreeBSD $Id$ */
/*
@@ -74,13 +74,9 @@ typedef struct ohci_softc {
#elif defined(__FreeBSD__)
int sc_iobase;
int unit;
-#endif
+#endif /* __FreeBSD__ */
-#if defined(__NetBSD__)
usb_dma_t sc_hccadma;
-#elif defined(__FreeBSD__)
- void *sc_hccadma;
-#endif
struct ohci_hcca *sc_hcca;
ohci_soft_ed_t *sc_eds[OHCI_NO_EDS];
u_int sc_bws[OHCI_NO_INTRS];
@@ -112,7 +108,7 @@ int ohci_intr __P((void *));
#ifdef USB_DEBUG
#define DPRINTF(x) if (ohcidebug) printf x
#define DPRINTFN(n,x) if (ohcidebug>(n)) printf x
-int ohcidebug;
+extern int ohcidebug;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c
index 1b1bf0e..3e753c0 100644
--- a/sys/dev/usb/ucom.c
+++ b/sys/dev/usb/ucom.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ucom.c,v 1.1 1998/12/02 22:47:19 augustss Exp $ */
+/* $NetBSD: ucom.c,v 1.4 1998/12/30 17:46:20 augustss Exp $ */
/* FreeBSD $Id$ */
/*
@@ -65,7 +65,6 @@
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -85,84 +84,29 @@ struct ucom_softc {
usbd_interface_handle sc_iface; /* interface */
};
-#if defined(__NetBSD__)
-int ucom_match __P((struct device *, struct cfdata *, void *));
-void ucom_attach __P((struct device *, struct device *, void *));
-#elif defined(__FreeBSD__)
-static device_probe_t ucom_match;
-static device_attach_t ucom_attach;
-static device_detach_t ucom_detach;
-#endif
-
void ucom_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void ucom_disco __P((void *));
-#if defined(__NetBSD__)
-extern struct cfdriver ucom_cd;
-
-struct cfattach ucom_ca = {
- sizeof(struct ucom_softc), ucom_match, ucom_attach
-};
-#elif defined(__FreeBSD__)
-static devclass_t ucom_devclass;
+USB_DECLARE_DRIVER(ucom);
-static device_method_t ucom_methods[] = {
- DEVMETHOD(device_probe, ucom_match),
- DEVMETHOD(device_attach, ucom_attach),
- DEVMETHOD(device_detach, ucom_detach),
- {0,0}
-};
-
-static driver_t ucom_driver = {
- "ucom",
- ucom_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct ucom_softc)
-};
-#endif
-
-
-#if defined(__NetBSD__)
-int
-ucom_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(ucom)
{
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ucom_match(device_t device)
-{
- struct usb_attach_arg *uaa = device_get_ivars(device);
-#endif
+ USB_MATCH_START(ucom, uaa);
usb_interface_descriptor_t *id;
if (!uaa->iface)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
- if (id->bInterfaceClass != UCLASS_CDC ||
+ if (id &&
+ id->bInterfaceClass != UCLASS_CDC ||
id->bInterfaceSubClass != USUBCLASS_MODEM)
return (UMATCH_NONE);
return (UMATCH_IFACECLASS_IFACESUBCLASS);
}
-#if defined(__NetBSD__)
-void
-ucom_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
-{
- struct ucom_softc *sc = (struct ucom_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ucom_attach(device_t self)
+USB_ATTACH(ucom)
{
- struct ucom_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
-#endif
+ USB_ATTACH_START(ucom, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
char devinfo[1024];
@@ -170,15 +114,11 @@ ucom_attach(device_t self)
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
-#if defined(__FreeBSD__)
- usb_device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
-#endif
- sc->sc_dev = self;
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
+ devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
- printf(": %s, iclass %d/%d\n", devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
-
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
}
#if defined(__FreeBSD__)
@@ -192,12 +132,10 @@ ucom_detach(device_t self)
device_set_desc(self, NULL);
free(devinfo, M_USB);
}
-
return 0;
}
#endif
#if defined(__FreeBSD__)
-DRIVER_MODULE(ucom, usb, ucom_driver, ucom_devclass, usb_driver_load, 0);
+DRIVER_MODULE(ucom, usb, ucom_driver, ucom_devclass, usbd_driver_load, 0);
#endif
-
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 856e0dc..341cc93 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,11 +1,13 @@
+/* $NetBSD: ugen.c,v 1.9 1999/01/03 01:03:22 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,150 +38,950 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#if defined(__NetBSD__)
#include <sys/device.h>
+#include <sys/ioctl.h>
#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
-#endif
-#include <sys/uio.h>
+#include <sys/ioccom.h>
#include <sys/conf.h>
-#include <sys/syslog.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#endif
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/select.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/poll.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
-#include <dev/usb/usbdevs.h>
-#include <dev/usb/usb_quirks.h>
#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) printf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
-extern int usbdebug;
+#define DPRINTF(x) if (ugendebug) printf x
+#define DPRINTFN(n,x) if (ugendebug>(n)) printf x
+int ugendebug = 0;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif
-struct ugen_softc {
- bdevice sc_dev;
- usbd_device_handle sc_udev; /* device */
- usbd_interface_handle sc_iface; /* interface */
- int sc_ifaceno;
- int sc_bulk;
+struct ugen_endpoint {
+ struct ugen_softc *sc;
+ usb_endpoint_descriptor_t *edesc;
+ usbd_interface_handle iface;
+ int state;
+#define UGEN_OPEN 0x01 /* device is open */
+#define UGEN_ASLP 0x02 /* waiting for data */
+#define UGEN_SHORT_OK 0x04 /* short xfers are OK */
+ usbd_pipe_handle pipeh;
+ struct clist q;
+ struct selinfo rsel;
+ void *ibuf;
};
-#if defined(__NetBSD__)
-int ugen_match __P((struct device *, struct cfdata *, void *));
-void ugen_attach __P((struct device *, struct device *, void *));
+#define UGEN_CHUNK 128 /* chunk size for read */
+#define UGEN_IBSIZE 1020 /* buffer size */
+#define UGEN_BBSIZE 1024
+
+struct ugen_softc {
+ bdevice sc_dev; /* base device */
+ struct usbd_device *sc_udev;
-extern struct cfdriver ugen_cd;
+ struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
+#define OUT 0 /* index order is important, from UE_OUT */
+#define IN 1 /* from UE_IN */
-struct cfattach ugen_ca = {
- sizeof(struct ugen_softc), ugen_match, ugen_attach
+ int sc_disconnected; /* device is gone */
};
-#elif defined(__FreeBSD__)
-static device_probe_t ugen_match;
-static device_attach_t ugen_attach;
-static device_detach_t ugen_detach;
-static devclass_t ugen_devclass;
+/* XXX NWH Supposedly in USB_DECLARE_DRIVER_NAME_INIT
+int ugen_match __P((bdevice *, struct cfdata *, void *));
+void ugen_attach __P((bdevice *, struct device *, void *));
+*/
-static device_method_t ugen_methods[] = {
- DEVMETHOD(device_probe, ugen_match),
- DEVMETHOD(device_attach, ugen_attach),
- DEVMETHOD(device_detach, ugen_detach),
- {0,0}
-};
+int ugenopen __P((dev_t, int, int, struct proc *));
+int ugenclose __P((dev_t, int, int, struct proc *p));
+int ugenread __P((dev_t, struct uio *uio, int));
+int ugenwrite __P((dev_t, struct uio *uio, int));
+int ugenioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+int ugenpoll __P((dev_t, int, struct proc *));
+void ugenintr __P((usbd_request_handle reqh, usbd_private_handle addr,
+ usbd_status status));
+void ugen_disco __P((void *));
-static driver_t ugen_driver = {
- "ugen",
- ugen_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct ugen_softc)
-};
-#endif
+int ugen_set_config __P((struct ugen_softc *sc, int configno));
+usb_config_descriptor_t *ugen_get_cdesc __P((struct ugen_softc *sc, int index,
+ int *lenp));
+usbd_status ugen_set_interface __P((struct ugen_softc *, int, int));
+int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx));
+#define UGENUNIT(n) (((n) >> 4) & 0xf)
+#define UGENENDPOINT(n) ((n) & 0xf)
+
+USB_DECLARE_DRIVER(ugen);
+
+USB_MATCH(ugen)
+{
+ USB_MATCH_START(ugen, uaa);
+
+ if (uaa->usegeneric)
+ return (UMATCH_GENERIC);
+ else
+ return (UMATCH_NONE);
+}
+
+USB_ATTACH(ugen)
+{
+ USB_ATTACH_START(ugen, sc, uaa);
+ char devinfo[1024];
+ usbd_status r;
+ int conf;
+
+ usbd_devinfo(uaa->device, 0, devinfo);
+ USB_ATTACH_SETUP;
+ printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
+
+ sc->sc_udev = uaa->device;
+ conf = 1; /* XXX should not hard code 1 */
+ r = ugen_set_config(sc, conf);
+ if (r != USBD_NORMAL_COMPLETION) {
+ printf("%s: setting configuration %d failed\n",
+ USBDEVNAME(sc->sc_dev), conf);
+ sc->sc_disconnected = 1;
+ USB_ATTACH_ERROR_RETURN;
+ }
+ USB_ATTACH_SUCCESS_RETURN;
+}
+
+int
+ugen_set_config(sc, configno)
+ struct ugen_softc *sc;
+ int configno;
+{
+ usbd_device_handle dev = sc->sc_udev;
+ usbd_interface_handle iface;
+ usb_endpoint_descriptor_t *ed;
+ struct ugen_endpoint *sce;
+ u_int8_t niface, nendpt;
+ int ifaceno, endptno, endpt;
+ usbd_status r;
+
+ DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
+ USBDEVNAME(sc->sc_dev), configno, sc));
+ if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
+ /* Avoid setting the current value. */
+ r = usbd_set_config_no(dev, configno, 0);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ }
+
+ r = usbd_interface_count(dev, &niface);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
+ for (ifaceno = 0; ifaceno < niface; ifaceno++) {
+ DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
+ r = usbd_device2interface_handle(dev, ifaceno, &iface);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ r = usbd_endpoint_count(iface, &nendpt);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ for (endptno = 0; endptno < nendpt; endptno++) {
+ ed = usbd_interface2endpoint_descriptor(iface,endptno);
+ endpt = ed->bEndpointAddress;
+ sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)]
+ [UE_GET_IN(endpt)];
+ DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
+ "(%d,%d), sce=%p\n",
+ endptno, endpt, UE_GET_ADDR(endpt),
+ UE_GET_IN(endpt), sce));
+ sce->sc = sc;
+ sce->edesc = ed;
+ sce->iface = iface;
+ }
+ }
+ return (USBD_NORMAL_COMPLETION);
+}
+
+void
+ugen_disco(p)
+ void *p;
+{
+ struct ugen_softc *sc = p;
+ sc->sc_disconnected = 1;
+}
-#if defined(__NetBSD__)
int
-ugen_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+ugenopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
{
- struct usb_attach_arg *uaa = aux;
+ int unit = UGENUNIT(dev);
+ int endpt = UGENENDPOINT(dev);
+ usb_endpoint_descriptor_t *edesc;
+ struct ugen_endpoint *sce;
+ int dir, isize;
+ usbd_status r;
+
+ USB_GET_SC_OPEN(ugen, unit, sc);
+ DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
+ flag, mode, unit, endpt));
+
+ if (sc->sc_disconnected)
+ return (EIO);
+
+ if (endpt == USB_CONTROL_ENDPOINT) {
+ /*if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
+ return (EACCES);*/
+ sce = &sc->sc_endpoints[USB_CONTROL_ENDPOINT][OUT];
+ if (sce->state & UGEN_OPEN)
+ return (EBUSY);
+ } else {
+ switch (flag & (FWRITE|FREAD)) {
+ case FWRITE:
+ dir = OUT;
+ break;
+ case FREAD:
+ dir = IN;
+ break;
+ default:
+ return (EACCES);
+ }
+ sce = &sc->sc_endpoints[endpt][dir];
+ DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
+ sc, endpt, dir, sce));
+ if (sce->state & UGEN_OPEN)
+ return (EBUSY);
+ edesc = sce->edesc;
+ if (!edesc)
+ return (ENXIO);
+ switch (edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_INTERRUPT:
+ isize = UGETW(edesc->wMaxPacketSize);
+ if (isize == 0) /* shouldn't happen */
+ return (EINVAL);
+ sce->ibuf = malloc(isize, M_USB, M_WAITOK);
+ DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
+ endpt, isize));
+#if defined(__NetBSD__)
+ if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
+ return (ENOMEM);
#elif defined(__FreeBSD__)
-static int
-ugen_match(device_t device)
+ clist_alloc_cblocks(&sce->q, UGEN_IBSIZE, 0);
+#endif
+ r = usbd_open_pipe_intr(sce->iface,
+ edesc->bEndpointAddress,
+ USBD_SHORT_XFER_OK, &sce->pipeh, sce,
+ sce->ibuf, isize, ugenintr);
+ if (r != USBD_NORMAL_COMPLETION) {
+ free(sce->ibuf, M_USB);
+#if defined(__NetBSD__)
+ clfree(&sce->q);
+#elif defined(__FreeBSD__)
+ clist_free_cblocks(&sce->q);
+#endif
+ return (EIO);
+ }
+ usbd_set_disco(sce->pipeh, ugen_disco, sc);
+ DPRINTFN(5, ("ugenopen: interrupt open done\n"));
+ break;
+ case UE_BULK:
+ r = usbd_open_pipe(sce->iface,
+ edesc->bEndpointAddress, 0,
+ &sce->pipeh);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EIO);
+ break;
+ case UE_CONTROL:
+ case UE_ISOCHRONOUS:
+ return (EINVAL);
+ }
+ }
+ sce->state |= UGEN_OPEN;
+ return (0);
+}
+
+int
+ugenclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
{
- struct usb_attach_arg *uaa = device_get_ivars(device);
+ USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ int endpt = UGENENDPOINT(dev);
+ struct ugen_endpoint *sce;
+ int dir;
+
+ DPRINTFN(5, ("ugenclose: flag=%d, mode=%d\n", flag, mode));
+ if (sc->sc_disconnected)
+ return (EIO);
+
+ if (endpt == USB_CONTROL_ENDPOINT) {
+ DPRINTFN(5, ("ugenclose: close control\n"));
+ sc->sc_endpoints[endpt][OUT].state = 0;
+ return (0);
+ }
+
+ flag = FWRITE | FREAD; /* XXX bug if generic open/close */
+
+ /* The open modes have been joined, so check for both modes. */
+ for (dir = OUT; dir <= IN; dir++) {
+ if (flag & (dir == OUT ? FWRITE : FREAD)) {
+ sce = &sc->sc_endpoints[endpt][dir];
+ if (!sce || !sce->pipeh) /* XXX */
+ continue; /* XXX */
+ DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
+ endpt, dir, sce));
+ sce->state = 0;
+
+ usbd_abort_pipe(sce->pipeh);
+ usbd_close_pipe(sce->pipeh);
+ sce->pipeh = 0;
+
+ if (sce->ibuf) {
+ free(sce->ibuf, M_USB);
+ sce->ibuf = 0;
+ }
+ }
+ }
+
+ return (0);
+}
+
+int
+ugenread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ int endpt = UGENENDPOINT(dev);
+ struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
+ u_int32_t n, tn;
+ char buf[UGEN_BBSIZE];
+ usbd_request_handle reqh;
+ usbd_status r;
+ int s;
+ int error = 0;
+ u_char buffer[UGEN_CHUNK];
+
+ DPRINTFN(5, ("ugenread: %d:%d\n", UGENUNIT(dev), UGENENDPOINT(dev)));
+ if (sc->sc_disconnected)
+ return (EIO);
+
+#ifdef DIAGNOSTIC
+ if (!sce->edesc) {
+ printf("ugenread: no edesc\n");
+ return (EIO);
+ }
+ if (!sce->pipeh) {
+ printf("ugenread: no pipe\n");
+ return (EIO);
+ }
#endif
- usb_interface_descriptor_t *id;
-
- DPRINTFN(10,("ugen_match\n"));
- if (uaa->usegeneric)
- return UMATCH_GENERIC;
- else
- return UMATCH_NONE;
+
+ switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_INTERRUPT:
+ /* Block until activity occured. */
+ s = splusb();
+ while (sce->q.c_cc == 0) {
+ if (flag & IO_NDELAY) {
+ splx(s);
+ return (EWOULDBLOCK);
+ }
+ sce->state |= UGEN_ASLP;
+ DPRINTFN(5, ("ugenread: sleep on %p\n", sc));
+ error = tsleep((caddr_t)sce, PZERO | PCATCH,
+ "ugenri", 0);
+ DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
+ if (error) {
+ sce->state &= ~UGEN_ASLP;
+ splx(s);
+ return (error);
+ }
+ }
+ splx(s);
+
+ /* Transfer as many chunks as possible. */
+ while (sce->q.c_cc > 0 && uio->uio_resid > 0) {
+ n = min(sce->q.c_cc, uio->uio_resid);
+ if (n > sizeof(buffer))
+ n = sizeof(buffer);
+
+ /* Remove a small chunk from the input queue. */
+ q_to_b(&sce->q, buffer, n);
+ DPRINTFN(5, ("ugenread: got %d chars\n", n));
+
+ /* Copy the data to the user process. */
+ error = uiomove(buffer, n, uio);
+ if (error)
+ break;
+ }
+ break;
+ case UE_BULK:
+ reqh = usbd_alloc_request();
+ if (reqh == 0)
+ return (ENOMEM);
+ while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
+ DPRINTFN(1, ("ugenread: transfer %d bytes\n", n));
+ r = usbd_bulk_transfer(reqh, sce->pipeh, 0, buf,
+ &tn, "ugenrb");
+ if (r != USBD_NORMAL_COMPLETION) {
+ if (r == USBD_INTERRUPTED)
+ error = EINTR;
+ else
+ error = EIO;
+ break;
+ }
+ error = uiomove(buf, tn, uio);
+ if (error || tn < n)
+ break;
+ }
+ usbd_free_request(reqh);
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ return (error);
}
-#if defined(__NetBSD__)
+int
+ugenwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ int endpt = UGENENDPOINT(dev);
+ struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
+ size_t n;
+ int error = 0;
+ char buf[UGEN_BBSIZE];
+ usbd_request_handle reqh;
+ usbd_status r;
+
+ if (sc->sc_disconnected)
+ return (EIO);
+
+#ifdef DIAGNOSTIC
+ if (!sce->edesc) {
+ printf("ugenwrite: no edesc\n");
+ return (EIO);
+ }
+ if (!sce->pipeh) {
+ printf("ugenwrite: no pipe\n");
+ return (EIO);
+ }
+#endif
+
+ DPRINTF(("ugenwrite\n"));
+ switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_BULK:
+ reqh = usbd_alloc_request();
+ if (reqh == 0)
+ return (EIO);
+ while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
+ error = uiomove(buf, n, uio);
+ if (error)
+ break;
+ DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
+ r = usbd_bulk_transfer(reqh, sce->pipeh, 0, buf,
+ &n, "ugenwb");
+ if (r != USBD_NORMAL_COMPLETION) {
+ if (r == USBD_INTERRUPTED)
+ error = EINTR;
+ else
+ error = EIO;
+ break;
+ }
+ }
+ usbd_free_request(reqh);
+ break;
+ default:
+ return (ENXIO);
+ }
+ return (error);
+}
+
+
void
-ugen_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+ugenintr(reqh, addr, status)
+ usbd_request_handle reqh;
+ usbd_private_handle addr;
+ usbd_status status;
{
- struct ugen_softc *sc = (struct ugen_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ugen_attach(device_t self)
+ struct ugen_endpoint *sce = addr;
+ /*struct ugen_softc *sc = sce->sc;*/
+ usbd_private_handle priv;
+ void *buffer;
+ u_int32_t count;
+ usbd_status xstatus;
+ u_char *ibuf;
+
+ if (status == USBD_CANCELLED)
+ return;
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ DPRINTF(("ugenintr: status=%d\n", status));
+ usbd_clear_endpoint_stall_async(sce->pipeh);
+ return;
+ }
+
+ (void)usbd_get_request_status(reqh, &priv, &buffer, &count, &xstatus);
+ ibuf = sce->ibuf;
+
+ DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n",
+ reqh, xstatus, count));
+ DPRINTFN(5, (" data = %02x %02x %02x\n",
+ ibuf[0], ibuf[1], ibuf[2]));
+
+ (void)b_to_q(ibuf, count, &sce->q);
+
+ if (sce->state & UGEN_ASLP) {
+ sce->state &= ~UGEN_ASLP;
+ DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
+ wakeup((caddr_t)sce);
+ }
+ selwakeup(&sce->rsel);
+}
+
+usbd_status
+ugen_set_interface(sc, ifaceidx, altno)
+ struct ugen_softc *sc;
+ int ifaceidx, altno;
{
- struct ugen_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
+ usbd_interface_handle iface;
+ usb_endpoint_descriptor_t *ed;
+ usbd_status r;
+ struct ugen_endpoint *sce;
+ u_int8_t niface, nendpt, endptno, endpt;
+
+ DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
+
+ r = usbd_interface_count(sc->sc_udev, &niface);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ if (ifaceidx < 0 || ifaceidx >= niface)
+ return (USBD_INVAL);
+
+ r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ r = usbd_endpoint_count(iface, &nendpt);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ for (endptno = 0; endptno < nendpt; endptno++) {
+ ed = usbd_interface2endpoint_descriptor(iface,endptno);
+ endpt = ed->bEndpointAddress;
+ sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][UE_GET_IN(endpt)];
+ sce->sc = 0;
+ sce->edesc = 0;
+ sce->iface = 0;
+ }
+
+ /* change setting */
+ r = usbd_set_interface(iface, altno);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+
+ r = usbd_endpoint_count(iface, &nendpt);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ for (endptno = 0; endptno < nendpt; endptno++) {
+ ed = usbd_interface2endpoint_descriptor(iface,endptno);
+ endpt = ed->bEndpointAddress;
+ sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][UE_GET_IN(endpt)];
+ sce->sc = sc;
+ sce->edesc = ed;
+ sce->iface = iface;
+ }
+ return (0);
+}
+
+/* Retrieve a complete descriptor for a certain device and index. */
+usb_config_descriptor_t *
+ugen_get_cdesc(sc, index, lenp)
+ struct ugen_softc *sc;
+ int index;
+ int *lenp;
+{
+ usb_config_descriptor_t *cdesc, *tdesc, cdescr;
+ int len;
+ usbd_status r;
+
+ if (index == USB_CURRENT_CONFIG_INDEX) {
+ tdesc = usbd_get_config_descriptor(sc->sc_udev);
+ len = UGETW(tdesc->wTotalLength);
+ if (lenp)
+ *lenp = len;
+ cdesc = malloc(len, M_TEMP, M_WAITOK);
+ memcpy(cdesc, tdesc, len);
+ DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
+ } else {
+ r = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (0);
+ len = UGETW(cdescr.wTotalLength);
+ DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
+ if (lenp)
+ *lenp = len;
+ cdesc = malloc(len, M_TEMP, M_WAITOK);
+ r = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
+ if (r != USBD_NORMAL_COMPLETION) {
+ free(cdesc, M_TEMP);
+ return (0);
+ }
+ }
+ return (cdesc);
+}
+
+int
+ugen_get_alt_index(sc, ifaceidx)
+ struct ugen_softc *sc;
+ int ifaceidx;
+{
+ usbd_interface_handle iface;
+ usbd_status r;
+
+ r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (-1);
+ return (usbd_get_interface_altindex(iface));
+}
+
+int
+ugenioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t addr;
+ int flag;
+ struct proc *p;
+{
+ USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ int endpt = UGENENDPOINT(dev);
+ struct ugen_endpoint *sce;
+ usbd_status r;
+ usbd_interface_handle iface;
+ struct usb_config_desc *cd;
+ usb_config_descriptor_t *cdesc;
+ struct usb_interface_desc *id;
+ usb_interface_descriptor_t *idesc;
+ struct usb_endpoint_desc *ed;
+ usb_endpoint_descriptor_t *edesc;
+ struct usb_alt_interface *ai;
+ struct usb_string_desc *si;
+ u_int8_t conf, alt;
+
+ DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
+ if (sc->sc_disconnected)
+ return (EIO);
+
+ switch (cmd) {
+ case FIONBIO:
+ /* All handled in the upper FS layer. */
+ return (0);
+ case USB_SET_SHORT_XFER:
+ /* This flag only affects read */
+ sce = &sc->sc_endpoints[endpt][IN];
+#ifdef DIAGNOSTIC
+ if (!sce->pipeh) {
+ printf("ugenioctl: no pipe\n");
+ return (EIO);
+ }
#endif
- usbd_device_handle dev = uaa->device;
- usb_device_descriptor_t *udd = &dev->ddesc;
- char devinfo[1024];
+ if (*(int *)addr)
+ sce->state |= UGEN_SHORT_OK;
+ else
+ sce->state &= ~UGEN_SHORT_OK;
+ return (0);
+ default:
+ break;
+ }
- usbd_devinfo(dev, 0, devinfo);
-#if defined(__FreeBSD__)
- device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
+ if (endpt != USB_CONTROL_ENDPOINT)
+ return (EINVAL);
+
+ switch (cmd) {
+#ifdef USB_DEBUG
+ case USB_SETDEBUG:
+ ugendebug = *(int *)addr;
+ break;
#endif
- printf(": %s (device class %d/%d)\n", devinfo,
- udd->bDeviceClass, udd->bDeviceSubClass);
- sc->sc_dev = self;
+ case USB_GET_CONFIG:
+ r = usbd_get_config(sc->sc_udev, &conf);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EIO);
+ *(int *)addr = conf;
+ break;
+ case USB_SET_CONFIG:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ r = ugen_set_config(sc, *(int *)addr);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EIO);
+ break;
+ case USB_GET_ALTINTERFACE:
+ ai = (struct usb_alt_interface *)addr;
+ r = usbd_device2interface_handle(sc->sc_udev,
+ ai->interface_index, &iface);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EINVAL);
+ idesc = usbd_get_interface_descriptor(iface);
+ if (!idesc)
+ return (EIO);
+ ai->alt_no = idesc->bAlternateSetting;
+ break;
+ case USB_SET_ALTINTERFACE:
+ if (!(flag & FWRITE))
+ return (EPERM);
+ ai = (struct usb_alt_interface *)addr;
+ r = usbd_device2interface_handle(sc->sc_udev,
+ ai->interface_index, &iface);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EINVAL);
+ r = ugen_set_interface(sc, ai->interface_index, ai->alt_no);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EINVAL);
+ break;
+ case USB_GET_NO_ALT:
+ ai = (struct usb_alt_interface *)addr;
+ cdesc = ugen_get_cdesc(sc, ai->config_index, 0);
+ if (!cdesc)
+ return (EINVAL);
+ idesc = usbd_find_idesc(cdesc, ai->interface_index, 0);
+ if (!idesc)
+ return (EINVAL);
+ ai->alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber);
+ break;
+ case USB_GET_DEVICE_DESC:
+ *(usb_device_descriptor_t *)addr =
+ *usbd_get_device_descriptor(sc->sc_udev);
+ break;
+ case USB_GET_CONFIG_DESC:
+ cd = (struct usb_config_desc *)addr;
+ cdesc = ugen_get_cdesc(sc, cd->config_index, 0);
+ if (!cdesc)
+ return (EINVAL);
+ cd->desc = *cdesc;
+ free(cdesc, M_TEMP);
+ break;
+ case USB_GET_INTERFACE_DESC:
+ id = (struct usb_interface_desc *)addr;
+ cdesc = ugen_get_cdesc(sc, id->config_index, 0);
+ if (!cdesc)
+ return (EINVAL);
+ if (id->config_index == USB_CURRENT_CONFIG_INDEX &&
+ id->alt_index == USB_CURRENT_ALT_INDEX)
+ alt = ugen_get_alt_index(sc, id->interface_index);
+ else
+ alt = id->alt_index;
+ idesc = usbd_find_idesc(cdesc, id->interface_index, alt);
+ if (!idesc) {
+ free(cdesc, M_TEMP);
+ return (EINVAL);
+ }
+ id->desc = *idesc;
+ free(cdesc, M_TEMP);
+ break;
+ case USB_GET_ENDPOINT_DESC:
+ ed = (struct usb_endpoint_desc *)addr;
+ cdesc = ugen_get_cdesc(sc, ed->config_index, 0);
+ if (!cdesc)
+ return (EINVAL);
+ if (ed->config_index == USB_CURRENT_CONFIG_INDEX &&
+ ed->alt_index == USB_CURRENT_ALT_INDEX)
+ alt = ugen_get_alt_index(sc, ed->interface_index);
+ else
+ alt = ed->alt_index;
+ edesc = usbd_find_edesc(cdesc, ed->interface_index,
+ alt, ed->endpoint_index);
+ if (!edesc) {
+ free(cdesc, M_TEMP);
+ return (EINVAL);
+ }
+ ed->desc = *edesc;
+ free(cdesc, M_TEMP);
+ break;
+ case USB_GET_FULL_DESC:
+ {
+ int len;
+ struct iovec iov;
+ struct uio uio;
+ struct usb_full_desc *fd = (struct usb_full_desc *)addr;
+ int error;
+
+ cdesc = ugen_get_cdesc(sc, fd->config_index, &len);
+ if (len > fd->size)
+ len = fd->size;
+ iov.iov_base = (caddr_t)fd->data;
+ iov.iov_len = len;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_resid = len;
+ uio.uio_offset = 0;
+ uio.uio_segflg = UIO_USERSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_procp = p;
+ error = uiomove(cdesc, len, &uio);
+ free(cdesc, M_TEMP);
+ return (error);
+ }
+ case USB_GET_STRING_DESC:
+ si = (struct usb_string_desc *)addr;
+ r = usbd_get_string_desc(sc->sc_udev, si->string_index,
+ si->language_id, &si->desc);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EINVAL);
+ break;
+ case USB_DO_REQUEST:
+ {
+ struct usb_ctl_request *ur = (void *)addr;
+ int len = UGETW(ur->request.wLength);
+ struct iovec iov;
+ struct uio uio;
+ void *ptr = 0;
+ usbd_status r;
+ int error = 0;
+
+ if (!(flag & FWRITE))
+ return (EPERM);
+ /* Avoid requests that would damage the bus integrity. */
+ if ((ur->request.bmRequestType == UT_WRITE_DEVICE &&
+ ur->request.bRequest == UR_SET_ADDRESS) ||
+ (ur->request.bmRequestType == UT_WRITE_DEVICE &&
+ ur->request.bRequest == UR_SET_CONFIG) ||
+ (ur->request.bmRequestType == UT_WRITE_INTERFACE &&
+ ur->request.bRequest == UR_SET_INTERFACE))
+ return (EINVAL);
+
+ if (len < 0 || len > 32767)
+ return (EINVAL);
+ if (len != 0) {
+ iov.iov_base = (caddr_t)ur->data;
+ iov.iov_len = len;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_resid = len;
+ uio.uio_offset = 0;
+ uio.uio_segflg = UIO_USERSPACE;
+ uio.uio_rw =
+ ur->request.bmRequestType & UT_READ ?
+ UIO_READ : UIO_WRITE;
+ uio.uio_procp = p;
+ ptr = malloc(len, M_TEMP, M_WAITOK);
+ if (uio.uio_rw == UIO_WRITE) {
+ error = uiomove(ptr, len, &uio);
+ if (error)
+ goto ret;
+ }
+ }
+ r = usbd_do_request_flags(sc->sc_udev, &ur->request,
+ ptr, ur->flags, &ur->actlen);
+ if (r) {
+ error = EIO;
+ goto ret;
+ }
+ if (len != 0) {
+ if (uio.uio_rw == UIO_READ) {
+ error = uiomove(ptr, len, &uio);
+ if (error)
+ goto ret;
+ }
+ }
+ ret:
+ if (ptr)
+ free(ptr, M_TEMP);
+ return (error);
+ }
+ case USB_GET_DEVICEINFO:
+ usbd_fill_deviceinfo(sc->sc_udev,
+ (struct usb_device_info *)addr);
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+int
+ugenpoll(dev, events, p)
+ dev_t dev;
+ int events;
+ struct proc *p;
+{
+ USB_GET_SC(ugen, UGENUNIT(dev), sc);
+ /* XXX */
+ struct ugen_endpoint *sce;
+ int revents = 0;
+ int s;
+
+ if (sc->sc_disconnected)
+ return (EIO);
- ATTACH_SUCCESS_RETURN;
+ sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
+#ifdef DIAGNOSTIC
+ if (!sce->edesc) {
+ printf("ugenwrite: no edesc\n");
+ return (EIO);
+ }
+ if (!sce->pipeh) {
+ printf("ugenpoll: no pipe\n");
+ return (EIO);
+ }
+#endif
+ s = splusb();
+ switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_INTERRUPT:
+ if (events & (POLLIN | POLLRDNORM)) {
+ if (sce->q.c_cc > 0)
+ revents |= events & (POLLIN | POLLRDNORM);
+ else
+ selrecord(p, &sce->rsel);
+ }
+ 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 &
+ (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
+ break;
+ default:
+ break;
+ }
+ splx(s);
+ return (revents);
}
#if defined(__FreeBSD__)
static int
ugen_detach(device_t self)
-{
- /* we need to cast away the const returned by
- * device_get_desc
- */
+{
+ struct ugen_softc *sc = device_get_softc(self);
char *devinfo = (char *) device_get_desc(self);
if (devinfo) {
device_set_desc(self, NULL);
free(devinfo, M_USB);
}
-
return 0;
}
-DRIVER_MODULE(ugen, usb, ugen_driver, ugen_devclass, usb_driver_load, 0);
+DRIVER_MODULE(ugen, usb, ugen_driver, ugen_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index 212a04b..12554b3 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,12 +1,13 @@
-/* $NetBSD: uhci.c,v 1.10 1998/08/02 22:30:52 augustss Exp $ */
+/* $NetBSD: uhci.c,v 1.20 1998/12/30 18:06:25 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -47,8 +48,6 @@
* USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -76,7 +75,6 @@
#if defined(__FreeBSD__)
#include <machine/clock.h>
-#include "dev/usb/queue.addendum.h"
#define delay(d) DELAY(d)
#endif
@@ -94,7 +92,7 @@ struct uhci_pipe {
uhci_soft_qh_t *sqh;
usb_dma_t reqdma;
usb_dma_t datadma;
- uhci_soft_td_t *setup, *stat, *xferend;
+ uhci_soft_td_t *setup, *stat;
u_int length;
} ctl;
/* Interrupt pipe */
@@ -110,6 +108,13 @@ struct uhci_pipe {
u_int length;
int isread;
} bulk;
+ /* Iso pipe */
+ struct iso {
+ u_int bufsize;
+ u_int nbuf;
+ usb_dma_t *bufs;
+ uhci_soft_td_t **stds;
+ } iso;
} u;
};
@@ -120,21 +125,23 @@ struct uhci_pipe {
LIST_HEAD(, uhci_intr_info) uhci_ii_free;
void uhci_busreset __P((uhci_softc_t *));
-void uhci_run __P((uhci_softc_t *, int run));
+usbd_status uhci_run __P((uhci_softc_t *, int run));
uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *));
void uhci_free_std __P((uhci_softc_t *, uhci_soft_td_t *));
uhci_soft_qh_t *uhci_alloc_sqh __P((uhci_softc_t *));
void uhci_free_sqh __P((uhci_softc_t *, uhci_soft_qh_t *));
uhci_intr_info_t *uhci_alloc_intr_info __P((uhci_softc_t *));
void uhci_free_intr_info __P((uhci_intr_info_t *ii));
+#if 0
void uhci_enter_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *,
uhci_intr_info_t *));
void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *));
+#endif
void uhci_free_std_chain __P((uhci_softc_t *,
uhci_soft_td_t *, uhci_soft_td_t *));
usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *, uhci_softc_t *,
- int, int, usb_dma_t *,
+ int, int, int, usb_dma_t *,
uhci_soft_td_t **,
uhci_soft_td_t **));
void uhci_timo __P((void *));
@@ -151,24 +158,32 @@ void uhci_remove_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *));
void uhci_remove_bulk __P((uhci_softc_t *, uhci_soft_qh_t *));
int uhci_str __P((usb_string_descriptor_t *, int, char *));
-void uhci_device_close __P((struct uhci_pipe *));
-
void uhci_wakeup_cb __P((usbd_request_handle reqh));
usbd_status uhci_device_ctrl_transfer __P((usbd_request_handle));
+usbd_status uhci_device_ctrl_start __P((usbd_request_handle));
void uhci_device_ctrl_abort __P((usbd_request_handle));
void uhci_device_ctrl_close __P((usbd_pipe_handle));
usbd_status uhci_device_intr_transfer __P((usbd_request_handle));
+usbd_status uhci_device_intr_start __P((usbd_request_handle));
void uhci_device_intr_abort __P((usbd_request_handle));
void uhci_device_intr_close __P((usbd_pipe_handle));
usbd_status uhci_device_bulk_transfer __P((usbd_request_handle));
+usbd_status uhci_device_bulk_start __P((usbd_request_handle));
void uhci_device_bulk_abort __P((usbd_request_handle));
void uhci_device_bulk_close __P((usbd_pipe_handle));
+usbd_status uhci_device_isoc_transfer __P((usbd_request_handle));
+usbd_status uhci_device_isoc_start __P((usbd_request_handle));
+void uhci_device_isoc_abort __P((usbd_request_handle));
+void uhci_device_isoc_close __P((usbd_pipe_handle));
+usbd_status uhci_device_isoc_setbuf __P((usbd_pipe_handle, u_int, u_int));
usbd_status uhci_root_ctrl_transfer __P((usbd_request_handle));
+usbd_status uhci_root_ctrl_start __P((usbd_request_handle));
void uhci_root_ctrl_abort __P((usbd_request_handle));
void uhci_root_ctrl_close __P((usbd_pipe_handle));
usbd_status uhci_root_intr_transfer __P((usbd_request_handle));
+usbd_status uhci_root_intr_start __P((usbd_request_handle));
void uhci_root_intr_abort __P((usbd_request_handle));
void uhci_root_intr_close __P((usbd_pipe_handle));
@@ -184,6 +199,7 @@ void uhci_remove_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *));
usbd_status uhci_device_setintr __P((uhci_softc_t *sc,
struct uhci_pipe *pipe, int ival));
void uhci_intr_done __P((uhci_intr_info_t *ii));
+void uhci_isoc_done __P((uhci_intr_info_t *ii));
#ifdef USB_DEBUG
static void uhci_dumpregs __P((uhci_softc_t *));
@@ -209,8 +225,6 @@ void uhci_dump_td __P((uhci_soft_td_t *));
#define UHCISTS(sc) UREAD2(sc, UHCI_STS)
#define UHCI_RESET_TIMEOUT 100 /* reset timeout */
-#define UHCI_CTRL_TIMEOUT 500 /* control transaction timeout */
-#define UHCI_ISO_DELAY 50 /* delay of start of iso */
#define UHCI_CURFRAME(sc) (UREAD2(sc, UHCI_FRNUM) & UHCI_FRNUM_MASK)
@@ -218,6 +232,7 @@ void uhci_dump_td __P((uhci_soft_td_t *));
struct usbd_methods uhci_root_ctrl_methods = {
uhci_root_ctrl_transfer,
+ uhci_root_ctrl_start,
uhci_root_ctrl_abort,
uhci_root_ctrl_close,
0,
@@ -225,6 +240,7 @@ struct usbd_methods uhci_root_ctrl_methods = {
struct usbd_methods uhci_root_intr_methods = {
uhci_root_intr_transfer,
+ uhci_root_intr_start,
uhci_root_intr_abort,
uhci_root_intr_close,
0,
@@ -232,6 +248,7 @@ struct usbd_methods uhci_root_intr_methods = {
struct usbd_methods uhci_device_ctrl_methods = {
uhci_device_ctrl_transfer,
+ uhci_device_ctrl_start,
uhci_device_ctrl_abort,
uhci_device_ctrl_close,
0,
@@ -239,6 +256,7 @@ struct usbd_methods uhci_device_ctrl_methods = {
struct usbd_methods uhci_device_intr_methods = {
uhci_device_intr_transfer,
+ uhci_device_intr_start,
uhci_device_intr_abort,
uhci_device_intr_close,
0,
@@ -246,17 +264,26 @@ struct usbd_methods uhci_device_intr_methods = {
struct usbd_methods uhci_device_bulk_methods = {
uhci_device_bulk_transfer,
+ uhci_device_bulk_start,
uhci_device_bulk_abort,
uhci_device_bulk_close,
0,
};
+struct usbd_methods uhci_device_isoc_methods = {
+ uhci_device_isoc_transfer,
+ uhci_device_isoc_start,
+ uhci_device_isoc_abort,
+ uhci_device_isoc_close,
+ uhci_device_isoc_setbuf,
+};
+
void
uhci_busreset(sc)
uhci_softc_t *sc;
{
UHCICMD(sc, UHCI_CMD_GRESET); /* global reset */
- usbd_delay_ms(&sc->sc_bus, USB_RESET_DELAY); /* wait at least 10ms */
+ usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); /* wait a little */
UHCICMD(sc, 0); /* do nothing */
}
@@ -355,8 +382,7 @@ uhci_init(sc)
UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */
- uhci_run(sc, 1); /* and here we go... */
- return (USBD_NORMAL_COMPLETION);
+ return (uhci_run(sc, 1)); /* and here we go... */
}
#ifdef USB_DEBUG
@@ -364,7 +390,9 @@ static void
uhci_dumpregs(sc)
uhci_softc_t *sc;
{
- DEVICE_MSG(sc->sc_bus.bdev,("regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
+ printf("%s; regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, "
+ "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
+ USBDEVNAME(sc->sc_bus.bdev),
UREAD2(sc, UHCI_CMD),
UREAD2(sc, UHCI_STS),
UREAD2(sc, UHCI_INTR),
@@ -372,7 +400,7 @@ uhci_dumpregs(sc)
UREAD2(sc, UHCI_FLBASEADDR),
UREAD2(sc, UHCI_SOF),
UREAD2(sc, UHCI_PORTSC1),
- UREAD2(sc, UHCI_PORTSC2)));
+ UREAD2(sc, UHCI_PORTSC2));
}
int uhci_longtd = 1;
@@ -388,11 +416,13 @@ uhci_dump_td(p)
(long)p->td->td_token,
(long)p->td->td_buffer);
if (uhci_longtd)
- printf(" %b %b,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d,D=%d,maxlen=%d\n",
+ printf(" %b %b,errcnt=%d,actlen=%d pid=%02x,addr=%d,endpt=%d,"
+ "D=%d,maxlen=%d\n",
(long)p->td->td_link,
"\20\1T\2Q\3VF",
(long)p->td->td_status,
- "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD",
+ "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
+ "STALLED\30ACTIVE\31IOC\32ISO\33LS\36SPD",
UHCI_TD_GET_ERRCNT(p->td->td_status),
UHCI_TD_GET_ACTLEN(p->td->td_status),
UHCI_TD_GET_PID(p->td->td_token),
@@ -458,27 +488,19 @@ uhci_timo(addr)
p[0] |= 1<<1;
if (UREAD2(sc, UHCI_PORTSC2) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
p[0] |= 1<<2;
+ s = splusb();
if (p[0] != 0) {
reqh->actlen = 1;
reqh->status = USBD_NORMAL_COMPLETION;
- s = splusb();
reqh->xfercb(reqh);
- splx(s);
}
if (reqh->pipe->intrreqh == reqh) {
-#if defined(__NetBSD__)
- timeout(uhci_timo, reqh, sc->sc_ival);
-#elif defined(__FreeBSD__)
- /* To avoid race conditions we first initialise the struct
- * before we use it. The timeout might happen between the
- * setting of the timeout and the setting of timo_handle
- */
- callout_handle_init(&reqh->timo_handle);
- reqh->timo_handle = timeout(uhci_timo, reqh, sc->sc_ival);
-#endif
+ usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
} else {
usb_freemem(sc->sc_dmatag, &upipe->u.intr.datadma);
+ usb_start_next(reqh->pipe);
}
+ splx(s);
}
@@ -600,7 +622,9 @@ uhci_remove_bulk(sc, sqh)
uhci_soft_qh_t *pqh;
DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
- for (pqh = sc->sc_bulk_start; pqh->qh->hlink != sqh; pqh=pqh->qh->hlink)
+ for (pqh = sc->sc_bulk_start;
+ pqh->qh->hlink != sqh;
+ pqh = pqh->qh->hlink)
#if defined(DIAGNOSTIC) || defined(USB_DEBUG)
if (pqh->qh->qh_hlink & UHCI_PTR_T) {
printf("uhci_remove_bulk: QH not found\n");
@@ -626,7 +650,7 @@ uhci_intr(p)
sc->sc_intrs++;
#if defined(USB_DEBUG)
if (uhcidebug > 9) {
- DEVICE_MSG(sc->sc_bus.bdev, ("uhci_intr %p\n", sc));
+ printf("uhci_intr %p\n", sc);
uhci_dumpregs(sc);
}
#endif
@@ -642,21 +666,21 @@ uhci_intr(p)
}
if (status & UHCI_STS_RD) {
UWRITE2(sc, UHCI_STS, UHCI_STS_RD); /* acknowledge */
- DEVICE_MSG(sc->sc_bus.bdev, ("resume detect\n"));
+ printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev));
ret = 1;
}
if (status & UHCI_STS_HSE) {
UWRITE2(sc, UHCI_STS, UHCI_STS_HSE); /* acknowledge */
- DEVICE_MSG(sc->sc_bus.bdev, ("Host System Error\n"));
+ printf("%s: Host System Error\n", USBDEVNAME(sc->sc_bus.bdev));
ret = 1;
}
if (status & UHCI_STS_HCPE) {
UWRITE2(sc, UHCI_STS, UHCI_STS_HCPE); /* acknowledge */
- DEVICE_MSG(sc->sc_bus.bdev, ("Host System Error\n"));
+ printf("%s: Host System Error\n", USBDEVNAME(sc->sc_bus.bdev));
ret = 1;
}
if (status & UHCI_STS_HCH)
- DEVICE_ERROR(sc->sc_bus.bdev, ("controller halted\n"));
+ printf("%s: controller halted\n", USBDEVNAME(sc->sc_bus.bdev));
if (!ret)
return 0;
@@ -686,6 +710,7 @@ uhci_check_intr(sc, ii)
{
struct uhci_pipe *upipe;
uhci_soft_td_t *std, *lstd;
+ u_int32_t status;
DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii));
#ifdef DIAGNOSTIC
@@ -706,21 +731,22 @@ uhci_check_intr(sc, ii)
/* If the last TD is still active the whole transfer probably is. */
if (lstd->td->td_status & UHCI_TD_ACTIVE) {
DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
- for (std = ii->stdstart; std != lstd; std = std->td->link.std)
- if (std->td->td_status & UHCI_TD_STALLED)
+ for (std = ii->stdstart; std != lstd; std = std->td->link.std){
+ status = std->td->td_status;
+ if ((status & UHCI_TD_STALLED) ||
+ (status & (UHCI_TD_SPD | UHCI_TD_ACTIVE)) ==
+ UHCI_TD_SPD)
goto done;
- DPRINTFN(15, ("uhci_check_intr: ii=%p still active\n", ii));
+ }
+ DPRINTFN(15, ("uhci_check_intr: ii=%p std=%p still active\n",
+ ii, ii->stdstart));
return;
}
done:
upipe = (struct uhci_pipe *)ii->reqh->pipe;
upipe->pipe.endpoint->toggle = upipe->newtoggle;
uhci_ii_done(ii, 0);
-#if defined(__NetBSD__)
- untimeout(uhci_timeout, ii);
-#elif defined(__FreeBSD__)
- untimeout(uhci_timeout, ii, ii->timeout_handle);
-#endif
+ usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
}
void
@@ -731,7 +757,7 @@ uhci_ii_done(ii, timo)
usbd_request_handle reqh = ii->reqh;
uhci_soft_td_t *std;
u_int32_t tst;
- int len, status;
+ int len, status, attr;
DPRINTFN(10, ("uhci_ii_done: ii=%p ready %d\n", ii, timo));
@@ -749,13 +775,15 @@ uhci_ii_done(ii, timo)
#endif
/* The transfer is done, compute length and status. */
+ /* XXX stop at first inactive to get toggle right. */
+ /* XXX Is this correct for control xfers? */
for (len = status = 0, std = ii->stdstart;
std != 0;
std = std->td->link.std) {
tst = std->td->td_status;
status |= tst;
#ifdef USB_DEBUG
- if ((tst & UHCI_TD_ERROR) && uhcidebug>10) {
+ if ((tst & UHCI_TD_ERROR) && uhcidebug) {
printf("uhci_ii_done: intr error TD:\n");
uhci_dump_td(std);
}
@@ -764,11 +792,16 @@ uhci_ii_done(ii, timo)
len += UHCI_TD_GET_ACTLEN(tst);
}
status &= UHCI_TD_ERROR;
- DPRINTFN(10, ("uhci_ii_done: len=%d\n", len));
+ DPRINTFN(10, ("uhci_check_intr: len=%d, status=0x%x\n", len, status));
if (status != 0) {
- DPRINTFN(10,
- ("uhci_ii_done: error, status 0x%b\n", (long)status,
- "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27STALLED\30ACTIVE"));
+ DPRINTFN(-1+(status==UHCI_TD_STALLED),
+ ("uhci_ii_done: error, addr=%d, endpt=0x%02x, "
+ "status 0x%b\n",
+ reqh->pipe->device->address,
+ reqh->pipe->endpoint->edesc->bEndpointAddress,
+ (long)status,
+ "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
+ "STALLED\30ACTIVE"));
if (status == UHCI_TD_STALLED)
reqh->status = USBD_STALLED;
else
@@ -787,15 +820,19 @@ uhci_ii_done(ii, timo)
}
DPRINTFN(5, ("uhci_ii_done: calling handler ii=%p\n", ii));
- switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
+ attr = reqh->pipe->endpoint->edesc->bmAttributes;
+ switch (attr & UE_XFERTYPE) {
case UE_CONTROL:
uhci_ctrl_done(ii);
+ usb_start_next(reqh->pipe);
break;
case UE_ISOCHRONOUS:
- printf("uhci_ii_done: ISO??\n");
+ uhci_isoc_done(ii);
+ usb_start_next(reqh->pipe);
break;
case UE_BULK:
uhci_bulk_done(ii);
+ usb_start_next(reqh->pipe);
break;
case UE_INTERRUPT:
uhci_intr_done(ii);
@@ -806,6 +843,9 @@ uhci_ii_done(ii, timo)
reqh->xfercb(reqh);
}
+/*
+ * Called when a request does not complete.
+ */
void
uhci_timeout(addr)
void *addr;
@@ -823,6 +863,7 @@ uhci_timeout(addr)
* Wait here until controller claims to have an interrupt.
* Then call uhci_intr and return. Use timeout to avoid waiting
* too long.
+ * Only used during boot when interrupts are not enabled yet.
*/
void
uhci_waitintr(sc, reqh)
@@ -831,28 +872,31 @@ uhci_waitintr(sc, reqh)
{
int timo = reqh->timeout;
int usecs;
- int hzs;
+ uhci_intr_info_t *ii;
- DPRINTFN(10,("uhci_waitintr: timout = %ds\n", timo));
+ DPRINTFN(10,("uhci_waitintr: timeout = %ds\n", timo));
reqh->status = USBD_IN_PROGRESS;
- for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 100000) {
- /* NWH replaced by usbd_delay_ms
- delay(1000);
- NWH and descreased frequency from 1ms to 100ms, see also usecs -=...
- */
- usbd_delay_ms(&(sc->sc_bus), 100);
- /* NWH disabled
+ for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
+ usb_delay_ms(&sc->sc_bus, 1);
DPRINTFN(10,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS)));
- */
if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) {
uhci_intr(sc);
if (reqh->status != USBD_IN_PROGRESS)
return;
}
}
- reqh->status = USBD_TIMEOUT;
- reqh->xfercb(reqh);
+
+ /* Timeout */
+ DPRINTF(("uhci_waitintr: timeout\n"));
+ for (ii = LIST_FIRST(&sc->sc_intrhead);
+ ii && ii->reqh != reqh;
+ ii = LIST_NEXT(ii, list))
+ ;
+ if (ii)
+ uhci_ii_done(ii, 1);
+ else
+ panic("uhci_waitintr: lost intr_info\n");
}
void
@@ -879,39 +923,39 @@ uhci_reset(p)
(UREAD2(sc, UHCI_CMD) & UHCI_CMD_HCRESET); n++)
delay(100);
if (n >= UHCI_RESET_TIMEOUT)
- DEVICE_ERROR(sc->sc_bus.bdev, ("controller did not reset\n"));
+ printf("%s: controller did not reset\n",
+ USBDEVNAME(sc->sc_bus.bdev));
}
#endif
-void
+usbd_status
uhci_run(sc, run)
uhci_softc_t *sc;
int run;
{
int s, n, running;
- run = (run? UHCI_STS_HCH:0);
- s = splusb(); /* XXX really? */
+ run = run != 0;
+ s = splusb();
running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH);
if (run == running) {
splx(s);
- return;
+ return (USBD_NORMAL_COMPLETION);
}
UWRITE2(sc, UHCI_CMD, run ? UHCI_CMD_RS : 0);
- for(n = 0; n < 100; n++) {
- /* XXX NWH should this not be a delay of 2ms (>1024usecs)
- * followed by one check? This fails in case a large transfer
- * is going on on a fast processor.
- */
+ for(n = 0; n < 10; n++) {
running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH);
/* return when we've entered the state we want */
if (run == running) {
splx(s);
- return;
+ return (USBD_NORMAL_COMPLETION);
}
+ usb_delay_ms(&sc->sc_bus, 1);
}
splx(s);
- DEVICE_ERROR(sc->sc_bus.bdev, ("cannot %s\n", (run ? "start" : "stop")));
+ printf("%s: cannot %s\n", USBDEVNAME(sc->sc_bus.bdev),
+ run ? "start" : "stop");
+ return (USBD_IOERROR);
}
/*
@@ -921,7 +965,7 @@ uhci_run(sc, run)
* These two routines do their own free list management,
* partly for speed, partly because allocating DMAable memory
* has page size granularaity so much memory would be wasted if
- * only one TD/QH (32 bytes) was placed in each alloacted chunk.
+ * only one TD/QH (32 bytes) was placed in each allocated chunk.
*/
uhci_soft_td_t *
@@ -938,16 +982,15 @@ uhci_alloc_std(sc)
std = malloc(sizeof(uhci_soft_td_t) * UHCI_TD_CHUNK,
M_USBDEV, M_NOWAIT);
if (!std)
- return 0;
+ return (0);
r = usb_allocmem(sc->sc_dmatag, UHCI_TD_SIZE * UHCI_TD_CHUNK,
UHCI_TD_ALIGN, &dma);
if (r != USBD_NORMAL_COMPLETION) {
free(std, M_USBDEV);
- return 0;
+ return (0);
}
for(i = 0; i < UHCI_TD_CHUNK; i++, std++) {
- std->physaddr = DMAADDR(&dma) +
- i * UHCI_TD_SIZE;
+ std->physaddr = DMAADDR(&dma) + i * UHCI_TD_SIZE;
std->td = (uhci_td_t *)
((char *)KERNADDR(&dma) + i * UHCI_TD_SIZE);
std->td->link.std = sc->sc_freetds;
@@ -1010,7 +1053,7 @@ uhci_alloc_sqh(sc)
sqh = sc->sc_freeqhs;
sc->sc_freeqhs = sqh->qh->hlink;
memset(sqh->qh, 0, UHCI_QH_SIZE);
- return sqh;
+ return (sqh);
}
void
@@ -1022,6 +1065,7 @@ uhci_free_sqh(sc, sqh)
sc->sc_freeqhs = sqh;
}
+#if 0
/*
* Enter a list of transfers onto a control queue.
* Called at splusb()
@@ -1035,6 +1079,7 @@ uhci_enter_ctl_q(sc, sqh, ii)
DPRINTFN(5, ("uhci_enter_ctl_q: sqh=%p\n", sqh));
}
+#endif
void
uhci_free_std_chain(sc, std, stdend)
@@ -1051,27 +1096,28 @@ uhci_free_std_chain(sc, std, stdend)
}
usbd_status
-uhci_alloc_std_chain(upipe, sc, len, rd, dma, sp, ep)
+uhci_alloc_std_chain(upipe, sc, len, rd, spd, dma, sp, ep)
struct uhci_pipe *upipe;
uhci_softc_t *sc;
- int len, rd;
+ int len, rd, spd;
usb_dma_t *dma;
uhci_soft_td_t **sp, **ep;
{
uhci_soft_td_t *p, *lastp;
uhci_physaddr_t lastlink;
- u_int32_t ls;
int i, ntd, l, tog, maxp;
+ u_int32_t status;
int addr = upipe->pipe.device->address;
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
- DPRINTFN(15, ("uhci_alloc_std_chain: len=%d\n", len));
+ DPRINTFN(15, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d "
+ "spd=%d\n", addr, endpt, len,
+ upipe->pipe.device->lowspeed, spd));
if (len == 0) {
*sp = *ep = 0;
- printf("uhci_alloc_std_chain: len=0\n");
+ DPRINTFN(-1,("uhci_alloc_std_chain: len=0\n"));
return (USBD_NORMAL_COMPLETION);
}
- ls = upipe->pipe.device->lowspeed ? UHCI_TD_LS : 0;
maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize);
if (maxp == 0) {
printf("uhci_alloc_std_chain: maxp=0\n");
@@ -1085,6 +1131,11 @@ uhci_alloc_std_chain(upipe, sc, len, rd, dma, sp, ep)
lastp = 0;
lastlink = UHCI_PTR_T;
ntd--;
+ status = UHCI_TD_SET_ERRCNT(2) | UHCI_TD_ACTIVE;
+ if (upipe->pipe.device->lowspeed)
+ status |= UHCI_TD_LS;
+ if (spd)
+ status |= UHCI_TD_SPD;
for (i = ntd; i >= 0; i--) {
p = uhci_alloc_std(sc);
if (!p) {
@@ -1095,7 +1146,7 @@ uhci_alloc_std_chain(upipe, sc, len, rd, dma, sp, ep)
p->td->td_link = lastlink;
lastp = p;
lastlink = p->physaddr;
- p->td->td_status = UHCI_TD_SET_ERRCNT(2) | ls | UHCI_TD_ACTIVE;
+ p->td->td_status = status;
if (i == ntd) {
/* last TD */
l = len % maxp;
@@ -1120,6 +1171,22 @@ usbd_status
uhci_device_bulk_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (uhci_device_bulk_start(reqh));
+}
+
+usbd_status
+uhci_device_bulk_start(reqh)
+ usbd_request_handle reqh;
+{
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
@@ -1131,7 +1198,8 @@ uhci_device_bulk_transfer(reqh)
int len, isread;
int s;
- DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p buf=%p len=%d flags=%d\n",
+ DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p buf=%p len=%d "
+ "flags=%d\n",
reqh, reqh->buffer, reqh->length, reqh->flags));
if (reqh->isreq)
@@ -1149,6 +1217,7 @@ uhci_device_bulk_transfer(reqh)
if (r != USBD_NORMAL_COMPLETION)
goto ret1;
r = uhci_alloc_std_chain(upipe, sc, len, isread,
+ reqh->flags & USBD_SHORT_XFER_OK,
dmap, &xfer, &xferend);
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
@@ -1181,17 +1250,8 @@ uhci_device_bulk_transfer(reqh)
LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
if (reqh->timeout && !sc->sc_bus.use_polling) {
-#if defined(__NetBSD__)
- timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout));
-#elif defined(__FreeBSD__)
- /* To avoid race conditions we first initialise the struct
- * before we use it. The timeout might happen between the
- * setting of the timeout and the setting of timeout_handle
- */
- callout_handle_init(&ii->timeout_handle);
- ii->timeout_handle = timeout(uhci_timeout, ii,
- MS_TO_TICKS(reqh->timeout));
-#endif
+ usb_timeout(uhci_timeout, ii,
+ MS_TO_TICKS(reqh->timeout), ii->timeout_handle);
}
splx(s);
@@ -1217,7 +1277,7 @@ uhci_device_bulk_abort(reqh)
usbd_request_handle reqh;
{
/* XXX inactivate */
- usbd_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is finished */
+ usb_delay_ms(reqh->pipe->device->bus, 1);/* make sure it is done */
/* XXX call done */
}
@@ -1239,6 +1299,22 @@ usbd_status
uhci_device_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (uhci_device_ctrl_start(reqh));
+}
+
+usbd_status
+uhci_device_ctrl_start(reqh)
+ usbd_request_handle reqh;
+{
uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
usbd_status r;
@@ -1258,6 +1334,22 @@ usbd_status
uhci_device_intr_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (uhci_device_intr_start(reqh));
+}
+
+usbd_status
+uhci_device_intr_start(reqh)
+ usbd_request_handle reqh;
+{
struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
usbd_device_handle dev = upipe->pipe.device;
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
@@ -1269,7 +1361,8 @@ uhci_device_intr_transfer(reqh)
int len, i;
int s;
- DPRINTFN(3, ("uhci_device_intr_transfer: reqh=%p buf=%p len=%d flags=%d\n",
+ DPRINTFN(3, ("uhci_device_intr_transfer: reqh=%p buf=%p len=%d "
+ "flags=%d\n",
reqh, reqh->buffer, reqh->length, reqh->flags));
if (reqh->isreq)
@@ -1283,7 +1376,9 @@ uhci_device_intr_transfer(reqh)
r = usb_allocmem(sc->sc_dmatag, len, 0, dmap);
if (r != USBD_NORMAL_COMPLETION)
goto ret1;
- r = uhci_alloc_std_chain(upipe, sc, len, 1, dmap, &xfer, &xferend);
+ r = uhci_alloc_std_chain(upipe, sc, len, 1,
+ reqh->flags & USBD_SHORT_XFER_OK,
+ dmap, &xfer, &xferend);
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
xferend->td->td_status |= UHCI_TD_IOC;
@@ -1305,7 +1400,8 @@ uhci_device_intr_transfer(reqh)
ii->isdone = 0;
#endif
-DPRINTFN(10,("uhci_device_intr_transfer: qhs[0]=%p\n", upipe->u.intr.qhs[0]));
+ DPRINTFN(10,("uhci_device_intr_transfer: qhs[0]=%p\n",
+ upipe->u.intr.qhs[0]));
for (i = 0; i < upipe->u.intr.npoll; i++) {
sqh = upipe->u.intr.qhs[i];
sqh->qh->elink = xfer;
@@ -1336,7 +1432,7 @@ uhci_device_ctrl_abort(reqh)
usbd_request_handle reqh;
{
/* XXX inactivate */
- usbd_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is finished */
+ usb_delay_ms(reqh->pipe->device->bus, 1); /* make sure it is done */
/* XXX call done */
}
@@ -1360,7 +1456,7 @@ uhci_device_intr_abort(reqh)
DPRINTFN(1, ("uhci_device_intr_abort: reqh=%p\n", reqh));
/* XXX inactivate */
- usbd_delay_ms(reqh->pipe->device->bus, 2); /* make sure it is finished */
+ usb_delay_ms(reqh->pipe->device->bus, 2); /* make sure it is done */
if (reqh->pipe->intrreqh == reqh) {
DPRINTF(("uhci_device_intr_abort: remove\n"));
reqh->pipe->intrreqh = 0;
@@ -1392,7 +1488,7 @@ uhci_device_intr_close(pipe)
* We now have to wait for any activity on the physical
* descriptors to stop.
*/
- usbd_delay_ms(&sc->sc_bus, 2);
+ usb_delay_ms(&sc->sc_bus, 2);
for(i = 0; i < npoll; i++)
uhci_free_sqh(sc, upipe->u.intr.qhs[i]);
@@ -1426,7 +1522,8 @@ uhci_device_request(reqh)
int isread;
int s;
- DPRINTFN(5,("uhci_device_control type=0x%02x, request=0x%02x, wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
+ DPRINTFN(3,("uhci_device_control type=0x%02x, request=0x%02x, "
+ "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
req->bmRequestType, req->bRequest, UGETW(req->wValue),
UGETW(req->wIndex), UGETW(req->wLength),
addr, endpt));
@@ -1447,6 +1544,7 @@ uhci_device_request(reqh)
goto ret1;
upipe->pipe.endpoint->toggle = 1;
r = uhci_alloc_std_chain(upipe, sc, len, isread,
+ reqh->flags & USBD_SHORT_XFER_OK,
dmap, &xfer, &xferend);
if (r != USBD_NORMAL_COMPLETION)
goto ret2;
@@ -1454,11 +1552,9 @@ uhci_device_request(reqh)
xferend->td->link.std = stat;
xferend->td->td_link = stat->physaddr;
} else {
- xfer = 0;
next = stat;
}
upipe->u.ctl.length = len;
- upipe->u.ctl.xferend = xferend;
memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
if (!isread && len != 0)
@@ -1519,12 +1615,8 @@ uhci_device_request(reqh)
}
for (sxqh = xqh = (uhci_soft_qh_t *)std;
xqh;
- /* FIXME NWH seems to be a circular list ??
- * checking for beginning of list end of list
- * and printing a maximum of 5 QH's ...
- xqh = xqh->qh->hlink)
- */
- xqh = (maxqh++ == 5 || xqh->qh->hlink==sxqh || xqh->qh->hlink==xqh? NULL : xqh->qh->hlink)) {
+ xqh = (maxqh++ == 5 || xqh->qh->hlink==sxqh ||
+ xqh->qh->hlink==xqh ? NULL : xqh->qh->hlink)) {
uhci_dump_qh(xqh);
uhci_dump_qh(sxqh);
}
@@ -1534,17 +1626,8 @@ uhci_device_request(reqh)
}
#endif
if (reqh->timeout && !sc->sc_bus.use_polling) {
-#if defined(__NetBSD__)
- timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout));
-#elif defined(__FreeBSD__)
- /* To avoid race conditions we first initialise the struct
- * before we use it. The timeout may happen between the setting
- * of the timeout and the setting of callout_handle
- */
- callout_handle_init(&ii->timeout_handle);
- ii->timeout_handle = timeout(uhci_timeout, ii,
- MS_TO_TICKS(reqh->timeout));
-#endif
+ usb_timeout(uhci_timeout, ii,
+ MS_TO_TICKS(reqh->timeout), ii->timeout_handle);
}
splx(s);
@@ -1557,6 +1640,179 @@ uhci_device_request(reqh)
return (r);
}
+usbd_status
+uhci_device_isoc_transfer(reqh)
+ usbd_request_handle reqh;
+{
+ struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+#ifdef USB_DEBUG
+ usbd_device_handle dev = upipe->pipe.device;
+ uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
+#endif
+
+ DPRINTFN(1,("uhci_device_isoc_transfer: sc=%p\n", sc));
+ if (upipe->u.iso.bufsize == 0)
+ return (USBD_INVAL);
+
+ /* XXX copy data */
+ return (USBD_XXX);
+}
+
+usbd_status
+uhci_device_isoc_start(reqh)
+ usbd_request_handle reqh;
+{
+ return (USBD_XXX);
+}
+
+void
+uhci_device_isoc_abort(reqh)
+ usbd_request_handle reqh;
+{
+ /* XXX Can't abort a single request. */
+}
+
+void
+uhci_device_isoc_close(pipe)
+ usbd_pipe_handle pipe;
+{
+ struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
+ usbd_device_handle dev = upipe->pipe.device;
+ uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
+ struct iso *iso;
+ int i;
+
+ /*
+ * Make sure all TDs are marked as inactive.
+ * Wait for completion.
+ * Unschedule.
+ * Deallocate.
+ */
+ iso = &upipe->u.iso;
+
+ for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++)
+ iso->stds[i]->td->td_status &= ~UHCI_TD_ACTIVE;
+ usb_delay_ms(&sc->sc_bus, 2); /* wait for completion */
+
+ uhci_lock_frames(sc);
+ for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
+ uhci_soft_td_t *std, *vstd;
+
+ std = iso->stds[i];
+ for (vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd;
+ vstd && vstd->td->link.std != std;
+ vstd = vstd->td->link.std)
+ ;
+ if (!vstd) {
+ /*panic*/
+ printf("uhci_device_isoc_close: %p not found\n", std);
+ uhci_unlock_frames(sc);
+ return;
+ }
+ vstd->td->link = std->td->link;
+ vstd->td->td_link = std->td->td_link;
+ uhci_free_std(sc, std);
+ }
+ uhci_unlock_frames(sc);
+
+ for (i = 0; i < iso->nbuf; i++)
+ usb_freemem(sc->sc_dmatag, &iso->bufs[i]);
+ free(iso->stds, M_USB);
+ free(iso->bufs, M_USB);
+
+ /* XXX what else? */
+}
+
+usbd_status
+uhci_device_isoc_setbuf(pipe, bufsize, nbuf)
+ usbd_pipe_handle pipe;
+ u_int bufsize;
+ u_int nbuf;
+{
+ struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
+ usbd_device_handle dev = upipe->pipe.device;
+ uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
+ int addr = upipe->pipe.device->address;
+ int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
+ int rd = upipe->pipe.endpoint->edesc->bEndpointAddress & UE_IN;
+ struct iso *iso;
+ int i;
+ usbd_status r;
+
+ /*
+ * For simplicity the number of buffers must fit nicely in the frame
+ * list.
+ */
+ if (UHCI_VFRAMELIST_COUNT % nbuf != 0)
+ return (USBD_INVAL);
+
+ iso = &upipe->u.iso;
+ iso->bufsize = bufsize;
+ iso->nbuf = nbuf;
+
+ /* Allocate memory for buffers. */
+ iso->bufs = malloc(nbuf * sizeof(usb_dma_t), M_USB, M_WAITOK);
+ iso->stds = malloc(UHCI_VFRAMELIST_COUNT * sizeof (uhci_soft_td_t *),
+ M_USB, M_WAITOK);
+
+ for (i = 0; i < nbuf; i++) {
+ r = usb_allocmem(sc->sc_dmatag, bufsize, 0, &iso->bufs[i]);
+ if (r != USBD_NORMAL_COMPLETION) {
+ nbuf = i;
+ goto bad1;
+ }
+ }
+
+ /* Allocate the TDs. */
+ for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
+ iso->stds[i] = uhci_alloc_std(sc);
+ if (iso->stds[i] == 0)
+ goto bad2;
+ }
+
+ /* XXX check schedule */
+
+ /* XXX interrupts */
+
+ /* Insert TDs into schedule, all marked inactive. */
+ uhci_lock_frames(sc);
+ for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
+ uhci_soft_td_t *std, *vstd;
+
+ std = iso->stds[i];
+ std->td->td_status = UHCI_TD_IOS; /* iso, inactive */
+ std->td->td_token =
+ rd ? UHCI_TD_IN (0, endpt, addr, 0) :
+ UHCI_TD_OUT(0, endpt, addr, 0);
+ std->td->td_buffer = DMAADDR(&iso->bufs[i % nbuf]);
+
+ vstd = sc->sc_vframes[i % UHCI_VFRAMELIST_COUNT].htd;
+ std->td->link = vstd->td->link;
+ std->td->td_link = vstd->td->td_link;
+ vstd->td->link.std = std;
+ vstd->td->td_link = std->physaddr;
+ }
+ uhci_unlock_frames(sc);
+
+ return (USBD_NORMAL_COMPLETION);
+
+ bad2:
+ while (--i >= 0)
+ uhci_free_std(sc, iso->stds[i]);
+ bad1:
+ for (i = 0; i < nbuf; i++)
+ usb_freemem(sc->sc_dmatag, &iso->bufs[i]);
+ free(iso->stds, M_USB);
+ free(iso->bufs, M_USB);
+ return (USBD_NOMEM);
+}
+
+void
+uhci_isoc_done(ii)
+ uhci_intr_info_t *ii;
+{
+}
+
void
uhci_intr_done(ii)
uhci_intr_info_t *ii;
@@ -1585,8 +1841,9 @@ uhci_intr_done(ii)
uhci_soft_td_t *xfer, *xferend;
/* This alloc cannot fail since we freed the chain above. */
- uhci_alloc_std_chain(upipe, sc, reqh->length, 1, dma,
- &xfer, &xferend);
+ uhci_alloc_std_chain(upipe, sc, reqh->length, 1,
+ reqh->flags & USBD_SHORT_XFER_OK,
+ dma, &xfer, &xferend);
xferend->td->td_status |= UHCI_TD_IOC;
#ifdef USB_DEBUG
@@ -1610,6 +1867,7 @@ uhci_intr_done(ii)
} else {
usb_freemem(sc->sc_dmatag, dma);
ii->stdstart = 0; /* mark as inactive */
+ usb_start_next(reqh->pipe);
}
}
@@ -1843,8 +2101,9 @@ uhci_open(pipe)
pipe->methods = &uhci_device_intr_methods;
return (uhci_device_setintr(sc, upipe, ed->bInterval));
case UE_ISOCHRONOUS:
- printf("uhci_open: iso not implemented\n");
- return (USBD_XXX);
+ pipe->methods = &uhci_device_isoc_methods;
+ upipe->u.iso.nbuf = 0;
+ return (USBD_NORMAL_COMPLETION);
case UE_BULK:
pipe->methods = &uhci_device_bulk_methods;
upipe->u.bulk.sqh = uhci_alloc_sqh(sc);
@@ -1918,7 +2177,6 @@ usb_hub_descriptor_t uhci_hubd_piix = {
50, /* power on to power good */
0,
{ 0x00 }, /* both ports are removable */
- { 0x00 }, /* no ports can power down individually */
};
int
@@ -1948,6 +2206,22 @@ usbd_status
uhci_root_ctrl_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (uhci_root_ctrl_start(reqh));
+}
+
+usbd_status
+uhci_root_ctrl_start(reqh)
+ usbd_request_handle reqh;
+{
uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
usb_device_request_t *req;
void *buf;
@@ -1973,7 +2247,7 @@ uhci_root_ctrl_transfer(reqh)
case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
/*
- * DEVICE_REMOTE_WAKEUP and ENDPOINT_STALL are no-ops
+ * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
* for the integrated root hub.
*/
break;
@@ -2079,7 +2353,8 @@ uhci_root_ctrl_transfer(reqh)
case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
break;
case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
- DPRINTFN(3, ("uhci_root_ctrl_control: UR_CLEAR_PORT_FEATURE port=%d feature=%d\n",
+ DPRINTFN(3, ("uhci_root_ctrl_control: UR_CLEAR_PORT_FEATURE "
+ "port=%d feature=%d\n",
index, value));
if (index == 1)
port = UHCI_PORTSC1;
@@ -2227,7 +2502,7 @@ uhci_root_ctrl_transfer(reqh)
case UHF_PORT_RESET:
x = UREAD2(sc, port);
UWRITE2(sc, port, x | UHCI_PORTSC_PR);
- usbd_delay_ms(&sc->sc_bus, 10);
+ usb_delay_ms(&sc->sc_bus, 10);
UWRITE2(sc, port, x & ~UHCI_PORTSC_PR);
delay(100);
x = UREAD2(sc, port);
@@ -2260,6 +2535,7 @@ uhci_root_ctrl_transfer(reqh)
ret:
reqh->status = r;
reqh->xfercb(reqh);
+ usb_start_next(reqh->pipe);
return (USBD_IN_PROGRESS);
}
@@ -2276,11 +2552,7 @@ void
uhci_root_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
-#if defined(__NetBSD__)
- untimeout(uhci_timo, pipe->intrreqh);
-#elif defined(__FreeBSD__)
- untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
-#endif
+ usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
DPRINTF(("uhci_root_ctrl_close\n"));
}
@@ -2289,18 +2561,30 @@ void
uhci_root_intr_abort(reqh)
usbd_request_handle reqh;
{
-#if defined(__NetBSD__)
- untimeout(uhci_timo, reqh);
-#elif defined(__FreeBSD__)
- untimeout(uhci_timo, reqh, reqh->timo_handle);
-#endif
+ usb_untimeout(uhci_timo, reqh, reqh->timo_handle);
}
-/* Start a transfer on the root interrupt pipe */
usbd_status
uhci_root_intr_transfer(reqh)
usbd_request_handle reqh;
{
+ int s;
+ usbd_status r;
+
+ s = splusb();
+ r = usb_insert_transfer(reqh);
+ splx(s);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ else
+ return (uhci_root_intr_start(reqh));
+}
+
+/* Start a transfer on the root interrupt pipe */
+usbd_status
+uhci_root_intr_start(reqh)
+ usbd_request_handle reqh;
+{
usbd_pipe_handle pipe = reqh->pipe;
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
@@ -2308,7 +2592,8 @@ uhci_root_intr_transfer(reqh)
usbd_status r;
int len;
- DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p buf=%p len=%d flags=%d\n",
+ DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p buf=%p len=%d "
+ "flags=%d\n",
reqh, reqh->buffer, reqh->length, reqh->flags));
len = reqh->length;
@@ -2321,16 +2606,7 @@ uhci_root_intr_transfer(reqh)
return (r);
sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval);
-#if defined(__NetBSD__)
- timeout(uhci_timo, reqh, sc->sc_ival);
-#elif defined(__FreeBSD__)
- /* To avoid race conditions we first initialise the struct
- * before we use it. The timeout happen between the setting
- * of the timeout and the setting of callout_handle
- */
- callout_handle_init(&reqh->timo_handle);
- reqh->timo_handle = timeout(uhci_timo, reqh, sc->sc_ival);
-#endif
+ usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
return (USBD_IN_PROGRESS);
}
@@ -2339,10 +2615,6 @@ void
uhci_root_intr_close(pipe)
usbd_pipe_handle pipe;
{
-#if defined(__NetBSD__)
- untimeout(uhci_timo, pipe->intrreqh);
-#elif defined(__FreeBSD__)
- untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
-#endif
+ usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
DPRINTF(("uhci_root_intr_close\n"));
}
diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h
index ab2f306..9c8ef00 100644
--- a/sys/dev/usb/uhcireg.h
+++ b/sys/dev/usb/uhcireg.h
@@ -1,12 +1,13 @@
-/* $NetBSD: uhcireg.h,v 1.2 1998/07/26 00:40:59 augustss Exp $ */
+/* $NetBSD: uhcireg.h,v 1.5 1998/12/27 23:40:52 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -154,7 +155,7 @@ typedef struct {
#define UHCI_TD_GET_PID(s) ((s) & 0xff)
#define UHCI_TD_SET_DEVADDR(a) ((a) << 8)
#define UHCI_TD_GET_DEVADDR(s) (((s) >> 8) & 0x7f)
-#define UHCI_TD_SET_ENDPT(e) ((e) << 15)
+#define UHCI_TD_SET_ENDPT(e) (((e)&0xf) << 15)
#define UHCI_TD_GET_ENDPT(s) (((s) >> 15) & 0xf)
#define UHCI_TD_SET_DT(t) ((t) << 19)
#define UHCI_TD_GET_DT(s) (((s) >> 19) & 1)
@@ -169,9 +170,14 @@ typedef struct {
#define UHCI_TD_ERROR (UHCI_TD_BITSTUFF|UHCI_TD_CRCTO|UHCI_TD_BABBLE|UHCI_TD_DBUFFER|UHCI_TD_STALLED)
-#define UHCI_TD_SETUP(len, endp, dev) (UHCI_TD_SET_MAXLEN(len) | UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_SETUP)
-#define UHCI_TD_OUT(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_OUT | UHCI_TD_SET_DT(dt))
-#define UHCI_TD_IN(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_IN | UHCI_TD_SET_DT(dt))
+#define UHCI_TD_SETUP(len, endp, dev) (UHCI_TD_SET_MAXLEN(len) | \
+ UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_SETUP)
+#define UHCI_TD_OUT(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \
+ UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | \
+ UHCI_TD_PID_OUT | UHCI_TD_SET_DT(dt))
+#define UHCI_TD_IN(len, endp, dev, dt) (UHCI_TD_SET_MAXLEN(len) | \
+ UHCI_TD_SET_ENDPT(endp) | UHCI_TD_SET_DEVADDR(dev) | UHCI_TD_PID_IN | \
+ UHCI_TD_SET_DT(dt))
typedef struct {
uhci_physaddr_t qh_hlink;
diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h
index b714269..7143c42 100644
--- a/sys/dev/usb/uhcivar.h
+++ b/sys/dev/usb/uhcivar.h
@@ -1,12 +1,13 @@
-/* $NetBSD: uhcivar.h,v 1.3 1998/07/26 00:40:59 augustss Exp $ */
+/* $NetBSD: uhcivar.h,v 1.5 1998/12/26 12:53:02 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -63,14 +64,14 @@ typedef struct uhci_soft_td uhci_soft_td_t;
* searched at interrupt time.
*/
typedef struct uhci_intr_info {
-#if defined(__FreeBSD__)
- struct callout_handle timeout_handle;
-#endif
struct uhci_softc *sc;
usbd_request_handle reqh;
uhci_soft_td_t *stdstart;
uhci_soft_td_t *stdend;
LIST_ENTRY(uhci_intr_info) list;
+#if defined(__FreeBSD__)
+ struct callout_handle timeout_handle;
+#endif /* defined(__FreeBSD__) */
#ifdef DIAGNOSTIC
int isdone;
#endif
@@ -121,12 +122,12 @@ typedef struct uhci_softc {
bus_space_tag_t iot;
bus_space_handle_t ioh;
- bus_dma_tag_t sc_dmatag; /* DMA tag */
+ bus_dma_tag_t sc_dmatag; /* DMA tag */
/* XXX should keep track of all DMA memory */
#elif defined(__FreeBSD__)
int sc_iobase;
int unit;
-#endif
+#endif /* defined(__FreeBSD__) */
uhci_physaddr_t *sc_pframes;
struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT];
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index a74f124..06d1c75 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -1,12 +1,13 @@
-/* $NetBSD: uhid.c,v 1.3 1998/08/01 20:52:45 augustss Exp $ */
+/* $NetBSD: uhid.c,v 1.12 1998/12/26 12:53:02 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,7 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -51,6 +51,7 @@
#include <sys/filio.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/ioccom.h>
#endif
#include <sys/tty.h>
#include <sys/file.h>
@@ -64,7 +65,6 @@
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
#include <dev/usb/hid.h>
#include <dev/usb/usb_quirks.h>
@@ -78,7 +78,7 @@ int uhiddebug = 0;
#endif
struct uhid_softc {
- bdevice sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
@@ -100,7 +100,7 @@ struct uhid_softc {
struct selinfo sc_rsel;
u_char sc_state; /* driver state */
#define UHID_OPEN 0x01 /* device is open */
-#define UHID_ASLP 0x02 /* waiting for mouse data */
+#define UHID_ASLP 0x02 /* waiting for device data */
#define UHID_NEEDCLEAR 0x04 /* needs clearing endpoint stall */
#define UHID_IMMED 0x08 /* return read data immediately */
int sc_disconnected; /* device is gone */
@@ -110,14 +110,6 @@ struct uhid_softc {
#define UHID_CHUNK 128 /* chunk size for read */
#define UHID_BSIZE 1020 /* buffer size */
-#if defined(__NetBSD__)
-int uhid_match __P((struct device *, struct cfdata *, void *));
-void uhid_attach __P((struct device *, struct device *, void *));
-#elif defined(__FreeBSD__)
-static device_probe_t uhid_match;
-static device_attach_t uhid_attach;
-#endif
-
int uhidopen __P((dev_t, int, int, struct proc *));
int uhidclose __P((dev_t, int, int, struct proc *p));
int uhidread __P((dev_t, struct uio *uio, int));
@@ -127,45 +119,11 @@ int uhidpoll __P((dev_t, int, struct proc *));
void uhid_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void uhid_disco __P((void *));
-#if defined(__NetBSD__)
-extern struct cfdriver uhid_cd;
-
-struct cfattach uhid_ca = {
- sizeof(struct uhid_softc), uhid_match, uhid_attach
-};
-#elif defined(__FreeBSD__)
+USB_DECLARE_DRIVER(uhid);
-static devclass_t uhid_devclass;
-
-static device_method_t uhid_methods[] = {
- DEVMETHOD(device_probe, uhid_match),
- DEVMETHOD(device_attach, uhid_attach),
- {0,0}
-};
-
-static driver_t uhid_driver = {
- "uhid",
- uhid_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct uhid_softc)
-};
-#endif
-
-
-#if defined(__NetBSD__)
-int
-uhid_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(uhid)
{
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-uhid_match(device_t device)
-{
- struct usb_attach_arg *uaa = device_get_ivars(device);
-#endif
+ USB_MATCH_START(uhid, uaa);
usb_interface_descriptor_t *id;
if (!uaa->iface)
@@ -176,22 +134,9 @@ uhid_match(device_t device)
return (UMATCH_IFACECLASS_GENERIC);
}
-#if defined(__NetBSD__)
-void
-uhid_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(uhid)
{
- struct uhid_softc *sc = (struct uhid_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-uhid_attach(device_t self)
-{
- struct uhid_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
-#endif
+ USB_ATTACH_START(uhid, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
@@ -204,31 +149,30 @@ uhid_attach(device_t self)
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
-#if defined(__FreeBSD__)
- usb_device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
-#endif
- printf(": %s (interface class %d/%d)\n", devinfo,
- id->bInterfaceClass, id->bInterfaceSubClass);
- sc->sc_dev = self;
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
+ devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (!ed) {
- DEVICE_ERROR(sc->sc_dev, ("could not read endpoint descriptor\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: could not read endpoint descriptor\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
- DPRINTFN(10,("uhid_attach: \
-bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d bInterval=%d\n",
- ed->bLength, ed->bDescriptorType, ed->bEndpointAddress & UE_ADDR,
- ed->bEndpointAddress & UE_IN ? "in" : "out",
- ed->bmAttributes & UE_XFERTYPE,
- UGETW(ed->wMaxPacketSize), ed->bInterval));
+ DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d "
+ "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
+ " bInterval=%d\n",
+ ed->bLength, ed->bDescriptorType,
+ ed->bEndpointAddress & UE_ADDR,
+ ed->bEndpointAddress & UE_IN ? "in" : "out",
+ ed->bmAttributes & UE_XFERTYPE,
+ UGETW(ed->wMaxPacketSize), ed->bInterval));
if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
- DEVICE_ERROR(sc->sc_dev, ("unexpected endpoint\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
sc->sc_ep_addr = ed->bEndpointAddress;
@@ -236,8 +180,8 @@ bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketS
r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USB);
if (r != USBD_NORMAL_COMPLETION) {
- DEVICE_ERROR(sc->sc_dev, ("no report descriptor\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
(void)usbd_set_idle(iface, 0, 0);
@@ -249,9 +193,24 @@ bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketS
sc->sc_repdesc = desc;
sc->sc_repdesc_size = size;
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
}
+#if defined(__FreeBSD__)
+static int
+uhid_detach(device_t self)
+{
+ struct uhid_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+ return 0;
+}
+#endif
+
void
uhid_disco(p)
void *p;
@@ -302,18 +261,10 @@ uhidopen(dev, flag, mode, p)
struct proc *p;
{
usbd_status r;
-#if defined(__NetBSD__)
- struct uhid_softc *sc;
- int unit = UHIDUNIT(dev);
+ USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
- if (unit >= uhid_cd.cd_ndevs)
- return ENXIO;
- sc = uhid_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct uhid_softc *sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev));
-#endif
if (!sc)
- return ENXIO;
+ return (ENXIO);
DPRINTF(("uhidopen: sc=%p, disco=%d\n", sc, sc->sc_disconnected));
@@ -321,11 +272,11 @@ uhidopen(dev, flag, mode, p)
return (EIO);
if (sc->sc_state & UHID_OPEN)
- return EBUSY;
+ return (EBUSY);
#if defined(__NetBSD__)
if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1)
- return ENOMEM;
+ return (ENOMEM);
#elif defined(__FreeBSD__)
clist_alloc_cblocks(&sc->sc_q, UHID_BSIZE, 0);
#endif
@@ -342,13 +293,14 @@ uhidopen(dev, flag, mode, p)
&sc->sc_intrpipe, sc, sc->sc_ibuf,
sc->sc_isize, uhid_intr);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("uhidopen: usbd_open_pipe_intr failed, error=%d\n",r));
+ DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
+ "error=%d\n",r));
sc->sc_state &= ~UHID_OPEN;
return (EIO);
}
usbd_set_disco(sc->sc_intrpipe, uhid_disco, sc);
- return 0;
+ return (0);
}
int
@@ -358,16 +310,7 @@ uhidclose(dev, flag, mode, p)
int mode;
struct proc *p;
{
-#if defined(__NetBSD__)
- struct uhid_softc *sc;
- int unit = UHIDUNIT(dev);
-
- if (unit >= uhid_cd.cd_ndevs)
- return ENXIO;
- sc = uhid_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct uhid_softc *sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev));
-#endif
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -389,7 +332,7 @@ uhidclose(dev, flag, mode, p)
free(sc->sc_ibuf, M_USB);
free(sc->sc_obuf, M_USB);
- return 0;
+ return (0);
}
int
@@ -403,16 +346,7 @@ uhidread(dev, uio, flag)
size_t length;
u_char buffer[UHID_CHUNK];
usbd_status r;
-#if defined(__NetBSD__)
- struct uhid_softc *sc;
- int unit = UHIDUNIT(dev);
-
- if (unit >= uhid_cd.cd_ndevs)
- return ENXIO;
- sc = uhid_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct uhid_softc *sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev));
-#endif
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -428,7 +362,7 @@ uhidread(dev, uio, flag)
return (uiomove(buffer, sc->sc_isize, uio));
}
- s = spltty();
+ s = splusb();
while (sc->sc_q.c_cc == 0) {
if (flag & IO_NDELAY) {
splx(s);
@@ -478,16 +412,7 @@ uhidwrite(dev, uio, flag)
int error;
int size;
usbd_status r;
-#if defined(__NetBSD__)
- struct uhid_softc *sc;
- int unit = UHIDUNIT(dev);
-
- if (unit >= uhid_cd.cd_ndevs)
- return ENXIO;
- sc = uhid_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct uhid_softc *sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev));
-#endif
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -528,16 +453,7 @@ uhidioctl(dev, cmd, addr, flag, p)
struct usb_ctl_report *re;
int size, id;
usbd_status r;
-#if defined(__NetBSD__)
- struct uhid_softc *sc;
- int unit = UHIDUNIT(dev);
-
- if (unit >= uhid_cd.cd_ndevs)
- return ENXIO;
- sc = uhid_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct uhid_softc *sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev));
-#endif
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -557,12 +473,12 @@ uhidioctl(dev, cmd, addr, flag, p)
case USB_SET_IMMED:
if (*(int *)addr) {
- /* XXX should read into ibuf, but does it matter */
- r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
- sc->sc_iid, sc->sc_ibuf,
- sc->sc_isize);
- if (r != USBD_NORMAL_COMPLETION)
- return (EOPNOTSUPP);
+ /* XXX should read into ibuf, but does it matter */
+ r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
+ sc->sc_iid, sc->sc_ibuf,
+ sc->sc_isize);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (EOPNOTSUPP);
sc->sc_state |= UHID_IMMED;
} else
@@ -607,21 +523,12 @@ uhidpoll(dev, events, p)
{
int revents = 0;
int s;
-#if defined(__NetBSD__)
- struct uhid_softc *sc;
- int unit = UHIDUNIT(dev);
-
- if (unit >= uhid_cd.cd_ndevs)
- return ENXIO;
- sc = uhid_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct uhid_softc *sc = devclass_get_softc(uhid_devclass, UHIDUNIT(dev));
-#endif
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
- s = spltty();
+ s = splusb();
if (events & (POLLOUT | POLLWRNORM))
revents |= events & (POLLOUT | POLLWRNORM);
if (events & (POLLIN | POLLRDNORM)) {
@@ -636,5 +543,5 @@ uhidpoll(dev, events, p)
}
#if defined(__FreeBSD__)
-DRIVER_MODULE(uhid, usb, uhid_driver, uhid_devclass, usb_driver_load, 0);
+DRIVER_MODULE(uhid, usb, uhid_driver, uhid_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index b182009..8a44380 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -1,12 +1,13 @@
-/* $NetBSD: uhub.c,v 1.5 1998/08/02 22:30:52 augustss Exp $ */
+/* $NetBSD: uhub.c,v 1.13 1998/12/30 18:06:25 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,8 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -61,6 +60,7 @@
#define DPRINTF(x) if (usbdebug) printf x
#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
extern int usbdebug;
+extern char *usbd_error_strs[];
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -74,73 +74,27 @@ struct uhub_softc {
u_char sc_running;
};
-#if defined(__NetBSD__)
-int uhub_match __P((struct device *, struct cfdata *, void *));
-void uhub_attach __P((struct device *, struct device *, void *));
-void uhub_detach __P((struct device *));
-#elif defined(__FreeBSD__)
-static device_probe_t uhub_match;
-static device_attach_t uhub_attach;
-static device_detach_t uhub_detach;
-#endif
-
-usbd_status uhub_init_port __P((int, struct usbd_port *, usbd_device_handle));
-void uhub_disconnect __P((struct usbd_port *up, int portno));
+usbd_status uhub_init_port __P((struct usbd_port *));
+void uhub_disconnect __P((struct usbd_port *up));
usbd_status uhub_explore __P((usbd_device_handle hub));
void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
/*void uhub_disco __P((void *));*/
-#if defined(__NetBSD__)
-extern struct cfdriver uhub_cd;
-
-struct cfattach uhub_ca = {
- sizeof(struct uhub_softc), uhub_match, uhub_attach
-};
+USB_DECLARE_DRIVER_NAME(usb, uhub);
+/* FIXME what does FreeBSD need? */
+#if defined(__NetBSD__)
struct cfattach uhub_uhub_ca = {
sizeof(struct uhub_softc), uhub_match, uhub_attach
};
-
-#elif defined(__FreeBSD__)
-static devclass_t uhub_devclass;
-
-static device_method_t uhub_methods[] = {
- DEVMETHOD(device_probe, uhub_match),
- DEVMETHOD(device_attach, uhub_attach),
- DEVMETHOD(device_detach, uhub_detach),
- {0,0}
-};
-
-static driver_t uhub_driver = {
- "usb", /* this is silly, but necessary. The uhub
- * implements a usb bus on top of a usb bus,
- * but the problem is that name of the driver
- * is used a the name of the device class it
- * implements.
- */
- uhub_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct uhub_softc)
-};
#endif
-#if defined(__NetBSD__)
-int
-uhub_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
-{
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-uhub_match(device_t device)
+USB_MATCH(uhub)
{
- struct usb_attach_arg *uaa = device_get_ivars(device);
-#endif
+ USB_MATCH_START(uhub, uaa);
usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
-
+
DPRINTFN(5,("uhub_match, dd=%p\n", dd));
/*
* The subclass for hubs seems to be 0 for some and 1 for others,
@@ -151,52 +105,36 @@ uhub_match(device_t device)
return (UMATCH_NONE);
}
-#if defined(__NetBSD__)
-void
-uhub_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(uhub)
{
- struct uhub_softc *sc = (struct uhub_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-uhub_attach(device_t self)
-{
- struct uhub_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
-#endif
+ USB_ATTACH_START(uhub, sc, uaa);
usbd_device_handle dev = uaa->device;
char devinfo[1024];
usbd_status r;
struct usbd_hub *hub;
usb_device_request_t req;
usb_hub_descriptor_t hubdesc;
- int port, nports;
+ int p, port, nports, nremov;
usbd_interface_handle iface;
usb_endpoint_descriptor_t *ed;
-
- DPRINTFN(10,("uhub_attach\n"));
+
+ DPRINTFN(1,("uhub_attach\n"));
sc->sc_hub = dev;
usbd_devinfo(dev, 1, devinfo);
-#if defined(__FreeBSD__)
- usb_device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
-#endif
- printf(": %s\n", devinfo);
- sc->sc_dev = self;
+ USB_ATTACH_SETUP;
+ printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
- r = usbd_set_config_no(dev, 0, 1);
+ r = usbd_set_config_index(dev, 0, 1);
if (r != USBD_NORMAL_COMPLETION) {
- DEVICE_ERROR(sc->sc_dev, ("configuration failed, error=%d\n", r));
- ATTACH_ERROR_RETURN;
+ DPRINTF(("%s: configuration failed, error=%d(%s)\n",
+ USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r]));
+ USB_ATTACH_ERROR_RETURN;
}
if (dev->depth > USB_HUB_MAX_DEPTH) {
- DEVICE_ERROR(sc->sc_dev, ("hub depth (%d) exceeded, hub ignored\n",
- USB_HUB_MAX_DEPTH));
- ATTACH_ERROR_RETURN;
+ printf("%s: hub depth (%d) exceeded, hub ignored\n",
+ USBDEVNAME(sc->sc_dev), USB_HUB_MAX_DEPTH);
+ USB_ATTACH_ERROR_RETURN;
}
/* Get hub descriptor. */
@@ -206,49 +144,62 @@ uhub_attach(device_t self)
USETW(req.wIndex, 0);
USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);
DPRINTFN(1,("usb_init_hub: getting hub descriptor\n"));
- /* XXX not correct for hubs with >7 ports */
r = usbd_do_request(dev, &req, &hubdesc);
+ nports = hubdesc.bNbrPorts;
+ if (r == USBD_NORMAL_COMPLETION && nports > 7) {
+ USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8);
+ r = usbd_do_request(dev, &req, &hubdesc);
+ }
if (r != USBD_NORMAL_COMPLETION) {
- DEVICE_ERROR(sc->sc_dev, ("getting hub descriptor failed, error=%d\n", r));
- ATTACH_ERROR_RETURN;
+ DPRINTF(("%s: getting hub descriptor failed, error=%d(%s)\n",
+ USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r]));
+ USB_ATTACH_ERROR_RETURN;
}
- /* XXX block should be moved down to avoid memory leaking (or an overdose of free()'s) */
- nports = hubdesc.bNbrPorts;
+ for (nremov = 0, port = 1; port <= nports; port++)
+ if (!UHD_NOT_REMOV(&hubdesc, port))
+ nremov++;
+ printf("%s: %d port%s with %d removable, %s powered\n",
+ USBDEVNAME(sc->sc_dev), nports, nports != 1 ? "s" : "",
+ nremov, dev->self_powered ? "self" : "bus");
+
+
hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
M_USB, M_NOWAIT);
if (hub == 0)
- ATTACH_ERROR_RETURN;
+ USB_ATTACH_ERROR_RETURN;
dev->hub = hub;
- dev->hub->hubdata = sc;
+ dev->hub->hubsoftc = sc;
hub->explore = uhub_explore;
hub->hubdesc = hubdesc;
- hub->nports = nports;
-
- DPRINTFN(1,("usbhub_init_hub: selfpowered=%d, parent=%p, parent->selfpowered=%d\n",
+
+ DPRINTFN(1,("usbhub_init_hub: selfpowered=%d, parent=%p, "
+ "parent->selfpowered=%d\n",
dev->self_powered, dev->powersrc->parent,
dev->powersrc->parent ?
dev->powersrc->parent->self_powered : 0));
if (!dev->self_powered && dev->powersrc->parent &&
!dev->powersrc->parent->self_powered) {
- DEVICE_ERROR(sc->sc_dev, ("bus powered hub connected to bus powered hub, ignored\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: bus powered hub connected to bus powered hub, "
+ "ignored\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
/* Set up interrupt pipe. */
r = usbd_device2interface_handle(dev, 0, &iface);
if (r != USBD_NORMAL_COMPLETION) {
- DEVICE_ERROR(sc->sc_dev, ("no interface handle\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (ed == 0) {
- DEVICE_ERROR(sc->sc_dev, ("no endpoint descriptor\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
- DEVICE_ERROR(sc->sc_dev, ("bad interrupt endpoint\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: bad interrupt endpoint\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
r = usbd_open_pipe_intr(iface, ed->bEndpointAddress,USBD_SHORT_XFER_OK,
@@ -256,82 +207,91 @@ uhub_attach(device_t self)
sizeof(sc->sc_status),
uhub_intr);
if (r != USBD_NORMAL_COMPLETION) {
- DEVICE_ERROR(sc->sc_dev, ("cannot open interrupt pipe\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: cannot open interrupt pipe\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
- for (port = 1; port <= nports; port++) {
- r = uhub_init_port(port, &hub->ports[port-1], dev);
+ /* Wait with power off for a while. */
+ usbd_delay_ms(dev, USB_POWER_DOWN_TIME);
+
+ for (p = 0; p < nports; p++) {
+ struct usbd_port *up = &hub->ports[p];
+ up->device = 0;
+ up->parent = dev;
+ up->portno = p+1;
+ r = uhub_init_port(up);
if (r != USBD_NORMAL_COMPLETION)
- DEVICE_ERROR(sc->sc_dev, ("init of port %d failed\n", port));
+ printf("%s: init of port %d failed\n",
+ USBDEVNAME(sc->sc_dev), up->portno);
}
sc->sc_running = 1;
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
}
-#if defined(__NetBSD__)
-static int
-uhub_detach(self)
- struct device *self;
-{
- struct uhub_softc *sc = (struct uhub_softc *)self;
-#elif defined(__FreeBSD__)
+#if defined(__FreeBSD__)
static int
uhub_detach(device_t self)
{
struct uhub_softc *sc = device_get_softc(self);
-#endif
int nports = sc->sc_hub->hub->hubdesc.bNbrPorts;
- int port;
+ int p;
- for (port = 1; port <= nports; port++) {
- if (sc->sc_hub->hub->ports[port-1].device)
- uhub_disconnect(&sc->sc_hub->hub->ports[port-1], port);
+ for (p = 0; p < nports; p++) {
+ struct usbd_port *up = &sc->sc_hub->hub->ports[p];
+ if (up->device)
+ uhub_disconnect(up);
}
free(sc->sc_hub->hub, M_USB);
return 0;
}
+#endif
usbd_status
-uhub_init_port(port, uport, dev)
- int port;
- struct usbd_port *uport;
- usbd_device_handle dev;
+uhub_init_port(up)
+ struct usbd_port *up;
{
+ int port = up->portno;
+ usbd_device_handle dev = up->parent;
usbd_status r;
u_int16_t pstatus;
- uport->device = 0;
- uport->parent = dev;
- r = usbd_get_port_status(dev, port, &uport->status);
+ r = usbd_get_port_status(dev, port, &up->status);
if (r != USBD_NORMAL_COMPLETION)
- return r;
- pstatus = UGETW(uport->status.wPortStatus);
- DPRINTF(("usbd_init_port: adding hub port=%d status=0x%04x change=0x%04x\n",
- port, pstatus, UGETW(uport->status.wPortChange)));
+ return (r);
+ pstatus = UGETW(up->status.wPortStatus);
+ DPRINTF(("usbd_init_port: adding hub port=%d status=0x%04x "
+ "change=0x%04x\n",
+ port, pstatus, UGETW(up->status.wPortChange)));
if ((pstatus & UPS_PORT_POWER) == 0) {
/* Port lacks power, turn it on */
+
+ /* First let the device go through a good power cycle, */
+ usbd_delay_ms(dev, USB_PORT_POWER_DOWN_TIME);
+
+ /* then turn the power on. */
r = usbd_set_port_feature(dev, port, UHF_PORT_POWER);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- r = usbd_get_port_status(dev, port, &uport->status);
+ r = usbd_get_port_status(dev, port, &up->status);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- DPRINTF(("usb_init_port: turn on port %d power status=0x%04x change=0x%04x\n",
- port, UGETW(uport->status.wPortStatus),
- UGETW(uport->status.wPortChange)));
+ DPRINTF(("usb_init_port: turn on port %d power status=0x%04x "
+ "change=0x%04x\n",
+ port, UGETW(up->status.wPortStatus),
+ UGETW(up->status.wPortChange)));
/* Wait for stable power. */
- usbd_delay_ms(dev->bus, dev->hub->hubdesc.bPwrOn2PwrGood *
- UHD_PWRON_FACTOR);
+ usbd_delay_ms(dev, dev->hub->hubdesc.bPwrOn2PwrGood *
+ UHD_PWRON_FACTOR);
}
if (dev->self_powered)
/* Self powered hub, give ports maximum current. */
- uport->power = USB_MAX_POWER;
+ up->power = USB_MAX_POWER;
else
- uport->power = USB_MIN_POWER;
+ up->power = USB_MIN_POWER;
return (USBD_NORMAL_COMPLETION);
}
@@ -340,7 +300,7 @@ uhub_explore(dev)
usbd_device_handle dev;
{
usb_hub_descriptor_t *hd = &dev->hub->hubdesc;
- struct uhub_softc *sc = dev->hub->hubdata;
+ struct uhub_softc *sc = dev->hub->hubsoftc;
struct usbd_port *up;
usbd_status r;
int port;
@@ -359,15 +319,35 @@ uhub_explore(dev)
up = &dev->hub->ports[port-1];
r = usbd_get_port_status(dev, port, &up->status);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("uhub_explore: get port status failed, error=%d\n",
- r));
+ DPRINTF(("uhub_explore: get port status failed, "
+ "error=%d(%s)\n",
+ r, usbd_error_strs[r]));
continue;
}
status = UGETW(up->status.wPortStatus);
change = UGETW(up->status.wPortChange);
DPRINTFN(5, ("uhub_explore: port %d status 0x%04x 0x%04x\n",
port, status, change));
- if (!(change & UPS_CURRENT_CONNECT_STATUS)) {
+ if (change & UPS_C_PORT_ENABLED) {
+ usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);
+ if (status & UPS_PORT_ENABLED) {
+ printf("%s: illegal enable change, port %d\n",
+ USBDEVNAME(sc->sc_dev), port);
+ } else {
+ /* Port error condition. */
+ if (up->restartcnt++ < USBD_RESTART_MAX) {
+ printf("%s: port error, restarting "
+ "port %d\n",
+ USBDEVNAME(sc->sc_dev), port);
+ goto disco;
+ } else {
+ printf("%s: port error, giving up "
+ "port %d\n",
+ USBDEVNAME(sc->sc_dev), port);
+ }
+ }
+ }
+ if (!(change & UPS_C_CONNECT_STATUS)) {
/* No status change, just do recursive explore. */
if (up->device && up->device->hub)
up->device->hub->explore(up->device);
@@ -384,11 +364,13 @@ uhub_explore(dev)
* since a new unit may have been connected before we handle
* the disconnect.
*/
+ disco:
if (up->device) {
/* Disconnected */
- DPRINTF(("uhub_explore: device %d disappeared on port %d\n",
+ DPRINTF(("uhub_explore: device %d disappeared "
+ "on port %d\n",
up->device->address, port));
- uhub_disconnect(up, port);
+ uhub_disconnect(up);
usbd_clear_port_feature(dev, port,
UHF_C_PORT_CONNECTION);
}
@@ -396,23 +378,24 @@ uhub_explore(dev)
continue;
/* Connected */
+ up->restartcnt = 0;
+
/* Wait for maximum device power up time. */
- usbd_delay_ms(dev->bus, USB_PORT_POWERUP_DELAY);
+ usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY);
+
/* Reset port, which implies enabling it. */
if (usbd_reset_port(dev, port, &up->status) !=
USBD_NORMAL_COMPLETION)
continue;
- /* Wait for power to settle in device. */
- usbd_delay_ms(dev->bus, USB_POWER_SETTLE);
-
/* Get device info and set its address. */
r = usbd_new_device(&sc->sc_dev, dev->bus,
dev->depth + 1, status & UPS_LOW_SPEED,
port, up);
/* XXX retry a few times? */
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTFN(-1,("uhub_explore: usb_new_device failed, error=%d\n", r));
+ DPRINTFN(-1,("uhub_explore: usb_new_device failed, "
+ "error=%d(%s)\n", r, usbd_error_strs[r]));
/* Avoid addressing problems by disabling. */
/* usbd_reset_port(dev, port, &up->status); */
/* XXX
@@ -426,12 +409,13 @@ uhub_explore(dev)
* address, and since we cannot leave
* at 0 we have to disable the port
* instead. */
- /*
- DEVICE_ERROR(*parent, ("device problem, disable port %d\n",
- port));
- */
+ printf("%s: device problem, disabling "
+ "port %d\n",
+ USBDEVNAME(sc->sc_dev), port);
usbd_clear_port_feature(dev, port,
UHF_PORT_ENABLE);
+ /* Make sure we don't try to restart it. */
+ up->restartcnt = USBD_RESTART_MAX;
}
} else {
if (up->device->hub)
@@ -442,21 +426,28 @@ uhub_explore(dev)
}
void
-uhub_disconnect(up, portno)
+uhub_disconnect(up)
struct usbd_port *up;
- int portno;
{
usbd_device_handle dev = up->device;
usbd_pipe_handle p, n;
- usb_hub_descriptor_t *hd;
- struct usbd_port *spi;
- int i, port;
+ int i;
+ struct softc { bdevice sc_dev; }; /* all softc begin like this */
DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
- up, dev, portno));
-
- DEVICE_MSG(dev->bdev, ("device addr %d%s on hub addr %d, port %d disconnected\n",
- dev->address, dev->hub ? " (hub)" : "", up->parent->address, portno));
+ up, dev, up->portno));
+
+ printf("%s: at %s port %d (addr %d) disconnected\n",
+ USBDEVNAME(((struct softc *)dev->softc)->sc_dev),
+ USBDEVNAME(((struct uhub_softc *)up->parent->softc)->sc_dev),
+ up->portno, dev->address);
+
+ if (!dev->cdesc) {
+ /* Partially attached device, just drop it. */
+ dev->bus->devices[dev->address] = 0;
+ up->device = 0;
+ return;
+ }
for (i = 0; i < dev->cdesc->bNumInterface; i++) {
for (p = LIST_FIRST(&dev->ifaces[i].pipes); p; p = n) {
@@ -468,8 +459,26 @@ uhub_disconnect(up, portno)
}
}
- /* clean up the kindergarten, get rid of the kids */
- usbd_remove_device(dev, up);
+ /* XXX Free all data structures and disable further I/O. */
+ if (dev->hub) {
+ struct usbd_port *rup;
+ int p, nports;
+
+ DPRINTFN(3,("usb_disconnect: hub, recursing\n"));
+ nports = dev->hub->hubdesc.bNbrPorts;
+ for(p = 0; p < nports; p++) {
+ rup = &dev->hub->ports[p];
+ if (rup->device)
+ uhub_disconnect(rup);
+ }
+ }
+
+ dev->bus->devices[dev->address] = 0;
+ up->device = 0;
+ /* XXX free */
+#if defined(__FreeBSD__)
+ device_delete_child(device_get_parent(((struct softc *)dev->softc)->sc_dev), ((struct softc *)dev->softc)->sc_dev);
+#endif
}
void
@@ -481,14 +490,12 @@ uhub_intr(reqh, addr, status)
struct uhub_softc *sc = addr;
DPRINTFN(5,("uhub_intr: sc=%p\n", sc));
-#if 0
if (status != USBD_NORMAL_COMPLETION)
- usbd_clear_endpoint_stall(sc->sc_ipipe);
+ usbd_clear_endpoint_stall_async(sc->sc_ipipe);
else
-#endif
usb_needs_explore(sc->sc_hub->bus);
}
#if defined(__FreeBSD__)
-DRIVER_MODULE(uhub, usb, uhub_driver, uhub_devclass, usb_driver_load, 0);
+DRIVER_MODULE(uhub, usb, uhub_driver, uhub_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
index 3fa423e..3ccde1b 100644
--- a/sys/dev/usb/ukbd.c
+++ b/sys/dev/usb/ukbd.c
@@ -1,11 +1,13 @@
+/* $NetBSD: ukbd.c,v 1.20 1998/12/30 19:25:27 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,7 +38,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
+/*
+ * Information about USB keyboard can be found in the USB HID spec.
+ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -60,7 +64,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -75,13 +78,17 @@
#include "opt_pckbd_layout.h"
#include "opt_wsdisplay_compat.h"
+
+#elif defined(__FreeBSD__)
+#include <machine/clock.h>
+#define delay(d) DELAY(d)
#endif
#ifdef USB_DEBUG
#define DPRINTF(x) if (ukbddebug) printf x
#define DPRINTFN(n,x) if (ukbddebug>(n)) printf x
int ukbddebug = 0;
-#elif defined(__FreeBSD__)
+#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif
@@ -124,7 +131,10 @@ static struct {
};
#define NN 0 /* no translation */
-/* Translate USB keycodes to US keyboard AT scancodes. */
+/*
+ * Translate USB keycodes to US keyboard AT scancodes.
+ * Scancodes >= 128 represent EXTENDED keycodes.
+ */
static u_int8_t ukbd_trtab[256] = {
0, 0, 0, 0, 30, 48, 46, 32, /* 00 - 07 */
18, 33, 34, 35, 23, 36, 37, 38, /* 08 - 0F */
@@ -162,6 +172,8 @@ static u_int8_t ukbd_trtab[256] = {
#define KEY_ERROR 0x01
+#define MAXKEYS (NMOD+2*NKEYCODE)
+
struct ukbd_softc {
bdevice sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
@@ -178,27 +190,22 @@ struct ukbd_softc {
#if defined(__NetBSD__)
struct device *sc_wskbddev;
#ifdef WSDISPLAY_COMPAT_RAWKBD
+#define REP_DELAY1 400
+#define REP_DELAYN 100
int sc_rawkbd;
-#endif
+ int sc_nrep;
+ char sc_rep[MAXKEYS];
#endif
int sc_polling;
int sc_pollchar;
+#endif
};
#define UKBDUNIT(dev) (minor(dev))
#define UKBD_CHUNK 128 /* chunk size for read */
#define UKBD_BSIZE 1020 /* buffer size */
-#if defined(__NetBSD__)
-int ukbd_match __P((struct device *, struct cfdata *, void *));
-void ukbd_attach __P((struct device *, struct device *, void *));
-#elif defined(__FreeBSD__)
-static device_probe_t ukbd_match;
-static device_attach_t ukbd_attach;
-static device_detach_t ukbd_detach;
-#endif
-
void ukbd_cngetc __P((void *, u_int *, int *));
void ukbd_cnpollc __P((void *, int));
@@ -216,11 +223,16 @@ int ukbd_enable __P((void *, int));
void ukbd_set_leds __P((void *, int));
#if defined(__NetBSD__)
int ukbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
+int ukbd_cnattach __P((void *v));
+void ukbd_rawrepeat __P((void *v));
const struct wskbd_accessops ukbd_accessops = {
ukbd_enable,
ukbd_set_leds,
ukbd_ioctl,
+#if 0
+ ukbd_cnattach,
+#endif
};
const struct wskbd_mapdata ukbd_keymapdata = {
@@ -233,73 +245,28 @@ const struct wskbd_mapdata ukbd_keymapdata = {
};
#endif
-#if defined(__NetBSD__)
-extern struct cfdriver ukbd_cd;
-
-struct cfattach ukbd_ca = {
- sizeof(struct ukbd_softc), ukbd_match, ukbd_attach
-};
-#elif defined(__FreeBSD__)
-static devclass_t ukbd_devclass;
-
-static device_method_t ukbd_methods[] = {
- DEVMETHOD(device_probe, ukbd_match),
- DEVMETHOD(device_attach, ukbd_attach),
- DEVMETHOD(device_detach, ukbd_detach),
- {0,0}
-};
+USB_DECLARE_DRIVER(ukbd);
-static driver_t ukbd_driver = {
- "ukbd",
- ukbd_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct ukbd_softc)
-};
-#endif
-
-#if defined(__NetBSD__)
-int
-ukbd_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(ukbd)
{
- struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux;
-#elif defined(__FreeBSD__)
-static int
-ukbd_match(device_t device)
-{
- struct usb_attach_arg *uaa = device_get_ivars(device);
-#endif
+ USB_MATCH_START(ukbd, uaa);
usb_interface_descriptor_t *id;
/* Check that this is a keyboard that speaks the boot protocol. */
if (!uaa->iface)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
- if (id->bInterfaceClass != UCLASS_HID ||
+ if (!id ||
+ id->bInterfaceClass != UCLASS_HID ||
id->bInterfaceSubClass != USUBCLASS_BOOT ||
id->bInterfaceProtocol != UPROTO_BOOT_KEYBOARD)
return (UMATCH_NONE);
return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
}
-#if defined(__NetBSD__)
-void
-ukbd_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(ukbd)
{
- struct ukbd_softc *sc = (struct ukbd_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ukbd_attach(device_t self)
-{
- struct ukbd_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
-#endif
+ USB_ATTACH_START(ukbd, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
@@ -315,40 +282,43 @@ ukbd_attach(device_t self)
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
-#if defined(__FreeBSD__)
- usb_device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
-#endif
- printf(": %s (interface class %d/%d)\n", devinfo,
- id->bInterfaceClass, id->bInterfaceSubClass);
- sc->sc_dev = self;
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
+ devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
+
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (!ed) {
- DEVICE_ERROR(sc->sc_dev, ("could not read endpoint descriptor\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: could not read endpoint descriptor\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
- DPRINTFN(10,("ukbd_attach: \
-bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d bInterval=%d\n",
- ed->bLength, ed->bDescriptorType, ed->bEndpointAddress & UE_ADDR,
- ed->bEndpointAddress & UE_IN ? "in" : "out",
- ed->bmAttributes & UE_XFERTYPE,
- UGETW(ed->wMaxPacketSize), ed->bInterval));
+ DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d "
+ "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
+ " bInterval=%d\n",
+ ed->bLength, ed->bDescriptorType,
+ ed->bEndpointAddress & UE_ADDR,
+ ed->bEndpointAddress & UE_IN ? "in" : "out",
+ ed->bmAttributes & UE_XFERTYPE,
+ UGETW(ed->wMaxPacketSize), ed->bInterval));
if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
- DEVICE_ERROR(sc->sc_dev, ("unexpected endpoint\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: unexpected endpoint\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
if ((usbd_get_quirks(uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) {
r = usbd_set_protocol(iface, 0);
DPRINTFN(5, ("ukbd_attach: protocol set\n"));
if (r != USBD_NORMAL_COMPLETION) {
- DEVICE_ERROR(sc->sc_dev, ("set protocol failed\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: set protocol failed\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
}
+
/* Ignore if SETIDLE fails since it is not crucial. */
usbd_set_idle(iface, 0, 0);
@@ -356,34 +326,40 @@ bLength=%d bDescriptorType=%d bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketS
sc->sc_disconnected = 0;
#if defined(__NetBSD__)
- a.console = 0; /* XXX */
+ a.console = 0;
a.keymap = &ukbd_keymapdata;
a.accessops = &ukbd_accessops;
a.accesscookie = sc;
+ /* Flash the leds; no real purpose, just shows we're alive. */
+ ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
+ usbd_delay_ms(uaa->device, 300);
+ ukbd_set_leds(sc, 0);
+
sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
#elif defined(__FreeBSD__)
- /* it's alive! IT'S ALIVE! */
+ /* XXX why waste CPU in delay() ? */
+ /* It's alive! IT'S ALIVE! Do a little song and dance. */
ukbd_set_leds(sc, NUM_LOCK);
- DELAY(15000);
+ delay(15000);
ukbd_set_leds(sc, CAPS_LOCK);
- DELAY(20000);
+ delay(20000);
ukbd_set_leds(sc, SCROLL_LOCK);
- DELAY(30000);
+ delay(30000);
ukbd_set_leds(sc, CAPS_LOCK);
- DELAY(50000);
+ delay(50000);
ukbd_set_leds(sc, NUM_LOCK);
ukbd_enable(sc, 1);
#endif
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
}
-
+#if defined(__FreeBSD__)
int
ukbd_detach(device_t self)
{
@@ -391,16 +367,16 @@ ukbd_detach(device_t self)
char *devinfo = (char *) device_get_desc(self);
if (sc->sc_enabled)
- return ENXIO;
+ return (ENXIO);
if (devinfo) {
device_set_desc(self, NULL);
free(devinfo, M_USB);
}
- return 0;
+ return (0);
}
-
+#endif
void
ukbd_disco(p)
@@ -424,7 +400,7 @@ ukbd_enable(v, on)
if (on) {
/* Set up interrupt pipe. */
if (sc->sc_enabled)
- return EBUSY;
+ return (EBUSY);
sc->sc_enabled = 1;
r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
@@ -454,7 +430,7 @@ ukbd_intr(reqh, addr, status)
struct ukbd_softc *sc = addr;
struct ukbd_data *ud = &sc->sc_ndata;
int mod, omod;
- int ibuf[NMOD+2*NKEYCODE]; /* chars events */
+ int ibuf[MAXKEYS]; /* chars events */
int nkeys, i, j;
int key, c;
#define ADDKEY(c) ibuf[nkeys++] = (c)
@@ -519,28 +495,66 @@ ukbd_intr(reqh, addr, status)
}
sc->sc_odata = *ud;
+ if (nkeys == 0)
+ return;
+
+#if defined(__NetBSD__)
if (sc->sc_polling) {
+ DPRINTFN(1,("ukbd_intr: pollchar = 0x%02x\n", ibuf[0]));
if (nkeys > 0)
sc->sc_pollchar = ibuf[0]; /* XXX lost keys? */
return;
}
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+ if (sc->sc_rawkbd) {
+ char cbuf[MAXKEYS * 2];
+ int npress;
+
+ for (npress = i = j = 0; i < nkeys; i++, j++) {
+ c = ibuf[i];
+ if (c & 0x80)
+ cbuf[j++] = 0xe0;
+ cbuf[j] = c & 0x7f;
+ if (c & RELEASE)
+ cbuf[j] |= 0x80;
+ else {
+ /* remember keys for autorepeat */
+ if (c & 0x80)
+ sc->sc_rep[npress++] = 0xe0;
+ sc->sc_rep[npress++] = c & 0x7f;
+ }
+ }
+ wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
+ untimeout(ukbd_rawrepeat, sc);
+ if (npress != 0) {
+ sc->sc_nrep = npress;
+ timeout(ukbd_rawrepeat, sc, hz * REP_DELAY1 / 1000);
+ }
+ return;
+ }
+#endif
+
for (i = 0; i < nkeys; i++) {
c = ibuf[i];
-#if defined(__NetBSD__)
wskbd_input(sc->sc_wskbddev,
c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
c & 0xff);
+ }
#elif defined(__FreeBSD__)
- printf("%c (%d) %s\n", ((c&0xff) < 32 || (c&0xff) > 126? '.':(c&0xff)), c,
- (c&RELEASE? "released":"pressed"));
+ /* XXX shouldn't the keys be used? */
+ for (i = 0; i < nkeys; i++) {
+ c = ibuf[i];
+ printf("%c (%d) %s\n",
+ ((c&0xff) < 32 || (c&0xff) > 126? '.':(c&0xff)), c,
+ (c&RELEASE? "released":"pressed"));
if (ud->modifiers)
printf("0x%04x\n", ud->modifiers);
for (i = 0; i < NKEYCODE; i++)
if (ud->keycode[i])
printf("%d ", ud->keycode[i]);
printf("\n");
-#endif
}
+#endif
}
void
@@ -549,7 +563,7 @@ ukbd_set_leds(v, leds)
int leds;
{
struct ukbd_softc *sc = v;
- u_int8_t res = leds;
+ u_int8_t res;
DPRINTF(("ukbd_set_leds: sc=%p leds=%d\n", sc, leds));
@@ -562,11 +576,26 @@ ukbd_set_leds(v, leds)
res |= NUM_LOCK;
if (leds & WSKBD_LED_CAPS)
res |= CAPS_LOCK;
+#elif defined(__FreeBSD__)
+ res = leds;
#endif
usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1);
}
#if defined(__NetBSD__)
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+void
+ukbd_rawrepeat(v)
+ void *v;
+{
+ struct ukbd_softc *sc = v;
+
+ wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
+ timeout(ukbd_rawrepeat, sc, hz * REP_DELAYN / 1000);
+}
+#endif
+
int
ukbd_ioctl(v, cmd, data, flag, p)
void *v;
@@ -579,25 +608,26 @@ ukbd_ioctl(v, cmd, data, flag, p)
switch (cmd) {
case WSKBDIO_GTYPE:
- *(int *)data = WSKBD_TYPE_PC_XT;
- return 0;
+ *(int *)data = WSKBD_TYPE_USB;
+ return (0);
case WSKBDIO_SETLEDS:
ukbd_set_leds(v, *(int *)data);
- return 0;
+ return (0);
case WSKBDIO_GETLEDS:
*(int *)data = sc->sc_leds;
return (0);
#ifdef WSDISPLAY_COMPAT_RAWKBD
case WSKBDIO_SETMODE:
+ DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data));
sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
+ untimeout(ukbd_rawrepeat, sc);
return (0);
#endif
}
- return -1;
+ return (-1);
}
/* Console interface. */
-/* XXX does not work. */
void
ukbd_cngetc(v, type, data)
void *v;
@@ -629,12 +659,24 @@ ukbd_cnpollc(v, on)
{
struct ukbd_softc *sc = v;
- DPRINTFN(1,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
+ DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on));
usbd_set_polling(sc->sc_iface, on);
}
-#endif
+
+int
+ukbd_cnattach(v)
+ void *v;
+{
+ struct ukbd_softc *sc = v;
+
+ DPRINTF(("ukbd_cnattach: sc=%p\n", sc));
+ wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
+ return (0);
+}
+
+#endif /* NetBSD */
#if defined(__FreeBSD__)
-DRIVER_MODULE(ukbd, usb, ukbd_driver, ukbd_devclass, usb_driver_load, 0);
+DRIVER_MODULE(ukbd, usb, ukbd_driver, ukbd_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/dev/usb/ulpt.c b/sys/dev/usb/ulpt.c
index bad1843..c0d2519 100644
--- a/sys/dev/usb/ulpt.c
+++ b/sys/dev/usb/ulpt.c
@@ -1,12 +1,13 @@
-/* $NetBSD: ulpt.c,v 1.2 1998/07/25 15:19:09 augustss Exp $ */
+/* $NetBSD: ulpt.c,v 1.9 1998/12/30 17:46:20 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,14 +38,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
-#if defined(__NetBSD__)
-#include <sys/user.h>
-#endif
#include <sys/malloc.h>
#include <sys/kernel.h>
#if defined(__NetBSD__)
@@ -61,7 +57,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -108,14 +103,6 @@ struct ulpt_softc {
u_char sc_laststatus;
};
-#if defined(__NetBSD__)
-int ulpt_match __P((struct device *, struct cfdata *, void *));
-void ulpt_attach __P((struct device *, struct device *, void *));
-#elif defined(__FreeBSD__)
-static device_probe_t ulpt_match;
-static device_attach_t ulpt_attach;
-#endif
-
int ulptopen __P((dev_t, int, int, struct proc *));
int ulptclose __P((dev_t, int, int, struct proc *p));
int ulptwrite __P((dev_t, struct uio *uio, int));
@@ -129,51 +116,19 @@ int ulpt_statusmsg __P((u_char, struct ulpt_softc *));
#define ULPTUNIT(s) (minor(s) & 0x1f)
#define ULPTFLAGS(s) (minor(s) & 0xe0)
-#if defined(__NetBSD__)
-extern struct cfdriver ulpt_cd;
-
-struct cfattach ulpt_ca = {
- sizeof(struct ulpt_softc), ulpt_match, ulpt_attach
-};
-#elif defined(__FreeBSD__)
-static devclass_t ulpt_devclass;
-
-static device_method_t ulpt_methods[] = {
- DEVMETHOD(device_probe, ulpt_match),
- DEVMETHOD(device_attach, ulpt_attach),
- {0,0}
-};
-
-static driver_t ulpt_driver = {
- "ulpt",
- ulpt_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct ulpt_softc)
-};
-#endif
-
+USB_DECLARE_DRIVER(ulpt);
-#if defined(__NetBSD__)
-int
-ulpt_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(ulpt)
{
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ulpt_match(device_t device)
-{
- struct usb_attach_arg *uaa = device_get_ivars(device);
-#endif
+ USB_MATCH_START(ulpt, uaa);
usb_interface_descriptor_t *id;
DPRINTFN(10,("ulpt_match\n"));
if (!uaa->iface)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
- if (id->bInterfaceClass == UCLASS_PRINTER &&
+ if (id &&
+ id->bInterfaceClass == UCLASS_PRINTER &&
id->bInterfaceSubClass == USUBCLASS_PRINTER &&
(id->bInterfaceProtocol == UPROTO_PRINTER_UNI ||
id->bInterfaceProtocol == UPROTO_PRINTER_BI))
@@ -181,22 +136,9 @@ ulpt_match(device_t device)
return (UMATCH_NONE);
}
-#if defined(__NetBSD__)
-void
-ulpt_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(ulpt)
{
- struct ulpt_softc *sc = (struct ulpt_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ulpt_attach(device_t self)
-{
- struct ulpt_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
-#endif
+ USB_ATTACH_START(ulpt, sc, uaa);
usbd_device_handle dev = uaa->device;
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
@@ -210,13 +152,9 @@ ulpt_attach(device_t self)
DPRINTFN(10,("ulpt_attach: sc=%p\n", sc));
usbd_devinfo(dev, 0, devinfo);
-#if defined(__FreeBSD__)
- usb_device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
-#endif
- printf(": %s (interface class %d/%d)\n", devinfo,
- id->bInterfaceClass, id->bInterfaceSubClass);
- sc->sc_dev = self;
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
+ devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
/* Figure out which endpoint is the bulk out endpoint. */
ed = usbd_interface2endpoint_descriptor(iface, 0);
@@ -238,7 +176,7 @@ ulpt_attach(device_t self)
sc->sc_iface = iface;
r = usbd_interface2device_handle(iface, &sc->sc_udev);
if (r != USBD_NORMAL_COMPLETION)
- ATTACH_ERROR_RETURN;
+ USB_ATTACH_ERROR_RETURN;
sc->sc_ifaceno = id->bInterfaceNumber;
#if 0
@@ -257,18 +195,17 @@ is unknown. usbd_do_request() returns error on a short transfer.
/* devinfo now contains an IEEE-1284 device ID */
idstr = devinfo+2;
idstr[len] = 0;
- DEVICE_ERROR(sc->sc_dev, ("device id <%s>\n", idstr));
+ printf("%s: device id <%s>\n", USBDEVNAME(sc->sc_dev), idstr);
} else {
- printf("%s: \n", sc->sc_dev.dv_xname);
- DEVICE_ERROR(sc->sc_dev, ("cannot get device id"));
+ printf("%s: cannot get device id\n", USBDEVNAME(sc->sc_dev));
}
#endif
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
nobulk:
- DEVICE_ERROR(sc->sc_dev, ("could not find bulk endpoint\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: could not find bulk endpoint\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
int
@@ -320,16 +257,7 @@ ulptopen(dev, flag, mode, p)
u_char flags = ULPTFLAGS(dev);
usbd_status r;
int spin, error;
-#if defined(__NetBSD__)
- int unit = ULPTUNIT(dev);
- struct ulpt_softc *sc;
-
- if (unit >= ulpt_cd.cd_ndevs)
- return ENXIO;
- sc = ulpt_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct ulpt_softc *sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev));
-#endif
+ USB_GET_SC_OPEN(ulpt, ULPTUNIT(dev), sc);
if (!sc || !sc->sc_iface)
return ENXIO;
@@ -381,26 +309,12 @@ ulpt_statusmsg(status, sc)
new = status & ~sc->sc_laststatus;
sc->sc_laststatus = status;
-/* XXX should be tidied up into one block and a definition in usb_ports.h
- */
-#if defined(__NetBSD__)
if (new & LPS_SELECT)
- log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
+ log(LOG_NOTICE, "%s: offline\n", USBDEVNAME(sc->sc_dev));
else if (new & LPS_NOPAPER)
- log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
+ log(LOG_NOTICE, "%s: out of paper\n", USBDEVNAME(sc->sc_dev));
else if (new & LPS_NERR)
- log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
-#elif defined(__FreeBSD__)
- if (new & LPS_SELECT)
- log(LOG_NOTICE, "%s%d: offline\n",
- device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev));
- else if (new & LPS_NOPAPER)
- log(LOG_NOTICE, "%s%d: out of paper\n",
- device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev));
- else if (new & LPS_NERR)
- log(LOG_NOTICE, "%s%d: output error\n",
- device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev));
-#endif
+ log(LOG_NOTICE, "%s: output error\n", USBDEVNAME(sc->sc_dev));
return status;
}
@@ -412,16 +326,7 @@ ulptclose(dev, flag, mode, p)
int mode;
struct proc *p;
{
-#if defined(__NetBSD__)
- int unit = ULPTUNIT(dev);
- struct ulpt_softc *sc;
-
- if (unit >= ulpt_cd.cd_ndevs)
- return (ENXIO);
- sc = ulpt_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct ulpt_softc *sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev));
-#endif
+ USB_GET_SC(ulpt, ULPTUNIT(dev), sc);
usbd_close_pipe(sc->sc_bulkpipe);
@@ -442,24 +347,17 @@ ulptwrite(dev, uio, flags)
char buf[ULPT_BSIZE];
usbd_request_handle reqh;
usbd_status r;
-#if defined(__NetBSD__)
- int unit = ULPTUNIT(dev);
- struct ulpt_softc *sc;
-
- if (unit >= ulpt_cd.cd_ndevs)
- return (ENXIO);
- sc = ulpt_cd.cd_devs[unit];
-#elif defined(__FreeBSD__)
- struct ulpt_softc *sc = devclass_get_softc(ulpt_devclass, ULPTUNIT(dev));
-#endif
+ USB_GET_SC(ulpt, ULPTUNIT(dev), sc);
DPRINTF(("ulptwrite\n"));
reqh = usbd_alloc_request();
if (reqh == 0)
- return (EIO);
+ return (ENOMEM);
while ((n = min(ULPT_BSIZE, uio->uio_resid)) != 0) {
ulpt_statusmsg(ulpt_status(sc), sc);
- uiomove(buf, n, uio);
+ error = uiomove(buf, n, uio);
+ if (error)
+ break;
/* XXX use callback to enable interrupt? */
r = usbd_setup_request(reqh, sc->sc_bulkpipe, 0, buf, n,
0, USBD_NO_TIMEOUT, 0);
@@ -499,5 +397,18 @@ ulptioctl(dev, cmd, data, flag, p)
}
#if defined(__FreeBSD__)
-DRIVER_MODULE(ulpt, usb, ulpt_driver, ulpt_devclass, usb_driver_load, 0);
+static int
+ulpt_detach(device_t self)
+{
+ struct ulpt_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+ return 0;
+}
+
+DRIVER_MODULE(ulpt, usb, ulpt_driver, ulpt_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/dev/usb/umodem.c b/sys/dev/usb/umodem.c
index fc1c4c1..7bc43fc 100644
--- a/sys/dev/usb/umodem.c
+++ b/sys/dev/usb/umodem.c
@@ -1,4 +1,4 @@
-/* $NetBSD: umodem.c,v 1.1 1998/12/03 19:58:09 augustss Exp $ */
+/* $NetBSD: umodem.c,v 1.4 1998/12/30 17:46:20 augustss Exp $ */
/* FreeBSD $Id$ */
/*
@@ -38,8 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -65,7 +63,6 @@
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -85,85 +82,31 @@ struct umodem_softc {
usbd_interface_handle sc_iface; /* interface */
};
-#if defined(__NetBSD__)
-int umodem_match __P((struct device *, struct cfdata *, void *));
-void umodem_attach __P((struct device *, struct device *, void *));
-#elif defined(__FreeBSD__)
-static device_probe_t umodem_match;
-static device_attach_t umodem_attach;
-static device_detach_t umodem_detach;
-#endif
-
void umodem_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void umodem_disco __P((void *));
-#if defined(__NetBSD__)
-extern struct cfdriver umodem_cd;
-
-struct cfattach umodem_ca = {
- sizeof(struct umodem_softc), umodem_match, umodem_attach
-};
-#elif defined(__FreeBSD__)
-static devclass_t umodem_devclass;
-
-static device_method_t umodem_methods[] = {
- DEVMETHOD(device_probe, umodem_match),
- DEVMETHOD(device_attach, umodem_attach),
- DEVMETHOD(device_detach, umodem_detach),
- {0,0}
-};
-
-static driver_t umodem_driver = {
- "umodem",
- umodem_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct umodem_softc)
-};
-#endif
+USB_DECLARE_DRIVER(umodem);
-#if defined(__NetBSD__)
-int
-umodem_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(umodem)
{
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-umodem_match(device_t device)
-{
- struct usb_attach_arg *uaa = device_get_ivars(device);
-#endif
+ USB_MATCH_START(umodem, uaa);
usb_interface_descriptor_t *id;
if (!uaa->iface)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
- if (id->bInterfaceClass != UCLASS_CDC ||
- id->bInterfaceSubClass != USUBCLASS_MODEM)
+ if (!id ||
+ id->bInterfaceClass != UCLASS_CDC ||
+ id->bInterfaceSubClass != USUBCLASS_ABSTRACT_CONTROL_MODEL ||
+ id->bInterfaceProtocol != UPROTO_CDC_AT)
return (UMATCH_NONE);
- return (UMATCH_IFACECLASS_IFACESUBCLASS);
+ return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
}
-#if defined(__NetBSD__)
-void
-umodem_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(umodem)
{
- struct umodem_softc *sc = (struct umodem_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-umodem_attach(device_t self)
-{
- struct umodem_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
-#endif
-
+ USB_ATTACH_START(umodem, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
char devinfo[1024];
@@ -171,15 +114,11 @@ umodem_attach(device_t self)
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
-#if defined(__FreeBSD__)
- usb_device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
-#endif
- sc->sc_dev = self;
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
+ devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
- printf(": %s, iclass %d/%d\n", devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
-
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
}
#if defined(__FreeBSD__)
@@ -192,13 +131,12 @@ umodem_detach(device_t self)
if (devinfo) {
device_set_desc(self, NULL);
free(devinfo, M_USB);
- }
+}
return 0;
}
#endif
#if defined(__FreeBSD__)
-DRIVER_MODULE(umodem, usb, umodem_driver, umodem_devclass, usb_driver_load, 0);
+DRIVER_MODULE(umodem, usb, umodem_driver, umodem_devclass, usbd_driver_load, 0);
#endif
-
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index 19aee47..4b3c783 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -1,12 +1,13 @@
-/* $NetBSD: ums.c,v 1.8 1998/08/01 20:11:39 augustss Exp $ */
-/* FreeBSD $Id: ums.c,v 1.3 1998/12/14 09:32:24 n_hibma Exp $ */
+/* $NetBSD: ums.c,v 1.18 1998/12/30 17:46:20 augustss Exp $ */
+/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,8 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -63,7 +62,6 @@
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -79,7 +77,7 @@
#ifdef USB_DEBUG
#define DPRINTF(x) if (umsdebug) printf x
#define DPRINTFN(n,x) if (umsdebug>(n)) printf x
-int umsdebug = 1;
+int umsdebug = 0;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -90,9 +88,9 @@ int umsdebug = 1;
#define PS2LBUTMASK x01
#define PS2RBUTMASK x02
#define PS2MBUTMASK x04
-#define PS2BUTMASK 0x0f
+#define PS2BUTMASK 0x0f
-#define QUEUE_BUFSIZE 240 /* MUST be dividable by 3 _and_ 4 */
+#define QUEUE_BUFSIZE 240 /* MUST be divisible by 3 _and_ 4 */
struct ums_softc {
bdevice sc_dev; /* base device */
@@ -110,7 +108,7 @@ struct ums_softc {
int sc_disconnected; /* device is gone */
int flags; /* device configuration */
-# define UMS_Z 0x01 /* z direction available */
+#define UMS_Z 0x01 /* z direction available */
int nbuttons;
#if defined(__NetBSD__)
@@ -131,17 +129,8 @@ struct ums_softc {
#endif
};
-#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
-#define MOUSE_FLAGS (HIO_RELATIVE)
-
-#if defined(__NetBSD__)
-int ums_match __P((struct device *, struct cfdata *, void *));
-void ums_attach __P((struct device *, struct device *, void *));
-#elif defined(__FreeBSD__)
-static device_probe_t ums_match;
-static device_attach_t ums_attach;
-static device_detach_t ums_detach;
-#endif
+#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
+#define MOUSE_FLAGS (HIO_RELATIVE)
void ums_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void ums_disco __P((void *));
@@ -151,6 +140,13 @@ static void ums_disable __P((void *));
#if defined(__NetBSD__)
static int ums_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
+
+const struct wsmouse_accessops ums_accessops = {
+ ums_enable,
+ ums_ioctl,
+ ums_disable,
+};
+
#elif defined(__FreeBSD__)
static d_open_t ums_open;
static d_close_t ums_close;
@@ -164,57 +160,15 @@ static struct cdevsw ums_cdevsw = {
ums_open, ums_close, ums_read, nowrite,
ums_ioctl, nostop, nullreset, nodevtotty,
ums_poll, nommap,
- NULL, "ums_", NULL, -1
-};
-#endif
-
-#if defined(__NetBSD__)
-const struct wsmouse_accessops ums_accessops = {
- ums_enable,
- ums_ioctl,
- ums_disable,
-};
-#endif
-
-#if defined(__NetBSD__)
-extern struct cfdriver ums_cd;
-
-struct cfattach ums_ca = {
- sizeof(struct ums_softc), ums_match, ums_attach
-};
-#elif defined(__FreeBSD__)
-static devclass_t ums_devclass;
-
-static device_method_t ums_methods[] = {
- DEVMETHOD(device_probe, ums_match),
- DEVMETHOD(device_attach, ums_attach),
- DEVMETHOD(device_detach, ums_detach),
- {0,0}
-};
-
-static driver_t ums_driver = {
- "ums",
- ums_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct ums_softc)
+ NULL, "ums", NULL, -1
};
#endif
+USB_DECLARE_DRIVER(ums);
-#if defined(__NetBSD__)
-int
-ums_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
-{
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ums_match(device_t device)
+USB_MATCH(ums)
{
- struct usb_attach_arg *uaa = device_get_ivars(device);
-#endif
+ USB_MATCH_START(ums, uaa);
usb_interface_descriptor_t *id;
int size, ret;
void *desc;
@@ -223,7 +177,7 @@ ums_match(device_t device)
if (!uaa->iface)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
- if (id->bInterfaceClass != UCLASS_HID)
+ if (!id || id->bInterfaceClass != UCLASS_HID)
return (UMATCH_NONE);
r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP);
@@ -240,108 +194,77 @@ ums_match(device_t device)
return (ret);
}
-#if defined(__NetBSD__)
-void
-ums_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
-{
- struct ums_softc *sc = (struct ums_softc *)self;
- struct usb_attach_arg *uaa = aux;
-#elif defined(__FreeBSD__)
-static int
-ums_attach(device_t self)
+USB_ATTACH(ums)
{
- struct ums_softc *sc = device_get_softc(self);
- struct usb_attach_arg *uaa = device_get_ivars(self);
-#endif
+ USB_ATTACH_START(ums, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
#if defined(__NetBSD__)
struct wsmousedev_attach_args a;
#endif
- char devinfo[1024];
int size;
void *desc;
usbd_status r;
+ char devinfo[1024];
u_int32_t flags;
- struct hid_location loc_btn;
int i;
+ struct hid_location loc_btn;
sc->sc_disconnected = 1;
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
-#if defined(__FreeBSD__)
- usb_device_set_desc(self, devinfo);
- printf("%s%d", device_get_name(self), device_get_unit(self));
-#endif
- printf(": %s (interface class %d/%d)\n", devinfo,
- id->bInterfaceClass, id->bInterfaceSubClass);
- sc->sc_dev = self;
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
+ devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (!ed) {
- DEVICE_ERROR(sc->sc_dev, ("could not read endpoint descriptor\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: could not read endpoint descriptor\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
DPRINTFN(10,("ums_attach: bLength=%d bDescriptorType=%d "
- "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d "
- "bInterval=%d\n",
- ed->bLength, ed->bDescriptorType, ed->bEndpointAddress & UE_ADDR,
- ed->bEndpointAddress & UE_IN ? "in" : "out",
- ed->bmAttributes & UE_XFERTYPE,
- UGETW(ed->wMaxPacketSize), ed->bInterval));
+ "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
+ " bInterval=%d\n",
+ ed->bLength, ed->bDescriptorType,
+ ed->bEndpointAddress & UE_ADDR,
+ ed->bEndpointAddress & UE_IN ? "in" : "out",
+ ed->bmAttributes & UE_XFERTYPE,
+ UGETW(ed->wMaxPacketSize), ed->bInterval));
if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
- DEVICE_ERROR(sc->sc_dev, ("unexpected endpoint\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: unexpected endpoint\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP);
if (r != USBD_NORMAL_COMPLETION)
- ATTACH_ERROR_RETURN;
+ USB_ATTACH_ERROR_RETURN;
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
hid_input, &sc->sc_loc_x, &flags)) {
- DEVICE_ERROR(sc->sc_dev, ("mouse has no X report\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: mouse has no X report\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+ if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ printf("%s: X report 0x%04x not supported\n",
+ USBDEVNAME(sc->sc_dev), flags);
+ USB_ATTACH_ERROR_RETURN;
}
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS)
- DEVICE_ERROR(sc->sc_dev, ("X report 0x%04x not supported\n",
- flags));
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
hid_input, &sc->sc_loc_y, &flags)) {
- DEVICE_ERROR(sc->sc_dev, ("mouse has no Y report\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: mouse has no Y report\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS)
- DEVICE_ERROR(sc->sc_dev, ("Y report 0x%04x not supported\n",
- flags));
-
-#ifndef USBVERBOSE
- if (bootverbose)
-#endif
- {
- if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
- hid_input, &sc->sc_loc_z, &flags))
- DEVICE_MSG(sc->sc_dev, ("Device has Z axis\n"));
- if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_SLIDER),
- hid_input, &sc->sc_loc_z, &flags))
- DEVICE_MSG(sc->sc_dev, ("Device has Slider\n"));
- if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_DIAL),
- hid_input, &sc->sc_loc_z, &flags))
- DEVICE_MSG(sc->sc_dev, ("Device has Dial\n"));
- if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
- hid_input, &sc->sc_loc_z, &flags))
- DEVICE_MSG(sc->sc_dev, ("Device has Wheel\n"));
- if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_HAT_SWITCH),
- hid_input, &sc->sc_loc_z, &flags))
- DEVICE_MSG(sc->sc_dev, ("Device has Hat Switch\n"));
+ if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ printf("%s: Y report 0x%04x not supported\n",
+ USBDEVNAME(sc->sc_dev), flags);
+ USB_ATTACH_ERROR_RETURN;
}
/* try to guess the Z activator: first check Z, then WHEEL */
@@ -351,13 +274,8 @@ ums_attach(device_t self)
hid_input, &sc->sc_loc_z, &flags)) {
if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
-#if !defined(__FreeBSD__) /* FIXME */
- /* IntelliMouse protocol is not properly implemented yet.
- * Probably the wisest to use the sysmouse protocol
- */
} else {
sc->flags |= UMS_Z;
-#endif
}
}
@@ -367,15 +285,13 @@ ums_attach(device_t self)
hid_input, &loc_btn, 0))
break;
sc->nbuttons = i - 1;
- sc->sc_loc_btn = malloc(sizeof(struct hid_location)*sc->nbuttons, M_USBDEV, M_NOWAIT);
+ sc->sc_loc_btn = malloc(sizeof(struct hid_location)*sc->nbuttons,
+ M_USBDEV, M_NOWAIT);
if (!sc->sc_loc_btn)
- ATTACH_ERROR_RETURN;
+ USB_ATTACH_ERROR_RETURN;
-#ifndef USBVERBOSE
- if (bootverbose)
-#endif
- DEVICE_MSG(sc->sc_dev, ("%d buttons%s\n",
- sc->nbuttons, (sc->flags & UMS_Z? " and Z dir.":"")));
+ printf("%s: %d buttons%s\n", USBDEVNAME(sc->sc_dev),
+ sc->nbuttons, (sc->flags & UMS_Z? " and Z dir." : ""));
for (i = 1; i <= sc->nbuttons; i++)
hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
@@ -385,7 +301,7 @@ ums_attach(device_t self)
sc->sc_ibuf = malloc(sc->sc_isize, M_USB, M_NOWAIT);
if (!sc->sc_ibuf) {
free(sc->sc_loc_btn, M_USB);
- ATTACH_ERROR_RETURN;
+ USB_ATTACH_ERROR_RETURN;
}
sc->sc_ep_addr = ed->bEndpointAddress;
@@ -444,7 +360,7 @@ ums_attach(device_t self)
sc->rsel.si_pid = 0;
#endif
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
}
@@ -488,6 +404,11 @@ ums_intr(reqh, addr, status)
int dx, dy, dz;
u_char buttons = 0;
int i;
+#if defined(__NetBSD__)
+#define UMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i)
+#elif defined(__FreeBSD__)
+#define UMS_BUT(i) (i)
+#endif
DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status));
DPRINTFN(5, ("ums_intr: data = %02x %02x %02x\n",
@@ -513,9 +434,9 @@ ums_intr(reqh, addr, status)
/* NWH Why are you modifying the button assignments here?
* That's the purpose of a high level mouse driver
*/
- for (i = 1; i <= sc->nbuttons; i++)
- if (hid_get_data(ibuf, &sc->sc_loc_btn[i-1]))
- buttons |= (1 << (i-1));
+ for (i = 0; i < sc->nbuttons; i++)
+ if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
+ buttons |= (1 << UMS_BUT(i));
#if defined(__NetBSD__)
if (dx || dy || buttons != sc->sc_buttons) {
@@ -559,14 +480,18 @@ ums_intr(reqh, addr, status)
}
#ifdef USB_DEBUG
if (sc->qhead > sizeof(sc->qbuf))
- DPRINTF(("Buffer overrun! %d %d\n", sc->qhead, sizeof(sc->qbuf)));
+ DPRINTF(("Buffer overrun! %d %d\n",
+ sc->qhead, sizeof(sc->qbuf)));
#endif
- if (sc->qhead >= sizeof(sc->qbuf)) /* wrap round at end of buffer */
+ /* wrap round at end of buffer */
+ if (sc->qhead >= sizeof(sc->qbuf))
sc->qhead = 0;
- if (sc->state & UMS_ASLEEP) /* someone waiting for data */
+ /* someone waiting for data */
+ if (sc->state & UMS_ASLEEP)
wakeup(sc);
- selwakeup(&sc->rsel); /* wake up any pending selects */
+ /* wake up any pending selects */
+ selwakeup(&sc->rsel);
sc->state &= ~UMS_SELECT;
#endif
}
@@ -592,7 +517,7 @@ ums_enable(v)
sc->qhead = sc->qtail = 0;
#ifdef USB_DEBUG
if (sizeof(sc->qbuf) % 4 || sizeof(sc->qbuf) % 3) {
- DPRINTF(("Buffer size not dividable by 3 or 4\n"));
+ DPRINTF(("Buffer size not divisible by 3 or 4\n"));
return ENXIO;
}
#endif
@@ -645,11 +570,11 @@ ums_ioctl(v, cmd, data, flag, p)
{
switch (cmd) {
case WSMOUSEIO_GTYPE:
- *(u_int *)data = WSMOUSE_TYPE_PS2;
+ *(u_int *)data = WSMOUSE_TYPE_USB;
return (0);
}
- return (-1); /* NWH XXX Should we not return something ? */
+ return (-1);
}
#elif defined(__FreeBSD__)
@@ -808,6 +733,5 @@ ums_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
#if defined(__FreeBSD__)
CDEV_DRIVER_MODULE(ums, usb, ums_driver, ums_devclass,
- UMS_CDEV_MAJOR, ums_cdevsw, usb_driver_load, 0);
+ UMS_CDEV_MAJOR, ums_cdevsw, usbd_driver_load, 0);
#endif
-
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index ad6d067..8af8da3 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,12 +1,13 @@
-/* $NetBSD: usb.c,v 1.3 1998/08/01 18:16:20 augustss Exp $ */
+/* $NetBSD: usb.c,v 1.10 1999/01/03 01:00:56 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -38,19 +39,18 @@
*/
/*
- * USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl
- * More USB specs at http://www.usb.org/developers/index.shtml
+ * USB specifications and other documentation can be found at
+ * http://www.usb.org/developers/data/ and
+ * http://www.usb.org/developers/index.html .
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#if defined(__NetBSD__)
#include <sys/device.h>
-#else
+#elif defined(__FreeBSD__)
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/ioccom.h>
@@ -66,22 +66,20 @@
#if defined(__FreeBSD__)
MALLOC_DEFINE(M_USB, "USB", "USB");
MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
-#endif
+
+#include "usb_if.h"
+#endif /* defined(__FreeBSD__) */
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_quirks.h>
-#if defined(__FreeBSD__)
-#include "usb_if.h"
-#endif
-
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) printf x
#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
-int usbdebug = 2;
-int uhcidebug = 2;
-int ohcidebug = 2;
+int usbdebug = 0;
+int uhcidebug;
+int ohcidebug;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -90,7 +88,7 @@ int ohcidebug = 2;
#define USBUNIT(dev) (minor(dev))
struct usb_softc {
- bdevice sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_bus_handle sc_bus; /* USB controller */
struct usbd_port sc_port; /* dummy port for root hub */
char sc_running;
@@ -99,19 +97,12 @@ struct usb_softc {
};
#if defined(__NetBSD__)
-int usb_match __P((struct device *, struct cfdata *, void *));
-void usb_attach __P((struct device *, struct device *, void *));
-
int usbopen __P((dev_t, int, int, struct proc *));
int usbclose __P((dev_t, int, int, struct proc *));
int usbioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
int usbpoll __P((dev_t, int, struct proc *));
-#else
-static device_probe_t usb_match;
-static device_attach_t usb_attach;
-static bus_print_child_t usb_print_child;
-
+#elif defined(__FreeBSD__)
d_open_t usbopen;
d_close_t usbclose;
d_ioctl_t usbioctl;
@@ -120,77 +111,36 @@ int usbpoll __P((dev_t, int, struct proc *));
struct cdevsw usb_cdevsw = {
usbopen, usbclose, noread, nowrite,
usbioctl, nullstop, nullreset, nodevtotty,
- seltrue, nommap, nostrat,
+ usbpoll, nommap, nostrat,
"usb", NULL, -1
};
#endif
usbd_status usb_discover __P((struct usb_softc *));
-#if defined(__NetBSD__)
-extern struct cfdriver usb_cd;
-
-struct cfattach usb_ca = {
- sizeof(struct usb_softc), usb_match, usb_attach
-};
-#else
-static devclass_t usb_devclass = NULL;
-
-static device_method_t usb_methods[] = {
- DEVMETHOD(device_probe, usb_match),
- DEVMETHOD(device_attach, usb_attach),
-
- DEVMETHOD(bus_print_child, usb_print_child),
- {0, 0}
-};
-
-static driver_t usb_driver = {
- "usb",
- usb_methods,
- DRIVER_TYPE_MISC,
- sizeof(struct usb_softc),
-};
-#endif
+USB_DECLARE_DRIVER_INIT(usb, DEVMETHOD(bus_print_child, usbd_print_child));
-#if defined(__NetBSD__)
-int
-usb_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
-#else
-static int
-usb_match(device_t device)
-#endif
+USB_MATCH(usb)
{
DPRINTF(("usbd_match\n"));
-#if defined(__NetBSD__)
- return (1);
-#else
- return (0);
-#endif
+ return (UMATCH_GENERIC);
}
-#if defined(__NetBSD__)
-void
-usb_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(usb)
{
+#if defined(__NetBSD__)
struct usb_softc *sc = (struct usb_softc *)self;
-#else
-static int
-usb_attach(device_t device)
-{
- struct usb_softc *sc = device_get_softc(device);
- void *aux = device_get_ivars(device);
+#elif defined(__FreeBSD__)
+ struct usb_softc *sc = device_get_softc(self);
+ void *aux = device_get_ivars(self);
#endif
usbd_device_handle dev;
usbd_status r;
-
+
#if defined(__NetBSD__)
printf("\n");
+#elif defined(__FreeBSD__)
+ sc->sc_dev = self;
#endif
DPRINTF(("usbd_attach\n"));
@@ -200,27 +150,26 @@ usb_attach(device_t device)
sc->sc_running = 1;
sc->sc_bus->use_polling = 1;
sc->sc_port.power = USB_MAX_POWER;
-#if defined(__FreeBSD__)
- sc->sc_dev = device;
-#endif
r = usbd_new_device(&sc->sc_dev, sc->sc_bus, 0, 0, 0, &sc->sc_port);
if (r == USBD_NORMAL_COMPLETION) {
dev = sc->sc_port.device;
if (!dev->hub) {
sc->sc_running = 0;
- DEVICE_ERROR(sc->sc_dev, ("root device is not a hub\n"));
- ATTACH_ERROR_RETURN;
+ printf("%s: root device is not a hub\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
sc->sc_bus->root_hub = dev;
dev->hub->explore(sc->sc_bus->root_hub);
} else {
- DEVICE_ERROR(sc->sc_dev, ("root hub problem, error=%d\n", r));
+ printf("%s: root hub problem, error=%d\n",
+ USBDEVNAME(sc->sc_dev), r);
sc->sc_running = 0;
}
sc->sc_bus->use_polling = 0;
- ATTACH_SUCCESS_RETURN;
+ USB_ATTACH_SUCCESS_RETURN;
}
#if defined(__NetBSD__)
@@ -235,94 +184,6 @@ usbctlprint(aux, pnp)
return (UNCONF);
}
-
-#else
-static void
-usb_print_child(device_t parent, device_t child)
-{
- struct usb_softc *sc = device_get_softc(child);
-
- printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
-
- /* How do we get to the usbd_device_handle???
- usbd_device_handle dev = invalidadosch;
-
- printf(" addr %d", dev->addr);
-
- if (bootverbose) {
- if (dev->lowspeed)
- printf(", lowspeed");
- if (dev->self_powered)
- printf(", self powered");
- else
- printf(", %dmA", dev->power);
- printf(", config %d", dev->config);
- }
- */
-}
-
-/* Reconfigure all the USB busses in the system
- */
-
-int
-usb_driver_load(module_t mod, int what, void *arg)
-{
- /* subroutine is there but inactive at the moment
- * the reconfiguration process has not been thought through yet.
- */
- devclass_t ugen_devclass = devclass_find("ugen");
- device_t *devlist;
- int devcount;
- int error;
-
- switch (what) {
- case MOD_LOAD:
- case MOD_UNLOAD:
- if (!usb_devclass)
- return 0; /* just ignore call */
-
- if (ugen_devclass) {
- /* detach devices from generic driver if possible
- */
- error = devclass_get_devices(ugen_devclass, &devlist,
- &devcount);
- if (!error)
- for (devcount--; devcount >= 0; devcount--)
- (void) DEVICE_DETACH(devlist[devcount]);
- }
-
- error = devclass_get_devices(usb_devclass, &devlist, &devcount);
- if (error)
- return 0; /* XXX maybe transient, or error? */
-
- for (devcount--; devcount >= 0; devcount--)
- USB_RECONFIGURE(devlist[devcount]);
-
- free(devlist, M_TEMP);
- return 0;
- }
-
- return 0; /* nothing to do by us */
-}
-
-/* Set the description of the device including a malloc and copy
- */
-void
-usb_device_set_desc(device_t device, char *devinfo)
-{
- size_t l;
- char *desc;
-
- if ( devinfo ) {
- l = strlen(devinfo);
- desc = malloc(l+1, M_USB, M_NOWAIT);
- if (desc)
- memcpy(desc, devinfo, l+1);
- } else
- desc = NULL;
-
- device_set_desc(device, desc);
-}
#endif
int
@@ -331,17 +192,7 @@ usbopen(dev, flag, mode, p)
int flag, mode;
struct proc *p;
{
-#if defined(__NetBSD__)
- int unit = USBUNIT(dev);
- struct usb_softc *sc;
-
- if (unit >= usb_cd.cd_ndevs)
- return (ENXIO);
- sc = usb_cd.cd_devs[unit];
-#else
- device_t device = devclass_get_device(usb_devclass, USBUNIT(dev));
- struct usb_softc *sc = device_get_softc(device);
-#endif
+ USB_GET_SC_OPEN(usb, USBUNIT(dev), sc);
if (sc == 0 || !sc->sc_running)
return (ENXIO);
@@ -366,17 +217,7 @@ usbioctl(dev, cmd, data, flag, p)
int flag;
struct proc *p;
{
-#if defined(__NetBSD__)
- int unit = USBUNIT(dev);
- struct usb_softc *sc;
-
- if (unit >= usb_cd.cd_ndevs)
- return (ENXIO);
- sc = usb_cd.cd_devs[unit];
-#else
- device_t device = devclass_get_device(usb_devclass, USBUNIT(dev));
- struct usb_softc *sc = device_get_softc(device);
-#endif
+ USB_GET_SC(usb, USBUNIT(dev), sc);
if (sc == 0 || !sc->sc_running)
return (ENXIO);
@@ -400,11 +241,12 @@ usbioctl(dev, cmd, data, flag, p)
usbd_status r;
int error = 0;
+ DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
if (len < 0 || len > 32768)
- return EINVAL;
+ return (EINVAL);
if (addr < 0 || addr >= USB_MAX_DEVICES ||
sc->sc_bus->devices[addr] == 0)
- return EINVAL;
+ return (EINVAL);
if (len != 0) {
iov.iov_base = (caddr_t)ur->data;
iov.iov_len = len;
@@ -424,8 +266,9 @@ usbioctl(dev, cmd, data, flag, p)
goto ret;
}
}
- r = usbd_do_request(sc->sc_bus->devices[addr],
- &ur->request, ptr);
+ r = usbd_do_request_flags(sc->sc_bus->devices[addr],
+ &ur->request, ptr,
+ ur->flags, &ur->actlen);
if (r) {
error = EIO;
goto ret;
@@ -441,7 +284,6 @@ usbioctl(dev, cmd, data, flag, p)
if (ptr)
free(ptr, M_TEMP);
return (error);
- break;
}
case USB_DEVICEINFO:
@@ -449,44 +291,13 @@ usbioctl(dev, cmd, data, flag, p)
struct usb_device_info *di = (void *)data;
int addr = di->addr;
usbd_device_handle dev;
- struct usbd_port *p;
- int i, r, s;
if (addr < 1 || addr >= USB_MAX_DEVICES)
return (EINVAL);
dev = sc->sc_bus->devices[addr];
if (dev == 0)
return (ENXIO);
- di->config = dev->config;
- usbd_devinfo_vp(dev, di->product, di->vendor);
- usbd_printBCD(di->revision, UGETW(dev->ddesc.bcdDevice));
- di->class = dev->ddesc.bDeviceClass;
- di->power = dev->self_powered ? 0 : dev->power;
- di->lowspeed = dev->lowspeed;
- if (dev->hub) {
- for (i = 0;
- i < sizeof(di->ports) / sizeof(di->ports[0]) &&
- i < dev->hub->hubdesc.bNbrPorts;
- i++) {
- p = &dev->hub->ports[i];
- if (p->device)
- r = p->device->address;
- else {
- s = UGETW(p->status.wPortStatus);
- if (s & UPS_PORT_ENABLED)
- r = USB_PORT_ENABLED;
- else if (s & UPS_SUSPEND)
- r = USB_PORT_SUSPENDED;
- else if (s & UPS_PORT_POWER)
- r = USB_PORT_POWERED;
- else
- r = USB_PORT_DISABLED;
- }
- di->ports[i] = r;
- }
- di->nports = dev->hub->hubdesc.bNbrPorts;
- } else
- di->nports = 0;
+ usbd_fill_deviceinfo(dev, di);
break;
}
@@ -507,17 +318,7 @@ usbpoll(dev, events, p)
struct proc *p;
{
int revents, s;
-#if defined(__NetBSD__)
- int unit = USBUNIT(dev);
- struct usb_softc *sc;
-
- if (unit >= usb_cd.cd_ndevs)
- return (ENXIO);
- sc = usb_cd.cd_devs[unit];
-#else
- device_t device = devclass_get_device(usb_devclass, USBUNIT(dev));
- struct usb_softc *sc = device_get_softc(device);
-#endif
+ USB_GET_SC(usb, USBUNIT(dev), sc);
DPRINTFN(2, ("usbpoll: sc=%p events=0x%x\n", sc, events));
s = splusb();
@@ -537,8 +338,6 @@ usbpoll(dev, events, p)
}
#if defined(__NetBSD__)
-/* See remarks on this in usbdi.c
- */
int
usb_bus_count()
{
@@ -600,5 +399,19 @@ usb_needs_explore(bus)
}
#if defined(__FreeBSD__)
+int
+usb_detach(device_t self)
+{
+ struct usb_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+
+ return (0);
+}
+
DRIVER_MODULE(usb, root, usb_driver, usb_devclass, 0, 0);
#endif
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index a6696cc..dae44ba 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,12 +1,13 @@
-/* $NetBSD: usb.h,v 1.3 1998/07/25 15:22:11 augustss Exp $ */
-/* FreeBSD $Id: usb.h,v 1.3 1998/12/14 09:32:24 n_hibma Exp $ */
+/* $NetBSD: usb.h,v 1.17 1999/01/03 01:09:18 augustss Exp $ */
+/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,14 +47,22 @@
#include <sys/ioctl.h>
#endif
-#if defined(__FreeBSD__)
+#if defined(__NetBSD__)
+#if defined(_KERNEL)
+#include <dev/usb/usb_port.h>
+#endif /* _KERNEL */
+
+#elif defined(__FreeBSD__)
#include <sys/malloc.h>
#if defined(KERNEL)
MALLOC_DECLARE(M_USB);
MALLOC_DECLARE(M_USBDEV);
-#endif
-#endif
+
+#include <dev/usb/usb_port.h>
+#endif /* KERNEL */
+#endif /* __FreeBSD__ */
+
#define USB_MAX_DEVICES 128
#define USB_START_ADDR 0
@@ -61,6 +70,8 @@ MALLOC_DECLARE(M_USBDEV);
#define USB_CONTROL_ENDPOINT 0
#define USB_MAX_ENDPOINTS 16
+#define USB_FRAMES_PER_SECOND 1000
+
/*
* The USB records contain some unaligned little-endian word
* components. The U[SG]ETW macros take care of both the alignment
@@ -72,6 +83,12 @@ typedef u_int8_t uWord[2];
#define UGETW(w) ((w)[0] | ((w)[1] << 8))
#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
+typedef u_int8_t uDWord[4];
+#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
+#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
+ (w)[1] = (u_int8_t)((v) >> 8), \
+ (w)[2] = (u_int8_t)((v) >> 16), \
+ (w)[3] = (u_int8_t)((v) >> 24))
/*
* On little-endian machines that can handle unanliged accesses
* (e.g. i386) these macros can be replaced by the following.
@@ -111,6 +128,12 @@ typedef struct {
#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE)
#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER)
+#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE)
+#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE)
+#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER)
+#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
+#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
+#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER)
/* Requests */
#define UR_GET_STATUS 0x00
@@ -131,7 +154,7 @@ typedef struct {
#define UR_SYNCH_FRAME 0x0c
/* Feature numbers */
-#define UF_ENDPOINT_STALL 0
+#define UF_ENDPOINT_HALT 0
#define UF_DEVICE_REMOTE_WAKEUP 1
#define USB_MAX_IPACKET 8 /* maximum size of the initial packet */
@@ -197,13 +220,18 @@ typedef struct {
#define UE_IN 0x80
#define UE_OUT 0x00
#define UE_ADDR 0x0f
+#define UE_GET_ADDR(a) ((a) & UE_ADDR)
#define UE_GET_IN(a) (((a) >> 7) & 1)
uByte bmAttributes;
-#define UE_CONTROL 0x00
-#define UE_ISOCHRONOUS 0x01
-#define UE_BULK 0x02
-#define UE_INTERRUPT 0x03
#define UE_XFERTYPE 0x03
+#define UE_CONTROL 0x00
+#define UE_ISOCHRONOUS 0x01
+#define UE_BULK 0x02
+#define UE_INTERRUPT 0x03
+#define UE_ISO_TYPE 0x0c
+#define UE_ISO_ASYNC 0x04
+#define UE_ISO_ADAPT 0x08
+#define UE_ISO_SYNC 0x0c
uWord wMaxPacketSize;
uByte bInterval;
} usb_endpoint_descriptor_t;
@@ -215,6 +243,7 @@ typedef struct {
uWord bString[127];
} usb_string_descriptor_t;
#define USB_MAX_STRING_LEN 128
+#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */
/* Hub specific request */
#define UR_GET_BUS_STATE 0x02
@@ -239,7 +268,7 @@ typedef struct {
uByte bDescLength;
uByte bDescriptorType;
uByte bNbrPorts;
- uWord bHubCharacteristics;
+ uWord wHubCharacteristics;
#define UHD_PWR 0x03
#define UHD_PWR_GANGED 0x00
#define UHD_PWR_INDIVIDUAL 0x01
@@ -252,17 +281,20 @@ typedef struct {
uByte bPwrOn2PwrGood; /* delay in 2 ms units */
#define UHD_PWRON_FACTOR 2
uByte bHubContrCurrent;
- uByte DeviceRemovable[1];
- /* this is only correct with 1-7 ports on the hub */
- uByte PortPowerCtrlMask[3];
+ uByte DeviceRemovable[32]; /* max 255 ports */
+#define UHD_NOT_REMOV(desc, i) \
+ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
+ /* deprecated uByte PortPowerCtrlMask[]; */
} usb_hub_descriptor_t;
-#define USB_HUB_DESCRIPTOR_SIZE 9
+#define USB_HUB_DESCRIPTOR_SIZE 8
typedef struct {
uWord wStatus;
/* Device status flags */
#define UDS_SELF_POWERED 0x0001
#define UDS_REMOTE_WAKEUP 0x0002
+/* Endpoint status flags */
+#define UES_HALT 0x0001
} usb_status_t;
typedef struct {
@@ -301,8 +333,9 @@ typedef struct {
#define UCLASS_AUDIO 1
#define USUBCLASS_AUDIOCONTROL 1
#define USUBCLASS_AUDIOSTREAM 2
-#define UCLASS_CDC 2
-#define USUBCLASS_MODEM 2
+#define UCLASS_CDC 2 /* communication */
+#define USUBCLASS_ABSTRACT_CONTROL_MODEL 2
+#define UPROTO_CDC_AT 1
#define UCLASS_HID 3
#define USUBCLASS_BOOT 1
#define UCLASS_PRINTER 7
@@ -310,20 +343,38 @@ typedef struct {
#define UPROTO_PRINTER_UNI 1
#define UPROTO_PRINTER_BI 2
#define UCLASS_HUB 9
-#define USUBCLASS_HUB 1
+#define USUBCLASS_HUB 0
+#define UCLASS_DATA 10
#define USB_HUB_MAX_DEPTH 5
+/*
+ * Minimum time a device needs to be powered down to go through
+ * a power cycle. XXX Are these time in the spec?
+ */
+#define USB_POWER_DOWN_TIME 200 /* ms */
+#define USB_PORT_POWER_DOWN_TIME 100 /* ms */
+
+#if 0
+/* These are the values from the spec. */
#define USB_PORT_RESET_DELAY 10 /* ms */
+#define USB_PORT_RESET_SETTLE 10 /* ms */
#define USB_PORT_POWERUP_DELAY 100 /* ms */
-#define USB_POWER_SETTLE 100 /* ms */
+#define USB_SET_ADDRESS_SETTLE 2 /* ms */
+#else
+/* Allow for marginal (i.e. non-conforming) devices. */
+#define USB_PORT_RESET_DELAY 20 /* ms */
+#define USB_PORT_RESET_RECOVERY 50 /* ms */
+#define USB_PORT_POWERUP_DELAY 200 /* ms */
+#define USB_SET_ADDRESS_SETTLE 10 /* ms */
+#endif
#define USB_MIN_POWER 100 /* mA */
#define USB_MAX_POWER 500 /* mA */
-#define USB_RESET_DELAY 100 /* ms XXX?*/
-#define USB_RESUME_DELAY 10 /* ms XXX?*/
+#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/
+#define USB_RESUME_DELAY 10 /* ms XXX?*/
/*** ioctl() related stuff ***/
@@ -331,10 +382,51 @@ struct usb_ctl_request {
int addr;
usb_device_request_t request;
void *data;
+ int flags;
+/* XXX must match flags in usbdi.h */
+#define USBD_SHORT_XFER_OK 0x04
+ int actlen;
};
-struct usb_all_desc {
- u_char data[1024]; /* filled data size will vary */
+struct usb_alt_interface {
+ int config_index;
+ int interface_index;
+ int alt_no;
+};
+
+#define USB_CURRENT_CONFIG_INDEX (-1)
+#define USB_CURRENT_ALT_INDEX (-1)
+
+struct usb_config_desc {
+ int config_index;
+ usb_config_descriptor_t desc;
+};
+
+struct usb_interface_desc {
+ int config_index;
+ int interface_index;
+ int alt_index;
+ usb_interface_descriptor_t desc;
+};
+
+struct usb_endpoint_desc {
+ int config_index;
+ int interface_index;
+ int alt_index;
+ int endpoint_index;
+ usb_endpoint_descriptor_t desc;
+};
+
+struct usb_full_desc {
+ int config_index;
+ u_int size;
+ u_char *data;
+};
+
+struct usb_string_desc {
+ int string_index;
+ int language_id;
+ usb_string_descriptor_t desc;
};
struct usb_ctl_report_desc {
@@ -343,16 +435,18 @@ struct usb_ctl_report_desc {
};
struct usb_device_info {
- uByte addr; /* device address */
- char product[USB_MAX_STRING_LEN];
- char vendor[USB_MAX_STRING_LEN];
- char revision[8];
- uByte class;
- uByte config;
- uByte lowspeed;
- int power; /* power consumption in mA, 0 if selfpowered */
- int nports;
- uByte ports[16]; /* hub only: addresses of devices on ports */
+ u_int8_t addr; /* device address */
+ char product[USB_MAX_STRING_LEN];
+ char vendor[USB_MAX_STRING_LEN];
+ char revision[8];
+ u_int16_t productNo;
+ u_int16_t vendorNo;
+ u_int8_t class;
+ u_int8_t config;
+ u_int8_t lowspeed;
+ int power; /* power consumption in mA, 0 if selfpowered */
+ int nports;
+ u_int8_t ports[16];/* hub only: addresses of devices on ports */
#define USB_PORT_ENABLED 0xff
#define USB_PORT_SUSPENDED 0xfe
#define USB_PORT_POWERED 0xfd
@@ -381,12 +475,19 @@ struct usb_device_stats {
#define USB_GET_REPORT _IOWR('U', 23, struct usb_ctl_report)
/* Generic USB device */
-#define USB_SET_CONFIG _IOW ('U', 100, int)
-#define USB_SET_INTERFACE _IOW ('U', 101, int)
-#define USB_GET_DEVICE_DESC _IOR ('U', 102, usb_device_descriptor_t)
-#define USB_GET_CONFIG_DESC _IOR ('U', 103, usb_config_descriptor_t)
-#define USB_GET_INTERFACE_DESC _IOR ('U', 104, usb_interface_descriptor_t)
-#define USB_GET_ALL_DESC _IOR ('U', 105, struct usb_all_desc)
-
+#define USB_GET_CONFIG _IOR ('U', 100, int)
+#define USB_SET_CONFIG _IOW ('U', 101, int)
+#define USB_GET_ALTINTERFACE _IOWR('U', 102, struct usb_alt_interface)
+#define USB_SET_ALTINTERFACE _IOWR('U', 103, struct usb_alt_interface)
+#define USB_GET_NO_ALT _IOWR('U', 104, struct usb_alt_interface)
+#define USB_GET_DEVICE_DESC _IOR ('U', 105, usb_device_descriptor_t)
+#define USB_GET_CONFIG_DESC _IOWR('U', 106, struct usb_config_desc)
+#define USB_GET_INTERFACE_DESC _IOWR('U', 107, struct usb_interface_desc)
+#define USB_GET_ENDPOINT_DESC _IOWR('U', 108, struct usb_endpoint_desc)
+#define USB_GET_FULL_DESC _IOWR('U', 109, struct usb_full_desc)
+#define USB_GET_STRING_DESC _IOWR('U', 110, struct usb_string_desc)
+#define USB_DO_REQUEST _IOWR('U', 111, struct usb_ctl_request)
+#define USB_GET_DEVICEINFO _IOR ('U', 112, struct usb_device_info)
+#define USB_SET_SHORT_XFER _IOW ('U', 113, int)
#endif /* _USB_H_ */
diff --git a/sys/dev/usb/usb_if.m b/sys/dev/usb/usb_if.m
index f9cb673..fa5649c 100644
--- a/sys/dev/usb/usb_if.m
+++ b/sys/dev/usb/usb_if.m
@@ -1,3 +1,33 @@
+#
+# Copyright (c) 1992-1998 Nick Hibma <hibma@skylink.it>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer,
+# without modification, immediately at the beginning of the file.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $Id$
+#
+
# USB interface description
#
diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h
index fd1576d..8a49b29 100644
--- a/sys/dev/usb/usb_mem.h
+++ b/sys/dev/usb/usb_mem.h
@@ -1,12 +1,13 @@
-/* $NetBSD: usb_mem.h,v 1.1 1998/07/24 21:09:08 augustss Exp $ */
+/* $NetBSD: usb_mem.h,v 1.3 1998/12/26 12:53:03 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -61,9 +62,10 @@ typedef struct {
usbd_status usb_allocmem __P((bus_dma_tag_t, size_t, size_t, usb_dma_t *));
void usb_freemem __P((bus_dma_tag_t, usb_dma_t *));
-#else
+#elif defined(__FreeBSD__)
-/* FreeBSD does not have special functions for dma memory, so let's keep it
+/*
+ * FreeBSD does not have special functions for dma memory, so let's keep it
* simple for now.
*/
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index 4a5e06f..b544a20 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -1,8 +1,13 @@
+/* $NetBSD$ */
/* FreeBSD $Id$ */
/*
- * Copyright (c) 1997, 1998
- * Nick Hibma <n_hibma@freebsd.org>. All rights reserved.
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -14,23 +19,23 @@
* 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 Bill Paul.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * 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.
*
- * THIS SOFTWARE IS PROVIDED BY NICK HIBMA AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/* Macro's to cope with the differences between NetBSD and FreeBSD
@@ -38,72 +43,176 @@
/*
* NetBSD
- *
*/
#if defined(__NetBSD__)
#include "opt_usbverbose.h"
-#define DEVICE_NAME(bdev) \
- printf("%s: ", (bdev).dv_xname)
+#define USBDEVNAME(bdev) ((bdev).dv_xname)
typedef struct device bdevice; /* base device */
+#define usb_timeout(f, d, t, h) timeout((f), (d), (t))
+#define usb_untimeout(f, d, h) untimeout((f), (d))
+#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2...) \
+int __CONCAT(dname,_match) __P((struct device *, struct cfdata *, void *)); \
+void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \
+\
+extern struct cfdriver __CONCAT(dname,_cd); \
+\
+struct cfattach __CONCAT(dname,_ca) = { \
+ sizeof(struct __CONCAT(dname,_softc)), \
+ __CONCAT(dname,_match), \
+ __CONCAT(dname,_attach) \
+}
-/*
- * FreeBSD
- *
- */
+#define USB_MATCH(dname) \
+int \
+__CONCAT(dname,_match)(parent, match, aux) \
+ struct device *parent; \
+ struct cfdata *match; \
+ void *aux;
-#elif defined(__FreeBSD__)
-#include "opt_usb.h"
-#define DEVICE_NAME(bdev) \
- printf("%s%d: ", \
- device_get_name(bdev), device_get_unit(bdev))
+#define USB_MATCH_START(dname, uaa) \
+ struct usb_attach_arg *uaa = aux
-/* XXX Change this when FreeBSD has memset
- */
-#define memset(d, v, s) \
- do{ \
- if ((v) == 0) \
- bzero((d), (s)); \
- else \
- panic("Non zero filler for memset, cannot handle!"); \
- } while (0)
+#define USB_ATTACH(dname) \
+void \
+__CONCAT(dname,_attach)(parent, self, aux) \
+ struct device *parent; \
+ struct device *self; \
+ void *aux;
-/* XXX can't we put this somehow into a typedef? */
-#define bdevice device_t /* base device */
+#define USB_ATTACH_START(dname, sc, uaa) \
+ struct __CONCAT(dname,_softc) *sc = \
+ (struct __CONCAT(dname,_softc) *)self; \
+ struct usb_attach_arg *uaa = aux
-#endif
+/* Returns from attach */
+#define USB_ATTACH_ERROR_RETURN return
+#define USB_ATTACH_SUCCESS_RETURN return
+#define USB_ATTACH_SETUP printf("\n")
-/*
- * General
- *
- */
+#define USB_GET_SC_OPEN(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc; \
+ if (unit >= __CONCAT(dname,_cd).cd_ndevs) \
+ return (ENXIO); \
+ sc = __CONCAT(dname,_cd).cd_devs[unit]; \
+ if (!sc) \
+ return (ENXIO)
-#define DEVICE_MSG(bdev, s) (DEVICE_NAME(bdev), printf s)
-#define DEVICE_ERROR(bdev, s) DEVICE_MSG(bdev, s)
+#define USB_GET_SC(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc = __CONCAT(dname,_cd).cd_devs[unit]
+#define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \
+ ((dev)->softc = config_found_sm(parent, args, print, sub))
-/* Returns from attach for NetBSD vs. FreeBSD
- */
-/* Error returns */
-#if defined(__NetBSD__)
-#define ATTACH_ERROR_RETURN return
-#define ATTACH_SUCCESS_RETURN return
-#elif defined(__FreeBSD__)
-#define ATTACH_ERROR_RETURN return ENXIO
-#define ATTACH_SUCCESS_RETURN return 0
-#endif
+#elif defined(__FreeBSD__)
/*
- * The debugging subsystem
+ * FreeBSD
*/
-/* XXX to be filled in
+#include "opt_usb.h"
+/* The following is not a type def to avoid error messages
+ * because of includes in the wrong order.
*/
+#define bdevice device_t
+#define USBDEVNAME(bdev) usbd_devname(&bdev)
+
+/* XXX Change this when FreeBSD has memset
+ */
+#define memset(d, v, s) \
+ do{ \
+ if ((v) == 0) \
+ bzero((d), (s)); \
+ else \
+ panic("Non zero filler for memset, cannot handle!"); \
+ } while (0)
+
+#define usb_timeout(f, d, t, h) ((h) = timeout((f), (d), (t)))
+#define usb_untimeout(f, d, h) untimeout((f), (d), (h))
+
+#define USB_DECLARE_DRIVER_NAME_INIT(name, dname, init...) \
+static device_probe_t __CONCAT(dname,_match); \
+static device_attach_t __CONCAT(dname,_attach); \
+static device_detach_t __CONCAT(dname,_detach); \
+\
+static devclass_t __CONCAT(dname,_devclass); \
+\
+static device_method_t __CONCAT(dname,_methods)[] = { \
+ DEVMETHOD(device_probe, __CONCAT(dname,_match)), \
+ DEVMETHOD(device_attach, __CONCAT(dname,_attach)), \
+ DEVMETHOD(device_detach, __CONCAT(dname,_detach)), \
+ init, \
+ {0,0} \
+}; \
+\
+static driver_t __CONCAT(dname,_driver) = { \
+ name, \
+ __CONCAT(dname,_methods), \
+ DRIVER_TYPE_MISC, \
+ sizeof(struct __CONCAT(dname,_softc)) \
+}
+
+#define USB_MATCH(dname) \
+static int \
+__CONCAT(dname,_match)(device_t device)
+
+#define USB_MATCH_START(dname, uaa) \
+ struct usb_attach_arg *uaa = device_get_ivars(device)
+
+#define USB_ATTACH(dname) \
+static int \
+__CONCAT(dname,_attach)(device_t self)
+
+#define USB_ATTACH_START(dname, sc, uaa) \
+ struct __CONCAT(dname,_softc) *sc = device_get_softc(self); \
+ struct usb_attach_arg *uaa = device_get_ivars(self)
+
+/* Returns from attach */
+#define USB_ATTACH_ERROR_RETURN return ENXIO
+#define USB_ATTACH_SUCCESS_RETURN return 0
+
+#define USB_ATTACH_SETUP \
+ usbd_device_set_desc(self, devinfo); \
+ sc->sc_dev = self
+
+#define USB_GET_SC_OPEN(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc = \
+ devclass_get_softc(__CONCAT(dname,_devclass), unit); \
+ if (!sc) \
+ return (ENXIO)
+
+#define USB_GET_SC(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc = \
+ devclass_get_softc(__CONCAT(dname,_devclass), unit)
+
+#define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \
+ (device_probe_and_attach((bdev)) == 0 ? ((dev)->softc = (bdev)) : 0)
+
+/* conversion from one type of queue to the other */
+#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD_UNTIL
+#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD
+#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL
+#define SIMPLEQ_NEXT STAILQ_NEXT
+#define SIMPLEQ_FIRST STAILQ_FIRST
+#define SIMPLEQ_HEAD STAILQ_HEAD
+#define SIMPLEQ_INIT STAILQ_INIT
+#define SIMPLEQ_ENTRY STAILQ_ENTRY
+
+#endif /* __FreeBSD__ */
+
+
+
+#define USB_DECLARE_DRIVER_NAME(name, dname) \
+ USB_DECLARE_DRIVER_NAME_INIT(#name, dname, {0,0} )
+#define USB_DECLARE_DRIVER_INIT(dname, init) \
+ USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, init )
+#define USB_DECLARE_DRIVER(dname) \
+ USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, {0,0} )
diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c
index fafa947..3aebeee 100644
--- a/sys/dev/usb/usb_quirks.c
+++ b/sys/dev/usb/usb_quirks.c
@@ -1,12 +1,13 @@
-/* $NetBSD: usb_quirks.c,v 1.1 1998/07/12 19:52:00 augustss Exp $ */
+/* $NetBSD: usb_quirks.c,v 1.6 1998/12/29 15:23:59 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,12 +38,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
-#if defined(__NetBSD__)
-#include <sys/device.h>
+#if defined(__FreeBSD__)
+#include <sys/bus.h>
#endif
#include <sys/select.h>
@@ -61,7 +60,10 @@ struct usbd_quirk_entry {
{ USB_VENDOR_INSIDEOUT,USB_PRODUCT_INSIDEOUT_EDGEPORT4,
0x094, { UQ_SWAP_UNICODE}},
{ USB_VENDOR_UNIXTAR, USB_PRODUCT_UNIXTAR_UTUSB41, 0x100, { UQ_HUB_POWER }},
- { USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932, 0x100, { UQ_NO_STRINGS }},
+ { USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932, 0x100, { UQ_NO_STRINGS }},
+ { USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET, 0x002, { UQ_NO_STRINGS }},
+ { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1, 0x101, { UQ_NO_STRINGS }},
+ { USB_VENDOR_JAZZ, USB_PRODUCT_JAZZ_J6502, 0x0a2, { UQ_BAD_ADC }},
{ 0, 0, 0, { 0 } }
};
@@ -82,7 +84,7 @@ usbd_find_quirk(d)
#ifdef USB_DEBUG
{ extern int usbdebug;
if (usbdebug && t->quirks.uq_flags)
- printf("quirk %d/%d/%x: %d\n",
+ printf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n",
UGETW(d->idVendor), UGETW(d->idProduct),
UGETW(d->bcdDevice), t->quirks.uq_flags);
}
diff --git a/sys/dev/usb/usb_quirks.h b/sys/dev/usb/usb_quirks.h
index cc0cf09..07935d5 100644
--- a/sys/dev/usb/usb_quirks.h
+++ b/sys/dev/usb/usb_quirks.h
@@ -1,12 +1,13 @@
-/* $NetBSD: usb_quirks.h,v 1.1 1998/07/12 19:52:00 augustss Exp $ */
+/* $NetBSD: usb_quirks.h,v 1.5 1998/12/29 15:23:59 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,11 +40,12 @@
struct usbd_quirks {
u_int32_t uq_flags; /* Device problems: */
-#define UQ_NO_SET_PROTO 0x01 /* cannot handle SET PROTOCOL */
+#define UQ_NO_SET_PROTO 0x01 /* cannot handle SET PROTOCOL. */
#define UQ_SWAP_UNICODE 0x02 /* has some Unicode strings swapped. */
#define UQ_HUB_POWER 0x04 /* does not respond correctly to get
device status; use get hub status. */
-#define UQ_NO_STRINGS 0x08 /* string descriptors are broken. */
+#define UQ_NO_STRINGS 0x08 /* string descriptors are broken. */
+#define UQ_BAD_ADC 0x10 /* bad audio spec version number. */
};
extern struct usbd_quirks usbd_no_quirk;
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 684cd89..69035f2 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,12 +1,13 @@
-/* $NetBSD: usb_subr.c,v 1.7 1998/08/02 22:30:53 augustss Exp $ */
+/* $NetBSD: usb_subr.c,v 1.24 1999/01/01 15:21:42 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,8 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -62,7 +61,7 @@
#if defined(__FreeBSD__)
#include <machine/clock.h>
-#define delay(d) DELAY(d)
+#define delay(d) DELAY(d)
#endif
#ifdef USB_DEBUG
@@ -77,16 +76,17 @@ extern int usbdebug;
static usbd_status usbd_set_config __P((usbd_device_handle, int));
char *usbd_get_string __P((usbd_device_handle, int, char *));
int usbd_getnewaddr __P((usbd_bus_handle bus));
-int usbd_print __P((void *aux, const char *pnp));
#if defined(__NetBSD__)
-int usbd_submatch __P((struct device *, struct cfdata *cf, void *));
+int usbd_print __P((void *aux, const char *pnp));
+int usbd_submatch __P((bdevice *, struct cfdata *cf, void *));
#endif
usb_interface_descriptor_t *usbd_find_idesc __P((usb_config_descriptor_t *cd,
- int ino, int ano));
-usbd_status usbd_fill_iface_data __P((usbd_device_handle dev, int i, int a));
+ int ifaceidx, int altidx));
void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno));
void usbd_kill_pipe __P((usbd_pipe_handle));
-static usbd_status usbd_probe_and_attach(bdevice *parent, usbd_device_handle dev);
+usbd_status usbd_probe_and_attach
+ __P((bdevice *parent, usbd_device_handle dev, int port, int addr));
+
#ifdef USBVERBOSE
typedef u_int16_t usb_vendor_id_t;
@@ -106,6 +106,53 @@ struct usb_knowndev {
#include <dev/usb/usbdevs_data.h>
#endif /* USBVERBOSE */
+#ifdef USB_DEBUG
+char *usbd_error_strs[] = {
+ "NORMAL_COMPLETION",
+ "IN_PROGRESS",
+ "PENDING_REQUESTS",
+ "NOT_STARTED",
+ "INVAL",
+ "IS_IDLE",
+ "NOMEM",
+ "CANCELLED",
+ "BAD_ADDRESS",
+ "IN_USE",
+ "INTERFACE_NOT_ACTIVE",
+ "NO_ADDR",
+ "SET_ADDR_FAILED",
+ "NO_POWER",
+ "TOO_DEEP",
+ "IOERROR",
+ "NOT_CONFIGURED",
+ "TIMEOUT",
+ "SHORT_XFER",
+ "STALLED",
+ "XXX",
+};
+#endif
+
+usbd_status
+usbd_get_string_desc(dev, sindex, langid, sdesc)
+ usbd_device_handle dev;
+ int sindex;
+ int langid;
+ usb_string_descriptor_t *sdesc;
+{
+ usb_device_request_t req;
+ usbd_status r;
+
+ req.bmRequestType = UT_READ_DEVICE;
+ req.bRequest = UR_GET_DESCRIPTOR;
+ USETW2(req.wValue, UDESC_STRING, sindex);
+ USETW(req.wIndex, langid);
+ USETW(req.wLength, 1); /* only size byte first */
+ r = usbd_do_request(dev, &req, sdesc);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ USETW(req.wLength, sdesc->bLength); /* the whole string */
+ return (usbd_do_request(dev, &req, sdesc));
+}
char *
usbd_get_string(dev, si, buf)
@@ -114,41 +161,29 @@ usbd_get_string(dev, si, buf)
char *buf;
{
int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE;
- usb_device_request_t req;
usb_string_descriptor_t us;
char *s;
int i, n;
u_int16_t c;
usbd_status r;
- int lang; /* NWH */
if (si == 0)
return (0);
if (dev->quirks->uq_flags & UQ_NO_STRINGS)
return (0);
-
- req.bmRequestType = UT_READ_DEVICE; /* fetch default language */
- req.bRequest = UR_GET_DESCRIPTOR;
- USETW2(req.wValue, UDESC_STRING, 0);
- USETW(req.wIndex, 0);
- USETW(req.wLength, 1); /* only first word in bString */
- r = usbd_do_request(dev, &req, &us);
- if (r != USBD_NORMAL_COMPLETION)
- return 0;
- lang = UGETW(us.bString[0]);
-
- req.bmRequestType = UT_READ_DEVICE;
- req.bRequest = UR_GET_DESCRIPTOR;
- USETW2(req.wValue, UDESC_STRING, si);
- USETW(req.wIndex, lang);
- USETW(req.wLength, 1); /* only size byte first */
- r = usbd_do_request(dev, &req, &us);
- if (r != USBD_NORMAL_COMPLETION)
- return 0;
- USETW(req.wLength, us.bLength); /* the whole string */
- r = usbd_do_request(dev, &req, &us);
+ if (dev->langid == USBD_NOLANG) {
+ /* Set up default language */
+ r = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
+ if (r != USBD_NORMAL_COMPLETION || us.bLength < 4) {
+ dev->langid = 0; /* Well, just pick English then */
+ } else {
+ /* Pick the first language as the default. */
+ dev->langid = UGETW(us.bString[0]);
+ }
+ }
+ r = usbd_get_string_desc(dev, si, dev->langid, &us);
if (r != USBD_NORMAL_COMPLETION)
- return 0;
+ return (0);
s = buf;
n = us.bLength / 2 - 1;
for (i = 0; i < n; i++) {
@@ -229,23 +264,23 @@ usbd_devinfo(dev, showclass, cp)
usbd_devinfo_vp(dev, vendor, product);
cp += sprintf(cp, "%s %s", vendor, product);
if (showclass)
- cp += sprintf(cp, " (class %d/%d)",
+ cp += sprintf(cp, ", class %d/%d",
udd->bDeviceClass, udd->bDeviceSubClass);
bcdUSB = UGETW(udd->bcdUSB);
bcdDevice = UGETW(udd->bcdDevice);
- cp += sprintf(cp, " (rev ");
+ cp += sprintf(cp, ", rev ");
cp += usbd_printBCD(cp, bcdUSB);
*cp++ = '/';
cp += usbd_printBCD(cp, bcdDevice);
- *cp++ = ')';
- cp += sprintf(cp, " addr %d", dev->address);
+ cp += sprintf(cp, ", addr %d", dev->address);
+ *cp = 0;
}
/* Delay for a certain number of ms */
void
-usbd_delay_ms(bus, ms)
+usb_delay_ms(bus, ms)
usbd_bus_handle bus;
- int ms;
+ u_int ms;
{
/* Wait at least two clock ticks so we know the time has passed. */
if (bus->use_polling)
@@ -254,6 +289,15 @@ usbd_delay_ms(bus, ms)
tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
}
+/* Delay given a device handle. */
+void
+usbd_delay_ms(dev, ms)
+ usbd_device_handle dev;
+ u_int ms;
+{
+ usb_delay_ms(dev->bus, ms);
+}
+
usbd_status
usbd_reset_port(dev, port, ps)
usbd_device_handle dev;
@@ -270,14 +314,14 @@ usbd_reset_port(dev, port, ps)
USETW(req.wIndex, port);
USETW(req.wLength, 0);
r = usbd_do_request(dev, &req, 0);
- DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d\n",
- port, r));
+ DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d(%s)\n",
+ port, r, usbd_error_strs[r]));
if (r != USBD_NORMAL_COMPLETION)
return (r);
n = 10;
do {
/* Wait for device to recover from reset. */
- usbd_delay_ms(dev->bus, USB_PORT_RESET_DELAY);
+ usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
r = usbd_get_port_status(dev, port, ps);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTF(("usbd_reset_port: get status failed %d\n",r));
@@ -293,47 +337,100 @@ usbd_reset_port(dev, port, ps)
if (r != USBD_NORMAL_COMPLETION)
DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r));
#endif
+
+ /* Wait for the device to recover from reset. */
+ usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
return (r);
}
usb_interface_descriptor_t *
-usbd_find_idesc(cd, ino, ano)
+usbd_find_idesc(cd, ifaceidx, altidx)
usb_config_descriptor_t *cd;
- int ino;
- int ano;
+ int ifaceidx;
+ int altidx;
{
char *p = (char *)cd;
char *end = p + UGETW(cd->wTotalLength);
usb_interface_descriptor_t *d;
+ int curidx, lastidx, curaidx = 0;
- for (; p < end; p += d->bLength) {
+ for (curidx = lastidx = -1; p < end; ) {
d = (usb_interface_descriptor_t *)p;
- if (p + d->bLength <= end &&
- d->bDescriptorType == UDESC_INTERFACE &&
- d->bInterfaceNumber == ino && d->bAlternateSetting == ano)
- return (d);
+ DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
+ "type=%d\n",
+ ifaceidx, curidx, altidx, curaidx,
+ d->bLength, d->bDescriptorType));
+ if (d->bLength == 0) /* bad descriptor */
+ break;
+ p += d->bLength;
+ if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
+ if (d->bInterfaceNumber != lastidx) {
+ lastidx = d->bInterfaceNumber;
+ curidx++;
+ curaidx = 0;
+ } else
+ curaidx++;
+ if (ifaceidx == curidx && altidx == curaidx)
+ return (d);
+ }
+ }
+ return (0);
+}
+
+usb_endpoint_descriptor_t *
+usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
+ usb_config_descriptor_t *cd;
+ int ifaceidx;
+ int altidx;
+ int endptidx;
+{
+ char *p = (char *)cd;
+ char *end = p + UGETW(cd->wTotalLength);
+ usb_interface_descriptor_t *d;
+ usb_endpoint_descriptor_t *e;
+ int curidx;
+
+ d = usbd_find_idesc(cd, ifaceidx, altidx);
+ if (!d)
+ return (0);
+ if (endptidx >= d->bNumEndpoints) /* quick exit */
+ return (0);
+
+ curidx = -1;
+ for (p = (char *)d + d->bLength; p < end; ) {
+ e = (usb_endpoint_descriptor_t *)p;
+ if (e->bLength == 0) /* bad descriptor */
+ break;
+ p += e->bLength;
+ if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
+ return (0);
+ if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
+ curidx++;
+ if (curidx == endptidx)
+ return (e);
+ }
}
return (0);
}
usbd_status
-usbd_fill_iface_data(dev, ino, ano)
+usbd_fill_iface_data(dev, ifaceidx, altidx)
usbd_device_handle dev;
- int ino;
- int ano;
+ int ifaceidx;
+ int altidx;
{
- usbd_interface_handle ifc = &dev->ifaces[ino];
- usb_endpoint_descriptor_t *ed;
+ usbd_interface_handle ifc = &dev->ifaces[ifaceidx];
char *p, *end;
int endpt, nendpt;
- usbd_status r;
- DPRINTFN(5,("usbd_fill_iface_data: ino=%d ano=%d\n", ino, ano));
+ DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
+ ifaceidx, altidx));
ifc->device = dev;
- ifc->state = USBD_INTERFACE_ACTIVE;
- ifc->idesc = usbd_find_idesc(dev->cdesc, ino, ano);
+ ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
if (ifc->idesc == 0)
return (USBD_INVAL);
+ ifc->index = ifaceidx;
+ ifc->altindex = altidx;
nendpt = ifc->idesc->bNumEndpoints;
DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
if (nendpt != 0) {
@@ -346,31 +443,38 @@ usbd_fill_iface_data(dev, ino, ano)
ifc->priv = 0;
p = (char *)ifc->idesc + ifc->idesc->bLength;
end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
+#define ed ((usb_endpoint_descriptor_t *)p)
for (endpt = 0; endpt < nendpt; endpt++) {
DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt));
for (; p < end; p += ed->bLength) {
ed = (usb_endpoint_descriptor_t *)p;
- DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p len=%d type=%d\n",
+ DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p "
+ "len=%d type=%d\n",
p, end, ed->bLength, ed->bDescriptorType));
- if (p + ed->bLength <= end &&
+ if (p + ed->bLength <= end && ed->bLength != 0 &&
ed->bDescriptorType == UDESC_ENDPOINT)
goto found;
- if (ed->bDescriptorType == UDESC_INTERFACE)
+ if (ed->bDescriptorType == UDESC_INTERFACE ||
+ ed->bLength == 0)
break;
}
- r = USBD_INVAL;
+ /* passed end, or bad desc */
goto bad;
found:
ifc->endpoints[endpt].edesc = ed;
ifc->endpoints[endpt].state = USBD_ENDPOINT_ACTIVE;
ifc->endpoints[endpt].refcnt = 0;
ifc->endpoints[endpt].toggle = 0;
+ p += ed->bLength;
}
+#undef ed
LIST_INIT(&ifc->pipes);
+ ifc->state = USBD_INTERFACE_ACTIVE;
return (USBD_NORMAL_COMPLETION);
+
bad:
free(ifc->endpoints, M_USB);
- return (r);
+ return (USBD_INVAL);
}
void
@@ -404,21 +508,43 @@ usbd_set_config_no(dev, no, msg)
int no;
int msg;
{
+ int index;
+ usb_config_descriptor_t cd;
+ usbd_status r;
+
+ DPRINTFN(5,("usbd_set_config_no: %d\n", no));
+ /* Figure out what config index to use. */
+ for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
+ r = usbd_get_config_desc(dev, index, &cd);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ if (cd.bConfigurationValue == no)
+ return (usbd_set_config_index(dev, index, msg));
+ }
+ return (USBD_INVAL);
+}
+
+usbd_status
+usbd_set_config_index(dev, index, msg)
+ usbd_device_handle dev;
+ int index;
+ int msg;
+{
usb_status_t ds;
usb_hub_status_t hs;
usb_config_descriptor_t cd, *cdp;
usbd_status r;
- int ifcno, nifc, len, selfpowered, power;
+ int ifcidx, nifc, len, selfpowered, power;
- DPRINTFN(5, ("usbd_set_config_no: dev=%p no=%d\n", dev, no));
+ DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
/* XXX check that all interfaces are idle */
if (dev->config != 0) {
- DPRINTF(("usbd_set_config_no: free old config\n"));
+ DPRINTF(("usbd_set_config_index: free old config\n"));
/* Free all configuration data structures. */
nifc = dev->cdesc->bNumInterface;
- for (ifcno = 0; ifcno < nifc; ifcno++)
- usbd_free_iface_data(dev, ifcno);
+ for (ifcidx = 0; ifcidx < nifc; ifcidx++)
+ usbd_free_iface_data(dev, ifcidx);
free(dev->ifaces, M_USB);
free(dev->cdesc, M_USB);
dev->ifaces = 0;
@@ -428,16 +554,22 @@ usbd_set_config_no(dev, no, msg)
}
/* Figure out what config number to use. */
- r = usbd_get_config_desc(dev, no, &cd);
+ r = usbd_get_config_desc(dev, index, &cd);
if (r != USBD_NORMAL_COMPLETION)
return (r);
len = UGETW(cd.wTotalLength);
cdp = malloc(len, M_USB, M_NOWAIT);
if (cdp == 0)
return (USBD_NOMEM);
- r = usbd_get_desc(dev, UDESC_CONFIG, no, len, cdp);
+ r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
if (r != USBD_NORMAL_COMPLETION)
goto bad;
+ if (cdp->bDescriptorType != UDESC_CONFIG) {
+ DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
+ cdp->bDescriptorType));
+ r = USBD_INVAL;
+ goto bad;
+ }
selfpowered = 0;
if (cdp->bmAttributes & UC_SELF_POWERED) {
/* May be self powered. */
@@ -455,43 +587,48 @@ usbd_set_config_no(dev, no, msg)
(UGETW(ds.wStatus) & UDS_SELF_POWERED))
selfpowered = 1;
}
- DPRINTF(("usbd_set_config_no: status=0x%04x, error=%d\n",
- UGETW(ds.wStatus), r));
+ DPRINTF(("usbd_set_config_index: status=0x%04x, "
+ "error=%d(%s)\n",
+ UGETW(ds.wStatus), r, usbd_error_strs[r]));
} else
selfpowered = 1;
}
- DPRINTF(("usbd_set_config_no: (addr %d) attr=0x%02x, selfpowered=%d, power=%d, powerquirk=%x\n",
+ DPRINTF(("usbd_set_config_index: (addr %d) attr=0x%02x, "
+ "selfpowered=%d, power=%d, powerquirk=%x\n",
dev->address, cdp->bmAttributes,
selfpowered, cdp->bMaxPower * 2,
dev->quirks->uq_flags & UQ_HUB_POWER));
#ifdef USB_DEBUG
if (!dev->powersrc) {
- printf("usbd_set_config_no: No power source?\n");
- return (EIO);
+ printf("usbd_set_config_index: No power source?\n");
+ return (USBD_IOERROR);
}
#endif
power = cdp->bMaxPower * 2;
if (power > dev->powersrc->power) {
/* XXX print nicer message. */
if (msg)
- DEVICE_ERROR(dev->bus->bdev,
- ("device addr %d (config %d) exceeds power budget, %d mA > %d mA\n",
- dev->address,
+ printf("%s: device addr %d (config %d) exceeds power "
+ "budget, %d mA > %d mA\n",
+ USBDEVNAME(dev->bus->bdev), dev->address,
cdp->bConfigurationValue,
- power, dev->powersrc->power));
+ power, dev->powersrc->power);
r = USBD_NO_POWER;
goto bad;
}
dev->power = power;
dev->self_powered = selfpowered;
+ DPRINTF(("usbd_set_config_index: set config %d\n",
+ cdp->bConfigurationValue));
r = usbd_set_config(dev, cdp->bConfigurationValue);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("usbd_set_config_no: setting config=%d failed, error=%d\n",
- cdp->bConfigurationValue, r));
+ DPRINTF(("usbd_set_config_index: setting config=%d failed, "
+ "error=%d(%s)\n",
+ cdp->bConfigurationValue, r, usbd_error_strs[r]));
goto bad;
}
- DPRINTF(("usbd_set_config_no: setting new config %d\n",
+ DPRINTF(("usbd_set_config_index: setting new config %d\n",
cdp->bConfigurationValue));
nifc = cdp->bNumInterface;
dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
@@ -500,15 +637,15 @@ usbd_set_config_no(dev, no, msg)
r = USBD_NOMEM;
goto bad;
}
- DPRINTFN(5,("usbd_set_config_no: dev=%p cdesc=%p\n", dev, cdp));
+ DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
dev->cdesc = cdp;
dev->config = cdp->bConfigurationValue;
dev->state = USBD_DEVICE_CONFIGURED;
- for (ifcno = 0; ifcno < nifc; ifcno++) {
- r = usbd_fill_iface_data(dev, ifcno, 0);
+ for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
+ r = usbd_fill_iface_data(dev, ifcidx, 0);
if (r != USBD_NORMAL_COMPLETION) {
- while (--ifcno >= 0)
- usbd_free_iface_data(dev, ifcno);
+ while (--ifcidx >= 0)
+ usbd_free_iface_data(dev, ifcidx);
goto bad;
}
}
@@ -548,8 +685,9 @@ usbd_setup_pipe(dev, iface, ep, pipe)
SIMPLEQ_INIT(&p->queue);
r = dev->bus->open_pipe(p);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTF(("usbd_setup_pipe: endpoint=%d failed, error=%d\n",
- ep->edesc->bEndpointAddress, r));
+ DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=%d"
+ "(%s)\n",
+ ep->edesc->bEndpointAddress, r, usbd_error_strs[r]));
free(p, M_USB);
return (r);
}
@@ -580,82 +718,112 @@ usbd_getnewaddr(bus)
}
-/* NWH separated out the probe and attach code
- */
-static usbd_status
-usbd_probe_and_attach(parent, dev)
+usbd_status
+usbd_probe_and_attach(parent, dev, port, addr)
bdevice *parent;
usbd_device_handle dev;
+ int port;
+ int addr;
{
+ bdevice bdev;
struct usb_attach_arg uaa;
usb_device_descriptor_t *dd = &dev->ddesc;
- int r, found, i, confi;
+ int r, found, i, confi, nifaces;
+ usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
#if defined(__FreeBSD__)
- dev->bdev = device_add_child(*parent, NULL, -1, &uaa);
- if (!dev->bdev) {
- DEVICE_ERROR(dev->bus->bdev, ("Device creation failed\n"));
- return ENXIO;
+/* XXX uaa is a static var. Not a problem as it _should_ be used only
+ * during probe and attach. Should be changed however
+ */
+ bdev = device_add_child(*parent, NULL, -1, &uaa);
+ if (!bdev) {
+ printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
+ return (USBD_INVAL);
}
#endif
uaa.device = dev;
uaa.iface = 0;
+ uaa.ifaces = 0;
+ uaa.nifaces = 0;
uaa.usegeneric = 0;
+ uaa.port = port;
+ uaa.configno = UHUB_UNK_CONFIGURATION;
+ uaa.ifaceno = UHUB_UNK_INTERFACE;
/* First try with device specific drivers. */
-#if defined(__NetBSD__)
- if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0)
-#elif defined(__FreeBSD__)
- if (device_probe_and_attach(dev->bdev) == 0)
-#endif
+ if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
return (USBD_NORMAL_COMPLETION);
- DPRINTF(("usbd_new_device: no device driver found\n"));
+ DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
/* Next try with interface drivers. */
for (confi = 0; confi < dd->bNumConfigurations; confi++) {
- r = usbd_set_config_no(dev, confi, 1);
+ DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
+ confi));
+ r = usbd_set_config_index(dev, confi, 1);
if (r != USBD_NORMAL_COMPLETION) {
- DEVICE_ERROR(*parent, ("set config failed, r=%d\n", r));
- return r;
- }
- for (found = i = 0; i < dev->cdesc->bNumInterface; i++) {
- uaa.iface = &dev->ifaces[i];
-#if defined(__NetBSD__)
- if (config_found_sm(parent, &uaa, usbd_print,
- usbd_submatch))
-#elif defined(__FreeBSD__)
- if (device_probe_and_attach(dev->bdev) == 0)
+#ifdef USB_DEBUG
+ DPRINTF(("%s: port %d, set config at addr %d failed, "
+ "error=%d(%s)\n", USBDEVNAME(*parent), port,
+ addr, r, usbd_error_strs[r]));
+#else
+ printf("%s: port %d, set config at addr %d failed\n",
+ USBDEVNAME(*parent), port, addr);
#endif
+#if defined(__FreeBSD__)
+ device_delete_child(*parent, bdev);
+#endif
+ return (r);
+ }
+ nifaces = dev->cdesc->bNumInterface;
+ uaa.configno = dev->cdesc->bConfigurationValue;
+ for (i = 0; i < nifaces; i++)
+ ifaces[i] = &dev->ifaces[i];
+ uaa.ifaces = ifaces;
+ uaa.nifaces = nifaces;
+ for (found = i = 0; i < nifaces; i++) {
+ if (!ifaces[i])
+ continue; /* interface already claimed */
+ uaa.iface = ifaces[i];
+ uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
+ if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
+ usbd_submatch)) {
found++;
+ ifaces[i] = 0; /* consumed */
+ }
}
if (found != 0)
return (USBD_NORMAL_COMPLETION);
}
- /* No interfaces were attach in any of the configurations. */
- if (dd->bNumConfigurations > 0)
- usbd_set_config_no(dev, 0, 0);
+ /* No interfaces were attached in any of the configurations. */
+ if (dd->bNumConfigurations > 1)/* don't change if only 1 config */
+ usbd_set_config_index(dev, 0, 0);
- DPRINTF(("usbd_new_device: no interface drivers found\n"));
+ DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
/* Finally try the generic driver. */
uaa.iface = 0;
uaa.usegeneric = 1;
-#if defined(__NetBSD__)
- if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0)
- return (USBD_NORMAL_COMPLETION);
-#elif defined(__FreeBSD__)
- if (device_probe_and_attach(dev->bdev) == 0)
+ uaa.configno = UHUB_UNK_CONFIGURATION;
+ uaa.ifaceno = UHUB_UNK_INTERFACE;
+ if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
return (USBD_NORMAL_COMPLETION);
-#endif
- /* generic attach failed, but leave the device as it is
- * we just did not find any drivers, that's all. the device is
- * fully operational and not harming anyone
+ /*
+ * The generic attach failed, but leave the device as it is.
+ * We just did not find any drivers, that's all. The device is
+ * fully operational and not harming anyone.
*/
- DPRINTF(("usbd_new_device: generic attach failed\n"));
- return USBD_NORMAL_COMPLETION;
+ DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
+#if defined(__FreeBSD__)
+/*
+ * XXX should we delete the child again? Left for now to avoid dangling
+ * references.
+ device_delete_child(*parent, bdev);
+*/
+#endif
+ return (USBD_NORMAL_COMPLETION);
}
@@ -685,7 +853,8 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
bus, depth, lowspeed));
addr = usbd_getnewaddr(bus);
if (addr < 0) {
- DEVICE_ERROR(bus->bdev, ("No free USB addresses, new device ignored.\n"));
+ printf("%s: No free USB addresses, new device ignored.\n",
+ USBDEVNAME(bus->bdev));
return (USBD_NO_ADDR);
}
@@ -699,8 +868,6 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
/* Set up default endpoint handle. */
dev->def_ep.edesc = &dev->def_ep_desc;
dev->def_ep.state = USBD_ENDPOINT_ACTIVE;
- dev->def_ep.refcnt = 0;
- dev->def_ep.toggle = 0; /* XXX */
/* Set up default endpoint descriptor. */
dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
@@ -717,16 +884,13 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
dev->lowspeed = lowspeed != 0;
dev->depth = depth;
dev->powersrc = up;
-
-#if defined(__FreeBSD__)
- dev->bdev = NULL;
-#endif
+ dev->langid = USBD_NOLANG;
/* Establish the the default pipe. */
r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
if (r != USBD_NORMAL_COMPLETION) {
usbd_remove_device(dev, up);
- return r;
+ return (r);
}
up->device = dev;
@@ -737,17 +901,27 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
if (r == USBD_NORMAL_COMPLETION)
break;
- usbd_delay_ms(dev->bus, 200);
+ usbd_delay_ms(dev, 200);
}
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc failed\n",
+ DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
+ "failed\n",
addr));
usbd_remove_device(dev, up);
- return r;
+ return (r);
}
- DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
- addr, UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
+ if (dd->bDescriptorType != UDESC_DEVICE) {
+ /* Illegal device descriptor */
+ DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
+ dd->bDescriptorType));
+ usbd_remove_device(dev, up);
+ return (USBD_INVAL);
+ }
+
+ DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
+ "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
+ addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed));
USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
@@ -755,9 +929,10 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
/* Get the full device descriptor. */
r = usbd_get_device_desc(dev, dd);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc failed\n", addr));
+ DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
+ "failed\n", addr));
usbd_remove_device(dev, up);
- return r;
+ return (r);
}
/* Figure out what's wrong with this device. */
@@ -766,10 +941,14 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
/* Set the address */
r = usbd_set_address(dev, addr);
if (r != USBD_NORMAL_COMPLETION) {
- DPRINTFN(-1,("usbd_new_device: set address %d failed\n",addr));
+ DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
+ r = USBD_SET_ADDR_FAILED;
usbd_remove_device(dev, up);
- return USBD_SET_ADDR_FAILED;
+ return (r);
}
+ /* Allow device time to set new address */
+ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
+
dev->address = addr; /* New device address now */
dev->state = USBD_DEVICE_ADDRESSED;
bus->devices[addr] = dev;
@@ -781,13 +960,13 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
addr, dev, parent));
- r = usbd_probe_and_attach(parent, dev);
- if (r) {
+ r = usbd_probe_and_attach(parent, dev, port, addr);
+ if (r != USBD_NORMAL_COMPLETION) {
usbd_remove_device(dev, up);
- return r;
- }
-
- return (USBD_NORMAL_COMPLETION);
+ return (r);
+ }
+
+ return (USBD_NORMAL_COMPLETION);
}
void
@@ -796,20 +975,7 @@ usbd_remove_device(dev, up)
struct usbd_port *up;
{
DPRINTF(("usbd_remove_device: %p\n", dev));
-
-#if defined(__NetBSD__)
- /* XXX bit of a hack, only for hubs the detach is called
- *
- * easiest solution, register a detach method in the softc, call that
- * one and pass the device struct to it, or the softc. Whatever.
- */
- if (dev->bdev && dev->hub)
- uhub_detach(dev->hub->hubdata);
-#elif defined(__FreeBSD__)
- if (dev->bdev)
- device_delete_child(device_get_parent(dev->bdev), dev->bdev);
-#endif
-
+
if (dev->default_pipe)
usbd_kill_pipe(dev->default_pipe);
up->device = 0;
@@ -818,7 +984,7 @@ usbd_remove_device(dev, up)
free(dev, M_USB);
}
-#if defined(__NetBSD__)
+#if defined(__NetBSD__)
int
usbd_print(aux, pnp)
void *aux;
@@ -872,3 +1038,100 @@ usbd_bus_print_child(device_t bus, device_t dev)
*/
}
#endif
+
+usbd_status
+usb_insert_transfer(reqh)
+ usbd_request_handle reqh;
+{
+ usbd_pipe_handle pipe = reqh->pipe;
+ usbd_interface_handle iface = pipe->iface;
+
+ if (pipe->state == USBD_PIPE_IDLE ||
+ (iface && iface->state == USBD_INTERFACE_IDLE))
+ return (USBD_IS_IDLE);
+ SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
+ if (pipe->state != USBD_PIPE_ACTIVE ||
+ (iface && iface->state != USBD_INTERFACE_ACTIVE))
+ return (USBD_NOT_STARTED);
+ if (pipe->running)
+ return (USBD_IN_PROGRESS);
+ pipe->running = 1;
+ return (USBD_NORMAL_COMPLETION);
+}
+
+void
+usb_start_next(pipe)
+ usbd_pipe_handle pipe;
+{
+ usbd_request_handle reqh;
+ usbd_status r;
+
+#ifdef DIAGNOSTIC
+ if (SIMPLEQ_FIRST(&pipe->queue) == 0) {
+ printf("usb_start_next: empty\n");
+ return;
+ }
+#endif
+
+ /* First remove remove old */
+ SIMPLEQ_REMOVE_HEAD(&pipe->queue, SIMPLEQ_FIRST(&pipe->queue), next);
+ if (pipe->state != USBD_PIPE_ACTIVE) {
+ pipe->running = 0;
+ return;
+ }
+ reqh = SIMPLEQ_FIRST(&pipe->queue);
+ DPRINTFN(5, ("usb_start_next: start reqh=%p\n", reqh));
+ if (!reqh)
+ pipe->running = 0;
+ else {
+ r = pipe->methods->start(reqh);
+ if (r != USBD_IN_PROGRESS) {
+ printf("usb_start_next: error=%d\n", r);
+ pipe->running = 0;
+ /* XXX do what? */
+ }
+ }
+}
+
+void
+usbd_fill_deviceinfo(dev, di)
+ usbd_device_handle dev;
+ struct usb_device_info *di;
+{
+ struct usbd_port *p;
+ int i, r, s;
+
+ di->config = dev->config;
+ usbd_devinfo_vp(dev, di->vendor, di->product);
+ usbd_printBCD(di->revision, UGETW(dev->ddesc.bcdDevice));
+ di->vendorNo = UGETW(dev->ddesc.idVendor);
+ di->productNo = UGETW(dev->ddesc.idProduct);
+ di->class = dev->ddesc.bDeviceClass;
+ di->power = dev->self_powered ? 0 : dev->power;
+ di->lowspeed = dev->lowspeed;
+ di->addr = dev->address;
+ if (dev->hub) {
+ for (i = 0;
+ i < sizeof(di->ports) / sizeof(di->ports[0]) &&
+ i < dev->hub->hubdesc.bNbrPorts;
+ i++) {
+ p = &dev->hub->ports[i];
+ if (p->device)
+ r = p->device->address;
+ else {
+ s = UGETW(p->status.wPortStatus);
+ if (s & UPS_PORT_ENABLED)
+ r = USB_PORT_ENABLED;
+ else if (s & UPS_SUSPEND)
+ r = USB_PORT_SUSPENDED;
+ else if (s & UPS_PORT_POWER)
+ r = USB_PORT_POWERED;
+ else
+ r = USB_PORT_DISABLED;
+ }
+ di->ports[i] = r;
+ }
+ di->nports = dev->hub->hubdesc.bNbrPorts;
+ } else
+ di->nports = 0;
+}
diff --git a/sys/dev/usb/usbdevs.h b/sys/dev/usb/usbdevs.h
index 423196f..8f4d79d 100644
--- a/sys/dev/usb/usbdevs.h
+++ b/sys/dev/usb/usbdevs.h
@@ -1,19 +1,19 @@
-/* $NetBSD: usbdevs.h,v 1.8 1998/12/02 22:51:50 augustss Exp $ */
-/* FreeBSD $Id$ */
+/* $NetBSD$ */
/*
* THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
*
* generated from:
- * NetBSD: usbdevs,v 1.8 1998/12/02 22:49:51 augustss Exp
+ * NetBSD: usbdevs,v 1.14 1998/12/30 03:52:30 augustss Exp
*/
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -55,6 +55,7 @@
#define USB_VENDOR_NANAO 0x0440 /* Nanao */
#define USB_VENDOR_UNIXTAR 0x0451 /* Unixtar */
#define USB_VENDOR_GENIUS 0x0458 /* Genius */
+#define USB_VENDOR_MICROSOFT 0x045e /* Microsoft */
#define USB_VENDOR_CHERRY 0x046a /* Cherry */
/* Behavior Technology Corporation */
#define USB_VENDOR_BTC 0x046e /* BTC */
@@ -62,13 +63,17 @@
#define USB_VENDOR_CONNECTIX 0x0478 /* Connectix */
#define USB_VENDOR_CYPRESS 0x04b4 /* Cypress Semiconductor */
#define USB_VENDOR_3COM 0x04c1 /* 3Com */
+#define USB_VENDOR_SHUTTLE 0x04e6 /* Shuttle Technology */
#define USB_VENDOR_JAZZ 0x04fa /* Jazz */
#define USB_VENDOR_ATEN 0x0557 /* ATen */
+#define USB_VENDOR_PERACOM 0x0565 /* Peracom */
#define USB_VENDOR_EIZO 0x056d /* EIZO */
#define USB_VENDOR_AGILER 0x056e /* Agiler */
#define USB_VENDOR_BELKIN 0x05ab /* Belkin */
+#define USB_VENDOR_LOGITECH 0x05ac /* Logitech */
#define USB_VENDOR_EIZONANAO 0x05e7 /* EIZO Nanao */
#define USB_VENDOR_CHIC 0x05fe /* Chic Technology */
+#define USB_VENDOR_ADS 0x06e1 /* ADS Technologies */
#define USB_VENDOR_PLX 0x10b5 /* PLX */
#define USB_VENDOR_INSIDEOUT 0x1608 /* Inside Out Networks */
#define USB_VENDOR_INTEL 0x8086 /* Intel */
@@ -79,6 +84,7 @@
/* NEC products */
#define USB_PRODUCT_NEC_HUB 0x55aa /* hub */
+#define USB_PRODUCT_NEC_HUB_B 0x55ab /* hub */
/* Kodak products */
#define USB_PRODUCT_KODAK_DC260 0x0110 /* Digital Science DC260 */
@@ -97,6 +103,9 @@
#define USB_PRODUCT_GENIUS_NICHE 0x0001 /* Niche mouse */
#define USB_PRODUCT_GENIUS_FLIGHT2000 0x1004 /* Flight 2000 joystick */
+/* Microsoft products */
+#define USB_PRODUCT_MICROSOFT_INTELLIMOUSE 0x0009 /* IntelliMouse */
+
/* Cherry products */
#define USB_PRODUCT_CHERRY_MY3000KBD 0x0001 /* My3000 keyboard */
#define USB_PRODUCT_CHERRY_MY3000HUB 0x0003 /* My3000 hub */
@@ -111,33 +120,48 @@
/* Connectix products */
#define USB_PRODUCT_CONNECTIX_QUICKCAM 0x0001 /* QuickCam */
+/* Cypress Semiconduuctor products */
+#define USB_PRODUCT_CYPRESS_MOUSE 0x0001 /* mouse */
+
/* 3Com products */
#define USB_PRODUCT_3COM_USR56K 0x3021 /* U.S.Robotics 56000 Voice USB Modem */
+/* Shuttle Technology products */
+#define USB_PRODUCT_SHUTTLE_EUSB 0x0001 /* E-USB Bridge */
+
/* Jazz products */
#define USB_PRODUCT_JAZZ_J6502 0x4201 /* J-6502 speakers */
-/* Cypress Semiconduuctor products */
-#define USB_PRODUCT_CYPRESS_MOUSE 0x0001 /* mouse */
-
-/* ATen */
+/* ATen products */
#define USB_PRODUCT_ATEN_UC1284 0x2001 /* Parallel printer adapter */
+/* Peracom products */
+#define USB_PRODUCT_PERACOM_SERIAL1 0x0001 /* Serial Converter */
+
+/* EIZO products */
+#define USB_PRODUCT_EIZO_HUB 0x0000 /* hub */
+#define USB_PRODUCT_EIZO_MONITOR 0x0001 /* monitor */
+
/* Agiler products */
#define USB_PRODUCT_AGILER_MOUSE29UO 0x0002 /* mouse 29UO */
/* Belkin products */
#define USB_PRODUCT_BELKIN_F5U002 0x0002 /* Parallel printer adapter */
+/* Logitech products */
+#define USB_PRODUCT_LOGITECH_M2452 0x0203 /* M2452 keyboard */
+#define USB_PRODUCT_LOGITECH_M4848 0x0301 /* M4848 mouse */
+
/* EIZO Nanao products */
-#define USB_PRODUCT_EIZO_HUB 0x0000 /* hub */
-#define USB_PRODUCT_EIZO_MONITOR 0x0001 /* monitor */
#define USB_PRODUCT_EIZONANAO_HUB 0x0000 /* hub */
#define USB_PRODUCT_EIZONANAO_MONITOR 0x0001 /* monitor */
-/* Chic Technology */
+/* Chic Technology products */
#define USB_PRODUCT_CHIC_MOUSE1 0x0001 /* mouse */
+/* ADS products */
+#define USB_PRODUCT_ADS_ENET 0x0008 /* Ethernet adapter */
+
/* PLX products */
#define USB_PRODUCT_PLX_TESTBOARD 0x9060 /* test board */
diff --git a/sys/dev/usb/usbdevs_data.h b/sys/dev/usb/usbdevs_data.h
index 0a08afe..f888387 100644
--- a/sys/dev/usb/usbdevs_data.h
+++ b/sys/dev/usb/usbdevs_data.h
@@ -1,19 +1,21 @@
-/* $NetBSD: usbdevs_data.h,v 1.6 1998/10/05 02:31:14 mark Exp $ */
-/* FreeBSD $Id$ */
+/* $NetBSD$ */
+
+/* FreeBSD $Id$ */
/*
* THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
*
* generated from:
- * NetBSD: usbdevs,v 1.5 1998/10/05 02:30:17 mark Exp
+ * NetBSD: usbdevs,v 1.14 1998/12/30 03:52:30 augustss Exp
*/
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -52,12 +54,24 @@ struct usb_knowndev usb_knowndevs[] = {
"hub",
},
{
+ USB_VENDOR_NEC, USB_PRODUCT_NEC_HUB_B,
+ 0,
+ "NEC",
+ "hub",
+ },
+ {
USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC260,
0,
"Eastman Kodak",
"Digital Science DC260",
},
{
+ USB_VENDOR_CATC, USB_PRODUCT_CATC_ANDROMEDA,
+ 0,
+ "CATC",
+ "Andromeda hub",
+ },
+ {
USB_VENDOR_NANAO, USB_PRODUCT_NANAO_HUB,
0,
"Nanao",
@@ -88,6 +102,12 @@ struct usb_knowndev usb_knowndevs[] = {
"Flight 2000 joystick",
},
{
+ USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_INTELLIMOUSE,
+ 0,
+ "Microsoft",
+ "IntelliMouse",
+ },
+ {
USB_VENDOR_CHERRY, USB_PRODUCT_CHERRY_MY3000KBD,
0,
"Cherry",
@@ -100,6 +120,12 @@ struct usb_knowndev usb_knowndevs[] = {
"My3000 hub",
},
{
+ USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932,
+ 0,
+ "BTC",
+ "Keyboard with mouse port",
+ },
+ {
USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DSS,
0,
"Philips",
@@ -120,16 +146,40 @@ struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_MOUSE,
0,
- "Cypress Semicondutor",
+ "Cypress Semiconductor",
"mouse",
},
{
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U002,
+ USB_VENDOR_3COM, USB_PRODUCT_3COM_USR56K,
0,
- "Belkin",
+ "3Com",
+ "U.S.Robotics 56000 Voice USB Modem",
+ },
+ {
+ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB,
+ 0,
+ "Shuttle Technology",
+ "E-USB Bridge",
+ },
+ {
+ USB_VENDOR_JAZZ, USB_PRODUCT_JAZZ_J6502,
+ 0,
+ "Jazz",
+ "J-6502 speakers",
+ },
+ {
+ USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC1284,
+ 0,
+ "ATen",
"Parallel printer adapter",
},
{
+ USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1,
+ 0,
+ "Peracom",
+ "Serial Converter",
+ },
+ {
USB_VENDOR_EIZO, USB_PRODUCT_EIZO_HUB,
0,
"EIZO",
@@ -142,6 +192,30 @@ struct usb_knowndev usb_knowndevs[] = {
"monitor",
},
{
+ USB_VENDOR_AGILER, USB_PRODUCT_AGILER_MOUSE29UO,
+ 0,
+ "Agiler",
+ "mouse 29UO",
+ },
+ {
+ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U002,
+ 0,
+ "Belkin",
+ "Parallel printer adapter",
+ },
+ {
+ USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_M2452,
+ 0,
+ "Logitech",
+ "M2452 keyboard",
+ },
+ {
+ USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_M4848,
+ 0,
+ "Logitech",
+ "M4848 mouse",
+ },
+ {
USB_VENDOR_EIZONANAO, USB_PRODUCT_EIZONANAO_HUB,
0,
"EIZO Nanao",
@@ -160,6 +234,12 @@ struct usb_knowndev usb_knowndevs[] = {
"mouse",
},
{
+ USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET,
+ 0,
+ "ADS Technologies",
+ "Ethernet adapter",
+ },
+ {
USB_VENDOR_PLX, USB_PRODUCT_PLX_TESTBOARD,
0,
"PLX",
@@ -190,6 +270,12 @@ struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_CATC, 0,
+ USB_KNOWNDEV_NOPROD,
+ "CATC",
+ NULL,
+ },
+ {
USB_VENDOR_NANAO, 0,
USB_KNOWNDEV_NOPROD,
"Nanao",
@@ -208,12 +294,24 @@ struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_MICROSOFT, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Microsoft",
+ NULL,
+ },
+ {
USB_VENDOR_CHERRY, 0,
USB_KNOWNDEV_NOPROD,
"Cherry",
NULL,
},
{
+ USB_VENDOR_BTC, 0,
+ USB_KNOWNDEV_NOPROD,
+ "BTC",
+ NULL,
+ },
+ {
USB_VENDOR_PHILIPS, 0,
USB_KNOWNDEV_NOPROD,
"Philips",
@@ -228,7 +326,37 @@ struct usb_knowndev usb_knowndevs[] = {
{
USB_VENDOR_CYPRESS, 0,
USB_KNOWNDEV_NOPROD,
- "Cypress Semicondutor",
+ "Cypress Semiconductor",
+ NULL,
+ },
+ {
+ USB_VENDOR_3COM, 0,
+ USB_KNOWNDEV_NOPROD,
+ "3Com",
+ NULL,
+ },
+ {
+ USB_VENDOR_SHUTTLE, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Shuttle Technology",
+ NULL,
+ },
+ {
+ USB_VENDOR_JAZZ, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Jazz",
+ NULL,
+ },
+ {
+ USB_VENDOR_ATEN, 0,
+ USB_KNOWNDEV_NOPROD,
+ "ATen",
+ NULL,
+ },
+ {
+ USB_VENDOR_PERACOM, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Peracom",
NULL,
},
{
@@ -238,12 +366,24 @@ struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_AGILER, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Agiler",
+ NULL,
+ },
+ {
USB_VENDOR_BELKIN, 0,
USB_KNOWNDEV_NOPROD,
"Belkin",
NULL,
},
{
+ USB_VENDOR_LOGITECH, 0,
+ USB_KNOWNDEV_NOPROD,
+ "Logitech",
+ NULL,
+ },
+ {
USB_VENDOR_EIZONANAO, 0,
USB_KNOWNDEV_NOPROD,
"EIZO Nanao",
@@ -256,6 +396,12 @@ struct usb_knowndev usb_knowndevs[] = {
NULL,
},
{
+ USB_VENDOR_ADS, 0,
+ USB_KNOWNDEV_NOPROD,
+ "ADS Technologies",
+ NULL,
+ },
+ {
USB_VENDOR_PLX, 0,
USB_KNOWNDEV_NOPROD,
"PLX",
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index 39d1768..cbd0b1e 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,12 +1,13 @@
-/* $NetBSD: usbdi.c,v 1.9 1998/08/02 22:30:53 augustss Exp $ */
-/* FreeBSD $Id: usbdi.c,v 1.4 1999/01/03 16:48:03 n_hibma Exp $ */
+/* $NetBSD: usbdi.c,v 1.19 1999/01/03 01:00:56 augustss Exp $ */
+/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,8 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -52,17 +51,16 @@
#include <sys/malloc.h>
#include <sys/proc.h>
-#include <sys/queue.h>
-#if defined(__FreeBSD__)
-#include "dev/usb/queue.addendum.h"
-#endif
-
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdivar.h>
+#if defined(__FreeBSD__)
+#include "usb_if.h"
+#endif
+
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) printf x
#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
@@ -77,7 +75,6 @@ static usbd_status usbd_ar_iface __P((usbd_interface_handle iface));
static void usbd_transfer_cb __P((usbd_request_handle reqh));
static void usbd_sync_transfer_cb __P((usbd_request_handle reqh));
static usbd_status usbd_do_transfer __P((usbd_request_handle reqh));
-static usbd_status usbd_start __P((usbd_pipe_handle pipe));
void usbd_do_request_async_cb
__P((usbd_request_handle, usbd_private_handle, usbd_status));
@@ -98,7 +95,8 @@ usbd_open_pipe(iface, address, flags, pipe)
{
usbd_pipe_handle p;
struct usbd_endpoint *ep;
- int i, r;
+ usbd_status r;
+ int i;
if (iface->state != USBD_INTERFACE_ACTIVE)
return (USBD_INTERFACE_NOT_ACTIVE);
@@ -223,9 +221,18 @@ usbd_do_transfer(reqh)
usbd_request_handle reqh;
{
usbd_pipe_handle pipe = reqh->pipe;
- usbd_interface_handle iface = pipe->iface;
- usbd_status r;
- int s;
+
+ DPRINTFN(10,("usbd_do_transfer: reqh=%p\n", reqh));
+ reqh->done = 0;
+ return (pipe->methods->transfer(reqh));
+}
+
+#if 0
+static usbd_status
+usbd_do_transfer(reqh)
+ usbd_request_handle reqh;
+{
+ usbd_pipe_handle pipe = reqh->pipe;
DPRINTFN(10,("usbd_do_transfer: reqh=%p\n", reqh));
reqh->done = 0;
@@ -267,7 +274,7 @@ usbd_start(pipe)
pipe->curreqh = reqh;
return (pipe->methods->transfer(reqh));
}
-
+#endif
usbd_request_handle
usbd_alloc_request()
@@ -429,13 +436,14 @@ usbd_interface2endpoint_descriptor(iface, index)
u_int8_t index;
{
if (index >= iface->idesc->bNumEndpoints)
- return 0;
+ return (0);
return (iface->endpoints[index].edesc);
}
-usbd_status usbd_set_configuration(dev, conf)
+usbd_status
+usbd_set_configuration(dev, conf)
usbd_device_handle dev;
- u_int16_t conf;
+ u_int8_t conf;
{
return usbd_set_config_no(dev, conf, 0);
}
@@ -528,7 +536,7 @@ usbd_clear_endpoint_stall(pipe)
req.bmRequestType = UT_WRITE_ENDPOINT;
req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_STALL);
+ USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
r = usbd_do_request(dev, &req, 0);
@@ -552,7 +560,7 @@ usbd_clear_endpoint_stall_async(pipe)
req.bmRequestType = UT_WRITE_ENDPOINT;
req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_STALL);
+ USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
r = usbd_do_request_async(dev, &req, 0);
@@ -565,6 +573,8 @@ usbd_set_pipe_state(pipe, state)
usbd_pipe_state state;
{
int s;
+ usbd_status r;
+ usbd_request_handle reqh;
if (pipe->iface->state != USBD_INTERFACE_ACTIVE)
return (USBD_INTERFACE_NOT_ACTIVE);
@@ -573,12 +583,21 @@ usbd_set_pipe_state(pipe, state)
state != USBD_PIPE_IDLE)
return (USBD_INVAL);
pipe->state = state;
+ r = USBD_NORMAL_COMPLETION;
if (state == USBD_PIPE_ACTIVE) {
s = splusb();
- usbd_start(pipe);
- splx(s);
+ if (!pipe->running) {
+ reqh = SIMPLEQ_FIRST(&pipe->queue);
+ if (reqh != 0) {
+ pipe->running = 1;
+ splx(s);
+ r = pipe->methods->start(reqh);
+ } else
+ splx(s);
+ } else
+ splx(s);
}
- return (USBD_NORMAL_COMPLETION);
+ return (r);
}
usbd_status
@@ -689,10 +708,6 @@ usbd_interface_count(dev, count)
}
#if defined(__NetBSD__)
-/* Do we need these?
- * Alternative: let people probe every single device node they can
- * find for valid devices instead of counting through n of them.
- */
u_int8_t
usbd_bus_count()
{
@@ -838,22 +853,78 @@ usbd_unlock(tok)
splx(tok);
}
-/* XXX need to check that the interface is idle */
+/* XXXX use altno */
usbd_status
-usbd_set_interface(iface, aiface)
+usbd_set_interface(iface, altidx)
usbd_interface_handle iface;
- int aiface;
+ int altidx;
{
usb_device_request_t req;
+ usbd_status r;
+
+ if (LIST_FIRST(&iface->pipes) != 0)
+ return (USBD_IN_USE);
+
+ if (iface->endpoints)
+ free(iface->endpoints, M_USB);
+ iface->endpoints = 0;
+ iface->idesc = 0;
+ iface->state = USBD_INTERFACE_IDLE;
+
+ r = usbd_fill_iface_data(iface->device, iface->index, altidx);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
req.bmRequestType = UT_WRITE_INTERFACE;
req.bRequest = UR_SET_INTERFACE;
- USETW(req.wValue, aiface);
- USETW(req.wIndex, iface->idesc->iInterface);
+ USETW(req.wValue, iface->idesc->bAlternateSetting);
+ USETW(req.wIndex, iface->idesc->bInterfaceNumber);
USETW(req.wLength, 0);
return usbd_do_request(iface->device, &req, 0);
}
+int
+usbd_get_no_alts(cdesc, ifaceno)
+ usb_config_descriptor_t *cdesc;
+ int ifaceno;
+{
+ char *p = (char *)cdesc;
+ char *end = p + UGETW(cdesc->wTotalLength);
+ usb_interface_descriptor_t *d;
+ int n;
+
+ for (n = 0; p < end; p += d->bLength) {
+ d = (usb_interface_descriptor_t *)p;
+ if (p + d->bLength <= end &&
+ d->bDescriptorType == UDESC_INTERFACE &&
+ d->bInterfaceNumber == ifaceno)
+ n++;
+ }
+ return (n);
+}
+
+int
+usbd_get_interface_altindex(iface)
+ usbd_interface_handle iface;
+{
+ return (iface->altindex);
+}
+
+usbd_status
+usbd_get_interface(iface, aiface)
+ usbd_interface_handle iface;
+ u_int8_t *aiface;
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_READ_INTERFACE;
+ req.bRequest = UR_GET_INTERFACE;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, iface->idesc->bInterfaceNumber);
+ USETW(req.wLength, 1);
+ return usbd_do_request(iface->device, &req, aiface);
+}
+
/*** Internal routines ***/
/* Dequeue all pipe operations, called at splusb(). */
@@ -863,9 +934,6 @@ usbd_ar_pipe(pipe)
{
usbd_request_handle reqh;
- if (pipe->curreqh != 0)
- pipe->methods->abort(pipe->curreqh);
-
for (;;) {
reqh = SIMPLEQ_FIRST(&pipe->queue);
if (reqh == 0)
@@ -919,8 +987,6 @@ usbd_transfer_cb(reqh)
usbd_request_handle reqh;
{
usbd_pipe_handle pipe = reqh->pipe;
- usbd_request_handle nreqh;
- usbd_status r;
/* Count completed transfers. */
++pipe->device->bus->stats.requests
@@ -931,29 +997,12 @@ usbd_transfer_cb(reqh)
if (reqh->status == USBD_NORMAL_COMPLETION &&
reqh->actlen < reqh->length &&
!(reqh->flags & USBD_SHORT_XFER_OK)) {
- DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d+1<%d+1 (bytes)\n",
+ DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
reqh->actlen, reqh->length));
reqh->status = USBD_SHORT_XFER;
}
- pipe->curreqh = 0;
if (reqh->callback)
reqh->callback(reqh, reqh->priv, reqh->status);
-
- if (pipe->state != USBD_PIPE_ACTIVE) {
- pipe->running = 0;
- return;
- }
- nreqh = SIMPLEQ_FIRST(&pipe->queue);
- DPRINTFN(5, ("usbd_transfer_cb: nreqh=%p\n", nreqh));
- if (!nreqh)
- pipe->running = 0;
- else {
- SIMPLEQ_REMOVE_HEAD(&pipe->queue, nreqh, next);
- pipe->curreqh = nreqh;
- r = pipe->methods->transfer(nreqh);
- if (r != USBD_IN_PROGRESS)
- printf("usbd_transfer_cb: error=%d\n", r);
- }
}
static void
@@ -993,6 +1042,17 @@ usbd_do_request(dev, req, data)
usb_device_request_t *req;
void *data;
{
+ return (usbd_do_request_flags(dev, req, data, 0, 0));
+}
+
+usbd_status
+usbd_do_request_flags(dev, req, data, flags, actlen)
+ usbd_device_handle dev;
+ usb_device_request_t *req;
+ void *data;
+ u_int16_t flags;
+ int *actlen;
+{
usbd_request_handle reqh;
usbd_status r;
@@ -1008,21 +1068,66 @@ usbd_do_request(dev, req, data)
return (USBD_NOMEM);
r = usbd_setup_default_request(
reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
- UGETW(req->wLength), 0, 0);
- if (r != USBD_NORMAL_COMPLETION) {
- usbd_free_request(reqh);
- return (r);
- }
+ UGETW(req->wLength), flags, 0);
+ if (r != USBD_NORMAL_COMPLETION)
+ goto bad;
r = usbd_sync_transfer(reqh);
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
if (reqh->actlen > reqh->length)
- printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
+ printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
+ "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
dev->address, reqh->request.bmRequestType,
reqh->request.bRequest, UGETW(reqh->request.wValue),
UGETW(reqh->request.wIndex),
UGETW(reqh->request.wLength),
reqh->length, reqh->actlen);
#endif
+ if (actlen)
+ *actlen = reqh->actlen;
+ if (r == USBD_STALLED) {
+ /*
+ * The control endpoint has stalled. Control endpoints
+ * should not halt, but some may do so anyway so clear
+ * any halt condition.
+ */
+ usb_device_request_t treq;
+ usb_status_t status;
+ u_int16_t s;
+ usbd_status nr;
+
+ treq.bmRequestType = UT_READ_ENDPOINT;
+ treq.bRequest = UR_GET_STATUS;
+ USETW(treq.wValue, 0);
+ USETW(treq.wIndex, 0);
+ USETW(treq.wLength, sizeof(usb_status_t));
+ nr = usbd_setup_default_request(
+ reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
+ sizeof(usb_status_t), 0, 0);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ nr = usbd_sync_transfer(reqh);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ s = UGETW(status.wStatus);
+ DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
+ if (!(s & UES_HALT))
+ goto bad;
+ treq.bmRequestType = UT_WRITE_ENDPOINT;
+ treq.bRequest = UR_CLEAR_FEATURE;
+ USETW(treq.wValue, UF_ENDPOINT_HALT);
+ USETW(treq.wIndex, 0);
+ USETW(treq.wLength, 0);
+ nr = usbd_setup_default_request(
+ reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
+ 0, 0, 0);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ nr = usbd_sync_transfer(reqh);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ }
+
+ bad:
usbd_free_request(reqh);
return (r);
}
@@ -1035,7 +1140,8 @@ usbd_do_request_async_cb(reqh, priv, status)
{
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
if (reqh->actlen > reqh->length)
- printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
+ printf("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
+ "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
reqh->pipe->device->address,
reqh->request.bmRequestType,
reqh->request.bRequest, UGETW(reqh->request.wValue),
@@ -1111,3 +1217,119 @@ usbd_set_polling(iface, on)
{
iface->device->bus->use_polling = on;
}
+
+
+usb_endpoint_descriptor_t *
+usbd_get_endpoint_descriptor(iface, address)
+ usbd_interface_handle iface;
+ u_int8_t address;
+{
+ struct usbd_endpoint *ep;
+ int i;
+
+ for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
+ ep = &iface->endpoints[i];
+ if (ep->edesc->bEndpointAddress == address)
+ return (iface->endpoints[i].edesc);
+ }
+ return (0);
+}
+
+#if defined(__FreeBSD__)
+void
+usbd_print_child(device_t parent, device_t child)
+{
+ /*
+ struct usb_softc *sc = device_get_softc(child);
+ */
+
+ printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
+
+ /* XXX How do we get to the usbd_device_handle???
+ usbd_device_handle dev = invalidadosch;
+
+ printf(" addr %d", dev->addr);
+
+ if (bootverbose) {
+ if (dev->lowspeed)
+ printf(", lowspeed");
+ if (dev->self_powered)
+ printf(", self powered");
+ else
+ printf(", %dmA", dev->power);
+ printf(", config %d", dev->config);
+ }
+ */
+}
+
+/* Reconfigure all the USB busses in the system. */
+int
+usbd_driver_load(module_t mod, int what, void *arg)
+{
+ devclass_t usb_devclass = devclass_find("usb");
+ devclass_t ugen_devclass = devclass_find("ugen");
+ device_t *devlist;
+ int devcount;
+ int error;
+
+ switch (what) {
+ case MOD_LOAD:
+ case MOD_UNLOAD:
+ if (!usb_devclass)
+ return 0; /* just ignore call */
+
+ if (ugen_devclass) {
+ /* detach devices from generic driver if possible */
+ error = devclass_get_devices(ugen_devclass, &devlist,
+ &devcount);
+ if (!error)
+ for (devcount--; devcount >= 0; devcount--)
+ (void)DEVICE_DETACH(devlist[devcount]);
+ }
+
+ error = devclass_get_devices(usb_devclass, &devlist, &devcount);
+ if (error)
+ return 0; /* XXX maybe transient, or error? */
+
+ for (devcount--; devcount >= 0; devcount--)
+ USB_RECONFIGURE(devlist[devcount]);
+
+ free(devlist, M_TEMP);
+ return 0;
+ }
+
+ return 0; /* nothing to do by us */
+}
+
+/* Set the description of the device including a malloc and copy. */
+void
+usbd_device_set_desc(device_t device, char *devinfo)
+{
+ size_t l;
+ char *desc;
+
+ if ( devinfo ) {
+ l = strlen(devinfo);
+ desc = malloc(l+1, M_USB, M_NOWAIT);
+ if (desc)
+ memcpy(desc, devinfo, l+1);
+ } else
+ desc = NULL;
+
+ device_set_desc(device, desc);
+}
+
+/*
+ * A static buffer is a loss if this routine is used from an interrupt,
+ * but it's not fatal.
+ */
+char *
+usbd_devname(bdevice *bdev)
+{
+ static char buf[20];
+
+ sprintf(buf, "%s%d", device_get_name(*bdev), device_get_unit(*bdev));
+ return (buf);
+}
+
+#endif
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index fe8c19f..8f55297 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -1,12 +1,13 @@
-/* $NetBSD: usbdi.h,v 1.6 1998/08/02 22:30:53 augustss Exp $ */
+/* $NetBSD: usbdi.h,v 1.15 1999/01/03 01:00:56 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -92,6 +93,7 @@ typedef enum {
USBD_TIMEOUT,
USBD_SHORT_XFER,
USBD_STALLED,
+ USBD_INTERRUPTED,
USBD_XXX,
} usbd_status;
@@ -143,7 +145,7 @@ usb_descriptor_t *usbd_get_descriptor
usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor
__P((usbd_interface_handle iface, u_int8_t address));
usbd_status usbd_set_configuration
- __P((usbd_device_handle dev, u_int16_t conf));
+ __P((usbd_device_handle dev, u_int8_t conf));
usbd_status usbd_retry_request
__P((usbd_request_handle reqh, u_int32_t retry_count));
usbd_status usbd_abort_pipe __P((usbd_pipe_handle pipe));
@@ -216,6 +218,9 @@ usbd_status usbd_do_request
__P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
usbd_status usbd_do_request_async
__P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
+usbd_status usbd_do_request_flags
+ __P((usbd_device_handle pipe, usb_device_request_t *req,
+ void *data, u_int16_t flags, int *));
usb_interface_descriptor_t *usbd_get_interface_descriptor
__P((usbd_interface_handle iface));
usb_config_descriptor_t *usbd_get_config_descriptor
@@ -223,6 +228,18 @@ usb_config_descriptor_t *usbd_get_config_descriptor
usb_device_descriptor_t *usbd_get_device_descriptor
__P((usbd_device_handle dev));
usbd_status usbd_set_interface __P((usbd_interface_handle, int));
+int usbd_get_no_alts __P((usb_config_descriptor_t *, int));
+usbd_status usbd_get_interface
+ __P((usbd_interface_handle iface, u_int8_t *aiface));
+void usbd_fill_deviceinfo
+ __P((usbd_device_handle dev, struct usb_device_info *di));
+int usbd_get_interface_altindex __P((usbd_interface_handle iface));
+
+usb_interface_descriptor_t *usbd_find_idesc
+ __P((usb_config_descriptor_t *cd, int iindex, int ano));
+usb_endpoint_descriptor_t *usbd_find_edesc
+ __P((usb_config_descriptor_t *cd, int ifaceidx, int altidx,
+ int endptidx));
void usbd_dopoll __P((usbd_interface_handle));
void usbd_set_polling __P((usbd_interface_handle iface, int on));
@@ -231,9 +248,14 @@ void usbd_set_polling __P((usbd_interface_handle iface, int on));
/* Attach data */
struct usb_attach_arg {
- struct usbd_device *device;
- struct usbd_interface *iface;
+ int port;
+ int configno;
+ int ifaceno;
+ usbd_device_handle device; /* current device */
+ usbd_interface_handle iface; /* current interface */
int usegeneric;
+ usbd_interface_handle *ifaces; /* all interfaces */
+ int nifaces; /* number of interfaces */
};
#if defined(__NetBSD__)
@@ -302,3 +324,18 @@ struct usb_attach_arg {
void usbd_devinfo __P((usbd_device_handle, int, char *));
struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
void usbd_set_disco __P((usbd_pipe_handle, void (*)(void *), void *));
+usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
+ __P((usbd_interface_handle iface, u_int8_t address));
+
+#if defined(__FreeBSD__)
+int usbd_driver_load __P((module_t mod, int what, void *arg));
+void usbd_device_set_desc __P((device_t device, char *devinfo));
+char *usbd_devname(bdevice *bdev);
+bus_print_child_t usbd_print_child;
+#endif
+
+/* XXX */
+#define splusb splbio
+#define IPL_USB IPL_BIO
+/* XXX */
+
diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c
index 2d8160e..f94a35e0 100644
--- a/sys/dev/usb/usbdi_util.c
+++ b/sys/dev/usb/usbdi_util.c
@@ -1,12 +1,13 @@
-/* $NetBSD: usbdi_util.c,v 1.4 1998/08/02 22:30:53 augustss Exp $ */
+/* $NetBSD: usbdi_util.c,v 1.11 1999/01/03 01:00:56 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,16 +38,14 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <dev/usb/usb_port.h>
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
-#if defined(__NetBSD__)
-#include <sys/device.h>
-#endif
#include <sys/proc.h>
+#if defined(__FreeBSD__)
+#include <sys/bus.h>
+#endif
#include <sys/select.h>
#include <dev/usb/usb.h>
@@ -87,9 +86,19 @@ usbd_get_config_desc(dev, conf, d)
int conf;
usb_config_descriptor_t *d;
{
+ usbd_status r;
+
DPRINTFN(3,("usbd_get_config_desc: conf=%d\n", conf));
- return (usbd_get_desc(dev, UDESC_CONFIG,
- conf, USB_CONFIG_DESCRIPTOR_SIZE, d));
+ r = usbd_get_desc(dev, UDESC_CONFIG, conf,
+ USB_CONFIG_DESCRIPTOR_SIZE, d);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ if (d->bDescriptorType != UDESC_CONFIG) {
+ DPRINTFN(-1,("usbd_get_config_desc: conf %d, bad desc %d\n",
+ conf, d->bDescriptorType));
+ return (USBD_INVAL);
+ }
+ return (USBD_NORMAL_COMPLETION);
}
usbd_status
@@ -217,6 +226,8 @@ usbd_set_protocol(iface, report)
DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n",
iface, report, id->bInterfaceNumber));
+ if (!id)
+ return (USBD_IOERROR);
r = usbd_interface2device_handle(iface, &dev);
if (r != USBD_NORMAL_COMPLETION)
return (r);
@@ -244,6 +255,8 @@ usbd_set_report(iface, type, id, data, len)
usbd_status r;
DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
+ if (!ifd)
+ return (USBD_IOERROR);
r = usbd_interface2device_handle(iface, &dev);
if (r != USBD_NORMAL_COMPLETION)
return (r);
@@ -271,6 +284,8 @@ usbd_set_report_async(iface, type, id, data, len)
usbd_status r;
DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
+ if (!ifd)
+ return (USBD_IOERROR);
r = usbd_interface2device_handle(iface, &dev);
if (r != USBD_NORMAL_COMPLETION)
return (r);
@@ -298,6 +313,8 @@ usbd_get_report(iface, type, id, data, len)
usbd_status r;
DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
+ if (!id)
+ return (USBD_IOERROR);
r = usbd_interface2device_handle(iface, &dev);
if (r != USBD_NORMAL_COMPLETION)
return (r);
@@ -323,6 +340,8 @@ usbd_set_idle(iface, duration, id)
usbd_status r;
DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id));
+ if (!ifd)
+ return (USBD_IOERROR);
r = usbd_interface2device_handle(iface, &dev);
if (r != USBD_NORMAL_COMPLETION)
return (r);
@@ -365,6 +384,8 @@ usbd_get_hid_descriptor(ifc)
char *p, *end;
usbd_status r;
+ if (!idesc)
+ return (0);
r = usbd_interface2device_handle(ifc, &dev);
if (r != USBD_NORMAL_COMPLETION)
return (0);
@@ -414,11 +435,77 @@ usbd_alloc_report_desc(ifc, descp, sizep, mem)
if (!*descp)
return (USBD_NOMEM);
/* XXX should not use 0 Report ID */
- r = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0,
- *sizep, *descp);
+ r = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0,
+ *sizep, *descp);
if (r != USBD_NORMAL_COMPLETION) {
free(*descp, mem);
return (r);
}
return (USBD_NORMAL_COMPLETION);
}
+
+usbd_status
+usbd_get_config(dev, conf)
+ usbd_device_handle dev;
+ u_int8_t *conf;
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_READ_DEVICE;
+ req.bRequest = UR_GET_CONFIG;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 1);
+ return (usbd_do_request(dev, &req, conf));
+}
+
+static void usbd_bulk_transfer_cb __P((usbd_request_handle reqh,
+ usbd_private_handle priv, usbd_status status));
+static void
+usbd_bulk_transfer_cb(reqh, priv, status)
+ usbd_request_handle reqh;
+ usbd_private_handle priv;
+ usbd_status status;
+{
+ wakeup(reqh);
+}
+
+usbd_status
+usbd_bulk_transfer(reqh, pipe, flags, buf, size, lbl)
+ usbd_request_handle reqh;
+ usbd_pipe_handle pipe;
+ u_int16_t flags;
+ void *buf;
+ u_int32_t *size;
+ char *lbl;
+{
+ usbd_private_handle priv;
+ void *buffer;
+ usbd_status r;
+ int s, error;
+
+ r = usbd_setup_request(reqh, pipe, 0, buf, *size,
+ flags, USBD_NO_TIMEOUT, usbd_bulk_transfer_cb);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ DPRINTFN(1, ("usbd_bulk_transfer: transfer %d bytes\n", *size));
+ s = splusb(); /* don't want callback until tsleep() */
+ r = usbd_transfer(reqh);
+ if (r != USBD_IN_PROGRESS) {
+ splx(s);
+ return (r);
+ }
+ error = tsleep((caddr_t)reqh, PZERO | PCATCH, lbl, 0);
+ splx(s);
+ if (error) {
+ usbd_abort_pipe(pipe);
+ return (USBD_INTERRUPTED);
+ }
+ usbd_get_request_status(reqh, &priv, &buffer, size, &r);
+ if (r != USBD_NORMAL_COMPLETION) {
+ DPRINTF(("ugenread: error=%d\n", r));
+ usbd_clear_endpoint_stall(pipe);
+ }
+ return (r);
+}
+
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index b27022c..f5d700d 100644
--- a/sys/dev/usb/usbdi_util.h
+++ b/sys/dev/usb/usbdi_util.h
@@ -1,12 +1,13 @@
-/* $NetBSD: usbdi_util.h,v 1.4 1998/08/02 22:30:53 augustss Exp $ */
+/* $NetBSD: usbdi_util.h,v 1.12 1999/01/01 15:25:57 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -73,3 +74,19 @@ usbd_status usbd_alloc_report_desc
usbd_status usbd_alloc_report_desc
__P((usbd_interface_handle ifc, void **descp, int *sizep, struct malloc_type * mem));
#endif
+usbd_status usbd_get_config
+ __P((usbd_device_handle dev, u_int8_t *conf));
+usbd_status usbd_get_string_desc
+ __P((usbd_device_handle dev, int sindex, int langid,
+ usb_string_descriptor_t *sdesc));
+void usbd_delay_ms __P((usbd_device_handle, u_int));
+
+
+usbd_status usbd_set_config_no
+ __P((usbd_device_handle dev, int no, int msg));
+usbd_status usbd_set_config_index
+ __P((usbd_device_handle dev, int index, int msg));
+
+usbd_status usbd_bulk_transfer
+ __P((usbd_request_handle reqh, usbd_pipe_handle pipe, u_int16_t flags,
+ void *buf, u_int32_t *size, char *lbl));
diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
index c2cd600..6dae067 100644
--- a/sys/dev/usb/usbdivar.h
+++ b/sys/dev/usb/usbdivar.h
@@ -1,11 +1,13 @@
+/* $NetBSD: usbdivar.h,v 1.14 1998/12/30 18:06:25 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,18 +38,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(__FreeBSD__)
-/* conversiom from one type of queue to the other */
-#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD_QUEUE
-#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD
-#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL
-#define SIMPLEQ_NEXT STAILQ_NEXT
-#define SIMPLEQ_FIRST STAILQ_FIRST
-#define SIMPLEQ_HEAD STAILQ_HEAD
-#define SIMPLEQ_INIT STAILQ_INIT
-#define SIMPLEQ_ENTRY STAILQ_ENTRY
-#endif
-
struct usbd_request;
struct usbd_pipe;
@@ -62,6 +52,7 @@ typedef void (*usbd_xfercb)__P((usbd_request_handle req));
struct usbd_methods {
usbd_status (*transfer)__P((usbd_request_handle reqh));
+ usbd_status (*start)__P((usbd_request_handle reqh));
void (*abort)__P((usbd_request_handle reqh));
void (*close)__P((usbd_pipe_handle pipe));
usbd_status (*isobuf)__P((usbd_pipe_handle pipe,
@@ -70,16 +61,18 @@ struct usbd_methods {
struct usbd_port {
usb_port_status_t status;
- int power; /* mA of current on port */
+ u_int16_t power; /* mA of current on port */
+ u_int8_t portno;
+ u_int8_t restartcnt;
+#define USBD_RESTART_MAX 5
struct usbd_device *device;
struct usbd_device *parent; /* The ports hub */
};
struct usbd_hub {
usbd_status (*explore)__P((usbd_device_handle hub));
- void *hubdata;
+ void *hubsoftc;
usb_hub_descriptor_t hubdesc;
- int nports;
struct usbd_port ports[1];
};
@@ -112,6 +105,8 @@ struct usbd_device {
u_int16_t power;
u_int8_t self_powered;
int config;
+ int langid; /* language to use for strings */
+#define USBD_NOLANG (-1)
struct usbd_port *powersrc;
struct usbd_endpoint def_ep; /* for pipe 0 */
usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */
@@ -120,15 +115,15 @@ struct usbd_device {
usb_config_descriptor_t *cdesc; /* full config descr */
struct usbd_quirks *quirks;
struct usbd_hub *hub; /* only if this is a hub */
-#if defined(__FreeBSD__)
- bdevice bdev; /* base device */
-#endif
+ void *softc; /* device softc if attached */
};
struct usbd_interface {
struct usbd_device *device;
usbd_interface_state state;
usb_interface_descriptor_t *idesc;
+ int index;
+ int altindex;
struct usbd_endpoint *endpoints;
void *priv;
LIST_HEAD(, usbd_pipe) pipes;
@@ -148,7 +143,6 @@ struct usbd_pipe {
void *discoarg;
usbd_request_handle intrreqh; /* used for repeating requests */
- usbd_request_handle curreqh; /* currently running request */
/* Filled by HC driver. */
struct usbd_methods *methods;
@@ -184,7 +178,7 @@ void usbd_init __P((void));
/* Routines from usb_subr.c */
int usbctlprint __P((void *, const char *));
-void usbd_delay_ms __P((usbd_bus_handle, int));
+void usb_delay_ms __P((usbd_bus_handle, u_int));
void usbd_devinfo_vp __P((usbd_device_handle, char *, char *));
usbd_status usbd_set_config_no __P((usbd_device_handle, int, int));
usbd_status usbd_reset_port __P((usbd_device_handle dev,
@@ -200,38 +194,38 @@ usbd_status usbd_new_device __P((bdevice *parent,
void usbd_remove_device __P((usbd_device_handle,
struct usbd_port *));
int usbd_printBCD __P((char *cp, int bcd));
+usbd_status usb_insert_transfer __P((usbd_request_handle reqh));
+void usb_start_next __P((usbd_pipe_handle pipe));
+usbd_status usbd_fill_iface_data __P((usbd_device_handle dev,
+ int i, int a));
/* Routines from usb.c */
-int usb_bus_count __P((void));
+int usb_bus_count __P((void));
usbd_status usb_get_bus_handle __P((int, usbd_bus_handle *));
-void usb_needs_explore __P((usbd_bus_handle));
+void usb_needs_explore __P((usbd_bus_handle));
-#if defined(__FreeBSD__)
-int usb_driver_load __P((module_t mod, int what, void *arg));
-void usb_device_set_desc __P((device_t device, char *devinfo));
-#endif
extern int usbd_use_polling;
/* Locator stuff. */
#if defined(__NetBSD__)
-/* NWH File not found anywhere in NetBSD sources... */
#include "locators.h"
+#elif defined(__FreeBSD__)
+/* XXX these values are used to statically bind some elements in the USB tree
+ * to specific driver instances. This should be somehow emulated in FreeBSD
+ * but can be done later on.
+ * The values are copied from the files.usb file in the NetBSD sources.
+ */
+#define UHUBCF_PORT_DEFAULT -1
+#define UHUBCF_CONFIGURATION_DEFAULT -1
+#define UHUBCF_INTERFACE_DEFAULT -1
#endif
-#define uhubcf_port cf_loc[UHUBCF_PORT]
-#define uhubcf_configuration cf_loc[UHUBCF_CONFIGURATION]
-#define uhubcf_interface cf_loc[UHUBCF_INTERFACE]
-#define UHUB_UNK_PORT UHUBCF_PORT_DEFAULT /* wildcarded 'port' */
-#define UHUB_UNK_CONFIGURATION UHUBCF_CONFIGURATION_DEFAULT /* wildcarded 'configuration' */
-#define UHUB_UNK_INTERFACE UHUBCF_INTERFACE_DEFAULT /* wildcarded 'interface' */
-
-
-/* Junk. */
-
-/* XXX */
-#define splusb splbio
-#define IPL_USB IPL_BIO
-/* XXX */
+#define uhubcf_port cf_loc[UHUBCF_PORT]
+#define uhubcf_configuration cf_loc[UHUBCF_CONFIGURATION]
+#define uhubcf_interface cf_loc[UHUBCF_INTERFACE]
+#define UHUB_UNK_PORT UHUBCF_PORT_DEFAULT /* wildcarded 'port' */
+#define UHUB_UNK_CONFIGURATION UHUBCF_CONFIGURATION_DEFAULT /* wildcarded 'configuration' */
+#define UHUB_UNK_INTERFACE UHUBCF_INTERFACE_DEFAULT /* wildcarded 'interface' */
diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h
index 1fbde0c..edec413 100644
--- a/sys/dev/usb/usbhid.h
+++ b/sys/dev/usb/usbhid.h
@@ -1,12 +1,13 @@
-/* $NetBSD: usbhid.h,v 1.1 1998/07/12 19:52:01 augustss Exp $ */
+/* $NetBSD: usbhid.h,v 1.3 1998/12/26 12:53:04 augustss Exp $ */
/* FreeBSD $Id$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
- * Author: Lennart Augustsson <augustss@carlstedt.se>
- * Carlstedt Research & Technology
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
OpenPOWER on IntegriCloud