1 /* $NetBSD: usb.c,v 1.12 1999/01/10 19:13:16 augustss Exp $ */ 2 3 /* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (augustss@carlstedt.se) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * USB specifications and other documentation can be found at 42 * http://www.usb.org/developers/data/ and 43 * http://www.usb.org/developers/index.html . 44 */ 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/malloc.h> 50 #if defined(__NetBSD__) 51 #include <sys/device.h> 52 #elif defined(__FreeBSD__) 53 #include <sys/module.h> 54 #include <sys/bus.h> 55 #include <sys/ioccom.h> 56 #include <sys/uio.h> 57 #include <sys/conf.h> 58 #endif 59 #include <sys/poll.h> 60 #include <sys/proc.h> 61 #include <sys/select.h> 62 63 #include <dev/usb/usb.h> 64 65 #if defined(__FreeBSD__) 66 MALLOC_DEFINE(M_USB, "USB", "USB"); 67 MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device"); 68 69 #include "usb_if.h" 70 #endif /* defined(__FreeBSD__) */ 71 72 #include <dev/usb/usbdi.h> 73 #include <dev/usb/usbdivar.h> 74 #include <dev/usb/usb_quirks.h> 75 76 #ifdef USB_DEBUG 77 #define DPRINTF(x) if (usbdebug) printf x 78 #define DPRINTFN(n,x) if (usbdebug>(n)) printf x 79 int usbdebug = 0; 80 int uhcidebug; 81 int ohcidebug; 82 #else 83 #define DPRINTF(x) 84 #define DPRINTFN(n,x) 85 #endif 86 87 #define USBUNIT(dev) (minor(dev)) 88 89 struct usb_softc { 90 bdevice sc_dev; /* base device */ 91 usbd_bus_handle sc_bus; /* USB controller */ 92 struct usbd_port sc_port; /* dummy port for root hub */ 93 char sc_running; 94 char sc_exploring; 95 struct selinfo sc_consel; /* waiting for connect change */ 96 }; 97 98 #if defined(__NetBSD__) 99 int usbopen __P((dev_t, int, int, struct proc *)); 100 int usbclose __P((dev_t, int, int, struct proc *)); 101 int usbioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); 102 int usbpoll __P((dev_t, int, struct proc *)); 103 104 #elif defined(__FreeBSD__) 105 d_open_t usbopen; 106 d_close_t usbclose; 107 d_ioctl_t usbioctl; 108 int usbpoll __P((dev_t, int, struct proc *)); 109 110 struct cdevsw usb_cdevsw = { 111 usbopen, usbclose, noread, nowrite, 112 usbioctl, nullstop, nullreset, nodevtotty, 113 usbpoll, nommap, nostrat, 114 "usb", NULL, -1 115 }; 116 #endif 117 118 usbd_status usb_discover __P((struct usb_softc *)); 119 120 USB_DECLARE_DRIVER_INIT(usb, DEVMETHOD(bus_print_child, usbd_print_child)); 121 122 USB_MATCH(usb) 123 { 124 DPRINTF(("usbd_match\n")); 125 return (UMATCH_GENERIC); 126 } 127 128 USB_ATTACH(usb) 129 { 130 #if defined(__NetBSD__) 131 struct usb_softc *sc = (struct usb_softc *)self; 132 #elif defined(__FreeBSD__) 133 struct usb_softc *sc = device_get_softc(self); 134 void *aux = device_get_ivars(self); 135 #endif 136 usbd_device_handle dev; 137 usbd_status r; 138 139 #if defined(__NetBSD__) 140 printf("\n"); 141 #elif defined(__FreeBSD__) 142 sc->sc_dev = self; 143 #endif 144 145 DPRINTF(("usbd_attach\n")); 146 usbd_init(); 147 sc->sc_bus = aux; 148 sc->sc_bus->usbctl = sc; 149 sc->sc_running = 1; 150 sc->sc_bus->use_polling = 1; 151 sc->sc_port.power = USB_MAX_POWER; 152 r = usbd_new_device(&sc->sc_dev, sc->sc_bus, 0, 0, 0, &sc->sc_port); 153 154 if (r == USBD_NORMAL_COMPLETION) { 155 dev = sc->sc_port.device; 156 if (!dev->hub) { 157 sc->sc_running = 0; 158 printf("%s: root device is not a hub\n", 159 USBDEVNAME(sc->sc_dev)); 160 USB_ATTACH_ERROR_RETURN; 161 } 162 sc->sc_bus->root_hub = dev; 163 dev->hub->explore(sc->sc_bus->root_hub); 164 } else { 165 printf("%s: root hub problem, error=%d\n", 166 USBDEVNAME(sc->sc_dev), r); 167 sc->sc_running = 0; 168 } 169 sc->sc_bus->use_polling = 0; 170 171 USB_ATTACH_SUCCESS_RETURN; 172 } 173 174 #if defined(__NetBSD__) 175 int 176 usbctlprint(aux, pnp) 177 void *aux; 178 const char *pnp; 179 { 180 /* only "usb"es can attach to host controllers */ 181 if (pnp) 182 printf("usb at %s", pnp); 183 184 return (UNCONF); 185 } 186 #endif 187 188 int 189 usbopen(dev, flag, mode, p) 190 dev_t dev; 191 int flag, mode; 192 struct proc *p; 193 { 194 USB_GET_SC_OPEN(usb, USBUNIT(dev), sc); 195 196 if (sc == 0 || !sc->sc_running) 197 return (ENXIO); 198 199 return (0); 200 } 201 202 int 203 usbclose(dev, flag, mode, p) 204 dev_t dev; 205 int flag, mode; 206 struct proc *p; 207 { 208 return (0); 209 } 210 211 int 212 usbioctl(dev, cmd, data, flag, p) 213 dev_t dev; 214 u_long cmd; 215 caddr_t data; 216 int flag; 217 struct proc *p; 218 { 219 USB_GET_SC(usb, USBUNIT(dev), sc); 220 221 if (sc == 0 || !sc->sc_running) 222 return (ENXIO); 223 switch (cmd) { 224 #ifdef USB_DEBUG 225 case USB_SETDEBUG: 226 usbdebug = uhcidebug = ohcidebug = *(int *)data; 227 break; 228 #endif 229 case USB_DISCOVER: 230 usb_discover(sc); 231 break; 232 case USB_REQUEST: 233 { 234 struct usb_ctl_request *ur = (void *)data; 235 int len = UGETW(ur->request.wLength); 236 struct iovec iov; 237 struct uio uio; 238 void *ptr = 0; 239 int addr = ur->addr; 240 usbd_status r; 241 int error = 0; 242 243 DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len)); 244 if (len < 0 || len > 32768) 245 return (EINVAL); 246 if (addr < 0 || addr >= USB_MAX_DEVICES || 247 sc->sc_bus->devices[addr] == 0) 248 return (EINVAL); 249 if (len != 0) { 250 iov.iov_base = (caddr_t)ur->data; 251 iov.iov_len = len; 252 uio.uio_iov = &iov; 253 uio.uio_iovcnt = 1; 254 uio.uio_resid = len; 255 uio.uio_offset = 0; 256 uio.uio_segflg = UIO_USERSPACE; 257 uio.uio_rw = 258 ur->request.bmRequestType & UT_READ ? 259 UIO_READ : UIO_WRITE; 260 uio.uio_procp = p; 261 ptr = malloc(len, M_TEMP, M_WAITOK); 262 if (uio.uio_rw == UIO_WRITE) { 263 error = uiomove(ptr, len, &uio); 264 if (error) 265 goto ret; 266 } 267 } 268 r = usbd_do_request_flags(sc->sc_bus->devices[addr], 269 &ur->request, ptr, 270 ur->flags, &ur->actlen); 271 if (r) { 272 error = EIO; 273 goto ret; 274 } 275 if (len != 0) { 276 if (uio.uio_rw == UIO_READ) { 277 error = uiomove(ptr, len, &uio); 278 if (error) 279 goto ret; 280 } 281 } 282 ret: 283 if (ptr) 284 free(ptr, M_TEMP); 285 return (error); 286 } 287 288 case USB_DEVICEINFO: 289 { 290 struct usb_device_info *di = (void *)data; 291 int addr = di->addr; 292 usbd_device_handle dev; 293 294 if (addr < 1 || addr >= USB_MAX_DEVICES) 295 return (EINVAL); 296 dev = sc->sc_bus->devices[addr]; 297 if (dev == 0) 298 return (ENXIO); 299 usbd_fill_deviceinfo(dev, di); 300 break; 301 } 302 303 case USB_DEVICESTATS: 304 *(struct usb_device_stats *)data = sc->sc_bus->stats; 305 break; 306 307 default: 308 return (ENXIO); 309 } 310 return (0); 311 } 312 313 int 314 usbpoll(dev, events, p) 315 dev_t dev; 316 int events; 317 struct proc *p; 318 { 319 int revents, s; 320 USB_GET_SC(usb, USBUNIT(dev), sc); 321 322 DPRINTFN(2, ("usbpoll: sc=%p events=0x%x\n", sc, events)); 323 s = splusb(); 324 revents = 0; 325 if (events & (POLLOUT | POLLWRNORM)) 326 if (sc->sc_bus->needs_explore) 327 revents |= events & (POLLOUT | POLLWRNORM); 328 DPRINTFN(2, ("usbpoll: revents=0x%x\n", revents)); 329 if (revents == 0) { 330 if (events & (POLLOUT | POLLWRNORM)) { 331 DPRINTFN(2, ("usbpoll: selrecord\n")); 332 selrecord(p, &sc->sc_consel); 333 } 334 } 335 splx(s); 336 return (revents); 337 } 338 339 #if 0 340 int 341 usb_bus_count() 342 { 343 int i, n; 344 345 for (i = n = 0; i < usb_cd.cd_ndevs; i++) 346 if (usb_cd.cd_devs[i]) 347 n++; 348 return (n); 349 } 350 #endif 351 352 #if 0 353 usbd_status 354 usb_get_bus_handle(n, h) 355 int n; 356 usbd_bus_handle *h; 357 { 358 int i; 359 360 for (i = 0; i < usb_cd.cd_ndevs; i++) 361 if (usb_cd.cd_devs[i] && n-- == 0) { 362 *h = usb_cd.cd_devs[i]; 363 return (USBD_NORMAL_COMPLETION); 364 } 365 return (USBD_INVAL); 366 } 367 #endif 368 369 usbd_status 370 usb_discover(sc) 371 struct usb_softc *sc; 372 { 373 int s; 374 375 /* Explore device tree from the root */ 376 /* We need mutual exclusion while traversing the device tree. */ 377 s = splusb(); 378 while (sc->sc_exploring) 379 tsleep(&sc->sc_exploring, PRIBIO, "usbdis", 0); 380 sc->sc_exploring = 1; 381 sc->sc_bus->needs_explore = 0; 382 splx(s); 383 384 sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); 385 386 s = splusb(); 387 sc->sc_exploring = 0; 388 wakeup(&sc->sc_exploring); 389 splx(s); 390 /* XXX should we start over if sc_needsexplore is set again? */ 391 return (0); 392 } 393 394 void 395 usb_needs_explore(bus) 396 usbd_bus_handle bus; 397 { 398 bus->needs_explore = 1; 399 selwakeup(&bus->usbctl->sc_consel); 400 } 401 402 #if defined(__FreeBSD__) 403 int 404 usb_detach(device_t self) 405 { 406 struct usb_softc *sc = device_get_softc(self); 407 char *devinfo = (char *) device_get_desc(self); 408 409 if (devinfo) { 410 device_set_desc(self, NULL); 411 free(devinfo, M_USB); 412 } 413 414 return (0); 415 } 416 417 DRIVER_MODULE(usb, root, usb_driver, usb_devclass, 0, 0); 418 #endif 419