[BACK]Return to usb.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/usb.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb