diff options
| author | augustss <augustss@NetBSD.org> | 1998-12-26 12:53:00 +0000 |
|---|---|---|
| committer | augustss <augustss@NetBSD.org> | 1998-12-26 12:53:00 +0000 |
| commit | e0c228ae9ccccf6f66a1aa9af09b93b1aecd7218 (patch) | |
| tree | 88502f87b0b8f6cf6a605dea707b6a8657c6275b /sys/dev | |
| parent | fbff13e33e5a1d7fbf790ac60cfd70868190330e (diff) | |
Merge changes to make the USB stack work with FreeBSD. The original
diffs from Nick Hibma <n_hibma@freebsd.org>, but with substantial
changes from me.
XXX Not tested on FreeBSD yet.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/usb/hid.c | 8 | ||||
| -rw-r--r-- | sys/dev/usb/ohci.c | 150 | ||||
| -rw-r--r-- | sys/dev/usb/ohcivar.h | 10 | ||||
| -rw-r--r-- | sys/dev/usb/ucom.c | 64 | ||||
| -rw-r--r-- | sys/dev/usb/ugen.c | 56 | ||||
| -rw-r--r-- | sys/dev/usb/uhci.c | 121 | ||||
| -rw-r--r-- | sys/dev/usb/uhcivar.h | 12 | ||||
| -rw-r--r-- | sys/dev/usb/uhid.c | 113 | ||||
| -rw-r--r-- | sys/dev/usb/uhub.c | 277 | ||||
| -rw-r--r-- | sys/dev/usb/ukbd.c | 127 | ||||
| -rw-r--r-- | sys/dev/usb/ulpt.c | 95 | ||||
| -rw-r--r-- | sys/dev/usb/umodem.c | 68 | ||||
| -rw-r--r-- | sys/dev/usb/ums.c | 527 | ||||
| -rw-r--r-- | sys/dev/usb/usb.c | 216 | ||||
| -rw-r--r-- | sys/dev/usb/usb.h | 50 | ||||
| -rw-r--r-- | sys/dev/usb/usb_mem.h | 34 | ||||
| -rw-r--r-- | sys/dev/usb/usb_port.h | 180 | ||||
| -rw-r--r-- | sys/dev/usb/usb_quirks.c | 6 | ||||
| -rw-r--r-- | sys/dev/usb/usb_subr.c | 288 | ||||
| -rw-r--r-- | sys/dev/usb/usbdi.c | 85 | ||||
| -rw-r--r-- | sys/dev/usb/usbdi.h | 44 | ||||
| -rw-r--r-- | sys/dev/usb/usbdi_util.c | 24 | ||||
| -rw-r--r-- | sys/dev/usb/usbdi_util.h | 7 | ||||
| -rw-r--r-- | sys/dev/usb/usbdivar.h | 30 | ||||
| -rw-r--r-- | sys/dev/usb/usbhid.h | 37 |
25 files changed, 1958 insertions, 671 deletions
diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c index 1b9614c57a9..41948f17391 100644 --- a/sys/dev/usb/hid.c +++ b/sys/dev/usb/hid.c @@ -1,4 +1,4 @@ -/* $NetBSD: hid.c,v 1.4 1998/12/08 14:31:58 augustss Exp $ */ +/* $NetBSD: hid.c,v 1.5 1998/12/26 12:53:00 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -50,7 +50,7 @@ #ifdef USB_DEBUG #define DPRINTF(x) if (usbdebug) printf x #define DPRINTFN(n,x) if (usbdebug>(n)) printf x -int usbdebug; +extern int usbdebug; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -426,7 +426,7 @@ hid_get_data(buf, loc) u_int32_t data; int i, s; - DPRINTFN(1, ("hid_get_data: loc %d/%d\n", hpos, hsize)); + DPRINTFN(10, ("hid_get_data: loc %d/%d\n", hpos, hsize)); if (hsize == 0) return (0); @@ -440,7 +440,7 @@ hid_get_data(buf, loc) hsize = 32 - hsize; /* Sign extend */ data = ((int32_t)data << hsize) >> hsize; - DPRINTFN(2,("hid_get_data: loc %d/%d = %lu\n", + DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n", loc->pos, loc->size, (long)data)); return (data); } diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 5b8edd025fd..39b1cf62160 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.14 1998/12/10 23:16:47 augustss Exp $ */ +/* $NetBSD: ohci.c,v 1.15 1998/12/26 12:53:01 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -48,7 +48,12 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#if defined(__NetBSD__) #include <sys/device.h> +#elif defined(__FreeBSD__) +#include <sys/module.h> +#include <sys/bus.h> +#endif #include <sys/proc.h> #include <sys/queue.h> #include <sys/select.h> @@ -64,7 +69,13 @@ #include <dev/usb/ohcireg.h> #include <dev/usb/ohcivar.h> -int ohcidebug = 0; +#if defined(__FreeBSD__) +#include <machine/clock.h> +#include "dev/usb/queue.addendum.h" + +#define delay(d) DELAY(d) + +#endif struct ohci_pipe; @@ -79,6 +90,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)); @@ -125,9 +137,15 @@ void ohci_dump_td __P((ohci_soft_td_t *)); void ohci_dump_ed __P((ohci_soft_ed_t *)); #endif +#if defined(__NetBSD__) #define OWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) #define OREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) #define OREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) +#elif defined(__FreeBSD__) +#define OWRITE4(sc, r, x) outl((sc)->sc_iobase + (r), (x)) +#define OREAD4(sc, r) inl((sc)->sc_iobase + (r)) +#define OREAD2(sc, r) inw((sc)->sc_iobase + (r)) +#endif /* Reverse the bits in a value 0 .. 31 */ static u_int8_t revbits[OHCI_NO_INTRS] = @@ -303,12 +321,12 @@ ohci_init(sc) DPRINTF(("ohci_init: start\n")); rev = OREAD4(sc, OHCI_REVISION); - printf("%s: OHCI version %d.%d%s\n", sc->sc_bus.bdev.dv_xname, + 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" : ""); if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) { printf("%s: unsupported OHCI revision\n", - sc->sc_bus.bdev.dv_xname); + USBDEVNAME(sc->sc_bus.bdev)); return (USBD_INVAL); } @@ -376,8 +394,8 @@ ohci_init(sc) ctl = OREAD4(sc, OHCI_CONTROL); } if ((ctl & OHCI_IR) == 0) { - printf("%s: SMM does not respond, resetting\n", - sc->sc_bus.bdev.dv_xname); + printf("%s: SMM does not respond, resetting\n", + USBDEVNAME(sc->sc_bus.bdev)); OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); goto reset; } @@ -407,7 +425,7 @@ ohci_init(sc) break; } if (hcr) { - printf("%s: reset timeout\n", sc->sc_bus.bdev.dv_xname); + printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev)); r = USBD_IOERROR; goto bad3; } @@ -446,9 +464,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)); - printf("%s: %d downstream port%s\n", - sc->sc_bus.bdev.dv_xname, sc->sc_noport, - sc->sc_noport != 1 ? "s" : ""); #ifdef USB_DEBUG if (ohcidebug > 5) @@ -524,6 +539,14 @@ ohci_intr(p) u_int32_t intrs, eintrs; ohci_physaddr_t done; + /* In case the interrupt occurs before initialization has completed. */ + if (sc->sc_hcca == NULL) { +#ifdef DIAGNOSTIC + printf("ohci_intr: sc->sc_hcca == NULL\n"); +#endif + return (0); + } + done = sc->sc_hcca->hcca_done_head; if (done != 0) { intrs = OHCI_WDH; @@ -545,7 +568,7 @@ ohci_intr(p) (u_int)eintrs)); if (eintrs & OHCI_SO) { - printf("%s: scheduling overrun\n", sc->sc_bus.bdev.dv_xname); + printf("%s: scheduling overrun\n",USBDEVNAME(sc->sc_bus.bdev)); /* XXX do what */ intrs &= ~OHCI_SO; } @@ -558,8 +581,8 @@ ohci_intr(p) /* XXX process resume detect */ } if (eintrs & OHCI_UE) { - printf("%s: unrecoverable error, controller halted\n", - sc->sc_bus.bdev.dv_xname); + printf("%s: unrecoverable error, controller halted\n", + USBDEVNAME(sc->sc_bus.bdev)); OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); /* XXX what else */ } @@ -649,26 +672,13 @@ ohci_process_done(sc, done) 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; - } - /* And finally execute callback. */ - reqh->status = USBD_NORMAL_COMPLETION; - reqh->xfercb(reqh); - } + reqh->status = USBD_NORMAL_COMPLETION; + /* + * Only do a callback on the last stage of a transfer. + * Others have hcpriv = 0. + */ + if (reqh->hcpriv == std) + ohci_ii_done(sc, reqh); } else { ohci_soft_td_t *p, *n; struct ohci_pipe *opipe = @@ -693,7 +703,7 @@ ohci_process_done(sc, done) 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); @@ -701,6 +711,30 @@ 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); + 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; + } + + /* And finally execute callback. */ + reqh->xfercb(reqh); +} + +void ohci_ctrl_done(sc, reqh) ohci_softc_t *sc; usbd_request_handle reqh; @@ -722,7 +756,7 @@ ohci_ctrl_done(sc, reqh) memcpy(reqh->buffer, KERNADDR(dma), len); usb_freemem(sc->sc_dmatag, dma); } - untimeout(ohci_timeout, reqh); + usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); } void @@ -787,7 +821,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); - untimeout(ohci_timeout, reqh); + usb_untimeout(ohci_timeout, reqh, reqh->timo_handle); } void @@ -847,7 +881,7 @@ ohci_waitintr(sc, reqh) reqh->status = USBD_IN_PROGRESS; for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { - delay(1000); + usbd_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 @@ -860,9 +894,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 @@ -992,8 +1029,10 @@ ohci_device_request(reqh) sed->ed->ed_tailp = tail->physaddr; opipe->tail = tail; OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); - if (reqh->timeout && !sc->sc_bus.use_polling) - timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout)); + if (reqh->timeout && !sc->sc_bus.use_polling) { + usb_timeout(ohci_timeout, reqh, + MS_TO_TICKS(reqh->timeout), reqh->timo_handle); + } splx(s); #if USB_DEBUG @@ -1298,7 +1337,6 @@ usb_hub_descriptor_t ohci_hubd = { 0, 0, {0}, - {0}, }; int @@ -1356,7 +1394,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; @@ -1521,24 +1559,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); @@ -1806,8 +1836,10 @@ ohci_device_bulk_transfer(reqh) sed->ed->ed_tailp = tail->physaddr; opipe->tail = tail; OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); - if (reqh->timeout && !sc->sc_bus.use_polling) - timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout)); + if (reqh->timeout && !sc->sc_bus.use_polling) { + usb_timeout(ohci_timeout, reqh, + MS_TO_TICKS(reqh->timeout), reqh->timo_handle); + } splx(s); return (USBD_IN_PROGRESS); @@ -1917,8 +1949,10 @@ ohci_device_intr_transfer(reqh) sed->ed->ed_tailp = tail->physaddr; opipe->tail = tail; #if 0 - if (reqh->timeout && !sc->sc_bus.use_polling) - timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout)); + if (reqh->timeout && !sc->sc_bus.use_polling) { + usb_timeout(ohci_timeout, reqh, + MS_TO_TICKS(reqh->timeout), reqh->timo_handle); + } #endif sed->ed->ed_flags &= ~OHCI_ED_SKIP; splx(s); diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h index 6fd27b658d8..80d580365f1 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 $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -62,6 +62,7 @@ typedef struct ohci_soft_td { typedef struct ohci_softc { struct usbd_bus sc_bus; /* base device */ +#if defined(__NetBSD__) void *sc_ih; /* interrupt vectoring */ bus_space_tag_t iot; bus_space_handle_t ioh; @@ -69,6 +70,11 @@ typedef struct ohci_softc { 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 /* __FreeBSD__ */ + usb_dma_t sc_hccadma; struct ohci_hcca *sc_hcca; ohci_soft_ed_t *sc_eds[OHCI_NO_EDS]; @@ -101,7 +107,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 4bbd80d762d..e12175bce4c 100644 --- a/sys/dev/usb/ucom.c +++ b/sys/dev/usb/ucom.c @@ -1,4 +1,4 @@ -/* $NetBSD: ucom.c,v 1.2 1998/12/09 00:18:10 augustss Exp $ */ +/* $NetBSD: ucom.c,v 1.3 1998/12/26 12:53:01 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,13 +37,21 @@ * 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> #include <sys/ioctl.h> +#elif defined(__FreeBSD__) +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/ioccom.h> +#include <sys/conf.h> +#endif #include <sys/tty.h> #include <sys/file.h> #include <sys/select.h> @@ -56,6 +64,7 @@ #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> @@ -71,29 +80,18 @@ int ucomdebug = 0; #endif struct ucom_softc { - struct device sc_dev; /* base device */ + bdevice sc_dev; /* base device */ usbd_interface_handle sc_iface; /* interface */ }; -int ucom_match __P((struct device *, struct cfdata *, void *)); -void ucom_attach __P((struct device *, struct device *, void *)); - void ucom_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); void ucom_disco __P((void *)); -extern struct cfdriver ucom_cd; - -struct cfattach ucom_ca = { - sizeof(struct ucom_softc), ucom_match, ucom_attach -}; +USB_DECLARE_DRIVER(ucom); -int -ucom_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +USB_MATCH(ucom) { - struct usb_attach_arg *uaa = aux; + USB_MATCH_START(ucom, uaa); usb_interface_descriptor_t *id; if (!uaa->iface) @@ -106,14 +104,9 @@ ucom_match(parent, match, aux) return (UMATCH_IFACECLASS_IFACESUBCLASS); } -void -ucom_attach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; +USB_ATTACH(ucom) { - struct ucom_softc *sc = (struct ucom_softc *)self; - struct usb_attach_arg *uaa = aux; + USB_ATTACH_START(ucom, sc, uaa); usbd_interface_handle iface = uaa->iface; usb_interface_descriptor_t *id; char devinfo[1024]; @@ -121,6 +114,29 @@ ucom_attach(parent, self, aux) sc->sc_iface = iface; id = usbd_get_interface_descriptor(iface); usbd_devinfo(uaa->device, 0, devinfo); - printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname, + USB_ATTACH_SETUP; + printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), devinfo, id->bInterfaceClass, id->bInterfaceSubClass); + + USB_ATTACH_SUCCESS_RETURN; +} + +#if defined(__FreeBSD__) +static int +ucom_detach(device_t self) +{ + struct ucom_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 + +#if defined(__FreeBSD__) +DRIVER_MODULE(ucom, usb, ucom_driver, ucom_devclass, usb_driver_load, 0); +#endif + diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index b8a0f77767b..0195a36029e 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -1,4 +1,4 @@ -/* $NetBSD: ugen.c,v 1.4 1998/12/12 11:59:28 augustss Exp $ */ +/* $NetBSD: ugen.c,v 1.5 1998/12/26 12:53:01 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -115,19 +115,11 @@ int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx)); #define UGENUNIT(n) (((n) >> 4) & 0xf) #define UGENENDPOINT(n) ((n) & 0xf) -extern struct cfdriver ugen_cd; +USB_DECLARE_DRIVER(ugen); -struct cfattach ugen_ca = { - sizeof(struct ugen_softc), ugen_match, ugen_attach -}; - -int -ugen_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +USB_MATCH(ugen) { - struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux; + USB_MATCH_START(ugen, uaa); if (uaa->usegeneric) return (UMATCH_GENERIC); @@ -135,28 +127,25 @@ ugen_match(parent, match, aux) return (UMATCH_NONE); } -void -ugen_attach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; +USB_ATTACH(ugen) { - struct ugen_softc *sc = (struct ugen_softc *)self; - struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux; + USB_ATTACH_START(ugen, sc, uaa); char devinfo[1024]; usbd_status r; usbd_devinfo(uaa->device, 0, devinfo); - printf(": %s\n", devinfo); + USB_ATTACH_SETUP; + printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); sc->sc_udev = uaa->device; - r = ugen_set_config(sc, 1); + r = ugen_set_config(sc, 1); /* XXX 1 */ if (r != USBD_NORMAL_COMPLETION) { - printf("%s: setting configuration 0 failed\n", - sc->sc_dev.dv_xname); + printf("%s: setting configuration 1 failed\n", + USBDEVNAME(sc->sc_dev)); sc->sc_disconnected = 1; - return; + USB_ATTACH_ERROR_RETURN; } + USB_ATTACH_SUCCESS_RETURN; } int @@ -173,7 +162,7 @@ ugen_set_config(sc, configno) usbd_status r; DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", - sc->sc_dev.dv_xname, configno, sc)); + USBDEVNAME(sc->sc_dev), configno, sc)); r = usbd_set_config_no(dev, configno, 0); if (r != USBD_NORMAL_COMPLETION) return (r); @@ -687,7 +676,7 @@ ugenioctl(dev, cmd, addr, flag, p) case USB_SET_CONFIG: if (!(flag & FWRITE)) return (EPERM); - r = usbd_set_config_no(sc->sc_udev, *(int *)addr, 0); + r = ugen_set_config(sc, *(int *)addr); if (r != USBD_NORMAL_COMPLETION) return (EIO); break; @@ -915,3 +904,18 @@ ugenpoll(dev, events, p) splx(s); return (revents); } + +#if defined(__FreeBSD__) +static int +ugen_detach(device_t self) +{ + 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; +} +#endif diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index bd7e69690f8..267cf51cffd 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.12 1998/12/10 23:16:47 augustss Exp $ */ +/* $NetBSD: uhci.c,v 1.13 1998/12/26 12:53:01 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -51,7 +51,12 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#if defined(__NetBSD__) #include <sys/device.h> +#elif defined(__FreeBSD__) +#include <sys/module.h> +#include <sys/bus.h> +#endif #include <sys/proc.h> #include <sys/queue.h> #include <sys/select.h> @@ -67,6 +72,13 @@ #include <dev/usb/uhcireg.h> #include <dev/usb/uhcivar.h> +#if defined(__FreeBSD__) +#include <machine/clock.h> +#include "dev/usb/queue.addendum.h" + +#define delay(d) DELAY(d) +#endif + #define MS_TO_TICKS(ms) ((ms) * hz / 1000) struct uhci_pipe { @@ -103,7 +115,6 @@ struct uhci_pipe { * The uhci_intr_info free list can be global since they contain * no dma specific data. The other free lists do. */ -int uhci_global_init_done = 0; LIST_HEAD(, uhci_intr_info) uhci_ii_free; void uhci_busreset __P((uhci_softc_t *)); @@ -180,10 +191,17 @@ void uhci_dump __P((void)); void uhci_dump_td __P((uhci_soft_td_t *)); #endif +#if defined(__NetBSD__) #define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) #define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) #define UREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) #define UREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) +#elif defined(__FreeBSD__) +#define UWRITE2(sc,r,x) outw((sc)->sc_iobase + (r), (x)) +#define UWRITE4(sc,r,x) outl((sc)->sc_iobase + (r), (x)) +#define UREAD2(sc,r) inw((sc)->sc_iobase + (r)) +#define UREAD4(sc,r) inl((sc)->sc_iobase + (r)) +#endif #define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd) #define UHCISTS(sc) UREAD2(sc, UHCI_STS) @@ -249,6 +267,7 @@ uhci_init(sc) uhci_soft_qh_t *csqh, *bsqh, *sqh; uhci_soft_td_t *std; usb_dma_t dma; + static int uhci_global_init_done = 0; DPRINTFN(1,("uhci_init: start\n")); @@ -303,7 +322,7 @@ uhci_init(sc) std = uhci_alloc_std(sc); sqh = uhci_alloc_sqh(sc); if (!std || !sqh) - return (ENOMEM); + return (USBD_NOMEM); std->td->link.sqh = sqh; std->td->td_link = sqh->physaddr | UHCI_PTR_Q; std->td->td_status = UHCI_TD_IOS; /* iso, inactive */ @@ -343,8 +362,9 @@ static void uhci_dumpregs(sc) uhci_softc_t *sc; { - printf("%s: regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n", - sc->sc_bus.bdev.dv_xname, + 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), @@ -382,7 +402,6 @@ uhci_dump_td(p) UHCI_TD_GET_ENDPT(p->td->td_token), UHCI_TD_GET_DT(p->td->td_token), UHCI_TD_GET_MAXLEN(p->td->td_token)); - } void @@ -393,6 +412,7 @@ uhci_dump_qh(p) p->qh->qh_hlink, p->qh->qh_elink); } + #if 0 void uhci_dump() @@ -448,7 +468,7 @@ uhci_timo(addr) splx(s); } if (reqh->pipe->intrreqh == reqh) { - timeout(uhci_timo, addr, sc->sc_ival); + usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); } else { usb_freemem(sc->sc_dmatag, &upipe->u.intr.datadma); } @@ -601,7 +621,7 @@ uhci_intr(p) sc->sc_intrs++; #if defined(USB_DEBUG) if (uhcidebug > 9) { - DPRINTF(("uhci_intr %s, %p\n", sc->sc_bus.bdev.dv_xname, sc)); + printf("uhci_intr %p\n", sc); uhci_dumpregs(sc); } #endif @@ -617,22 +637,21 @@ uhci_intr(p) } if (status & UHCI_STS_RD) { UWRITE2(sc, UHCI_STS, UHCI_STS_RD); /* acknowledge */ - printf("%s: resume detect\n", sc->sc_bus.bdev.dv_xname); + 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 */ - printf("%s: Host System Error\n", sc->sc_bus.bdev.dv_xname); + 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 */ - printf("%s: Host System Error\n", sc->sc_bus.bdev.dv_xname); + printf("%s: Host System Error\n", USBDEVNAME(sc->sc_bus.bdev)); ret = 1; } - if (status & UHCI_STS_HCH) { - printf("%s: controller halted\n", sc->sc_bus.bdev.dv_xname); - } + if (status & UHCI_STS_HCH) + printf("%s: controller halted\n", USBDEVNAME(sc->sc_bus.bdev)); if (!ret) return 0; @@ -692,7 +711,7 @@ uhci_check_intr(sc, ii) upipe = (struct uhci_pipe *)ii->reqh->pipe; upipe->pipe.endpoint->toggle = upipe->newtoggle; uhci_ii_done(ii, 0); - untimeout(uhci_timeout, ii); + usb_untimeout(uhci_timeout, ii, ii->timeout_handle); } void @@ -728,7 +747,7 @@ uhci_ii_done(ii, timo) status |= tst; #ifdef USB_DEBUG if ((tst & UHCI_TD_ERROR) && uhcidebug) { - printf("uhci_intr: intr error TD:\n"); + printf("uhci_ii_done: intr error TD:\n"); uhci_dump_td(std); } #endif @@ -739,7 +758,7 @@ uhci_ii_done(ii, timo) DPRINTFN(10, ("uhci_check_intr: len=%d, status=0x%x\n", len, status)); if (status != 0) { DPRINTFN(-1+(status==UHCI_TD_STALLED), - ("uhci_intr: error, status 0x%b\n", (long)status, + ("uhci_ii_done: error, status 0x%b\n", (long)status, "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27" "STALLED\30ACTIVE")); if (status == UHCI_TD_STALLED) @@ -758,7 +777,7 @@ uhci_ii_done(ii, timo) std->td->td_status &= ~UHCI_TD_ACTIVE; /* XXX should we wait 1 ms */ } - DPRINTFN(5, ("uhci_intr: calling handler ii=%p\n", ii)); + DPRINTFN(5, ("uhci_ii_done: calling handler ii=%p\n", ii)); switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) { case UE_CONTROL: @@ -779,6 +798,9 @@ uhci_ii_done(ii, timo) reqh->xfercb(reqh); } +/* + * Called when a request does not complete. + */ void uhci_timeout(addr) void *addr; @@ -796,6 +818,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) @@ -804,10 +827,13 @@ uhci_waitintr(sc, reqh) { int timo = reqh->timeout; int usecs; + uhci_intr_info_t *ii; + + DPRINTFN(10,("uhci_waitintr: timeout = %ds\n", timo)); reqh->status = USBD_IN_PROGRESS; for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) { - delay(1000); + usbd_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); @@ -815,8 +841,17 @@ uhci_waitintr(sc, reqh) 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 @@ -843,7 +878,8 @@ uhci_reset(p) (UREAD2(sc, UHCI_CMD) & UHCI_CMD_HCRESET); n++) delay(100); if (n >= UHCI_RESET_TIMEOUT) - printf("%s: controller did not reset\n", sc->sc_bus.bdev.dv_xname); + printf("%s: controller did not reset\n", + USBDEVNAME(sc->sc_bus.bdev)); } #endif @@ -862,17 +898,18 @@ uhci_run(sc, run) return; } UWRITE2(sc, UHCI_CMD, run ? UHCI_CMD_RS : 0); - for(n = 0; n < 100; n++) { + 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; } + usbd_delay_ms(&sc->sc_bus, 1); } splx(s); - printf("%s: cannot %s\n", sc->sc_bus.bdev.dv_xname, - run ? "start" : "stop"); + printf("%s: cannot %s\n", USBDEVNAME(sc->sc_bus.bdev), + (run ? "start" : "stop")); } /* @@ -1142,8 +1179,10 @@ uhci_device_bulk_transfer(reqh) uhci_add_bulk(sc, sqh); LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list); - if (reqh->timeout && !sc->sc_bus.use_polling) - timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout)); + if (reqh->timeout && !sc->sc_bus.use_polling) { + usb_timeout(uhci_timeout, ii, + MS_TO_TICKS(reqh->timeout), ii->timeout_handle); + } splx(s); #ifdef USB_DEBUG @@ -1379,7 +1418,7 @@ uhci_device_request(reqh) int isread; int s; - DPRINTFN(1,("uhci_device_control type=0x%02x, request=0x%02x, " + 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), @@ -1461,6 +1500,8 @@ uhci_device_request(reqh) if (uhcidebug > 12) { uhci_soft_td_t *std; uhci_soft_qh_t *xqh; + uhci_soft_qh_t *sxqh; + int maxqh = 0; uhci_physaddr_t link; printf("uhci_enter_ctl_q: follow from [0]\n"); for (std = sc->sc_vframes[0].htd, link = 0; @@ -1469,17 +1510,22 @@ uhci_device_request(reqh) link = std->td->td_link; uhci_dump_td(std); } - for (xqh = (uhci_soft_qh_t *)std; + for (sxqh = xqh = (uhci_soft_qh_t *)std; xqh; - xqh = 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); + } printf("Enqueued QH:\n"); uhci_dump_qh(sqh); uhci_dump_tds(sqh->qh->elink); } #endif - if (reqh->timeout && !sc->sc_bus.use_polling) - timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout)); + if (reqh->timeout && !sc->sc_bus.use_polling) { + usb_timeout(uhci_timeout, ii, + MS_TO_TICKS(reqh->timeout), ii->timeout_handle); + } splx(s); return (USBD_NORMAL_COMPLETION); @@ -1852,7 +1898,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 @@ -1907,7 +1952,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; @@ -2211,7 +2256,7 @@ void uhci_root_ctrl_close(pipe) usbd_pipe_handle pipe; { - untimeout(uhci_timo, pipe->intrreqh); + usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle); DPRINTF(("uhci_root_ctrl_close\n")); } @@ -2220,7 +2265,7 @@ void uhci_root_intr_abort(reqh) usbd_request_handle reqh; { - untimeout(uhci_timo, reqh); + usb_untimeout(uhci_timo, reqh, reqh->timo_handle); } /* Start a transfer on the root interrupt pipe */ @@ -2249,7 +2294,7 @@ uhci_root_intr_transfer(reqh) return (r); sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval); - timeout(uhci_timo, reqh, sc->sc_ival); + usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle); return (USBD_IN_PROGRESS); } @@ -2258,6 +2303,6 @@ void uhci_root_intr_close(pipe) usbd_pipe_handle pipe; { - untimeout(uhci_timo, pipe->intrreqh); + usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle); DPRINTF(("uhci_root_intr_close\n")); } diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index 31d83385c60..aee1a3f6520 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: uhcivar.h,v 1.4 1998/11/25 22:32:05 augustss Exp $ */ +/* $NetBSD: uhcivar.h,v 1.5 1998/12/26 12:53:02 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -68,6 +68,9 @@ typedef struct uhci_intr_info { 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 @@ -113,12 +116,17 @@ struct uhci_vframe { typedef struct uhci_softc { struct usbd_bus sc_bus; /* base device */ +#if defined(__NetBSD__) void *sc_ih; /* interrupt vectoring */ bus_space_tag_t iot; bus_space_handle_t ioh; 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 /* defined(__FreeBSD__) */ uhci_physaddr_t *sc_pframes; struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT]; @@ -147,7 +155,9 @@ typedef struct uhci_softc { #define UHCI_HAS_LOCK 1 #define UHCI_WANT_LOCK 2 +#if defined(__NetBSD__) usb_dma_t *sc_mallocs; +#endif char sc_vendor[16]; } uhci_softc_t; diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c index 37782b673ca..9e50faa5aad 100644 --- a/sys/dev/usb/uhid.c +++ b/sys/dev/usb/uhid.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhid.c,v 1.11 1998/12/10 23:16:47 augustss Exp $ */ +/* $NetBSD: uhid.c,v 1.12 1998/12/26 12:53:02 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -42,6 +42,15 @@ #include <sys/systm.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/ioccom.h> +#include <sys/filio.h> +#include <sys/module.h> +#include <sys/bus.h> +#endif #include <sys/device.h> #include <sys/ioctl.h> #include <sys/tty.h> @@ -49,7 +58,6 @@ #include <sys/select.h> #include <sys/proc.h> #include <sys/vnode.h> -#include <sys/device.h> #include <sys/poll.h> #include <dev/usb/usb.h> @@ -70,7 +78,7 @@ int uhiddebug = 0; #endif struct uhid_softc { - struct device 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; @@ -102,9 +110,6 @@ struct uhid_softc { #define UHID_CHUNK 128 /* chunk size for read */ #define UHID_BSIZE 1020 /* buffer size */ -int uhid_match __P((struct device *, struct cfdata *, void *)); -void uhid_attach __P((struct device *, struct device *, void *)); - 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)); @@ -114,19 +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 *)); -extern struct cfdriver uhid_cd; - -struct cfattach uhid_ca = { - sizeof(struct uhid_softc), uhid_match, uhid_attach -}; +USB_DECLARE_DRIVER(uhid); -int -uhid_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +USB_MATCH(uhid) { - struct usb_attach_arg *uaa = aux; + USB_MATCH_START(uhid, uaa); usb_interface_descriptor_t *id; if (!uaa->iface) @@ -137,14 +134,9 @@ uhid_match(parent, match, aux) return (UMATCH_IFACECLASS_GENERIC); } -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; + USB_ATTACH_START(uhid, sc, uaa); usbd_interface_handle iface = uaa->iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; @@ -157,13 +149,15 @@ uhid_attach(parent, self, aux) sc->sc_iface = iface; id = usbd_get_interface_descriptor(iface); usbd_devinfo(uaa->device, 0, devinfo); - printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname, + 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) { printf("%s: could not read endpoint descriptor\n", - sc->sc_dev.dv_xname); - return; + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d " @@ -177,9 +171,8 @@ uhid_attach(parent, self, aux) if ((ed->bEndpointAddress & UE_IN) != UE_IN || (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - printf("%s: unexpected endpoint\n", - sc->sc_dev.dv_xname); - return; + printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } sc->sc_ep_addr = ed->bEndpointAddress; @@ -187,8 +180,8 @@ uhid_attach(parent, self, aux) r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USB); if (r != USBD_NORMAL_COMPLETION) { - printf("%s: no report descriptor\n", sc->sc_dev.dv_xname); - return; + printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } (void)usbd_set_idle(iface, 0, 0); @@ -199,8 +192,25 @@ uhid_attach(parent, self, aux) sc->sc_repdesc = desc; sc->sc_repdesc_size = size; + + 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; @@ -250,15 +260,11 @@ uhidopen(dev, flag, mode, p) int mode; struct proc *p; { - int unit = UHIDUNIT(dev); - struct uhid_softc *sc; usbd_status r; + USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc); - if (unit >= uhid_cd.cd_ndevs) - return ENXIO; - sc = uhid_cd.cd_devs[unit]; if (!sc) - return ENXIO; + return (ENXIO); DPRINTF(("uhidopen: sc=%p, disco=%d\n", sc, sc->sc_disconnected)); @@ -266,10 +272,14 @@ 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 sc->sc_state |= UHID_OPEN; sc->sc_state &= ~UHID_IMMED; @@ -290,7 +300,7 @@ uhidopen(dev, flag, mode, p) } usbd_set_disco(sc->sc_intrpipe, uhid_disco, sc); - return 0; + return (0); } int @@ -300,7 +310,7 @@ uhidclose(dev, flag, mode, p) int mode; struct proc *p; { - struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); if (sc->sc_disconnected) return (EIO); @@ -313,12 +323,16 @@ uhidclose(dev, flag, mode, p) sc->sc_state &= ~UHID_OPEN; +#if defined(__NetBSD__) clfree(&sc->sc_q); +#elif defined(__FreeBSD__) + clist_free_cblocks(&sc->sc_q); +#endif free(sc->sc_ibuf, M_USB); free(sc->sc_obuf, M_USB); - return 0; + return (0); } int @@ -327,12 +341,12 @@ uhidread(dev, uio, flag) struct uio *uio; int flag; { - struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; int s; int error = 0; size_t length; u_char buffer[UHID_CHUNK]; usbd_status r; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); if (sc->sc_disconnected) return (EIO); @@ -395,10 +409,10 @@ uhidwrite(dev, uio, flag) struct uio *uio; int flag; { - struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; int error; int size; usbd_status r; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); if (sc->sc_disconnected) return (EIO); @@ -435,11 +449,11 @@ uhidioctl(dev, cmd, addr, flag, p) int flag; struct proc *p; { - struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; struct usb_ctl_report_desc *rd; struct usb_ctl_report *re; int size, id; usbd_status r; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); if (sc->sc_disconnected) return (EIO); @@ -465,6 +479,7 @@ uhidioctl(dev, cmd, addr, flag, p) sc->sc_isize); if (r != USBD_NORMAL_COMPLETION) return (EOPNOTSUPP); + sc->sc_state |= UHID_IMMED; } else sc->sc_state &= ~UHID_IMMED; @@ -506,9 +521,9 @@ uhidpoll(dev, events, p) int events; struct proc *p; { - struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)]; int revents = 0; int s; + USB_GET_SC(uhid, UHIDUNIT(dev), sc); if (sc->sc_disconnected) return (EIO); @@ -526,3 +541,7 @@ uhidpoll(dev, events, p) splx(s); return (revents); } + +#if defined(__FreeBSD__) +DRIVER_MODULE(uhid, usb, uhid_driver, uhid_devclass, usb_driver_load, 0); +#endif diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index 2c1c621c314..befb69176a3 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhub.c,v 1.10 1998/12/09 19:24:28 drochner Exp $ */ +/* $NetBSD: uhub.c,v 1.11 1998/12/26 12:53:02 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,14 +37,17 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#if defined(__NetBSD__) #include <sys/device.h> +#elif defined(__FreeBSD__) +#include <sys/module.h> +#include <sys/bus.h> +#endif #include <sys/proc.h> -#include <sys/device.h> #include <dev/usb/usb.h> @@ -63,44 +66,35 @@ extern char *usbd_error_strs[]; #endif struct uhub_softc { - struct device sc_dev; /* base device */ - usbd_device_handle sc_hub; /* USB device */ - usbd_pipe_handle sc_ipipe; /* interrupt pipe */ - u_int8_t sc_status[1]; /* XXX more ports */ - u_char sc_running; + bdevice sc_dev; /* base device */ + usbd_device_handle sc_hub; /* USB device */ + usbd_pipe_handle sc_ipipe; /* interrupt pipe */ + u_int8_t sc_status[1]; /* XXX more ports */ + u_char sc_running; }; -int uhub_match __P((struct device *, struct cfdata *, void *)); -void uhub_attach __P((struct device *, struct device *, void *)); - -usbd_status uhub_init_port __P((int, struct usbd_port *, usbd_device_handle)); -void uhub_disconnect __P((struct uhub_softc *sc, struct device *parent, - struct usbd_port *up, int portno)); -usbd_status uhub_explore __P((struct device *parent, usbd_device_handle hub)); +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 *));*/ -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 }; +#endif -int -uhub_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +USB_MATCH(uhub) { - struct usb_attach_arg *uaa = aux; + USB_MATCH_START(uhub, uaa); usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device); - DPRINTFN(1,("uhub_match, dd=%p\n", dd)); + DPRINTFN(5,("uhub_match, dd=%p\n", dd)); /* * The subclass for hubs seems to be 0 for some and 1 for others, * so we just ignore the subclass. @@ -110,40 +104,36 @@ uhub_match(parent, match, aux) return (UMATCH_NONE); } -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; + 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(1,("uhub_attach\n")); sc->sc_hub = dev; usbd_devinfo(dev, 1, devinfo); - printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfo); + USB_ATTACH_SETUP; + printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); r = usbd_set_config_index(dev, 0, 1); if (r != USBD_NORMAL_COMPLETION) { DPRINTF(("%s: configuration failed, error=%d(%s)\n", - sc->sc_dev.dv_xname, r, usbd_error_strs[r])); - return; + USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r])); + USB_ATTACH_ERROR_RETURN; } if (dev->depth > USB_HUB_MAX_DEPTH) { printf("%s: hub depth (%d) exceeded, hub ignored\n", - sc->sc_dev.dv_xname, USB_HUB_MAX_DEPTH); - return; + USBDEVNAME(sc->sc_dev), USB_HUB_MAX_DEPTH); + USB_ATTACH_ERROR_RETURN; } /* Get hub descriptor. */ @@ -153,21 +143,32 @@ uhub_attach(parent, self, aux) 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) { DPRINTF(("%s: getting hub descriptor failed, error=%d(%s)\n", - sc->sc_dev.dv_xname, r, usbd_error_strs[r])); - return; + USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r])); + USB_ATTACH_ERROR_RETURN; } - 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) - return; + USB_ATTACH_ERROR_RETURN; dev->hub = hub; - dev->hub->hubdata = sc; + dev->hub->hubsoftc = sc; hub->explore = uhub_explore; hub->hubdesc = hubdesc; @@ -180,24 +181,24 @@ uhub_attach(parent, self, aux) !dev->powersrc->parent->self_powered) { printf("%s: bus powered hub connected to bus powered hub, " "ignored\n", - sc->sc_dev.dv_xname); - return; + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } /* Set up interrupt pipe. */ r = usbd_device2interface_handle(dev, 0, &iface); if (r != USBD_NORMAL_COMPLETION) { - printf("%s: no interface handle\n", sc->sc_dev.dv_xname); - return; + printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } ed = usbd_interface2endpoint_descriptor(iface, 0); if (ed == 0) { - printf("%s: no endpoint descriptor\n", sc->sc_dev.dv_xname); - return; + printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { - printf("%s: bad interrupt endpoint\n", sc->sc_dev.dv_xname); - 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, @@ -205,37 +206,65 @@ uhub_attach(parent, self, aux) sizeof(sc->sc_status), uhub_intr); if (r != USBD_NORMAL_COMPLETION) { - printf("%s: cannot open interrupt pipe\n",sc->sc_dev.dv_xname); - 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->bus, 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) printf("%s: init of port %d failed\n", - sc->sc_dev.dv_xname, port); + USBDEVNAME(sc->sc_dev), up->portno); } sc->sc_running = 1; + + USB_ATTACH_SUCCESS_RETURN; } +#if defined(__FreeBSD__) +static int +uhub_detach(device_t self) +{ + struct uhub_softc *sc = device_get_softc(self); + int nports = sc->sc_hub->hub->hubdesc.bNbrPorts; + int p; + + 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); + 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(uport->status.wPortChange))); + port, pstatus, UGETW(up->status.wPortChange))); if ((pstatus & UPS_PORT_POWER) == 0) { /* Port lacks power, turn it on */ #if 0 @@ -246,38 +275,37 @@ uhub_init_port(port, uport, dev) 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))); + 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); } 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); } usbd_status -uhub_explore(parent, dev) - struct device *parent; +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; int change, status; - DPRINTF(("uhub_explore dev=%p addr=%d\n", dev, dev->address)); + DPRINTFN(10, ("uhub_explore dev=%p addr=%d\n", dev, dev->address)); if (!sc->sc_running) return (USBD_NOT_STARTED); @@ -299,10 +327,29 @@ uhub_explore(parent, dev) 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(parent, up->device); + up->device->hub->explore(up->device); continue; } DPRINTF(("uhub_explore: status change hub=%d port=%d\n", @@ -316,12 +363,13 @@ uhub_explore(parent, 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", up->device->address, port)); - uhub_disconnect(sc, parent, up, port); + uhub_disconnect(up); usbd_clear_port_feature(dev, port, UHF_C_PORT_CONNECTION); } @@ -329,18 +377,18 @@ uhub_explore(parent, dev) continue; /* Connected */ + up->restartcnt = 0; + /* Wait for maximum device power up time. */ usbd_delay_ms(dev->bus, 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((struct device *)sc, dev->bus, + r = usbd_new_device(&sc->sc_dev, dev->bus, dev->depth + 1, status & UPS_LOW_SPEED, port, up); /* XXX retry a few times? */ @@ -362,37 +410,43 @@ uhub_explore(parent, dev) * instead. */ printf("%s: device problem, disabling " "port %d\n", - parent->dv_xname, port); + 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) - up->device->hub->explore(parent, up->device); + up->device->hub->explore(up->device); } } return (USBD_NORMAL_COMPLETION); } void -uhub_disconnect(sc, parent, up, portno) - struct uhub_softc *sc; - struct device *parent; +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)); + up, dev, up->portno)); - printf("%s: device addr %d%s on hub addr %d, port %d disconnected\n", - parent->dv_xname, dev->address, dev->hub ? " (hub)" : "", - up->parent->address, 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) { @@ -404,22 +458,29 @@ uhub_disconnect(sc, parent, up, portno) } } +#if defined(__NetBSD__) /* 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")); - hd = &dev->hub->hubdesc; - for(port = 1; port <= hd->bNbrPorts; port++) { - spi = &dev->hub->ports[port-1]; - if (spi->device) - uhub_disconnect(sc, parent, spi, port); + 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 */ +#elif defined(__FreeBSD__) + /* XXX this doesn't work. */ + /* clean up the kindergarten, get rid of the kids */ + usbd_remove_device(dev, up); +#endif } void @@ -430,9 +491,13 @@ uhub_intr(reqh, addr, status) { struct uhub_softc *sc = addr; - DPRINTFN(1,("uhub_intr: sc=%p\n", sc)); + DPRINTFN(5,("uhub_intr: sc=%p\n", sc)); if (status != USBD_NORMAL_COMPLETION) usbd_clear_endpoint_stall_async(sc->sc_ipipe); else usb_needs_explore(sc->sc_hub->bus); } + +#if defined(__FreeBSD__) +DRIVER_MODULE(uhub, usb, uhub_driver, uhub_devclass, usb_driver_load, 0); +#endif diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c index 1e0df9b8c5d..41317bd01b0 100644 --- a/sys/dev/usb/ukbd.c +++ b/sys/dev/usb/ukbd.c @@ -1,4 +1,4 @@ -/* $NetBSD: ukbd.c,v 1.15 1998/12/10 23:16:47 augustss Exp $ */ +/* $NetBSD: ukbd.c,v 1.16 1998/12/26 12:53:02 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,19 +37,23 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #include <sys/param.h> #include <sys/systm.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/ioccom.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <machine/clock.h> +#endif #include <sys/tty.h> #include <sys/file.h> #include <sys/select.h> #include <sys/proc.h> #include <sys/vnode.h> -#include <sys/device.h> #include <sys/poll.h> #include <dev/usb/usb.h> @@ -60,6 +64,7 @@ #include <dev/usb/usb_quirks.h> #include <dev/usb/hid.h> +#if defined(__NetBSD__) #include <dev/wscons/wsconsio.h> #include <dev/wscons/wskbdvar.h> #include <dev/wscons/wsksymdef.h> @@ -68,6 +73,7 @@ #include "opt_pckbd_layout.h" #include "opt_wsdisplay_compat.h" +#endif #ifdef USB_DEBUG #define DPRINTF(x) if (ukbddebug) printf x @@ -155,7 +161,7 @@ static u_int8_t ukbd_trtab[256] = { #define KEY_ERROR 0x01 struct ukbd_softc { - struct device 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; @@ -167,10 +173,12 @@ struct ukbd_softc { char sc_disconnected; /* device is gone */ int sc_leds; +#if defined(__NetBSD__) struct device *sc_wskbddev; #ifdef WSDISPLAY_COMPAT_RAWKBD int sc_rawkbd; #endif +#endif int sc_polling; int sc_pollchar; @@ -180,22 +188,22 @@ struct ukbd_softc { #define UKBD_CHUNK 128 /* chunk size for read */ #define UKBD_BSIZE 1020 /* buffer size */ -int ukbd_match __P((struct device *, struct cfdata *, void *)); -void ukbd_attach __P((struct device *, struct device *, void *)); - void ukbd_cngetc __P((void *, u_int *, int *)); void ukbd_cnpollc __P((void *, int)); +#if defined(__NetBSD__) const struct wskbd_consops ukbd_consops = { ukbd_cngetc, ukbd_cnpollc, }; +#endif void ukbd_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); void ukbd_disco __P((void *)); 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 *)); const struct wskbd_accessops ukbd_accessops = { @@ -212,20 +220,13 @@ const struct wskbd_mapdata ukbd_keymapdata = { KB_US, #endif }; +#endif -extern struct cfdriver ukbd_cd; +USB_DECLARE_DRIVER(ukbd); -struct cfattach ukbd_ca = { - sizeof(struct ukbd_softc), ukbd_match, ukbd_attach -}; - -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; + USB_MATCH_START(ukbd, uaa); usb_interface_descriptor_t *id; /* Check that this is a keyboard that speaks the boot protocol. */ @@ -240,32 +241,33 @@ ukbd_match(parent, match, aux) return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); } -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; + USB_ATTACH_START(ukbd, sc, uaa); usbd_interface_handle iface = uaa->iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_status r; char devinfo[1024]; +#if defined(__NetBSD__) struct wskbddev_attach_args a; +#else + int i; +#endif sc->sc_disconnected = 1; sc->sc_iface = iface; id = usbd_get_interface_descriptor(iface); usbd_devinfo(uaa->device, 0, devinfo); - printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname, + 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) { printf("%s: could not read endpoint descriptor\n", - sc->sc_dev.dv_xname); - return; + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d " @@ -280,8 +282,8 @@ ukbd_attach(parent, self, aux) if ((ed->bEndpointAddress & UE_IN) != UE_IN || (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { printf("%s: unexpected endpoint\n", - sc->sc_dev.dv_xname); - return; + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } if ((usbd_get_quirks(uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) { @@ -289,8 +291,8 @@ ukbd_attach(parent, self, aux) DPRINTFN(5, ("ukbd_attach: protocol set\n")); if (r != USBD_NORMAL_COMPLETION) { printf("%s: set protocol failed\n", - sc->sc_dev.dv_xname); - return; + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } } /* Ignore if SETIDLE fails since it is not crucial. */ @@ -299,6 +301,7 @@ ukbd_attach(parent, self, aux) sc->sc_ep_addr = ed->bEndpointAddress; sc->sc_disconnected = 0; +#if defined(__NetBSD__) a.console = 0; /* XXX */ a.keymap = &ukbd_keymapdata; @@ -307,8 +310,45 @@ ukbd_attach(parent, self, aux) a.accesscookie = sc; sc->sc_wskbddev = config_found(self, &a, wskbddevprint); + +#elif defined(__FreeBSD__) + /* 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); + ukbd_set_leds(sc, CAPS_LOCK); + delay(20000); + ukbd_set_leds(sc, SCROLL_LOCK); + delay(30000); + ukbd_set_leds(sc, CAPS_LOCK); + delay(50000); + ukbd_set_leds(sc, NUM_LOCK); + + ukbd_enable(sc, 1); +#endif + + USB_ATTACH_SUCCESS_RETURN; } +#if defined(__FreeBSD__) +int +ukbd_detach(device_t self) +{ + struct ukbd_softc *sc = device_get_softc(self); + char *devinfo = (char *) device_get_desc(self); + + if (sc->sc_enabled) + return (ENXIO); + + if (devinfo) { + device_set_desc(self, NULL); + free(devinfo, M_USB); + } + + return 0; +} +#endif + void ukbd_disco(p) void *p; @@ -433,9 +473,20 @@ ukbd_intr(reqh, addr, status) } 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")); + 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 } } @@ -450,6 +501,7 @@ ukbd_set_leds(v, leds) DPRINTF(("ukbd_set_leds: sc=%p leds=%d\n", sc, leds)); sc->sc_leds = leds; +#if defined(__NetBSD__) res = 0; if (leds & WSKBD_LED_SCROLL) res |= SCROLL_LOCK; @@ -457,9 +509,13 @@ 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__) int ukbd_ioctl(v, cmd, data, flag, p) void *v; @@ -526,3 +582,8 @@ ukbd_cnpollc(v, on) usbd_set_polling(sc->sc_iface, on); } +#endif + +#if defined(__FreeBSD__) +DRIVER_MODULE(ukbd, usb, ukbd_driver, ukbd_devclass, usb_driver_load, 0); +#endif diff --git a/sys/dev/usb/ulpt.c b/sys/dev/usb/ulpt.c index aa0ab11bcf4..23dfe9ab5b7 100644 --- a/sys/dev/usb/ulpt.c +++ b/sys/dev/usb/ulpt.c @@ -1,4 +1,4 @@ -/* $NetBSD: ulpt.c,v 1.7 1998/12/09 00:18:11 augustss Exp $ */ +/* $NetBSD: ulpt.c,v 1.8 1998/12/26 12:53:02 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -40,17 +40,23 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> -#include <sys/user.h> #include <sys/malloc.h> #include <sys/kernel.h> +#if defined(__NetBSD__) +#include <sys/device.h> #include <sys/ioctl.h> +#elif defined(__FreeBSD__) +#include <sys/ioccom.h> +#include <sys/module.h> +#include <sys/bus.h> +#endif #include <sys/uio.h> -#include <sys/device.h> #include <sys/conf.h> #include <sys/syslog.h> #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> @@ -81,7 +87,7 @@ int ulptdebug = 0; #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER) struct ulpt_softc { - struct device sc_dev; + bdevice sc_dev; usbd_device_handle sc_udev; /* device */ usbd_interface_handle sc_iface; /* interface */ int sc_ifaceno; @@ -97,9 +103,6 @@ struct ulpt_softc { u_char sc_laststatus; }; -int ulpt_match __P((struct device *, struct cfdata *, void *)); -void ulpt_attach __P((struct device *, struct device *, void *)); - 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)); @@ -110,24 +113,14 @@ int ulpt_status __P((struct ulpt_softc *)); void ulpt_reset __P((struct ulpt_softc *)); int ulpt_statusmsg __P((u_char, struct ulpt_softc *)); -extern struct cfdriver ulpt_cd; - #define ULPTUNIT(s) (minor(s) & 0x1f) #define ULPTFLAGS(s) (minor(s) & 0xe0) -extern struct cfdriver ulpt_cd; +USB_DECLARE_DRIVER(ulpt); -struct cfattach ulpt_ca = { - sizeof(struct ulpt_softc), ulpt_match, ulpt_attach -}; - -int -ulpt_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +USB_MATCH(ulpt) { - struct usb_attach_arg *uaa = aux; + USB_MATCH_START(ulpt, uaa); usb_interface_descriptor_t *id; DPRINTFN(10,("ulpt_match\n")); @@ -143,14 +136,9 @@ ulpt_match(parent, match, aux) return (UMATCH_NONE); } -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; + 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); @@ -162,9 +150,10 @@ ulpt_attach(parent, self, aux) usb_endpoint_descriptor_t *ed; usbd_status r; - DPRINTFN(2,("ulpt_attach: sc=%p\n", sc)); + DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); usbd_devinfo(dev, 0, devinfo); - printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname, + 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. */ @@ -182,12 +171,12 @@ ulpt_attach(parent, self, aux) goto nobulk; } sc->sc_bulk = ed->bEndpointAddress; - DPRINTFN(1, ("ulpt_attach: bulk=%d\n", sc->sc_bulk)); + DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_bulk)); sc->sc_iface = iface; r = usbd_interface2device_handle(iface, &sc->sc_udev); if (r != USBD_NORMAL_COMPLETION) - return; + USB_ATTACH_ERROR_RETURN; sc->sc_ifaceno = id->bInterfaceNumber; #if 0 @@ -206,17 +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; - printf("%s: device id <%s>\n", sc->sc_dev.dv_xname, idstr); + printf("%s: device id <%s>\n", USBDEVNAME(sc->sc_dev), idstr); } else { - printf("%s: cannot get device id\n", sc->sc_dev.dv_xname); + printf("%s: cannot get device id\n", USBDEVNAME(sc->sc_dev)); } #endif - return; + USB_ATTACH_SUCCESS_RETURN; nobulk: - printf("%s: could not find bulk endpoint\n", sc->sc_dev.dv_xname); - return; + printf("%s: could not find bulk endpoint\n", USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } int @@ -265,15 +254,11 @@ ulptopen(dev, flag, mode, p) int mode; struct proc *p; { - int unit = ULPTUNIT(dev); u_char flags = ULPTFLAGS(dev); - struct ulpt_softc *sc; usbd_status r; int spin, error; + USB_GET_SC_OPEN(ulpt, ULPTUNIT(dev), sc); - if (unit >= ulpt_cd.cd_ndevs) - return ENXIO; - sc = ulpt_cd.cd_devs[unit]; if (!sc || !sc->sc_iface) return ENXIO; @@ -325,11 +310,11 @@ ulpt_statusmsg(status, sc) sc->sc_laststatus = status; 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); + log(LOG_NOTICE, "%s: output error\n", USBDEVNAME(sc->sc_dev)); return status; } @@ -341,8 +326,7 @@ ulptclose(dev, flag, mode, p) int mode; struct proc *p; { - int unit = ULPTUNIT(dev); - struct ulpt_softc *sc = ulpt_cd.cd_devs[unit]; + USB_GET_SC(ulpt, ULPTUNIT(dev), sc); usbd_close_pipe(sc->sc_bulkpipe); @@ -358,12 +342,12 @@ ulptwrite(dev, uio, flags) struct uio *uio; int flags; { - struct ulpt_softc *sc = ulpt_cd.cd_devs[ULPTUNIT(dev)]; size_t n; int error = 0; char buf[ULPT_BSIZE]; usbd_request_handle reqh; usbd_status r; + USB_GET_SC(ulpt, ULPTUNIT(dev), sc); DPRINTF(("ulptwrite\n")); reqh = usbd_alloc_request(); @@ -411,3 +395,20 @@ ulptioctl(dev, cmd, data, flag, p) return error; } + +#if defined(__FreeBSD__) +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, usb_driver_load, 0); +#endif diff --git a/sys/dev/usb/umodem.c b/sys/dev/usb/umodem.c index 5ef2707dfe2..63c35d08798 100644 --- a/sys/dev/usb/umodem.c +++ b/sys/dev/usb/umodem.c @@ -1,4 +1,4 @@ -/* $NetBSD: umodem.c,v 1.2 1998/12/09 00:18:11 augustss Exp $ */ +/* $NetBSD: umodem.c,v 1.3 1998/12/26 12:53:02 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,13 +37,19 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #include <sys/param.h> #include <sys/systm.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> +#include <sys/ioccom.h> +#include <sys/conf.h> +#endif #include <sys/tty.h> #include <sys/file.h> #include <sys/select.h> @@ -56,6 +62,7 @@ #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> @@ -71,35 +78,25 @@ int umodemdebug = 0; #endif struct umodem_softc { - struct device sc_dev; /* base device */ + bdevice sc_dev; /* base device */ usbd_interface_handle sc_iface; /* interface */ }; -int umodem_match __P((struct device *, struct cfdata *, void *)); -void umodem_attach __P((struct device *, struct device *, void *)); - void umodem_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); void umodem_disco __P((void *)); -extern struct cfdriver umodem_cd; - -struct cfattach umodem_ca = { - sizeof(struct umodem_softc), umodem_match, umodem_attach -}; +USB_DECLARE_DRIVER(umodem); -int -umodem_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +USB_MATCH(umodem) { - struct usb_attach_arg *uaa = aux; + 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 && + if (!id || id->bInterfaceClass != UCLASS_CDC || id->bInterfaceSubClass != USUBCLASS_ABSTRACT_CONTROL_MODEL || id->bInterfaceProtocol != UPROTO_CDC_AT) @@ -107,14 +104,9 @@ umodem_match(parent, match, aux) return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO); } -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; + USB_ATTACH_START(umodem, sc, uaa); usbd_interface_handle iface = uaa->iface; usb_interface_descriptor_t *id; char devinfo[1024]; @@ -122,6 +114,30 @@ umodem_attach(parent, self, aux) sc->sc_iface = iface; id = usbd_get_interface_descriptor(iface); usbd_devinfo(uaa->device, 0, devinfo); - printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname, + USB_ATTACH_SETUP; + printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev), devinfo, id->bInterfaceClass, id->bInterfaceSubClass); + + USB_ATTACH_SUCCESS_RETURN; } + +#if defined(__FreeBSD__) +static int +umodem_detach(device_t self) +{ + struct umodem_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 + +#if defined(__FreeBSD__) +DRIVER_MODULE(umodem, usb, umodem_driver, umodem_devclass, usb_driver_load, 0); +#endif + diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c index e336b20d1d3..fc4f48ea528 100644 --- a/sys/dev/usb/ums.c +++ b/sys/dev/usb/ums.c @@ -1,4 +1,4 @@ -/* $NetBSD: ums.c,v 1.15 1998/12/10 23:16:47 augustss Exp $ */ +/* $NetBSD: ums.c,v 1.16 1998/12/26 12:53:03 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,32 +37,42 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #include <sys/param.h> #include <sys/systm.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> +#include <sys/ioccom.h> +#include <sys/conf.h> +#endif #include <sys/tty.h> #include <sys/file.h> #include <sys/select.h> #include <sys/proc.h> #include <sys/vnode.h> -#include <sys/device.h> #include <sys/poll.h> #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> #include <dev/usb/hid.h> +#if defined(__NetBSD__) #include <dev/wscons/wsconsio.h> #include <dev/wscons/wsmousevar.h> +#elif defined(__FreeBSD__) +#include <machine/mouse.h> +#endif #ifdef USB_DEBUG #define DPRINTF(x) if (umsdebug) printf x @@ -73,13 +83,17 @@ int umsdebug = 0; #define DPRINTFN(n,x) #endif -#define PS2LBUTMASK 0x01 -#define PS2RBUTMASK 0x02 -#define PS2MBUTMASK 0x04 +#define UMSUNIT(s) (minor(s)&0x1f) + +#define PS2LBUTMASK x01 +#define PS2RBUTMASK x02 +#define PS2MBUTMASK x04 #define PS2BUTMASK 0x0f +#define QUEUE_BUFSIZE 240 /* MUST be divisible by 3 _and_ 4 */ + struct ums_softc { - struct device 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; @@ -87,28 +101,45 @@ struct ums_softc { u_char *sc_ibuf; u_int8_t sc_iid; int sc_isize; - struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, - sc_loc_btn1, sc_loc_btn2, sc_loc_btn3; + struct hid_location sc_loc_x, sc_loc_y, sc_loc_z; + struct hid_location *sc_loc_btn; - u_char sc_buttons; /* mouse button status */ + int sc_enabled; int sc_disconnected; /* device is gone */ - int sc_enabled; + int flags; /* device configuration */ +#define UMS_Z 0x01 /* z direction available */ + int nbuttons; + +#if defined(__NetBSD__) + u_char sc_buttons; /* mouse button status */ struct device *sc_wsmousedev; +#elif defined(__FreeBSD__) + u_char qbuf[QUEUE_BUFSIZE]; + u_char dummy[100]; /* just for safety and for now */ + int qcount, qhead, qtail; + mousehw_t hw; + mousemode_t mode; + mousestatus_t status; + + int state; +# define UMS_ASLEEP 0x01 /* readFromDevice is waiting */ +# define UMS_SELECT 0x02 /* select is waiting */ + struct selinfo rsel; /* process waiting in select */ +#endif }; #define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE) #define MOUSE_FLAGS (HIO_RELATIVE) -int ums_match __P((struct device *, struct cfdata *, void *)); -void ums_attach __P((struct device *, struct device *, void *)); - void ums_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); void ums_disco __P((void *)); -int ums_enable __P((void *)); -int ums_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); -void ums_disable __P((void *)); +static int ums_enable __P((void *)); +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, @@ -116,19 +147,28 @@ const struct wsmouse_accessops ums_accessops = { ums_disable, }; -extern struct cfdriver ums_cd; +#elif defined(__FreeBSD__) +static d_open_t ums_open; +static d_close_t ums_close; +static d_read_t ums_read; +static d_ioctl_t ums_ioctl; +static d_poll_t ums_poll; + +#define UMS_CDEV_MAJOR 138 /* XXX NWH should be requested */ -struct cfattach ums_ca = { - sizeof(struct ums_softc), ums_match, ums_attach +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 -int -ums_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +USB_DECLARE_DRIVER(ums); + +USB_MATCH(ums) { - struct usb_attach_arg *uaa = aux; + USB_MATCH_START(ums, uaa); usb_interface_descriptor_t *id; int size, ret; void *desc; @@ -154,14 +194,9 @@ ums_match(parent, match, aux) return (ret); } -void -ums_attach(parent, self, aux) - struct device *parent; - struct device *self; - void *aux; +USB_ATTACH(ums) { - struct ums_softc *sc = (struct ums_softc *)self; - struct usb_attach_arg *uaa = aux; + USB_ATTACH_START(ums, sc, uaa); usbd_interface_handle iface = uaa->iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; @@ -171,18 +206,21 @@ ums_attach(parent, self, aux) usbd_status r; char devinfo[1024]; u_int32_t flags; + 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); - printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname, + 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) { printf("%s: could not read endpoint descriptor\n", - sc->sc_dev.dv_xname); - return; + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } DPRINTFN(10,("ums_attach: bLength=%d bDescriptorType=%d " @@ -197,76 +235,151 @@ ums_attach(parent, self, aux) if ((ed->bEndpointAddress & UE_IN) != UE_IN || (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) { printf("%s: unexpected endpoint\n", - sc->sc_dev.dv_xname); - return; + USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; } r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP); if (r != USBD_NORMAL_COMPLETION) - return; + USB_ATTACH_ERROR_RETURN; + if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), hid_input, &sc->sc_loc_x, &flags)) { - printf("%s: mouse has no X report\n", sc->sc_dev.dv_xname); - 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) - printf("%s: sorry, X report 0x%04x not supported yet\n", - sc->sc_dev.dv_xname, flags); if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), hid_input, &sc->sc_loc_y, &flags)) { - printf("%s: mouse has no Y report\n", sc->sc_dev.dv_xname); - return; + printf("%s: mouse has no Y report\n", USBDEVNAME(sc->sc_dev)); + USB_ATTACH_ERROR_RETURN; + } + 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; } - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) - printf("%s: sorry, Y report 0x%04x not supported yet\n", - sc->sc_dev.dv_xname, flags); + /* try to guess the Z activator: first check Z, then WHEEL */ if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), hid_input, &sc->sc_loc_z, &flags) || hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), hid_input, &sc->sc_loc_z, &flags)) { - if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) - /* Bad Z coord, ignore it */ - sc->sc_loc_z.size = 0; + if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { + sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */ + } else { + sc->flags |= UMS_Z; + } } - hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, 1), /* left */ - hid_input, &sc->sc_loc_btn1, 0); - hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, 2), /* right */ - hid_input, &sc->sc_loc_btn2, 0); - hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, 3), /* middle */ - hid_input, &sc->sc_loc_btn3, 0); - DPRINTF(("ums_attach: sc=%p\n", sc)); - DPRINTF(("ums_attach: X %d/%d\n", - sc->sc_loc_x.pos, sc->sc_loc_x.size)); - DPRINTF(("ums_attach: Y %d/%d\n", - sc->sc_loc_x.pos, sc->sc_loc_x.size)); - DPRINTF(("ums_attach: Z %d/%d\n", - sc->sc_loc_z.pos, sc->sc_loc_z.size)); - DPRINTF(("ums_attach: B1 %d/%d\n", - sc->sc_loc_btn1.pos,sc->sc_loc_btn1.size)); - DPRINTF(("ums_attach: B2 %d/%d\n", - sc->sc_loc_btn2.pos,sc->sc_loc_btn2.size)); - DPRINTF(("ums_attach: B3 %d/%d\n", - sc->sc_loc_btn3.pos,sc->sc_loc_btn3.size)); + /* figure out the number of buttons, 7 is an arbitrary limit */ + for (i = 1; i <= 7; i++) + if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), + 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); + if (!sc->sc_loc_btn) + USB_ATTACH_ERROR_RETURN; + + 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), + hid_input, &sc->sc_loc_btn[i-1], 0); sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid); - DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid)); sc->sc_ibuf = malloc(sc->sc_isize, M_USB, M_NOWAIT); - if (!sc->sc_ibuf) - return; + if (!sc->sc_ibuf) { + free(sc->sc_loc_btn, M_USB); + USB_ATTACH_ERROR_RETURN; + } sc->sc_ep_addr = ed->bEndpointAddress; sc->sc_disconnected = 0; free(desc, M_TEMP); +#ifdef USB_DEBUG + DPRINTF(("ums_attach: sc=%p\n", sc)); + DPRINTF(("ums_attach: X\t%d/%d\n", + sc->sc_loc_x.pos, sc->sc_loc_x.size)); + DPRINTF(("ums_attach: Y\t%d/%d\n", + sc->sc_loc_x.pos, sc->sc_loc_x.size)); + if (sc->flags & UMS_Z) + DPRINTF(("ums_attach: Z\t%d/%d\n", + sc->sc_loc_z.pos, sc->sc_loc_z.size)); + for (i = 1; i <= sc->nbuttons; i++) { + DPRINTF(("ums_attach: B%d\t%d/%d\n", + i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size)); + } + DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid)); +#endif + +#if defined(__NetBSD__) a.accessops = &ums_accessops; a.accesscookie = sc; sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); +#elif defined(__FreeBSD__) + sc->hw.buttons = 2; /* XXX hw&mode values are bogus */ + sc->hw.iftype = MOUSE_IF_PS2; + sc->hw.type = MOUSE_MOUSE; + if (sc->flags & UMS_Z) + sc->hw.model = MOUSE_MODEL_INTELLI; + else + sc->hw.model = MOUSE_MODEL_GENERIC; + sc->hw.hwid = 0; + sc->mode.protocol = MOUSE_PROTO_PS2; + sc->mode.rate = -1; + sc->mode.resolution = MOUSE_RES_DEFAULT; + sc->mode.accelfactor = 1; + sc->mode.level = 0; + if (sc->flags & UMS_Z) { + sc->mode.packetsize = MOUSE_INTELLI_PACKETSIZE; + sc->mode.syncmask[0] = 0xc8; + } else { + sc->mode.packetsize = MOUSE_PS2_PACKETSIZE; + sc->mode.syncmask[0] = 0xc0; + } + sc->mode.syncmask[1] = 0; + + sc->status.flags = 0; + sc->status.button = sc->status.obutton = 0; + sc->status.dx = sc->status.dy = sc->status.dz = 0; + + sc->rsel.si_flags = 0; + sc->rsel.si_pid = 0; +#endif + + USB_ATTACH_SUCCESS_RETURN; } + +#if defined(__FreeBSD__) +static int +ums_detach(device_t self) +{ + struct ums_softc *sc = device_get_softc(self); + char *devinfo = (char *) device_get_desc(self); + + if (devinfo) { + device_set_desc(self, NULL); + free(devinfo, M_USB); + } + free(sc->sc_loc_btn, M_USB); + free(sc->sc_ibuf, M_USB); + + return 0; +} +#endif + void ums_disco(p) void *p; @@ -287,7 +400,13 @@ ums_intr(reqh, addr, status) struct ums_softc *sc = addr; u_char *ibuf; int dx, dy, dz; - u_char buttons; + 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", @@ -310,31 +429,100 @@ ums_intr(reqh, addr, status) dx = hid_get_data(ibuf, &sc->sc_loc_x); dy = -hid_get_data(ibuf, &sc->sc_loc_y); dz = hid_get_data(ibuf, &sc->sc_loc_z); - buttons = 0; - if (hid_get_data(ibuf, &sc->sc_loc_btn1)) buttons |= 1 << 0; - if (hid_get_data(ibuf, &sc->sc_loc_btn2)) buttons |= 1 << 2; - if (hid_get_data(ibuf, &sc->sc_loc_btn3)) buttons |= 1 << 1; - + /* NWH Why are you modifying the button assignments here? + * That's the purpose of a high level mouse driver + */ + 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) { + DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n", + dx, dy, dz, buttons)); sc->sc_buttons = buttons; if (sc->sc_wsmousedev) wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, dz); +#elif defined(__FreeBSD__) + if (dx || dy || buttons != sc->status.button) { + DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n", + dx, dy, dz, buttons)); + + sc->status.button = buttons; + sc->status.dx += dx; + sc->status.dy += dy; + sc->status.dz += dz; + + /* Discard data in case of full buffer */ + if (sc->qcount == sizeof(sc->qbuf)) { + DPRINTF(("Buffer full, discarded packet")); + return; + } + + sc->qbuf[sc->qhead] = MOUSE_PS2_SYNC; + if (dx < 0) + sc->qbuf[sc->qhead] |= MOUSE_PS2_XNEG; + if (dx > 255 || dx < -255) + sc->qbuf[sc->qhead] |= MOUSE_PS2_XOVERFLOW; + if (dy < 0) + sc->qbuf[sc->qhead] |= MOUSE_PS2_YNEG; + if (dy > 255 || dy < -255) + sc->qbuf[sc->qhead] |= MOUSE_PS2_YOVERFLOW; + sc->qbuf[sc->qhead++] |= buttons; + sc->qbuf[sc->qhead++] = dx; + sc->qbuf[sc->qhead++] = dy; + sc->qcount += 3; + if (sc->flags & UMS_Z) { + sc->qbuf[sc->qhead++] = dz; + sc->qcount++; + } +#ifdef USB_DEBUG + if (sc->qhead > sizeof(sc->qbuf)) + DPRINTF(("Buffer overrun! %d %d\n", + sc->qhead, sizeof(sc->qbuf))); +#endif + /* wrap round at end of buffer */ + if (sc->qhead >= sizeof(sc->qbuf)) + sc->qhead = 0; + + /* someone waiting for data */ + if (sc->state & UMS_ASLEEP) + wakeup(sc); + /* wake up any pending selects */ + selwakeup(&sc->rsel); + sc->state &= ~UMS_SELECT; +#endif } } -/* wscons routines */ -int + +static int ums_enable(v) void *v; { struct ums_softc *sc = v; + usbd_status r; if (sc->sc_enabled) return EBUSY; sc->sc_enabled = 1; +#if defined(__NetBSD__) sc->sc_buttons = 0; +#elif defined(__FreeBSD__) + sc->qcount = 0; + sc->qhead = sc->qtail = 0; +#ifdef USB_DEBUG + if (sizeof(sc->qbuf) % 4 || sizeof(sc->qbuf) % 3) { + DPRINTF(("Buffer size not divisible by 3 or 4\n")); + return ENXIO; + } +#endif + sc->status.flags = 0; + sc->status.button = sc->status.obutton = 0; + sc->status.dx = sc->status.dy = sc->status.dz = 0; +#endif /* Set up interrupt pipe. */ r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, @@ -350,7 +538,7 @@ ums_enable(v) return (0); } -void +static void ums_disable(v) void *v; { @@ -361,25 +549,188 @@ ums_disable(v) usbd_close_pipe(sc->sc_intrpipe); sc->sc_enabled = 0; + +#if defined(USBVERBOSE) && defined(__FreeBSD__) + if (sc->qcount != 0) + DPRINTF(("Discarded %d bytes in queue\n", sc->qcount)); +#endif } -int +#if defined(__NetBSD__) +static int ums_ioctl(v, cmd, data, flag, p) void *v; u_long cmd; caddr_t data; int flag; struct proc *p; -{ -#if 0 - struct ums_softc *sc = v; -#endif +{ switch (cmd) { case WSMOUSEIO_GTYPE: *(u_int *)data = WSMOUSE_TYPE_PS2; return (0); } + return (-1); } +#elif defined(__FreeBSD__) +static int +ums_open(dev_t dev, int flag, int fmt, struct proc *p) +{ + struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); + + if (!sc) { + DPRINTF(("sc not found at open")); + return EINVAL; + } + + return ums_enable(sc); +} + +static int +ums_close(dev_t dev, int flag, int fmt, struct proc *p) +{ + struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); + + if (!sc) { + DPRINTF(("sc not found at close")); + return EINVAL; + } + + if (sc->sc_enabled) + ums_disable(sc); + return 0; +} + +static int +ums_read(dev_t dev, struct uio *uio, int flag) +{ + struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); + int s; + char buf[sizeof(sc->qbuf)]; + int l = 0; + int error; + + if (!sc || !sc->sc_enabled) { + DPRINTF(("sc not found at read")); + return EINVAL; + } + + s = splusb(); + while (sc->qcount == 0 ) { + /* NWH XXX non blocking I/O ?? + if (non blocking I/O ) { + splx(s); + return EWOULDBLOCK; + } else { + */ + sc->state |= UMS_ASLEEP; + error = tsleep(sc, PZERO | PCATCH, "umsrea", 0); + sc->state &= ~UMS_ASLEEP; + if (error) { + splx(s); + return error; + } + } + + while ((sc->qcount > 0) && (uio->uio_resid > 0)) { + l = (sc->qcount < uio->uio_resid? sc->qcount:uio->uio_resid); + if (l > sizeof(buf)) + l = sizeof(buf); + if (l > sizeof(sc->qbuf) - sc->qtail) /* transfer till end of buf */ + l = sizeof(sc->qbuf) - sc->qtail; + + splx(s); + uiomove(&sc->qbuf[sc->qtail], l, uio); + s = splusb(); + + if ( sc->qcount - l < 0 ) { + DPRINTF(("qcount below 0, count=%d l=%d\n", sc->qcount, l)); + sc->qcount = l; + } + sc->qcount -= l; /* remove the bytes from the buffer */ + sc->qtail = (sc->qtail + l) % sizeof(sc->qbuf); + } + splx(s); + + return 0; +} + +static int +ums_poll(dev_t dev, int events, struct proc *p) +{ + struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); + int revents = 0; + int s; + + if (!sc) { + DPRINTF(("sc not found at poll")); + return 0; /* just to make sure */ + } + + s = splusb(); + if (events & (POLLIN | POLLRDNORM)) + if (sc->qcount) { + revents = events & (POLLIN | POLLRDNORM); + } else { + sc->state |= UMS_SELECT; + selrecord(p, &sc->rsel); + } + splx(s); + + return revents; +} + +int +ums_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) +{ + struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); + int error = 0; + int s; + + if (!sc) { + DPRINTF(("sc not found at ioctl")); + return ENOENT; + } + + switch(cmd) { + case MOUSE_GETHWINFO: + *(mousehw_t *)addr = sc->hw; + break; + case MOUSE_GETMODE: + *(mousemode_t *)addr = sc->mode; + break; + case MOUSE_GETLEVEL: + *(int *)addr = sc->mode.level; + break; + case MOUSE_GETSTATUS: { + mousestatus_t *status = (mousestatus_t *) addr; + + s = splusb(); + *status = sc->status; + sc->status.obutton = sc->status.button; + sc->status.button = 0; + sc->status.dx = sc->status.dy = sc->status.dz = 0; + splx(s); + + if (status->dx || status->dy || status->dz) + status->flags |= MOUSE_POSCHANGED; + if (status->button != status->obutton) + status->flags |= MOUSE_BUTTONSCHANGED; + break; + } + default: + error = ENOTTY; + } + + return error; +} +#endif + +#if defined(__FreeBSD__) +CDEV_DRIVER_MODULE(ums, usb, ums_driver, ums_devclass, + UMS_CDEV_MAJOR, ums_cdevsw, usb_driver_load, 0); +#endif + diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 3b7012b305b..9b6f4d423ef 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.6 1998/12/09 00:18:11 augustss Exp $ */ +/* $NetBSD: usb.c,v 1.7 1998/12/26 12:53:03 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -42,19 +42,32 @@ * More USB specs at http://www.usb.org/developers/index.shtml */ -#include "opt_usbverbose.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#if defined(__NetBSD__) #include <sys/device.h> +#elif defined(__FreeBSD__) +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/ioccom.h> +#include <sys/uio.h> +#include <sys/conf.h> +#endif #include <sys/poll.h> #include <sys/proc.h> #include <sys/select.h> #include <dev/usb/usb.h> +#if defined(__FreeBSD__) +MALLOC_DEFINE(M_USB, "USB", "USB"); +MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device"); + +#include "usb_if.h" +#endif /* defined(__FreeBSD__) */ + #include <dev/usb/usbdi.h> #include <dev/usb/usbdivar.h> #include <dev/usb/usb_quirks.h> @@ -73,7 +86,7 @@ int ohcidebug; #define USBUNIT(dev) (minor(dev)) struct usb_softc { - struct device 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; @@ -81,42 +94,56 @@ struct usb_softc { struct selinfo sc_consel; /* waiting for connect change */ }; -int usb_match __P((struct device *, struct cfdata *, void *)); -void usb_attach __P((struct device *, struct device *, void *)); +#if defined(__NetBSD__) 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 *)); -usbd_status usb_discover __P((struct usb_softc *)); +#elif defined(__FreeBSD__) +static device_probe_t usb_match; +static device_attach_t usb_attach; +static bus_print_child_t usb_print_child; -extern struct cfdriver usb_cd; +d_open_t usbopen; +d_close_t usbclose; +d_ioctl_t usbioctl; +int usbpoll __P((dev_t, int, struct proc *)); -struct cfattach usb_ca = { - sizeof(struct usb_softc), usb_match, usb_attach +struct cdevsw usb_cdevsw = { + usbopen, usbclose, noread, nowrite, + usbioctl, nullstop, nullreset, nodevtotty, + usbpoll, nommap, nostrat, + "usb", NULL, -1 }; +#endif -int -usb_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +usbd_status usb_discover __P((struct usb_softc *)); + +USB_DECLARE_DRIVER_INIT(usb, DEVMETHOD(bus_print_child, usb_print_child)); + +USB_MATCH(usb) { DPRINTF(("usbd_match\n")); - return (1); + return (UMATCH_GENERIC); } -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; +#elif defined(__FreeBSD__) + struct usb_softc *sc = device_get_softc(device); + void *aux = device_get_ivars(device); +#endif usbd_device_handle dev; usbd_status r; +#if defined(__NetBSD__) printf("\n"); +#elif defined(__FreeBSD__) + sc->sc_dev = device; +#endif DPRINTF(("usbd_attach\n")); usbd_init(); @@ -126,24 +153,28 @@ usb_attach(parent, self, aux) sc->sc_bus->use_polling = 1; sc->sc_port.power = USB_MAX_POWER; 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; - printf("%s: root device is not a hub\n", - sc->sc_dev.dv_xname); - 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_dev, sc->sc_bus->root_hub); + dev->hub->explore(sc->sc_bus->root_hub); } else { printf("%s: root hub problem, error=%d\n", - sc->sc_dev.dv_xname, r); + USBDEVNAME(sc->sc_dev), r); sc->sc_running = 0; } sc->sc_bus->use_polling = 0; + + USB_ATTACH_SUCCESS_RETURN; } +#if defined(__NetBSD__) int usbctlprint(aux, pnp) void *aux; @@ -156,18 +187,114 @@ usbctlprint(aux, pnp) return (UNCONF); } +#elif defined(__FreeBSD__) +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); +} + +/* + * A static buffer is a loss if this routine is used from an interrupt, + * but it's not fatal. + */ +char * +usb_devname(struct device *bdev) +{ + static char buf[20]; + + sprintf(buf, "%s%d", device_get_name(*bdev), device_get_unit(*bdev)); + return (buf); +} + +#endif + int usbopen(dev, flag, mode, p) dev_t dev; int flag, mode; struct proc *p; { - int unit = USBUNIT(dev); - struct usb_softc *sc; + USB_GET_SC_OPEN(usb, USBUNIT(dev), sc); - if (unit >= usb_cd.cd_ndevs) - return (ENXIO); - sc = usb_cd.cd_devs[unit]; if (sc == 0 || !sc->sc_running) return (ENXIO); @@ -191,8 +318,7 @@ usbioctl(dev, cmd, data, flag, p) int flag; struct proc *p; { - int unit = USBUNIT(dev); - struct usb_softc *sc = usb_cd.cd_devs[unit]; + USB_GET_SC(usb, USBUNIT(dev), sc); if (sc == 0 || !sc->sc_running) return (ENXIO); @@ -257,7 +383,6 @@ usbioctl(dev, cmd, data, flag, p) if (ptr) free(ptr, M_TEMP); return (error); - break; } case USB_DEVICEINFO: @@ -291,9 +416,8 @@ usbpoll(dev, events, p) int events; struct proc *p; { - int unit = USBUNIT(dev); - struct usb_softc *sc = usb_cd.cd_devs[unit]; int revents, s; + USB_GET_SC(usb, USBUNIT(dev), sc); DPRINTFN(2, ("usbpoll: sc=%p events=0x%x\n", sc, events)); s = splusb(); @@ -353,7 +477,7 @@ usb_discover(sc) sc->sc_bus->needs_explore = 0; splx(s); - sc->sc_bus->root_hub->hub->explore(&sc->sc_dev, sc->sc_bus->root_hub); + sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); s = splusb(); sc->sc_exploring = 0; @@ -370,3 +494,21 @@ usb_needs_explore(bus) bus->needs_explore = 1; selwakeup(&bus->usbctl->sc_consel); } + +#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 20bdf5a0748..b5546851699 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -1,4 +1,4 @@ -/* $NetBSD: usb.h,v 1.7 1998/12/09 00:18:11 augustss Exp $ */ +/* $NetBSD: usb.h,v 1.8 1998/12/26 12:53:03 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -42,7 +42,26 @@ #define _USB_H_ #include <sys/types.h> +#if defined(__NetBSD__) #include <sys/ioctl.h> +#endif + +#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); + +#include <dev/usb/usb_port.h> +#endif /* KERNEL */ +#endif /* __FreeBSD__ */ + #define USB_MAX_DEVICES 128 #define USB_START_ADDR 0 @@ -120,7 +139,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 */ @@ -229,7 +248,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 @@ -242,17 +261,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,7 +323,7 @@ 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 @@ -312,9 +334,19 @@ typedef struct { */ #define USB_POWER_DOWN_TIME 1000 /* ms */ +#if 0 +/* These are the value 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 bad device */ +#define USB_PORT_RESET_DELAY 10 /* ms */ +#define USB_PORT_RESET_RECOVERY 20 /* 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 */ diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h index b09d5e22e94..092ddc4fb69 100644 --- a/sys/dev/usb/usb_mem.h +++ b/sys/dev/usb/usb_mem.h @@ -1,4 +1,4 @@ -/* $NetBSD: usb_mem.h,v 1.2 1998/11/25 22:32:05 augustss Exp $ */ +/* $NetBSD: usb_mem.h,v 1.3 1998/12/26 12:53:03 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,6 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#if defined(__NetBSD__) typedef struct usb_block_dma { bus_dma_tag_t tag; bus_dmamap_t map; @@ -59,3 +60,34 @@ 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 *)); + +#elif define(__FreeBSD__) + +/* + * FreeBSD does not have special functions for dma memory, so let's keep it + * simple for now. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/queue.h> +#include <sys/proc.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/pmap.h> /* for vtophys */ + + + +typedef void * usb_dma_t; + +#define usb_allocmem(t,s,a,p) (*(p) = malloc(s, M_USB, M_NOWAIT), (*(p) == NULL? USBD_NOMEM: USBD_NORMAL_COMPLETION)) +#define usb_freemem(t,p) (free(*(p), M_USB)) + +#define DMAADDR(dma) (vtophys(*(dma))) +#define KERNADDR(dma) ((void *) *(dma)) +#endif + diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h new file mode 100644 index 00000000000..ecb1ad17f34 --- /dev/null +++ b/sys/dev/usb/usb_port.h @@ -0,0 +1,180 @@ +/* Macro's to cope with the differences between NetBSD and FreeBSD + */ + +/* + * NetBSD + */ + +#if defined(__NetBSD__) +#include "opt_usbverbose.h" + +#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) \ +} + +#define USB_MATCH(dname) \ +int \ +__CONCAT(dname,_match)(parent, match, aux) \ + struct device *parent; \ + struct cfdata *match; \ + void *aux; + +#define USB_MATCH_START(dname, uaa) \ + struct usb_attach_arg *uaa = aux + +#define USB_ATTACH(dname) \ +void \ +__CONCAT(dname,_attach)(parent, self, aux) \ + struct device *parent; \ + struct device *self; \ + void *aux; + +#define USB_ATTACH_START(dname, sc, uaa) \ + struct __CONCAT(dname,_softc) *sc = (struct __CONCAT(dname,_softc) *)self; \ + struct usb_attach_arg *uaa = aux + +/* Returns from attach */ +#define USB_ATTACH_ERROR_RETURN return +#define USB_ATTACH_SUCCESS_RETURN return + +#define USB_ATTACH_SETUP printf("\n") + +#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 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)) + +#elif defined(__FreeBSD__) +/* + * FreeBSD + */ + +#include "opt_usb.h" +char *usb_devname(struct device *); +#define USBDEVNAME(bdev) usb_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) + +typedef device_t bdevice; + +/* + * 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 + */ +#define usb_timeout(f, d, t, h) \ + (callout_handle_init(&(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 \ + usb_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_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 /* __FreeBSD */ + +#define NONE {0,0} + +#define USB_DECLARE_DRIVER_NAME(name, dname) \ + USB_DECLARE_DRIVER_NAME_INIT(name, dname, NONE ) +#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, NONE ) + +#undef NONE diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c index dad2ce0c827..3a84389a7b3 100644 --- a/sys/dev/usb/usb_quirks.c +++ b/sys/dev/usb/usb_quirks.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb_quirks.c,v 1.3 1998/12/02 22:57:08 augustss Exp $ */ +/* $NetBSD: usb_quirks.c,v 1.4 1998/12/26 12:53:03 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -39,7 +39,6 @@ #include <sys/param.h> #include <sys/systm.h> -#include <sys/device.h> #include <sys/select.h> #include <dev/usb/usb.h> @@ -58,6 +57,7 @@ struct usbd_quirk_entry { 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_ADS, USB_PRODUCT_ADS_ENET, 0x002, { UQ_NO_STRINGS }}, { 0, 0, 0, { 0 } } }; @@ -78,7 +78,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_subr.c b/sys/dev/usb/usb_subr.c index 9f0f6cd27a9..273ca31a367 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb_subr.c,v 1.17 1998/12/12 12:18:26 augustss Exp $ */ +/* $NetBSD: usb_subr.c,v 1.18 1998/12/26 12:53:03 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -41,7 +41,12 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#if defined(__NetBSD__) #include <sys/device.h> +#elif defined(__FreeBSD__) +#include <sys/module.h> +#include <sys/bus.h> +#endif #include <sys/proc.h> #include <sys/select.h> @@ -53,8 +58,6 @@ #include <dev/usb/usbdevs.h> #include <dev/usb/usb_quirks.h> -#include "opt_usbverbose.h" - #ifdef USB_DEBUG #define DPRINTF(x) if (usbdebug) printf x #define DPRINTFN(n,x) if (usbdebug>(n)) printf x @@ -66,15 +69,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 *)); -usbd_status usbd_get_desc __P((usbd_device_handle dev, int type, - int index, int len, void *desc)); 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 *)); +#endif usb_interface_descriptor_t *usbd_find_idesc __P((usb_config_descriptor_t *cd, int ifaceidx, int altidx)); void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno)); void usbd_kill_pipe __P((usbd_pipe_handle)); +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; @@ -306,6 +311,9 @@ 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->bus, USB_PORT_RESET_RECOVERY); return (r); } @@ -322,6 +330,10 @@ usbd_find_idesc(cd, ifaceidx, altidx) for (curidx = lastno = -1; p < end; ) { d = (usb_interface_descriptor_t *)p; + 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; @@ -387,7 +399,7 @@ usbd_fill_iface_data(dev, ifaceidx, altidx) int endpt, nendpt; usbd_status r; - DPRINTFN(5,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n", + DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n", ifaceidx, altidx)); ifc->device = dev; ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx); @@ -523,6 +535,12 @@ usbd_set_config_index(dev, index, msg) 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. */ @@ -561,9 +579,9 @@ usbd_set_config_index(dev, index, msg) if (power > dev->powersrc->power) { /* XXX print nicer message. */ if (msg) - printf("%s: device addr %d (config %d) exceeds " - "power budget, %d mA > %d mA\n", - dev->bus->bdev.dv_xname, 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); r = USBD_NO_POWER; @@ -572,6 +590,8 @@ usbd_set_config_index(dev, index, msg) 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_index: setting config=%d failed, " @@ -659,14 +679,102 @@ int usbd_getnewaddr(bus) usbd_bus_handle bus; { - int i; + int addr; - for (i = 1; i < USB_MAX_DEVICES; i++) - if (bus->devices[i] == 0) - return (i); + for (addr = 1; addr < USB_MAX_DEVICES; addr++) + if (bus->devices[addr] == 0) + return (addr); return (-1); } + +usbd_status +usbd_probe_and_attach(parent, dev, port, addr) + bdevice *parent; + usbd_device_handle dev; + int port; + int addr; +{ + struct usb_attach_arg uaa; + usb_device_descriptor_t *dd = &dev->ddesc; + int r, found, i, confi; + +#if defined(__FreeBSD__) +/* XXX isn't it bad to build &uaa into a value that has a lifetime + longer than this function call? */ + bdevice bdev; + 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.usegeneric = 0; + uaa.port = port; + uaa.configno = UHUB_UNK_CONFIGURATION; + uaa.ifaceno = UHUB_UNK_INTERFACE; + + /* First try with device specific drivers. */ + if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch)) + return (USBD_NORMAL_COMPLETION); + + DPRINTF(("usbd_probe_and_attach: no device specific driver found\n")); + + /* Next try with interface drivers. */ + for (confi = 0; confi < dd->bNumConfigurations; confi++) { + 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) { +#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 + return (r); + } + uaa.configno = confi; + for (found = i = 0; i < dev->cdesc->bNumInterface; i++) { + uaa.iface = &dev->ifaces[i]; + uaa.ifaceno = dev->ifaces[i].idesc->bInterfaceNumber; + if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, + usbd_submatch)) + found++; + } + if (found != 0) + return (USBD_NORMAL_COMPLETION); + } + /* No interfaces were attach in any of the configurations. */ + if (dd->bNumConfigurations > 0) + usbd_set_config_index(dev, 0, 0); + + DPRINTF(("usbd_probe_and_attach: no interface drivers found\n")); + + /* Finally try the generic driver. */ + uaa.iface = 0; + uaa.usegeneric = 1; + 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); + + /* + * 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_probe_and_attach: generic attach failed\n")); + return (USBD_NORMAL_COMPLETION); +} + + + /* * Called when a new device has been put in the powered state, * but not yet in the addressed state. @@ -675,7 +783,7 @@ usbd_getnewaddr(bus) */ usbd_status usbd_new_device(parent, bus, depth, lowspeed, port, up) - struct device *parent; + bdevice *parent; usbd_bus_handle bus; int depth; int lowspeed; @@ -683,18 +791,17 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) struct usbd_port *up; { usbd_device_handle dev; - usb_device_descriptor_t *d; + usb_device_descriptor_t *dd; usbd_status r; - struct usb_attach_arg uaa; int addr; - int found, i, confi; + int i; DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n", bus, depth, lowspeed)); addr = usbd_getnewaddr(bus); if (addr < 0) { - printf("%s: No free USB addresses, new device ignored.\n", - bus->bdev.dv_xname); + printf("%s: No free USB addresses, new device ignored.\n", + USBDEVNAME(bus->bdev)); return (USBD_NO_ADDR); } @@ -708,8 +815,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; @@ -729,15 +834,17 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) /* Establish the the default pipe. */ r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe); - if (r != USBD_NORMAL_COMPLETION) - goto bad1; + if (r != USBD_NORMAL_COMPLETION) { + usbd_remove_device(dev, up); + return r; + } up->device = dev; - d = &dev->ddesc; + dd = &dev->ddesc; /* Try a few times in case the device is slow (i.e. outside specs.) */ for (i = 0; i < 5; i++) { /* Get the first 8 bytes of the device descriptor. */ - r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, d); + r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); if (r == USBD_NORMAL_COMPLETION) break; usbd_delay_ms(dev->bus, 200); @@ -746,34 +853,48 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up) DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc " "failed\n", addr)); - goto bad; + usbd_remove_device(dev, up); + return (r); + } + + 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(d->bcdUSB), d->bDeviceClass, d->bDeviceSubClass, - d->bDeviceProtocol, d->bMaxPacketSize, dev->lowspeed)); + addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, + dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed)); - USETW(dev->def_ep_desc.wMaxPacketSize, d->bMaxPacketSize); + USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); /* Get the full device descriptor. */ - r = usbd_get_device_desc(dev, d); + 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)); - goto bad; + usbd_remove_device(dev, up); + return (r); } /* Figure out what's wrong with this device. */ - dev->quirks = usbd_find_quirk(d); + dev->quirks = usbd_find_quirk(dd); /* Set the address */ r = usbd_set_address(dev, addr); if (r != USBD_NORMAL_COMPLETION) { DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr)); r = USBD_SET_ADDR_FAILED; - goto bad; + usbd_remove_device(dev, up); + return (r); } + /* Allow device time to set new address */ + usbd_delay_ms(dev->bus, USB_SET_ADDRESS_SETTLE); + dev->address = addr; /* New device address now */ dev->state = USBD_DEVICE_ADDRESSED; bus->devices[addr] = dev; @@ -785,72 +906,44 @@ 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)); - uaa.device = dev; - uaa.iface = 0; - uaa.usegeneric = 0; - uaa.port = port; - uaa.configno = UHUB_UNK_CONFIGURATION; - uaa.ifaceno = UHUB_UNK_INTERFACE; - /* First try with device specific drivers. */ - if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0) - return (USBD_NORMAL_COMPLETION); - - DPRINTF(("usbd_new_device: no device driver found\n")); + 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); +} - /* Next try with interface drivers. */ - for (confi = 0; confi < d->bNumConfigurations; confi++) { - DPRINTFN(1,("usbd_new_device: trying config idx=%d\n", confi)); - r = usbd_set_config_index(dev, confi, 1); - if (r != USBD_NORMAL_COMPLETION) { -#ifdef USB_DEBUG - DPRINTF(("%s: set config at addr %d failed, " - "error=%d(%s)\n", - parent->dv_xname, addr, r, - usbd_error_strs[r])); -#else - printf("%s: set config at addr %d failed\n", - parent->dv_xname, addr); +void +usbd_remove_device(dev, up) + usbd_device_handle dev; + 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 - goto bad; - } - uaa.configno = confi; - for (found = i = 0; i < dev->cdesc->bNumInterface; i++) { - uaa.iface = &dev->ifaces[i]; - uaa.ifaceno = dev->ifaces[i].idesc->bInterfaceNumber; - if (config_found_sm(parent, &uaa, usbd_print, - usbd_submatch)) - found++; - } - if (found != 0) - return (USBD_NORMAL_COMPLETION); - } - /* No interfaces were attached in any of the configurations. */ - if (d->bNumConfigurations > 0) - usbd_set_config_index(dev, 0, 0); - - DPRINTF(("usbd_new_device: no interface drivers found\n")); - - /* Finally try the generic driver. */ - uaa.iface = 0; - uaa.usegeneric = 1; - uaa.configno = UHUB_UNK_CONFIGURATION; - uaa.ifaceno = UHUB_UNK_INTERFACE; - if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0) - return (USBD_NORMAL_COMPLETION); - - DPRINTF(("usbd_new_device: generic attach failed\n")); - - return (USBD_NORMAL_COMPLETION); - - bad: - usbd_kill_pipe(dev->default_pipe); - bad1: + + if (dev->default_pipe) + usbd_kill_pipe(dev->default_pipe); up->device = 0; - bus->devices[addr] = 0; + dev->bus->devices[dev->address] = 0; + free(dev, M_USB); - return (r); } +#if defined(__NetBSD__) int usbd_print(aux, pnp) void *aux; @@ -896,6 +989,15 @@ usbd_submatch(parent, cf, aux) return ((*cf->cf_attach->ca_match)(parent, cf, aux)); } +#elif defined(__FreeBSD__) +static void +usbd_bus_print_child(device_t bus, device_t dev) +{ + /* FIXME print the device address and the configuration used + */ +} +#endif + void usbd_fill_deviceinfo(dev, di) usbd_device_handle dev; diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index 838240ce55b..9af92aa186f 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.c,v 1.14 1998/12/10 23:16:48 augustss Exp $ */ +/* $NetBSD: usbdi.c,v 1.15 1998/12/26 12:53:04 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,14 +37,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "opt_usbverbose.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#if defined(__NetBSD__) +#include <sys/device.h> +#else +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#endif #include <sys/malloc.h> #include <sys/proc.h> -#include <sys/device.h> #include <dev/usb/usb.h> @@ -72,6 +76,12 @@ void usbd_do_request_async_cb static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests; +#if defined(__FreeBSD__) +#define USB_CDEV_MAJOR 79 + +extern struct cdevsw usb_cdevsw; +#endif + usbd_status usbd_open_pipe(iface, address, flags, pipe) usbd_interface_handle iface; @@ -235,7 +245,7 @@ usbd_start(pipe) { usbd_request_handle reqh; - DPRINTFN(1, ("usbd_start: pipe=%p, running=%d\n", + DPRINTFN(5, ("usbd_start: pipe=%p, running=%d\n", pipe, pipe->running)); if (pipe->running) return (USBD_IN_PROGRESS); @@ -513,7 +523,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); @@ -537,7 +547,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); @@ -933,9 +943,18 @@ static int usbd_global_init_done = 0; void usbd_init() { +#if defined(__FreeBSD__) + dev_t dev; +#endif + if (!usbd_global_init_done) { usbd_global_init_done = 1; SIMPLEQ_INIT(&usbd_free_requests); + +#if defined(__FreeBSD__) + dev = makedev(USB_CDEV_MAJOR, 0); + cdevsw_add(&dev, &usb_cdevsw, NULL); +#endif } } @@ -956,7 +975,7 @@ 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 < %d\n", + DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d+1<%d+1 (bytes)\n", reqh->actlen, reqh->length)); reqh->status = USBD_SHORT_XFER; } @@ -1034,10 +1053,8 @@ usbd_do_request(dev, req, data) 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); - } + if (r != USBD_NORMAL_COMPLETION) + goto bad; r = usbd_sync_transfer(reqh); #if defined(USB_DEBUG) || defined(DIAGNOSTIC) if (reqh->actlen > reqh->length) @@ -1049,6 +1066,50 @@ usbd_do_request(dev, req, data) UGETW(reqh->request.wLength), reqh->length, reqh->actlen); #endif + 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); } diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index fb3235e7798..80dddbb78f2 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi.h,v 1.11 1998/12/10 23:16:48 augustss Exp $ */ +/* $NetBSD: usbdi.h,v 1.12 1998/12/26 12:53:04 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -251,6 +251,7 @@ struct usb_attach_arg { int usegeneric; }; +#if defined(__NetBSD__) /* Match codes. */ /* First five codes is for a whole device. */ #define UMATCH_VENDOR_PRODUCT_REV 14 @@ -272,6 +273,47 @@ struct usb_attach_arg { /* No match */ #define UMATCH_NONE 0 +#elif defined(__FreeBSD__) +/* FreeBSD needs values less than zero */ +/* for the moment disabled +#define UMATCH_VENDOR_PRODUCT_REV -14 +#define UMATCH_VENDOR_PRODUCT -13 +#define UMATCH_VENDOR_DEVCLASS_DEVPROTO -12 +#define UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO -11 +#define UMATCH_DEVCLASS_DEVSUBCLASS -10 +#define UMATCH_VENDOR_PRODUCT_REV_CONF_IFACE -9 +#define UMATCH_VENDOR_PRODUCT_CONF_IFACE -8 +#define UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO -7 +#define UMATCH_VENDOR_IFACESUBCLASS -6 +#define UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO -5 +#define UMATCH_IFACECLASS_IFACESUBCLASS -4 +#define UMATCH_IFACECLASS -3 +#define UMATCH_IFACECLASS_GENERIC -2 +#define UMATCH_GENERIC -1 +#define UMATCH_NONE ENXIO + +* For the moment we use Yes/No answers with appropriate +* sorting in the config file +*/ +#define UMATCH_VENDOR_PRODUCT_REV 0 +#define UMATCH_VENDOR_PRODUCT 0 +#define UMATCH_VENDOR_DEVCLASS_DEVPROTO 0 +#define UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO 0 +#define UMATCH_DEVCLASS_DEVSUBCLASS 0 +#define UMATCH_VENDOR_PRODUCT_REV_CONF_IFACE 0 +#define UMATCH_VENDOR_PRODUCT_CONF_IFACE 0 +#define UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO 0 +#define UMATCH_VENDOR_IFACESUBCLASS 0 +#define UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO 0 +#define UMATCH_IFACECLASS_IFACESUBCLASS 0 +#define UMATCH_IFACECLASS 0 +#define UMATCH_IFACECLASS_GENERIC 0 +#define UMATCH_GENERIC 0 +#define UMATCH_NONE ENXIO + + +#endif + 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 *)); diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c index 67c2645ce2f..7549321bbe7 100644 --- a/sys/dev/usb/usbdi_util.c +++ b/sys/dev/usb/usbdi_util.c @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi_util.c,v 1.8 1998/12/09 00:18:12 augustss Exp $ */ +/* $NetBSD: usbdi_util.c,v 1.9 1998/12/26 12:53:04 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -41,7 +41,6 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> -#include <sys/device.h> #include <sys/proc.h> #include <sys/select.h> @@ -51,8 +50,6 @@ #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> -#include "opt_usbverbose.h" - #ifdef USB_DEBUG #define DPRINTF(x) if (usbdebug) printf x #define DPRINTFN(n,x) if (usbdebug>(n)) printf x @@ -85,9 +82,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 @@ -398,7 +405,12 @@ usbd_alloc_report_desc(ifc, descp, sizep, mem) usbd_interface_handle ifc; void **descp; int *sizep; +#if defined(__NetBSD__) int mem; +#elif defined(__FreeBSD__) + struct malloc_type *mem; +#endif + { usb_interface_descriptor_t *id; usb_hid_descriptor_t *hid; diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h index df798cebd1a..c42bea94219 100644 --- a/sys/dev/usb/usbdi_util.h +++ b/sys/dev/usb/usbdi_util.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbdi_util.h,v 1.9 1998/12/10 23:16:48 augustss Exp $ */ +/* $NetBSD: usbdi_util.h,v 1.10 1998/12/26 12:53:04 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -66,8 +66,13 @@ usbd_status usbd_get_report __P((usbd_interface_handle iface,int type,int id,void *data,int len)); usbd_status usbd_set_idle __P((usbd_interface_handle iface, int duration, int id)); +#if defined(__NetBSD__) usbd_status usbd_alloc_report_desc __P((usbd_interface_handle ifc, void **descp, int *sizep, int mem)); +#elif defined(__FreeBSD__) +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 diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index b6226b58ab2..a6b3a82cae1 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbdivar.h,v 1.10 1998/12/09 00:18:12 augustss Exp $ */ +/* $NetBSD: usbdivar.h,v 1.11 1998/12/26 12:53:04 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -59,15 +59,17 @@ 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((struct device *parent, - usbd_device_handle hub)); - void *hubdata; + usbd_status (*explore)__P((usbd_device_handle hub)); + void *hubsoftc; usb_hub_descriptor_t hubdesc; struct usbd_port ports[1]; }; @@ -78,7 +80,7 @@ struct usb_softc; struct usbd_bus { /* Filled by HC driver */ - struct device bdev; /* base device */ + bdevice bdev; /* base device, host adapter */ usbd_status (*open_pipe)__P((struct usbd_pipe *pipe)); u_int32_t pipe_size; /* size of a pipe struct */ void (*do_poll)__P((struct usbd_bus *)); @@ -109,6 +111,7 @@ 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 */ + void *softc; /* device softc if attached */ }; struct usbd_interface { @@ -162,6 +165,10 @@ struct usbd_request { SIMPLEQ_ENTRY(usbd_request) next; void *hcpriv; /* XXX private use by the HC driver */ + +#if defined(__FreeBSD__) + struct callout_handle timo_handle; +#endif }; void usbd_init __P((void)); @@ -177,10 +184,12 @@ usbd_status usbd_setup_pipe __P((usbd_device_handle dev, usbd_interface_handle iface, struct usbd_endpoint *, usbd_pipe_handle *pipe)); -usbd_status usbd_new_device __P((struct device *parent, +usbd_status usbd_new_device __P((bdevice *parent, usbd_bus_handle bus, int depth, int lowspeed, int port, struct usbd_port *)); +void usbd_remove_device __P((usbd_device_handle, + struct usbd_port *)); int usbd_printBCD __P((char *cp, int bcd)); usbd_status usbd_fill_iface_data __P((usbd_device_handle dev, int i, int a)); @@ -190,11 +199,18 @@ 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)); +#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__) #include "locators.h" +#endif #define uhubcf_port cf_loc[UHUBCF_PORT] #define uhubcf_configuration cf_loc[UHUBCF_CONFIGURATION] diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h index 317f57e6c21..02231b578fb 100644 --- a/sys/dev/usb/usbhid.h +++ b/sys/dev/usb/usbhid.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbhid.h,v 1.2 1998/11/25 22:32:05 augustss Exp $ */ +/* $NetBSD: usbhid.h,v 1.3 1998/12/26 12:53:04 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -73,11 +73,46 @@ typedef struct usb_hid_descriptor { #define HUP_BUTTON 0x0009 /* Usages, generic desktop */ +#define HUG_POINTER 0x0001 #define HUG_MOUSE 0x0002 +#define HUG_JOYSTICK 0x0004 +#define HUG_GAME_PAD 0x0005 +#define HUG_KEYBOARD 0x0006 +#define HUG_KEYPAD 0x0007 #define HUG_X 0x0030 #define HUG_Y 0x0031 #define HUG_Z 0x0032 +#define HUG_RX 0x0033 +#define HUG_RY 0x0034 +#define HUG_RZ 0x0035 +#define HUG_SLIDER 0x0036 +#define HUG_DIAL 0x0037 #define HUG_WHEEL 0x0038 +#define HUG_HAT_SWITCH 0x0039 +#define HUG_COUNTED_BUFFER 0x003a +#define HUG_BYTE_COUNT 0x003b +#define HUG_MOTION_WAKEUP 0x003c +#define HUG_VX 0x0040 +#define HUG_VY 0x0041 +#define HUG_VZ 0x0042 +#define HUG_VBRX 0x0043 +#define HUG_VBRY 0x0044 +#define HUG_VBRZ 0x0045 +#define HUG_VNO 0x0046 +#define HUG_SYSTEM_CONTROL 0x0080 +#define HUG_SYSTEM_POWER_DOWN 0x0081 +#define HUG_SYSTEM_SLEEP 0x0082 +#define HUG_SYSTEM_WAKEUP 0x0083 +#define HUG_SYSTEM_CONTEXT_MENU 0x0084 +#define HUG_SYSTEM_MAIN_MENU 0x0085 +#define HUG_SYSTEM_APP_MENU 0x0086 +#define HUG_SYSTEM_MENU_HELP 0x0087 +#define HUG_SYSTEM_MENU_EXIT 0x0088 +#define HUG_SYSTEM_MENU_SELECT 0x0089 +#define HUG_SYSTEM_MENU_RIGHT 0x008a +#define HUG_SYSTEM_MENU_LEFT 0x008b +#define HUG_SYSTEM_MENU_UP 0x008c +#define HUG_SYSTEM_MENU_DOWN 0x008d #define HID_USAGE2(p,u) (((p) << 16) | u) |
