root/dev/usb/usb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usb_match
  2. usb_attach
  3. usb_create_event_thread
  4. usb_add_task
  5. usb_rem_task
  6. usb_event_thread
  7. usb_task_thread
  8. usbctlprint
  9. usbopen
  10. usbread
  11. usbclose
  12. usbioctl
  13. usbpoll
  14. filt_usbrdetach
  15. filt_usbread
  16. usbkqfilter
  17. usb_discover
  18. usb_needs_explore
  19. usb_needs_reattach
  20. usb_get_next_event
  21. usbd_add_dev_event
  22. usbd_add_drv_event
  23. usb_add_event
  24. usb_schedsoftintr
  25. usb_activate
  26. usb_detach

    1 /*      $OpenBSD: usb.c,v 1.56 2007/06/15 11:41:48 mbalmer Exp $        */
    2 /*      $NetBSD: usb.c,v 1.77 2003/01/01 00:10:26 thorpej Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) at
   10  * Carlstedt Research & Technology.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *        This product includes software developed by the NetBSD
   23  *        Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * USB specifications and other documentation can be found at
   43  * http://www.usb.org/developers/docs/ and
   44  * http://www.usb.org/developers/devclass_docs/
   45  */
   46 
   47 #include "ohci.h"
   48 #include "uhci.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/kernel.h>
   53 #include <sys/malloc.h>
   54 #include <sys/device.h>
   55 #include <sys/kthread.h>
   56 #include <sys/proc.h>
   57 #include <sys/conf.h>
   58 #include <sys/fcntl.h>
   59 #include <sys/poll.h>
   60 #include <sys/selinfo.h>
   61 #include <sys/vnode.h>
   62 #include <sys/signalvar.h>
   63 
   64 #include <dev/usb/usb.h>
   65 #include <dev/usb/usbdi.h>
   66 #include <dev/usb/usbdi_util.h>
   67 
   68 #define USB_DEV_MINOR 255
   69 
   70 #include <machine/bus.h>
   71 
   72 #include <dev/usb/usbdivar.h>
   73 #include <dev/usb/usb_quirks.h>
   74 
   75 #ifdef USB_DEBUG
   76 #define DPRINTF(x)      do { if (usbdebug) printf x; } while (0)
   77 #define DPRINTFN(n,x)   do { if (usbdebug>(n)) printf x; } while (0)
   78 int     usbdebug = 0;
   79 #if defined(UHCI_DEBUG) && NUHCI > 0
   80 extern int      uhcidebug;
   81 #endif
   82 #if defined(OHCI_DEBUG) && NOHCI > 0
   83 extern int      ohcidebug;
   84 #endif
   85 /*
   86  * 0  - do usual exploration
   87  * 1  - do not use timeout exploration
   88  * >1 - do no exploration
   89  */
   90 int     usb_noexplore = 0;
   91 #else
   92 #define DPRINTF(x)
   93 #define DPRINTFN(n,x)
   94 #endif
   95 
   96 struct usb_softc {
   97         struct device    sc_dev;        /* base device */
   98         usbd_bus_handle  sc_bus;        /* USB controller */
   99         struct usbd_port sc_port;       /* dummy port for root hub */
  100 
  101         struct proc     *sc_event_thread;
  102 
  103         char             sc_dying;
  104 };
  105 
  106 TAILQ_HEAD(, usb_task) usb_all_tasks;
  107 
  108 volatile int threads_pending = 0;
  109 
  110 void    usb_discover(void *);
  111 void    usb_create_event_thread(void *);
  112 void    usb_event_thread(void *);
  113 void    usb_task_thread(void *);
  114 struct proc *usb_task_thread_proc = NULL;
  115 
  116 #define USB_MAX_EVENTS 100
  117 struct usb_event_q {
  118         struct usb_event ue;
  119         SIMPLEQ_ENTRY(usb_event_q) next;
  120 };
  121 SIMPLEQ_HEAD(, usb_event_q) usb_events =
  122         SIMPLEQ_HEAD_INITIALIZER(usb_events);
  123 int usb_nevents = 0;
  124 struct selinfo usb_selevent;
  125 struct proc *usb_async_proc;  /* process that wants USB SIGIO */
  126 int usb_dev_open = 0;
  127 void usb_add_event(int, struct usb_event *);
  128 
  129 int usb_get_next_event(struct usb_event *);
  130 
  131 const char *usbrev_str[] = USBREV_STR;
  132 
  133 int usb_match(struct device *, void *, void *); 
  134 void usb_attach(struct device *, struct device *, void *); 
  135 int usb_detach(struct device *, int); 
  136 int usb_activate(struct device *, enum devact); 
  137 
  138 struct cfdriver usb_cd = { 
  139         NULL, "usb", DV_DULL 
  140 }; 
  141 
  142 const struct cfattach usb_ca = { 
  143         sizeof(struct usb_softc), 
  144         usb_match, 
  145         usb_attach, 
  146         usb_detach, 
  147         usb_activate, 
  148 };
  149 
  150 int
  151 usb_match(struct device *parent, void *match, void *aux)
  152 {
  153         DPRINTF(("usbd_match\n"));
  154         return (UMATCH_GENERIC);
  155 }
  156 
  157 void
  158 usb_attach(struct device *parent, struct device *self, void *aux)
  159 {
  160         struct usb_softc *sc = (struct usb_softc *)self;
  161         usbd_device_handle dev;
  162         usbd_status err;
  163         int usbrev;
  164         int speed;
  165         struct usb_event ue;
  166 
  167         DPRINTF(("usbd_attach\n"));
  168 
  169         usbd_init();
  170         sc->sc_bus = aux;
  171         sc->sc_bus->usbctl = sc;
  172         sc->sc_port.power = USB_MAX_POWER;
  173 
  174         usbrev = sc->sc_bus->usbrev;
  175         printf(": USB revision %s", usbrev_str[usbrev]);
  176         switch (usbrev) {
  177         case USBREV_1_0:
  178         case USBREV_1_1:
  179                 speed = USB_SPEED_FULL;
  180                 break;
  181         case USBREV_2_0:
  182                 speed = USB_SPEED_HIGH;
  183                 break;
  184         default:
  185                 printf(", not supported\n");
  186                 sc->sc_dying = 1;
  187                 return;
  188         }
  189         printf("\n");
  190 
  191         /* Make sure not to use tsleep() if we are cold booting. */
  192         if (cold)
  193                 sc->sc_bus->use_polling++;
  194 
  195         ue.u.ue_ctrlr.ue_bus = sc->sc_dev.dv_unit;
  196         usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue);
  197 
  198 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
  199         /* XXX we should have our own level */
  200         sc->sc_bus->soft = softintr_establish(IPL_SOFTNET,
  201             sc->sc_bus->methods->soft_intr, sc->sc_bus);
  202         if (sc->sc_bus->soft == NULL) {
  203                 printf("%s: can't register softintr\n", sc->sc_dev.dv_xname);
  204                 sc->sc_dying = 1;
  205                 return;
  206         }
  207 #endif
  208 
  209         err = usbd_new_device(&sc->sc_dev, sc->sc_bus, 0, speed, 0,
  210                   &sc->sc_port);
  211         if (!err) {
  212                 dev = sc->sc_port.device;
  213                 if (dev->hub == NULL) {
  214                         sc->sc_dying = 1;
  215                         printf("%s: root device is not a hub\n",
  216                                sc->sc_dev.dv_xname);
  217                         return;
  218                 }
  219                 sc->sc_bus->root_hub = dev;
  220 #if 1
  221                 /*
  222                  * Turning this code off will delay attachment of USB devices
  223                  * until the USB event thread is running, which means that
  224                  * the keyboard will not work until after cold boot.
  225                  */
  226                 if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1))
  227                         dev->hub->explore(sc->sc_bus->root_hub);
  228 #endif
  229         } else {
  230                 printf("%s: root hub problem, error=%d\n",
  231                        sc->sc_dev.dv_xname, err);
  232                 sc->sc_dying = 1;
  233         }
  234         if (cold)
  235                 sc->sc_bus->use_polling--;
  236 
  237         config_pending_incr();
  238         kthread_create_deferred(usb_create_event_thread, sc);
  239 }
  240 
  241 void
  242 usb_create_event_thread(void *arg)
  243 {
  244         struct usb_softc *sc = arg;
  245         static int created = 0;
  246 
  247         if (sc->sc_bus->usbrev == USBREV_2_0)
  248                 threads_pending++;
  249 
  250         if (kthread_create(usb_event_thread, sc, &sc->sc_event_thread,
  251             "%s", sc->sc_dev.dv_xname))
  252                 panic("unable to create event thread for %s",
  253                     sc->sc_dev.dv_xname);
  254 
  255         if (!created) {
  256                 created = 1;
  257                 TAILQ_INIT(&usb_all_tasks);
  258                 if (kthread_create(usb_task_thread, NULL,
  259                     &usb_task_thread_proc, "usbtask"))
  260                         panic("unable to create usb task thread");
  261         }
  262 }
  263 
  264 /*
  265  * Add a task to be performed by the task thread.  This function can be
  266  * called from any context and the task will be executed in a process
  267  * context ASAP.
  268  */
  269 void
  270 usb_add_task(usbd_device_handle dev, struct usb_task *task)
  271 {
  272         int s;
  273 
  274         s = splusb();
  275         if (!task->onqueue) {
  276                 DPRINTFN(2,("usb_add_task: task=%p\n", task));
  277                 TAILQ_INSERT_TAIL(&usb_all_tasks, task, next);
  278                 task->onqueue = 1;
  279         } else {
  280                 DPRINTFN(3,("usb_add_task: task=%p on q\n", task));
  281         }
  282         wakeup(&usb_all_tasks);
  283         splx(s);
  284 }
  285 
  286 void
  287 usb_rem_task(usbd_device_handle dev, struct usb_task *task)
  288 {
  289         int s;
  290 
  291         s = splusb();
  292         if (task->onqueue) {
  293                 TAILQ_REMOVE(&usb_all_tasks, task, next);
  294                 task->onqueue = 0;
  295         }
  296         splx(s);
  297 }
  298 
  299 void
  300 usb_event_thread(void *arg)
  301 {
  302         struct usb_softc *sc = arg;
  303         int pwrdly;
  304 
  305         DPRINTF(("usb_event_thread: start\n"));
  306 
  307         /* Wait for power to come good. */
  308         pwrdly = sc->sc_bus->root_hub->hub->hubdesc.bPwrOn2PwrGood * 
  309             UHD_PWRON_FACTOR + USB_EXTRA_POWER_UP_TIME;
  310         usb_delay_ms(sc->sc_bus, pwrdly);
  311 
  312         /* USB1 threads wait for USB2 threads to finish their first probe. */
  313         while (sc->sc_bus->usbrev != USBREV_2_0 && threads_pending)
  314                 (void)tsleep((void *)&threads_pending, PWAIT, "config", 0);
  315 
  316         /* Make sure first discover does something. */
  317         sc->sc_bus->needs_explore = 1;
  318         usb_discover(sc);
  319         config_pending_decr();
  320 
  321         /* Wake up any companions waiting for handover before their probes. */
  322         if (sc->sc_bus->usbrev == USBREV_2_0) {
  323                 threads_pending--;
  324                 wakeup((void *)&threads_pending);
  325         }
  326 
  327         while (!sc->sc_dying) {
  328 #ifdef USB_DEBUG
  329                 if (usb_noexplore < 2)
  330 #endif
  331                 usb_discover(sc);
  332 #ifdef USB_DEBUG
  333                 (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
  334                     usb_noexplore ? 0 : hz * 60);
  335 #else
  336                 (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
  337                     hz * 60);
  338 #endif
  339                 DPRINTFN(2,("usb_event_thread: woke up\n"));
  340         }
  341         sc->sc_event_thread = NULL;
  342 
  343         /* In case parent is waiting for us to exit. */
  344         wakeup(sc);
  345 
  346         DPRINTF(("usb_event_thread: exit\n"));
  347         kthread_exit(0);
  348 }
  349 
  350 void
  351 usb_task_thread(void *arg)
  352 {
  353         struct usb_task *task;
  354         int s;
  355 
  356         DPRINTF(("usb_task_thread: start\n"));
  357 
  358         s = splusb();
  359         for (;;) {
  360                 task = TAILQ_FIRST(&usb_all_tasks);
  361                 if (task == NULL) {
  362                         tsleep(&usb_all_tasks, PWAIT, "usbtsk", 0);
  363                         task = TAILQ_FIRST(&usb_all_tasks);
  364                 }
  365                 DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task));
  366                 if (task != NULL) {
  367                         TAILQ_REMOVE(&usb_all_tasks, task, next);
  368                         task->onqueue = 0;
  369                         splx(s);
  370                         task->fun(task->arg);
  371                         s = splusb();
  372                 }
  373         }
  374 }
  375 
  376 int
  377 usbctlprint(void *aux, const char *pnp)
  378 {
  379         /* only "usb"es can attach to host controllers */
  380         if (pnp)
  381                 printf("usb at %s", pnp);
  382 
  383         return (UNCONF);
  384 }
  385 
  386 int
  387 usbopen(dev_t dev, int flag, int mode, struct proc *p)
  388 {
  389         int unit = minor(dev);
  390         struct usb_softc *sc;
  391 
  392         if (unit == USB_DEV_MINOR) {
  393                 if (usb_dev_open)
  394                         return (EBUSY);
  395                 usb_dev_open = 1;
  396                 usb_async_proc = 0;
  397                 return (0);
  398         }
  399 
  400         if (unit >= usb_cd.cd_ndevs)
  401                 return (ENXIO);
  402         sc = usb_cd.cd_devs[unit];
  403         if (sc == NULL)
  404                 return (ENXIO);
  405 
  406         if (sc->sc_dying)
  407                 return (EIO);
  408 
  409         return (0);
  410 }
  411 
  412 int
  413 usbread(dev_t dev, struct uio *uio, int flag)
  414 {
  415         struct usb_event ue;
  416         int s, error, n;
  417 
  418         if (minor(dev) != USB_DEV_MINOR)
  419                 return (ENXIO);
  420 
  421         if (uio->uio_resid != sizeof(struct usb_event))
  422                 return (EINVAL);
  423 
  424         error = 0;
  425         s = splusb();
  426         for (;;) {
  427                 n = usb_get_next_event(&ue);
  428                 if (n != 0)
  429                         break;
  430                 if (flag & IO_NDELAY) {
  431                         error = EWOULDBLOCK;
  432                         break;
  433                 }
  434                 error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0);
  435                 if (error)
  436                         break;
  437         }
  438         splx(s);
  439         if (!error)
  440                 error = uiomove((void *)&ue, uio->uio_resid, uio);
  441 
  442         return (error);
  443 }
  444 
  445 int
  446 usbclose(dev_t dev, int flag, int mode, struct proc *p)
  447 {
  448         int unit = minor(dev);
  449 
  450         if (unit == USB_DEV_MINOR) {
  451                 usb_async_proc = 0;
  452                 usb_dev_open = 0;
  453         }
  454 
  455         return (0);
  456 }
  457 
  458 int
  459 usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, struct proc *p)
  460 {
  461         struct usb_softc *sc;
  462         int unit = minor(devt);
  463 
  464         if (unit == USB_DEV_MINOR) {
  465                 switch (cmd) {
  466                 case FIONBIO:
  467                         /* All handled in the upper FS layer. */
  468                         return (0);
  469 
  470                 case FIOASYNC:
  471                         if (*(int *)data)
  472                                 usb_async_proc = p;
  473                         else
  474                                 usb_async_proc = 0;
  475                         return (0);
  476 
  477                 default:
  478                         return (EINVAL);
  479                 }
  480         }
  481 
  482         sc = usb_cd.cd_devs[unit];
  483 
  484         if (sc->sc_dying)
  485                 return (EIO);
  486 
  487         switch (cmd) {
  488 #ifdef USB_DEBUG
  489         case USB_SETDEBUG:
  490                 if (!(flag & FWRITE))
  491                         return (EBADF);
  492                 usbdebug  = ((*(int *)data) & 0x000000ff);
  493 #if defined(UHCI_DEBUG) && NUHCI > 0
  494                 uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8;
  495 #endif
  496 #if defined(OHCI_DEBUG) && NOHCI > 0
  497                 ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16;
  498 #endif
  499                 break;
  500 #endif /* USB_DEBUG */
  501         case USB_REQUEST:
  502         {
  503                 struct usb_ctl_request *ur = (void *)data;
  504                 int len = UGETW(ur->ucr_request.wLength);
  505                 struct iovec iov;
  506                 struct uio uio;
  507                 void *ptr = 0;
  508                 int addr = ur->ucr_addr;
  509                 usbd_status err;
  510                 int error = 0;
  511 
  512                 if (!(flag & FWRITE))
  513                         return (EBADF);
  514 
  515                 DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
  516                 if (len < 0 || len > 32768)
  517                         return (EINVAL);
  518                 if (addr < 0 || addr >= USB_MAX_DEVICES ||
  519                     sc->sc_bus->devices[addr] == 0)
  520                         return (EINVAL);
  521                 if (len != 0) {
  522                         iov.iov_base = (caddr_t)ur->ucr_data;
  523                         iov.iov_len = len;
  524                         uio.uio_iov = &iov;
  525                         uio.uio_iovcnt = 1;
  526                         uio.uio_resid = len;
  527                         uio.uio_offset = 0;
  528                         uio.uio_segflg = UIO_USERSPACE;
  529                         uio.uio_rw =
  530                                 ur->ucr_request.bmRequestType & UT_READ ?
  531                                 UIO_READ : UIO_WRITE;
  532                         uio.uio_procp = p;
  533                         ptr = malloc(len, M_TEMP, M_WAITOK);
  534                         if (uio.uio_rw == UIO_WRITE) {
  535                                 error = uiomove(ptr, len, &uio);
  536                                 if (error)
  537                                         goto ret;
  538                         }
  539                 }
  540                 err = usbd_do_request_flags(sc->sc_bus->devices[addr],
  541                           &ur->ucr_request, ptr, ur->ucr_flags,
  542                           &ur->ucr_actlen, USBD_DEFAULT_TIMEOUT);
  543                 if (err) {
  544                         error = EIO;
  545                         goto ret;
  546                 }
  547                 if (len != 0) {
  548                         if (uio.uio_rw == UIO_READ) {
  549                                 error = uiomove(ptr, len, &uio);
  550                                 if (error)
  551                                         goto ret;
  552                         }
  553                 }
  554         ret:
  555                 if (ptr)
  556                         free(ptr, M_TEMP);
  557                 return (error);
  558         }
  559 
  560         case USB_DEVICEINFO:
  561         {
  562                 struct usb_device_info *di = (void *)data;
  563                 int addr = di->udi_addr;
  564                 usbd_device_handle dev;
  565 
  566                 if (addr < 1 || addr >= USB_MAX_DEVICES)
  567                         return (EINVAL);
  568                 dev = sc->sc_bus->devices[addr];
  569                 if (dev == NULL)
  570                         return (ENXIO);
  571                 usbd_fill_deviceinfo(dev, di, 1);
  572                 break;
  573         }
  574 
  575         case USB_DEVICESTATS:
  576                 *(struct usb_device_stats *)data = sc->sc_bus->stats;
  577                 break;
  578 
  579         default:
  580                 return (EINVAL);
  581         }
  582         return (0);
  583 }
  584 
  585 int
  586 usbpoll(dev_t dev, int events, struct proc *p)
  587 {
  588         int revents, mask, s;
  589 
  590         if (minor(dev) == USB_DEV_MINOR) {
  591                 revents = 0;
  592                 mask = POLLIN | POLLRDNORM;
  593 
  594                 s = splusb();
  595                 if (events & mask && usb_nevents > 0)
  596                         revents |= events & mask;
  597                 if (revents == 0 && events & mask)
  598                         selrecord(p, &usb_selevent);
  599                 splx(s);
  600 
  601                 return (revents);
  602         } else {
  603                 return (POLLERR);
  604         }
  605 }
  606 
  607 void filt_usbrdetach(struct knote *);
  608 int filt_usbread(struct knote *, long);
  609 int usbkqfilter(dev_t, struct knote *);
  610 
  611 void
  612 filt_usbrdetach(struct knote *kn)
  613 {
  614         int s;
  615 
  616         s = splusb();
  617         SLIST_REMOVE(&usb_selevent.si_note, kn, knote, kn_selnext);
  618         splx(s);
  619 }
  620 
  621 int
  622 filt_usbread(struct knote *kn, long hint)
  623 {
  624 
  625         if (usb_nevents == 0)
  626                 return (0);
  627 
  628         kn->kn_data = sizeof(struct usb_event);
  629         return (1);
  630 }
  631 
  632 struct filterops usbread_filtops =
  633         { 1, NULL, filt_usbrdetach, filt_usbread };
  634 
  635 int
  636 usbkqfilter(dev_t dev, struct knote *kn)
  637 {
  638         struct klist *klist;
  639         int s;
  640 
  641         switch (kn->kn_filter) {
  642         case EVFILT_READ:
  643                 if (minor(dev) != USB_DEV_MINOR)
  644                         return (1);
  645                 klist = &usb_selevent.si_note;
  646                 kn->kn_fop = &usbread_filtops;
  647                 break;
  648 
  649         default:
  650                 return (1);
  651         }
  652 
  653         kn->kn_hook = NULL;
  654 
  655         s = splusb();
  656         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
  657         splx(s);
  658 
  659         return (0);
  660 }
  661 
  662 /* Explore device tree from the root. */
  663 void
  664 usb_discover(void *v)
  665 {
  666         struct usb_softc *sc = v;
  667 
  668         DPRINTFN(2,("usb_discover\n"));
  669 #ifdef USB_DEBUG
  670         if (usb_noexplore > 1)
  671                 return;
  672 #endif
  673         /*
  674          * We need mutual exclusion while traversing the device tree,
  675          * but this is guaranteed since this function is only called
  676          * from the event thread for the controller.
  677          */
  678         while (sc->sc_bus->needs_explore && !sc->sc_dying) {
  679                 sc->sc_bus->needs_explore = 0;
  680                 sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
  681         }
  682 }
  683 
  684 void
  685 usb_needs_explore(usbd_device_handle dev)
  686 {
  687         DPRINTFN(2,("usb_needs_explore\n"));
  688         dev->bus->needs_explore = 1;
  689         wakeup(&dev->bus->needs_explore);
  690 }
  691 
  692 void
  693 usb_needs_reattach(usbd_device_handle dev)
  694 {
  695         DPRINTFN(2,("usb_needs_reattach\n"));
  696         dev->powersrc->reattach = 1;
  697         dev->bus->needs_explore = 1;
  698         wakeup(&dev->bus->needs_explore);
  699 }
  700 
  701 /* Called at splusb() */
  702 int
  703 usb_get_next_event(struct usb_event *ue)
  704 {
  705         struct usb_event_q *ueq;
  706 
  707         if (usb_nevents <= 0)
  708                 return (0);
  709         ueq = SIMPLEQ_FIRST(&usb_events);
  710 #ifdef DIAGNOSTIC
  711         if (ueq == NULL) {
  712                 printf("usb: usb_nevents got out of sync! %d\n", usb_nevents);
  713                 usb_nevents = 0;
  714                 return (0);
  715         }
  716 #endif
  717         *ue = ueq->ue;
  718         SIMPLEQ_REMOVE_HEAD(&usb_events, next);
  719         free(ueq, M_USBDEV);
  720         usb_nevents--;
  721         return (1);
  722 }
  723 
  724 void
  725 usbd_add_dev_event(int type, usbd_device_handle udev)
  726 {
  727         struct usb_event ue;
  728 
  729         usbd_fill_deviceinfo(udev, &ue.u.ue_device, USB_EVENT_IS_ATTACH(type));
  730         usb_add_event(type, &ue);
  731 }
  732 
  733 void
  734 usbd_add_drv_event(int type, usbd_device_handle udev, struct device *dev)
  735 {
  736         struct usb_event ue;
  737 
  738         ue.u.ue_driver.ue_cookie = udev->cookie;
  739         strncpy(ue.u.ue_driver.ue_devname, dev->dv_xname,
  740             sizeof ue.u.ue_driver.ue_devname);
  741         usb_add_event(type, &ue);
  742 }
  743 
  744 void
  745 usb_add_event(int type, struct usb_event *uep)
  746 {
  747         struct usb_event_q *ueq;
  748         struct usb_event ue;
  749         struct timespec thetime;
  750         int s;
  751 
  752         nanotime(&thetime);
  753         /* Don't want to wait here inside splusb() */
  754         ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK);
  755         ueq->ue = *uep;
  756         ueq->ue.ue_type = type;
  757         ueq->ue.ue_time = thetime;
  758 
  759         s = splusb();
  760         if (++usb_nevents >= USB_MAX_EVENTS) {
  761                 /* Too many queued events, drop an old one. */
  762                 DPRINTFN(-1,("usb: event dropped\n"));
  763                 (void)usb_get_next_event(&ue);
  764         }
  765         SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next);
  766         wakeup(&usb_events);
  767         selwakeup(&usb_selevent);
  768         if (usb_async_proc != NULL)
  769                 psignal(usb_async_proc, SIGIO);
  770         splx(s);
  771 }
  772 
  773 void
  774 usb_schedsoftintr(usbd_bus_handle bus)
  775 {
  776         DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus->use_polling));
  777 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
  778         if (bus->use_polling) {
  779                 bus->methods->soft_intr(bus);
  780         } else {
  781                 softintr_schedule(bus->soft);
  782         }
  783 #else
  784         bus->methods->soft_intr(bus);
  785 #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
  786 }
  787 
  788 int
  789 usb_activate(struct device *self, enum devact act)
  790 {
  791         struct usb_softc *sc = (struct usb_softc *)self;
  792         usbd_device_handle dev = sc->sc_port.device;
  793         int i, rv = 0;
  794 
  795         switch (act) {
  796         case DVACT_ACTIVATE:
  797                 break;
  798 
  799         case DVACT_DEACTIVATE:
  800                 sc->sc_dying = 1;
  801                 if (dev != NULL && dev->cdesc != NULL &&
  802                     dev->subdevs != NULL) {
  803                         for (i = 0; dev->subdevs[i]; i++)
  804                                 rv |= config_deactivate(dev->subdevs[i]);
  805                 }
  806                 break;
  807         }
  808         return (rv);
  809 }
  810 
  811 int
  812 usb_detach(struct device *self, int flags)
  813 {
  814         struct usb_softc *sc = (struct usb_softc *)self;
  815         struct usb_event ue;
  816 
  817         DPRINTF(("usb_detach: start\n"));
  818 
  819         sc->sc_dying = 1;
  820 
  821         /* Make all devices disconnect. */
  822         if (sc->sc_port.device != NULL)
  823                 usb_disconnect_port(&sc->sc_port, self);
  824 
  825         /* Kill off event thread. */
  826         if (sc->sc_event_thread != NULL) {
  827                 wakeup(&sc->sc_bus->needs_explore);
  828                 if (tsleep(sc, PWAIT, "usbdet", hz * 60))
  829                         printf("%s: event thread didn't die\n",
  830                                sc->sc_dev.dv_xname);
  831                 DPRINTF(("usb_detach: event thread dead\n"));
  832         }
  833 
  834         usbd_finish();
  835 
  836 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
  837         if (sc->sc_bus->soft != NULL) {
  838                 softintr_disestablish(sc->sc_bus->soft);
  839                 sc->sc_bus->soft = NULL;
  840         }
  841 #endif
  842 
  843         ue.u.ue_ctrlr.ue_bus = sc->sc_dev.dv_unit;
  844         usb_add_event(USB_EVENT_CTRLR_DETACH, &ue);
  845 
  846         return (0);
  847 }

/* [<][>][^][v][top][bottom][index][help] */