diff options
author | n_hibma <n_hibma@FreeBSD.org> | 1999-01-07 23:07:57 +0000 |
---|---|---|
committer | n_hibma <n_hibma@FreeBSD.org> | 1999-01-07 23:07:57 +0000 |
commit | f85edabd28f8c9ebaeed20a6bdb7ddef1ff1c098 (patch) | |
tree | c8f677155dd2322c9b2477c85e8f2959ef963429 /sys/dev/usb | |
parent | b118bd4907acdfd7a8cb3f83f50f0219e395b4a3 (diff) | |
download | FreeBSD-src-f85edabd28f8c9ebaeed20a6bdb7ddef1ff1c098.zip FreeBSD-src-f85edabd28f8c9ebaeed20a6bdb7ddef1ff1c098.tar.gz |
Major synchronisation with NetBSD USB code
Diffstat (limited to 'sys/dev/usb')
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 |