[BACK]Return to vhci.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/vhci.c, Revision 1.16

1.16    ! maxv        1: /*     $NetBSD: vhci.c,v 1.15 2020/03/31 16:28:28 maxv Exp $ */
1.1       maxv        2:
                      3: /*
1.10      maxv        4:  * Copyright (c) 2019-2020 The NetBSD Foundation, Inc.
1.1       maxv        5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Maxime Villard.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
1.16    ! maxv       33: __KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.15 2020/03/31 16:28:28 maxv Exp $");
1.1       maxv       34:
                     35: #ifdef _KERNEL_OPT
                     36: #include "opt_usb.h"
                     37: #endif
                     38:
                     39: #include <sys/param.h>
                     40:
                     41: #include <sys/bus.h>
                     42: #include <sys/cpu.h>
                     43: #include <sys/conf.h>
                     44: #include <sys/device.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/kmem.h>
                     47: #include <sys/mutex.h>
                     48: #include <sys/proc.h>
                     49: #include <sys/queue.h>
                     50: #include <sys/systm.h>
                     51: #include <sys/mman.h>
                     52: #include <sys/file.h>
                     53: #include <sys/filedesc.h>
                     54:
                     55: #include <machine/endian.h>
                     56:
                     57: #include "ioconf.h"
                     58:
                     59: #include <dev/usb/usb.h>
                     60: #include <dev/usb/usbdi.h>
                     61: #include <dev/usb/usbdivar.h>
                     62:
                     63: #include <dev/usb/usbroothub.h>
1.15      maxv       64: #include <dev/usb/vhci.h>
1.1       maxv       65:
                     66: #ifdef VHCI_DEBUG
                     67: #define DPRINTF(fmt, ...)      printf(fmt, __VA_ARGS__)
                     68: #else
                     69: #define DPRINTF(fmt, ...)      __nothing
                     70: #endif
                     71:
                     72: static usbd_status vhci_open(struct usbd_pipe *);
                     73: static void vhci_softintr(void *);
                     74:
                     75: static struct usbd_xfer *vhci_allocx(struct usbd_bus *, unsigned int);
                     76: static void vhci_freex(struct usbd_bus *, struct usbd_xfer *);
                     77: static void vhci_get_lock(struct usbd_bus *, kmutex_t **);
                     78: static int vhci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *,
                     79:     void *, int);
                     80:
                     81: static const struct usbd_bus_methods vhci_bus_methods = {
                     82:        .ubm_open =     vhci_open,
                     83:        .ubm_softint =  vhci_softintr,
                     84:        .ubm_dopoll =   NULL,
                     85:        .ubm_allocx =   vhci_allocx,
                     86:        .ubm_freex =    vhci_freex,
                     87:        .ubm_getlock =  vhci_get_lock,
                     88:        .ubm_rhctrl =   vhci_roothub_ctrl,
                     89: };
                     90:
                     91: static usbd_status vhci_device_ctrl_transfer(struct usbd_xfer *);
                     92: static usbd_status vhci_device_ctrl_start(struct usbd_xfer *);
                     93: static void vhci_device_ctrl_abort(struct usbd_xfer *);
                     94: static void vhci_device_ctrl_close(struct usbd_pipe *);
                     95: static void vhci_device_ctrl_cleartoggle(struct usbd_pipe *);
                     96: static void vhci_device_ctrl_done(struct usbd_xfer *);
                     97:
                     98: static const struct usbd_pipe_methods vhci_device_ctrl_methods = {
                     99:        .upm_init =             NULL,
                    100:        .upm_fini =             NULL,
                    101:        .upm_transfer =         vhci_device_ctrl_transfer,
                    102:        .upm_start =            vhci_device_ctrl_start,
                    103:        .upm_abort =            vhci_device_ctrl_abort,
                    104:        .upm_close =            vhci_device_ctrl_close,
                    105:        .upm_cleartoggle =      vhci_device_ctrl_cleartoggle,
                    106:        .upm_done =             vhci_device_ctrl_done,
                    107: };
                    108:
                    109: static usbd_status vhci_root_intr_transfer(struct usbd_xfer *);
                    110: static usbd_status vhci_root_intr_start(struct usbd_xfer *);
                    111: static void vhci_root_intr_abort(struct usbd_xfer *);
                    112: static void vhci_root_intr_close(struct usbd_pipe *);
                    113: static void vhci_root_intr_cleartoggle(struct usbd_pipe *);
                    114: static void vhci_root_intr_done(struct usbd_xfer *);
                    115:
                    116: static const struct usbd_pipe_methods vhci_root_intr_methods = {
                    117:        .upm_init =             NULL,
                    118:        .upm_fini =             NULL,
                    119:        .upm_transfer =         vhci_root_intr_transfer,
                    120:        .upm_start =            vhci_root_intr_start,
                    121:        .upm_abort =            vhci_root_intr_abort,
                    122:        .upm_close =            vhci_root_intr_close,
                    123:        .upm_cleartoggle =      vhci_root_intr_cleartoggle,
                    124:        .upm_done =             vhci_root_intr_done,
                    125: };
                    126:
1.9       maxv      127: /*
                    128:  * There are three structures to understand: vxfers, packets, and ports.
                    129:  *
                    130:  * Each xfer from the point of view of the USB stack is a vxfer from the point
                    131:  * of view of vHCI.
                    132:  *
                    133:  * A vxfer has a linked list containing a maximum of two packets: a request
                    134:  * packet and possibly a data packet. Packets basically contain data exchanged
                    135:  * between the Host and the virtual USB device. A packet is linked to both a
                    136:  * vxfer and a port.
                    137:  *
                    138:  * A port is an abstraction of an actual USB port. Each virtual USB device gets
                    139:  * connected to a port. A port has two lists:
                    140:  *  - The Usb-To-Host list, containing packets to be fetched from the USB
                    141:  *    device and provided to the host.
                    142:  *  - The Host-To-Usb list, containing packets to be sent from the Host to the
                    143:  *    USB device.
                    144:  * Request packets are always in the H->U direction. Data packets however can
                    145:  * be in both the H->U and U->H directions.
                    146:  *
                    147:  * With read() and write() operations on /dev/vhci, userland respectively
                    148:  * "fetches" and "sends" packets from or to the virtual USB device, which
                    149:  * respectively means reading/inserting packets in the H->U and U->H lists on
                    150:  * the port where the virtual USB device is connected.
                    151:  *
                    152:  *             +------------------------------------------------+
                    153:  *             |                 USB Stack                      |
                    154:  *             +---------------------^--------------------------+
                    155:  *                                   |
                    156:  *             +---------------------V--------------------------+
                    157:  *             | +----------------+    +-------------+          |
                    158:  *             | | Request Packet |    | Data Packet |     Xfer |
                    159:  *             | +-------|--------+    +----|---^----+          |
                    160:  *             +---------|------------------|---|---------------+
                    161:  *                       |                  |   |
                    162:  *                       |   +--------------+   |
                    163:  *                       |   |                  |
                    164:  *             +---------|---|------------------|---------------+
                    165:  *             |     +---V---V---+    +---------|-+             |
                    166:  *             |     | H->U List |    | U->H List |   vHCI Port |
                    167:  *             |     +-----|-----+    +-----^-----+             |
                    168:  *             +-----------|----------------|-------------------+
                    169:  *                         |                |
                    170:  *             +-----------|----------------|-------------------+
                    171:  *             |     +-----V-----+    +-----|-----+             |
                    172:  *             |     |   read()  |    |  write()  |     vHCI FD |
                    173:  *             |     +-----------+    +-----------+             |
                    174:  *             +------------------------------------------------+
                    175:  */
                    176:
1.13      maxv      177: struct vhci_xfer;
                    178:
1.1       maxv      179: typedef struct vhci_packet {
1.11      maxv      180:        /* General. */
1.2       maxv      181:        TAILQ_ENTRY(vhci_packet) portlist;
                    182:        TAILQ_ENTRY(vhci_packet) xferlist;
1.9       maxv      183:        struct vhci_xfer *vxfer;
1.2       maxv      184:        bool utoh;
1.10      maxv      185:        uint8_t addr;
1.11      maxv      186:
1.14      maxv      187:        /* Type. */
                    188:        struct {
                    189:                bool req:1;
                    190:                bool res:1;
                    191:                bool dat:1;
                    192:        } type;
                    193:
1.11      maxv      194:        /* Exposed for FD operations. */
1.1       maxv      195:        uint8_t *buf;
                    196:        size_t size;
                    197:        size_t cursor;
                    198: } vhci_packet_t;
                    199:
1.2       maxv      200: typedef TAILQ_HEAD(, vhci_packet) vhci_packet_list_t;
1.1       maxv      201:
1.10      maxv      202: #define VHCI_NADDRS    16      /* maximum supported by USB */
                    203:
1.1       maxv      204: typedef struct {
                    205:        kmutex_t lock;
                    206:        int status;
                    207:        int change;
                    208:        struct {
                    209:                vhci_packet_list_t usb_to_host;
                    210:                vhci_packet_list_t host_to_usb;
1.10      maxv      211:        } endpoints[VHCI_NADDRS];
1.1       maxv      212: } vhci_port_t;
                    213:
                    214: typedef struct {
                    215:        struct usbd_pipe pipe;
                    216: } vhci_pipe_t;
                    217:
                    218: typedef struct vhci_xfer {
                    219:        /* General. */
                    220:        struct usbd_xfer xfer;
                    221:
1.9       maxv      222:        /* Port where the xfer occurs. */
1.1       maxv      223:        vhci_port_t *port;
1.9       maxv      224:
                    225:        /* Packets in the xfer. */
                    226:        size_t npkts;
1.1       maxv      227:        vhci_packet_list_t pkts;
1.9       maxv      228:
1.13      maxv      229:        /* Header storage. */
                    230:        vhci_request_t reqbuf;
1.14      maxv      231:        vhci_response_t resbuf;
1.13      maxv      232:
1.9       maxv      233:        /* Used for G/C. */
1.2       maxv      234:        TAILQ_ENTRY(vhci_xfer) freelist;
1.1       maxv      235: } vhci_xfer_t;
                    236:
1.2       maxv      237: typedef TAILQ_HEAD(, vhci_xfer) vhci_xfer_list_t;
1.1       maxv      238:
                    239: #define VHCI_INDEX2PORT(idx)   (idx)
                    240: #define VHCI_NPORTS            4
                    241:
                    242: typedef struct {
                    243:        device_t sc_dev;
                    244:
                    245:        struct usbd_bus sc_bus;
                    246:        bool sc_dying;
                    247:        kmutex_t sc_lock;
                    248:
                    249:        /*
                    250:         * Intr Root. Used to attach the devices.
                    251:         */
                    252:        struct usbd_xfer *sc_intrxfer;
                    253:
                    254:        /*
                    255:         * The ports. Zero is for the roothub, one and beyond for the USB
                    256:         * devices.
                    257:         */
                    258:        size_t sc_nports;
                    259:        vhci_port_t sc_port[VHCI_NPORTS];
                    260:
                    261:        device_t sc_child; /* /dev/usb# device */
                    262: } vhci_softc_t;
                    263:
                    264: typedef struct {
                    265:        u_int port;
1.10      maxv      266:        uint8_t addr;
1.1       maxv      267:        vhci_softc_t *softc;
                    268: } vhci_fd_t;
                    269:
                    270: extern struct cfdriver vhci_cd;
                    271:
                    272: /* -------------------------------------------------------------------------- */
                    273:
                    274: static void
1.11      maxv      275: vhci_pkt_ctrl_create(vhci_port_t *port, struct usbd_xfer *xfer, bool utoh,
1.10      maxv      276:     uint8_t addr)
1.1       maxv      277: {
                    278:        vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
1.14      maxv      279:        vhci_packet_list_t *reqlist, *reslist, *datlist = NULL;
                    280:        vhci_packet_t *req, *res = NULL, *dat = NULL;
1.9       maxv      281:        size_t npkts = 0;
1.1       maxv      282:
1.9       maxv      283:        /* Request packet. */
1.10      maxv      284:        reqlist = &port->endpoints[addr].host_to_usb;
1.1       maxv      285:        req = kmem_zalloc(sizeof(*req), KM_SLEEP);
1.9       maxv      286:        req->vxfer = vxfer;
1.2       maxv      287:        req->utoh = false;
1.10      maxv      288:        req->addr = addr;
1.14      maxv      289:        req->type.req = true;
1.13      maxv      290:        req->buf = (uint8_t *)&vxfer->reqbuf;
                    291:        req->size = sizeof(vxfer->reqbuf);
1.1       maxv      292:        req->cursor = 0;
1.9       maxv      293:        npkts++;
1.1       maxv      294:
1.11      maxv      295:        /* Init the request buffer. */
1.13      maxv      296:        memset(&vxfer->reqbuf, 0, sizeof(vxfer->reqbuf));
                    297:        vxfer->reqbuf.type = VHCI_REQ_CTRL;
                    298:        memcpy(&vxfer->reqbuf.u.ctrl, &xfer->ux_request,
1.11      maxv      299:            sizeof(xfer->ux_request));
                    300:
1.14      maxv      301:        /* Response packet. */
                    302:        if (utoh && (xfer->ux_length > 0)) {
                    303:                reslist = &port->endpoints[addr].usb_to_host;
                    304:                res = kmem_zalloc(sizeof(*res), KM_SLEEP);
                    305:                res->vxfer = vxfer;
                    306:                res->utoh = true;
                    307:                res->addr = addr;
                    308:                res->type.res = true;
                    309:                res->buf = (uint8_t *)&vxfer->resbuf;
                    310:                res->size = sizeof(vxfer->resbuf);
                    311:                res->cursor = 0;
                    312:                npkts++;
                    313:        }
                    314:
1.1       maxv      315:        /* Data packet. */
1.2       maxv      316:        if (xfer->ux_length > 0) {
1.10      maxv      317:                if (utoh) {
                    318:                        datlist = &port->endpoints[addr].usb_to_host;
1.2       maxv      319:                } else {
1.10      maxv      320:                        datlist = &port->endpoints[addr].host_to_usb;
1.2       maxv      321:                }
1.9       maxv      322:                dat = kmem_zalloc(sizeof(*dat), KM_SLEEP);
                    323:                dat->vxfer = vxfer;
1.10      maxv      324:                dat->utoh = utoh;
                    325:                dat->addr = addr;
1.14      maxv      326:                dat->type.dat = true;
1.9       maxv      327:                dat->buf = xfer->ux_buf;
                    328:                dat->size = xfer->ux_length;
                    329:                dat->cursor = 0;
                    330:                npkts++;
1.1       maxv      331:        }
                    332:
                    333:        /* Insert in the xfer. */
                    334:        vxfer->port = port;
1.9       maxv      335:        vxfer->npkts = npkts;
1.2       maxv      336:        TAILQ_INIT(&vxfer->pkts);
                    337:        TAILQ_INSERT_TAIL(&vxfer->pkts, req, xferlist);
1.14      maxv      338:        if (res != NULL)
                    339:                TAILQ_INSERT_TAIL(&vxfer->pkts, res, xferlist);
1.9       maxv      340:        if (dat != NULL)
                    341:                TAILQ_INSERT_TAIL(&vxfer->pkts, dat, xferlist);
1.1       maxv      342:
                    343:        /* Insert in the port. */
1.3       maxv      344:        KASSERT(mutex_owned(&port->lock));
1.2       maxv      345:        TAILQ_INSERT_TAIL(reqlist, req, portlist);
1.14      maxv      346:        if (res != NULL)
                    347:                TAILQ_INSERT_TAIL(reslist, res, portlist);
1.9       maxv      348:        if (dat != NULL)
                    349:                TAILQ_INSERT_TAIL(datlist, dat, portlist);
1.1       maxv      350: }
                    351:
                    352: static void
                    353: vhci_pkt_destroy(vhci_softc_t *sc, vhci_packet_t *pkt)
                    354: {
1.9       maxv      355:        vhci_xfer_t *vxfer = pkt->vxfer;
1.1       maxv      356:        vhci_port_t *port = vxfer->port;
1.2       maxv      357:        vhci_packet_list_t *pktlist;
1.1       maxv      358:
                    359:        KASSERT(mutex_owned(&port->lock));
                    360:
1.9       maxv      361:        /* Remove from the port. */
1.2       maxv      362:        if (pkt->utoh) {
1.10      maxv      363:                pktlist = &port->endpoints[pkt->addr].usb_to_host;
1.2       maxv      364:        } else {
1.10      maxv      365:                pktlist = &port->endpoints[pkt->addr].host_to_usb;
1.2       maxv      366:        }
                    367:        TAILQ_REMOVE(pktlist, pkt, portlist);
                    368:
1.9       maxv      369:        /* Remove from the xfer. */
1.2       maxv      370:        TAILQ_REMOVE(&vxfer->pkts, pkt, xferlist);
1.1       maxv      371:        kmem_free(pkt, sizeof(*pkt));
                    372:
1.9       maxv      373:        /* Unref. */
                    374:        KASSERT(vxfer->npkts > 0);
                    375:        vxfer->npkts--;
                    376:        if (vxfer->npkts > 0)
1.1       maxv      377:                return;
1.2       maxv      378:        KASSERT(TAILQ_FIRST(&vxfer->pkts) == NULL);
1.1       maxv      379: }
                    380:
                    381: /* -------------------------------------------------------------------------- */
                    382:
                    383: static usbd_status
                    384: vhci_open(struct usbd_pipe *pipe)
                    385: {
                    386:        struct usbd_device *dev = pipe->up_dev;
                    387:        struct usbd_bus *bus = dev->ud_bus;
                    388:        usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc;
                    389:        vhci_softc_t *sc = bus->ub_hcpriv;
                    390:        uint8_t addr = dev->ud_addr;
                    391:
                    392:        if (sc->sc_dying)
                    393:                return USBD_IOERROR;
                    394:
                    395:        DPRINTF("%s: called, type=%d\n", __func__,
                    396:            UE_GET_XFERTYPE(ed->bmAttributes));
                    397:
                    398:        if (addr == bus->ub_rhaddr) {
                    399:                switch (ed->bEndpointAddress) {
                    400:                case USB_CONTROL_ENDPOINT:
                    401:                        DPRINTF("%s: roothub_ctrl\n", __func__);
                    402:                        pipe->up_methods = &roothub_ctrl_methods;
                    403:                        break;
                    404:                case UE_DIR_IN | USBROOTHUB_INTR_ENDPT:
                    405:                        DPRINTF("%s: root_intr\n", __func__);
                    406:                        pipe->up_methods = &vhci_root_intr_methods;
                    407:                        break;
                    408:                default:
                    409:                        DPRINTF("%s: inval\n", __func__);
                    410:                        return USBD_INVAL;
                    411:                }
                    412:        } else {
                    413:                switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
                    414:                case UE_CONTROL:
                    415:                        pipe->up_methods = &vhci_device_ctrl_methods;
                    416:                        break;
1.10      maxv      417:                case UE_INTERRUPT:
1.1       maxv      418:                case UE_BULK:
                    419:                default:
                    420:                        goto bad;
                    421:                }
                    422:        }
                    423:
                    424:        return USBD_NORMAL_COMPLETION;
                    425:
                    426: bad:
                    427:        return USBD_NOMEM;
                    428: }
                    429:
                    430: static void
                    431: vhci_softintr(void *v)
                    432: {
                    433:        DPRINTF("%s: called\n", __func__);
                    434: }
                    435:
                    436: static struct usbd_xfer *
                    437: vhci_allocx(struct usbd_bus *bus, unsigned int nframes)
                    438: {
                    439:        vhci_xfer_t *vxfer;
                    440:
                    441:        vxfer = kmem_zalloc(sizeof(*vxfer), KM_SLEEP);
                    442: #ifdef DIAGNOSTIC
                    443:        vxfer->xfer.ux_state = XFER_BUSY;
                    444: #endif
                    445:        return (struct usbd_xfer *)vxfer;
                    446: }
                    447:
                    448: static void
                    449: vhci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
                    450: {
                    451:        vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
                    452:
1.9       maxv      453:        KASSERT(vxfer->npkts == 0);
1.2       maxv      454:        KASSERT(TAILQ_FIRST(&vxfer->pkts) == NULL);
1.1       maxv      455:
                    456: #ifdef DIAGNOSTIC
                    457:        vxfer->xfer.ux_state = XFER_FREE;
                    458: #endif
                    459:        kmem_free(vxfer, sizeof(*vxfer));
                    460: }
                    461:
                    462: static void
                    463: vhci_get_lock(struct usbd_bus *bus, kmutex_t **lock)
                    464: {
                    465:        vhci_softc_t *sc = bus->ub_hcpriv;
                    466:
                    467:        *lock = &sc->sc_lock;
                    468: }
                    469:
                    470: static int
                    471: vhci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req,
                    472:     void *buf, int buflen)
                    473: {
                    474:        vhci_softc_t *sc = bus->ub_hcpriv;
                    475:        vhci_port_t *port;
                    476:        usb_hub_descriptor_t hubd;
                    477:        uint16_t len, value, index;
                    478:        int totlen = 0;
                    479:
                    480:        len = UGETW(req->wLength);
                    481:        value = UGETW(req->wValue);
                    482:        index = UGETW(req->wIndex);
                    483:
                    484: #define C(x,y) ((x) | ((y) << 8))
                    485:        switch (C(req->bRequest, req->bmRequestType)) {
                    486:        case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
                    487:                switch (value) {
                    488:                case C(0, UDESC_DEVICE): {
                    489:                        usb_device_descriptor_t devd;
                    490:
                    491:                        totlen = uimin(buflen, sizeof(devd));
                    492:                        memcpy(&devd, buf, totlen);
                    493:                        USETW(devd.idVendor, 0);
                    494:                        USETW(devd.idProduct, 0);
                    495:                        memcpy(buf, &devd, totlen);
                    496:                        break;
                    497:                }
                    498: #define sd ((usb_string_descriptor_t *)buf)
                    499:                case C(1, UDESC_STRING):
                    500:                        /* Vendor */
                    501:                        totlen = usb_makestrdesc(sd, len, "NetBSD");
                    502:                        break;
                    503:                case C(2, UDESC_STRING):
                    504:                        /* Product */
                    505:                        totlen = usb_makestrdesc(sd, len, "VHCI root hub");
                    506:                        break;
                    507: #undef sd
                    508:                default:
                    509:                        /* default from usbroothub */
                    510:                        return buflen;
                    511:                }
                    512:                break;
                    513:
                    514:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
                    515:                switch (value) {
                    516:                case UHF_PORT_RESET:
                    517:                        if (index < 1 || index >= sc->sc_nports) {
                    518:                                return -1;
                    519:                        }
1.4       maxv      520:                        port = &sc->sc_port[VHCI_INDEX2PORT(index)];
1.1       maxv      521:                        port->status |= UPS_C_PORT_RESET;
                    522:                        break;
                    523:                case UHF_PORT_POWER:
                    524:                        break;
                    525:                default:
                    526:                        return -1;
                    527:                }
                    528:                break;
                    529:
                    530:        /* Hub requests. */
                    531:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
                    532:                break;
                    533:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
                    534:                if (index < 1 || index >= sc->sc_nports) {
                    535:                        return -1;
                    536:                }
1.4       maxv      537:                port = &sc->sc_port[VHCI_INDEX2PORT(index)];
1.1       maxv      538:                switch (value) {
                    539:                case UHF_PORT_ENABLE:
                    540:                        port->status &= ~UPS_PORT_ENABLED;
                    541:                        break;
                    542:                case UHF_C_PORT_ENABLE:
                    543:                        port->change |= UPS_C_PORT_ENABLED;
                    544:                        break;
                    545:                default:
                    546:                        return -1;
                    547:                }
                    548:                break;
                    549:
                    550:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                    551:                totlen = uimin(buflen, sizeof(hubd));
                    552:                memcpy(&hubd, buf, totlen);
                    553:                hubd.bNbrPorts = sc->sc_nports - 1;
                    554:                hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE;
                    555:                totlen = uimin(totlen, hubd.bDescLength);
                    556:                memcpy(buf, &hubd, totlen);
                    557:                break;
                    558:
                    559:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                    560:                /* XXX The other HCs do this */
                    561:                memset(buf, 0, len);
                    562:                totlen = len;
                    563:                break;
                    564:
                    565:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): {
                    566:                usb_port_status_t ps;
                    567:
                    568:                if (index < 1 || index >= sc->sc_nports) {
                    569:                        return -1;
                    570:                }
1.4       maxv      571:                port = &sc->sc_port[VHCI_INDEX2PORT(index)];
1.1       maxv      572:                USETW(ps.wPortStatus, port->status);
                    573:                USETW(ps.wPortChange, port->change);
                    574:                totlen = uimin(len, sizeof(ps));
                    575:                memcpy(buf, &ps, totlen);
                    576:                break;
                    577:        }
                    578:        default:
                    579:                /* default from usbroothub */
                    580:                return buflen;
                    581:        }
                    582:
                    583:        return totlen;
                    584: }
                    585:
                    586: /* -------------------------------------------------------------------------- */
                    587:
                    588: static usbd_status
                    589: vhci_device_ctrl_transfer(struct usbd_xfer *xfer)
                    590: {
                    591:        vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
                    592:        usbd_status err;
                    593:
                    594:        DPRINTF("%s: called\n", __func__);
                    595:
                    596:        /* Insert last in queue. */
                    597:        mutex_enter(&sc->sc_lock);
                    598:        err = usb_insert_transfer(xfer);
                    599:        mutex_exit(&sc->sc_lock);
                    600:        if (err)
                    601:                return err;
                    602:
                    603:        /* Pipe isn't running, start first */
                    604:        return vhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
                    605: }
                    606:
                    607: static usbd_status
                    608: vhci_device_ctrl_start(struct usbd_xfer *xfer)
                    609: {
1.10      maxv      610:        usb_endpoint_descriptor_t *ed = xfer->ux_pipe->up_endpoint->ue_edesc;
1.1       maxv      611:        usb_device_request_t *req = &xfer->ux_request;
                    612:        struct usbd_device *dev = xfer->ux_pipe->up_dev;
                    613:        vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
                    614:        vhci_port_t *port;
                    615:        bool polling = sc->sc_bus.ub_usepolling;
                    616:        bool isread = (req->bmRequestType & UT_READ) != 0;
1.10      maxv      617:        uint8_t addr = UE_GET_ADDR(ed->bEndpointAddress);
1.3       maxv      618:        int portno, ret;
1.1       maxv      619:
1.10      maxv      620:        KASSERT(addr == 0);
1.1       maxv      621:        KASSERT(xfer->ux_rqflags & URQ_REQUEST);
                    622:        KASSERT(dev->ud_myhsport != NULL);
                    623:        portno = dev->ud_myhsport->up_portno;
                    624:
1.8       christos  625:        DPRINTF("%s: type=0x%02x, len=%d, isread=%d, portno=%d\n",
1.1       maxv      626:            __func__, req->bmRequestType, UGETW(req->wLength), isread, portno);
                    627:
                    628:        if (sc->sc_dying)
                    629:                return USBD_IOERROR;
                    630:
                    631:        port = &sc->sc_port[portno];
                    632:
                    633:        if (!polling)
                    634:                mutex_enter(&sc->sc_lock);
1.3       maxv      635:
                    636:        mutex_enter(&port->lock);
                    637:        if (port->status & UPS_PORT_ENABLED) {
                    638:                xfer->ux_status = USBD_IN_PROGRESS;
1.11      maxv      639:                vhci_pkt_ctrl_create(port, xfer, isread, addr);
1.3       maxv      640:                ret = USBD_IN_PROGRESS;
                    641:        } else {
                    642:                ret = USBD_IOERROR;
                    643:        }
                    644:        mutex_exit(&port->lock);
                    645:
1.1       maxv      646:        if (!polling)
                    647:                mutex_exit(&sc->sc_lock);
                    648:
1.3       maxv      649:        return ret;
1.1       maxv      650: }
                    651:
                    652: static void
                    653: vhci_device_ctrl_abort(struct usbd_xfer *xfer)
                    654: {
                    655:        vhci_xfer_t *vxfer = (vhci_xfer_t *)xfer;
                    656:        vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
                    657:        vhci_port_t *port = vxfer->port;
                    658:        vhci_packet_t *pkt;
                    659:
                    660:        DPRINTF("%s: called\n", __func__);
                    661:
                    662:        KASSERT(mutex_owned(&sc->sc_lock));
                    663:
                    664:        callout_halt(&xfer->ux_callout, &sc->sc_lock);
                    665:
1.11      maxv      666:        /* If anyone else beat us, we're done.  */
1.1       maxv      667:        KASSERT(xfer->ux_status != USBD_CANCELLED);
                    668:        if (xfer->ux_status != USBD_IN_PROGRESS)
                    669:                return;
                    670:
                    671:        mutex_enter(&port->lock);
1.9       maxv      672:        while (vxfer->npkts > 0) {
1.2       maxv      673:                pkt = TAILQ_FIRST(&vxfer->pkts);
1.1       maxv      674:                KASSERT(pkt != NULL);
                    675:                vhci_pkt_destroy(sc, pkt);
                    676:        }
1.2       maxv      677:        KASSERT(TAILQ_FIRST(&vxfer->pkts) == NULL);
1.1       maxv      678:        mutex_exit(&port->lock);
                    679:
                    680:        xfer->ux_status = USBD_CANCELLED;
                    681:        usb_transfer_complete(xfer);
                    682:        KASSERT(mutex_owned(&sc->sc_lock));
                    683: }
                    684:
                    685: static void
                    686: vhci_device_ctrl_close(struct usbd_pipe *pipe)
                    687: {
                    688:        DPRINTF("%s: called\n", __func__);
                    689: }
                    690:
                    691: static void
                    692: vhci_device_ctrl_cleartoggle(struct usbd_pipe *pipe)
                    693: {
                    694:        DPRINTF("%s: called\n", __func__);
                    695: }
                    696:
                    697: static void
                    698: vhci_device_ctrl_done(struct usbd_xfer *xfer)
                    699: {
                    700:        DPRINTF("%s: called\n", __func__);
                    701: }
                    702:
                    703: /* -------------------------------------------------------------------------- */
                    704:
                    705: static usbd_status
                    706: vhci_root_intr_transfer(struct usbd_xfer *xfer)
                    707: {
                    708:        vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
                    709:        usbd_status err;
                    710:
                    711:        DPRINTF("%s: called\n", __func__);
                    712:
                    713:        /* Insert last in queue. */
                    714:        mutex_enter(&sc->sc_lock);
                    715:        err = usb_insert_transfer(xfer);
                    716:        mutex_exit(&sc->sc_lock);
                    717:        if (err)
                    718:                return err;
                    719:
                    720:        /* Pipe isn't running, start first */
                    721:        return vhci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
                    722: }
                    723:
                    724: static usbd_status
                    725: vhci_root_intr_start(struct usbd_xfer *xfer)
                    726: {
                    727:        vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
                    728:        const bool polling = sc->sc_bus.ub_usepolling;
                    729:
                    730:        DPRINTF("%s: called, len=%zu\n", __func__, (size_t)xfer->ux_length);
                    731:
                    732:        if (sc->sc_dying)
                    733:                return USBD_IOERROR;
                    734:
                    735:        if (!polling)
                    736:                mutex_enter(&sc->sc_lock);
1.5       riastrad  737:        KASSERT(sc->sc_intrxfer == NULL);
1.1       maxv      738:        sc->sc_intrxfer = xfer;
1.6       riastrad  739:        xfer->ux_status = USBD_IN_PROGRESS;
1.1       maxv      740:        if (!polling)
                    741:                mutex_exit(&sc->sc_lock);
                    742:
                    743:        return USBD_IN_PROGRESS;
                    744: }
                    745:
                    746: static void
                    747: vhci_root_intr_abort(struct usbd_xfer *xfer)
                    748: {
                    749:        vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
                    750:
                    751:        DPRINTF("%s: called\n", __func__);
                    752:
                    753:        KASSERT(mutex_owned(&sc->sc_lock));
                    754:        KASSERT(xfer->ux_pipe->up_intrxfer == xfer);
                    755:
1.5       riastrad  756:        /* If xfer has already completed, nothing to do here.  */
                    757:        if (sc->sc_intrxfer == NULL)
                    758:                return;
1.1       maxv      759:
1.5       riastrad  760:        /*
                    761:         * Otherwise, sc->sc_intrxfer had better be this transfer.
                    762:         * Cancel it.
                    763:         */
                    764:        KASSERT(sc->sc_intrxfer == xfer);
1.6       riastrad  765:        KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
1.1       maxv      766:        xfer->ux_status = USBD_CANCELLED;
                    767:        usb_transfer_complete(xfer);
                    768: }
                    769:
                    770: static void
                    771: vhci_root_intr_close(struct usbd_pipe *pipe)
                    772: {
1.5       riastrad  773:        vhci_softc_t *sc __diagused = pipe->up_dev->ud_bus->ub_hcpriv;
1.1       maxv      774:
                    775:        DPRINTF("%s: called\n", __func__);
                    776:
                    777:        KASSERT(mutex_owned(&sc->sc_lock));
                    778:
1.5       riastrad  779:        /*
                    780:         * Caller must guarantee the xfer has completed first, by
                    781:         * closing the pipe only after normal completion or an abort.
                    782:         */
                    783:        KASSERT(sc->sc_intrxfer == NULL);
1.1       maxv      784: }
                    785:
                    786: static void
                    787: vhci_root_intr_cleartoggle(struct usbd_pipe *pipe)
                    788: {
                    789:        DPRINTF("%s: called\n", __func__);
                    790: }
                    791:
                    792: static void
                    793: vhci_root_intr_done(struct usbd_xfer *xfer)
                    794: {
1.5       riastrad  795:        vhci_softc_t *sc = xfer->ux_bus->ub_hcpriv;
                    796:
                    797:        KASSERT(mutex_owned(&sc->sc_lock));
                    798:
                    799:        /* Claim the xfer so it doesn't get completed again.  */
                    800:        KASSERT(sc->sc_intrxfer == xfer);
                    801:        KASSERT(xfer->ux_status != USBD_IN_PROGRESS);
                    802:        sc->sc_intrxfer = NULL;
1.1       maxv      803: }
                    804:
                    805: /* -------------------------------------------------------------------------- */
                    806:
                    807: static int
1.12      maxv      808: vhci_usb_attach(vhci_fd_t *vfd)
1.1       maxv      809: {
                    810:        vhci_softc_t *sc = vfd->softc;
                    811:        vhci_port_t *port;
                    812:        struct usbd_xfer *xfer;
                    813:        u_char *p;
                    814:        int ret = 0;
                    815:
1.12      maxv      816:        port = &sc->sc_port[vfd->port];
1.1       maxv      817:
                    818:        mutex_enter(&sc->sc_lock);
                    819:
1.3       maxv      820:        mutex_enter(&port->lock);
1.1       maxv      821:        port->status = UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED |
                    822:            UPS_PORT_POWER;
                    823:        port->change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
1.3       maxv      824:        mutex_exit(&port->lock);
1.1       maxv      825:
                    826:        xfer = sc->sc_intrxfer;
                    827:
                    828:        if (xfer == NULL) {
                    829:                ret = ENOBUFS;
                    830:                goto done;
                    831:        }
1.6       riastrad  832:        KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
1.1       maxv      833:
                    834:        p = xfer->ux_buf;
                    835:        memset(p, 0, xfer->ux_length);
1.12      maxv      836:        p[0] = __BIT(vfd->port);
1.1       maxv      837:        xfer->ux_actlen = xfer->ux_length;
                    838:        xfer->ux_status = USBD_NORMAL_COMPLETION;
                    839:
                    840:        usb_transfer_complete(xfer);
                    841:
                    842: done:
                    843:        mutex_exit(&sc->sc_lock);
                    844:        return ret;
                    845: }
                    846:
                    847: static void
                    848: vhci_port_flush(vhci_softc_t *sc, vhci_port_t *port)
                    849: {
                    850:        vhci_packet_list_t *pktlist;
                    851:        vhci_packet_t *pkt, *nxt;
                    852:        vhci_xfer_list_t vxferlist;
                    853:        vhci_xfer_t *vxfer;
1.10      maxv      854:        uint8_t addr;
1.1       maxv      855:
                    856:        KASSERT(mutex_owned(&sc->sc_lock));
1.3       maxv      857:        KASSERT(mutex_owned(&port->lock));
1.1       maxv      858:
1.2       maxv      859:        TAILQ_INIT(&vxferlist);
1.1       maxv      860:
1.10      maxv      861:        for (addr = 0; addr < VHCI_NADDRS; addr++) {
                    862:                /* Drop all the packets in the H->U direction. */
                    863:                pktlist = &port->endpoints[addr].host_to_usb;
                    864:                TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
                    865:                        vxfer = pkt->vxfer;
                    866:                        KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
                    867:                        vhci_pkt_destroy(sc, pkt);
                    868:                        if (vxfer->npkts == 0)
                    869:                                TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
                    870:                }
                    871:                KASSERT(TAILQ_FIRST(pktlist) == NULL);
1.1       maxv      872:
1.10      maxv      873:                /* Drop all the packets in the U->H direction. */
                    874:                pktlist = &port->endpoints[addr].usb_to_host;
                    875:                TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
                    876:                        vxfer = pkt->vxfer;
                    877:                        KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
                    878:                        vhci_pkt_destroy(sc, pkt);
                    879:                        if (vxfer->npkts == 0)
                    880:                                TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
                    881:                }
                    882:                KASSERT(TAILQ_FIRST(pktlist) == NULL);
1.1       maxv      883:
1.10      maxv      884:                /* Terminate all the xfers collected. */
                    885:                while ((vxfer = TAILQ_FIRST(&vxferlist)) != NULL) {
                    886:                        struct usbd_xfer *xfer = &vxfer->xfer;
                    887:                        TAILQ_REMOVE(&vxferlist, vxfer, freelist);
1.1       maxv      888:
1.10      maxv      889:                        xfer->ux_status = USBD_TIMEOUT;
                    890:                        usb_transfer_complete(xfer);
                    891:                }
1.1       maxv      892:        }
                    893: }
                    894:
                    895: static int
1.12      maxv      896: vhci_usb_detach(vhci_fd_t *vfd)
1.1       maxv      897: {
                    898:        vhci_softc_t *sc = vfd->softc;
                    899:        vhci_port_t *port;
                    900:        struct usbd_xfer *xfer;
                    901:        u_char *p;
                    902:
1.12      maxv      903:        port = &sc->sc_port[vfd->port];
1.1       maxv      904:
                    905:        mutex_enter(&sc->sc_lock);
                    906:
                    907:        xfer = sc->sc_intrxfer;
                    908:        if (xfer == NULL) {
                    909:                mutex_exit(&sc->sc_lock);
                    910:                return ENOBUFS;
                    911:        }
1.6       riastrad  912:        KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
1.1       maxv      913:
1.3       maxv      914:        mutex_enter(&port->lock);
                    915:
1.1       maxv      916:        port->status = 0;
                    917:        port->change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
                    918:
                    919:        p = xfer->ux_buf;
                    920:        memset(p, 0, xfer->ux_length);
1.12      maxv      921:        p[0] = __BIT(vfd->port);
1.1       maxv      922:        xfer->ux_actlen = xfer->ux_length;
                    923:        xfer->ux_status = USBD_NORMAL_COMPLETION;
                    924:
                    925:        usb_transfer_complete(xfer);
                    926:        vhci_port_flush(sc, port);
1.3       maxv      927:
                    928:        mutex_exit(&port->lock);
1.1       maxv      929:        mutex_exit(&sc->sc_lock);
                    930:        return 0;
                    931: }
                    932:
                    933: static int
                    934: vhci_get_info(vhci_fd_t *vfd, struct vhci_ioc_get_info *args)
                    935: {
                    936:        vhci_softc_t *sc = vfd->softc;
                    937:        vhci_port_t *port;
                    938:
                    939:        port = &sc->sc_port[vfd->port];
                    940:
                    941:        args->nports = VHCI_NPORTS;
                    942:        args->port = vfd->port;
                    943:        mutex_enter(&port->lock);
                    944:        args->status = port->status;
                    945:        mutex_exit(&port->lock);
1.10      maxv      946:        args->addr = vfd->addr;
1.1       maxv      947:
                    948:        return 0;
                    949: }
                    950:
                    951: static int
                    952: vhci_set_port(vhci_fd_t *vfd, struct vhci_ioc_set_port *args)
                    953: {
                    954:        vhci_softc_t *sc = vfd->softc;
                    955:
                    956:        if (args->port == 0 || args->port >= sc->sc_nports)
                    957:                return EINVAL;
                    958:
                    959:        vfd->port = args->port;
                    960:
                    961:        return 0;
                    962: }
                    963:
1.10      maxv      964: static int
                    965: vhci_set_addr(vhci_fd_t *vfd, struct vhci_ioc_set_addr *args)
                    966: {
                    967:        if (args->addr >= VHCI_NADDRS)
                    968:                return EINVAL;
                    969:
                    970:        vfd->addr = args->addr;
                    971:
                    972:        return 0;
                    973: }
                    974:
1.1       maxv      975: /* -------------------------------------------------------------------------- */
                    976:
                    977: static dev_type_open(vhci_fd_open);
                    978:
                    979: const struct cdevsw vhci_cdevsw = {
                    980:        .d_open = vhci_fd_open,
                    981:        .d_close = noclose,
                    982:        .d_read = noread,
                    983:        .d_write = nowrite,
                    984:        .d_ioctl = noioctl,
                    985:        .d_stop = nostop,
                    986:        .d_tty = notty,
                    987:        .d_poll = nopoll,
                    988:        .d_mmap = nommap,
                    989:        .d_kqfilter = nokqfilter,
                    990:        .d_discard = nodiscard,
                    991:        .d_flag = D_OTHER | D_MPSAFE
                    992: };
                    993:
                    994: static int vhci_fd_ioctl(file_t *, u_long, void *);
                    995: static int vhci_fd_close(file_t *);
                    996: static int vhci_fd_read(struct file *, off_t *, struct uio *, kauth_cred_t, int);
                    997: static int vhci_fd_write(struct file *, off_t *, struct uio *, kauth_cred_t, int);
                    998:
                    999: const struct fileops vhci_fileops = {
                   1000:        .fo_read = vhci_fd_read,
                   1001:        .fo_write = vhci_fd_write,
                   1002:        .fo_ioctl = vhci_fd_ioctl,
                   1003:        .fo_fcntl = fnullop_fcntl,
                   1004:        .fo_poll = fnullop_poll,
                   1005:        .fo_stat = fbadop_stat,
                   1006:        .fo_close = vhci_fd_close,
                   1007:        .fo_kqfilter = fnullop_kqfilter,
                   1008:        .fo_restart = fnullop_restart,
                   1009:        .fo_mmap = NULL,
                   1010: };
                   1011:
                   1012: static int
                   1013: vhci_fd_open(dev_t dev, int flags, int type, struct lwp *l)
                   1014: {
                   1015:        vhci_fd_t *vfd;
                   1016:        struct file *fp;
                   1017:        int error, fd;
                   1018:
                   1019:        if (minor(dev) != 0)
                   1020:                return EXDEV;
                   1021:        error = fd_allocfile(&fp, &fd);
                   1022:        if (error)
                   1023:                return error;
                   1024:
                   1025:        vfd = kmem_alloc(sizeof(*vfd), KM_SLEEP);
                   1026:        vfd->port = 1;
1.10      maxv     1027:        vfd->addr = 0;
1.1       maxv     1028:        vfd->softc = device_lookup_private(&vhci_cd, minor(dev));
                   1029:
                   1030:        return fd_clone(fp, fd, flags, &vhci_fileops, vfd);
                   1031: }
                   1032:
                   1033: static int
                   1034: vhci_fd_close(file_t *fp)
                   1035: {
                   1036:        vhci_fd_t *vfd = fp->f_data;
1.3       maxv     1037:        int ret __diagused;
1.1       maxv     1038:
                   1039:        KASSERT(vfd != NULL);
1.12      maxv     1040:        ret = vhci_usb_detach(vfd);
1.3       maxv     1041:        KASSERT(ret == 0);
1.1       maxv     1042:
                   1043:        kmem_free(vfd, sizeof(*vfd));
                   1044:        fp->f_data = NULL;
                   1045:
                   1046:        return 0;
                   1047: }
                   1048:
                   1049: static int
                   1050: vhci_fd_read(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
                   1051:     int flags)
                   1052: {
                   1053:        vhci_fd_t *vfd = fp->f_data;
                   1054:        vhci_softc_t *sc = vfd->softc;
                   1055:        vhci_packet_list_t *pktlist;
                   1056:        vhci_packet_t *pkt, *nxt;
                   1057:        vhci_xfer_list_t vxferlist;
                   1058:        vhci_xfer_t *vxfer;
                   1059:        vhci_port_t *port;
                   1060:        int error = 0;
                   1061:        uint8_t *buf;
                   1062:        size_t size;
                   1063:
                   1064:        if (uio->uio_resid == 0)
                   1065:                return 0;
                   1066:        port = &sc->sc_port[vfd->port];
1.10      maxv     1067:        pktlist = &port->endpoints[vfd->addr].host_to_usb;
1.1       maxv     1068:
1.2       maxv     1069:        TAILQ_INIT(&vxferlist);
1.1       maxv     1070:
                   1071:        mutex_enter(&port->lock);
                   1072:
                   1073:        if (!(port->status & UPS_PORT_ENABLED)) {
                   1074:                error = ENOBUFS;
                   1075:                goto out;
                   1076:        }
                   1077:
1.2       maxv     1078:        TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
1.9       maxv     1079:                vxfer = pkt->vxfer;
1.1       maxv     1080:                buf = pkt->buf + pkt->cursor;
1.14      maxv     1081:
1.2       maxv     1082:                KASSERT(pkt->size >= pkt->cursor);
1.1       maxv     1083:                size = uimin(uio->uio_resid, pkt->size - pkt->cursor);
                   1084:
                   1085:                KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
                   1086:
                   1087:                error = uiomove(buf, size, uio);
                   1088:                if (error) {
                   1089:                        DPRINTF("%s: error = %d\n", __func__, error);
                   1090:                        goto out;
                   1091:                }
                   1092:
                   1093:                pkt->cursor += size;
                   1094:
                   1095:                if (pkt->cursor == pkt->size) {
                   1096:                        vhci_pkt_destroy(sc, pkt);
1.9       maxv     1097:                        if (vxfer->npkts == 0) {
1.2       maxv     1098:                                TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
1.1       maxv     1099:                        }
                   1100:                }
                   1101:                if (uio->uio_resid == 0) {
                   1102:                        break;
                   1103:                }
                   1104:        }
                   1105:
                   1106: out:
                   1107:        mutex_exit(&port->lock);
                   1108:
1.2       maxv     1109:        while ((vxfer = TAILQ_FIRST(&vxferlist)) != NULL) {
1.1       maxv     1110:                struct usbd_xfer *xfer = &vxfer->xfer;
1.2       maxv     1111:                TAILQ_REMOVE(&vxferlist, vxfer, freelist);
1.1       maxv     1112:
                   1113:                mutex_enter(&sc->sc_lock);
                   1114:                xfer->ux_actlen = xfer->ux_length;
                   1115:                xfer->ux_status = USBD_NORMAL_COMPLETION;
                   1116:                usb_transfer_complete(xfer);
                   1117:                mutex_exit(&sc->sc_lock);
                   1118:        }
                   1119:
                   1120:        return error;
                   1121: }
                   1122:
                   1123: static int
                   1124: vhci_fd_write(struct file *fp, off_t *offp, struct uio *uio, kauth_cred_t cred,
                   1125:     int flags)
                   1126: {
                   1127:        vhci_fd_t *vfd = fp->f_data;
                   1128:        vhci_softc_t *sc = vfd->softc;
                   1129:        vhci_packet_list_t *pktlist;
                   1130:        vhci_packet_t *pkt, *nxt;
                   1131:        vhci_xfer_list_t vxferlist;
                   1132:        vhci_xfer_t *vxfer;
                   1133:        vhci_port_t *port;
                   1134:        int error = 0;
                   1135:        uint8_t *buf;
1.14      maxv     1136:        size_t pktsize, size;
1.1       maxv     1137:
                   1138:        if (uio->uio_resid == 0)
                   1139:                return 0;
                   1140:        port = &sc->sc_port[vfd->port];
1.10      maxv     1141:        pktlist = &port->endpoints[vfd->addr].usb_to_host;
1.1       maxv     1142:
1.2       maxv     1143:        TAILQ_INIT(&vxferlist);
1.1       maxv     1144:
                   1145:        mutex_enter(&port->lock);
                   1146:
                   1147:        if (!(port->status & UPS_PORT_ENABLED)) {
                   1148:                error = ENOBUFS;
                   1149:                goto out;
                   1150:        }
                   1151:
1.2       maxv     1152:        TAILQ_FOREACH_SAFE(pkt, pktlist, portlist, nxt) {
1.9       maxv     1153:                vxfer = pkt->vxfer;
1.1       maxv     1154:                buf = pkt->buf + pkt->cursor;
1.14      maxv     1155:
                   1156:                pktsize = pkt->size;
                   1157:                if (pkt->type.dat)
                   1158:                        pktsize = ulmin(vxfer->resbuf.size, pktsize);
                   1159:
                   1160:                KASSERT(pktsize >= pkt->cursor);
                   1161:                size = uimin(uio->uio_resid, pktsize - pkt->cursor);
1.1       maxv     1162:
                   1163:                KASSERT(vxfer->xfer.ux_status == USBD_IN_PROGRESS);
                   1164:
                   1165:                error = uiomove(buf, size, uio);
                   1166:                if (error) {
                   1167:                        DPRINTF("%s: error = %d\n", __func__, error);
                   1168:                        goto out;
                   1169:                }
                   1170:
                   1171:                pkt->cursor += size;
                   1172:
1.14      maxv     1173:                if (pkt->cursor == pktsize) {
1.1       maxv     1174:                        vhci_pkt_destroy(sc, pkt);
1.9       maxv     1175:                        if (vxfer->npkts == 0) {
1.2       maxv     1176:                                TAILQ_INSERT_TAIL(&vxferlist, vxfer, freelist);
1.1       maxv     1177:                        }
                   1178:                }
                   1179:                if (uio->uio_resid == 0) {
                   1180:                        break;
                   1181:                }
                   1182:        }
                   1183:
                   1184: out:
                   1185:        mutex_exit(&port->lock);
                   1186:
1.2       maxv     1187:        while ((vxfer = TAILQ_FIRST(&vxferlist)) != NULL) {
1.1       maxv     1188:                struct usbd_xfer *xfer = &vxfer->xfer;
1.2       maxv     1189:                TAILQ_REMOVE(&vxferlist, vxfer, freelist);
1.1       maxv     1190:
                   1191:                mutex_enter(&sc->sc_lock);
1.14      maxv     1192:                xfer->ux_actlen = ulmin(vxfer->resbuf.size, xfer->ux_length);
1.1       maxv     1193:                xfer->ux_status = USBD_NORMAL_COMPLETION;
                   1194:                usb_transfer_complete(xfer);
                   1195:                mutex_exit(&sc->sc_lock);
                   1196:        }
                   1197:
                   1198:        return error;
                   1199: }
                   1200:
                   1201: static int
                   1202: vhci_fd_ioctl(file_t *fp, u_long cmd, void *data)
                   1203: {
                   1204:        vhci_fd_t *vfd = fp->f_data;
                   1205:
                   1206:        KASSERT(vfd != NULL);
                   1207:
                   1208:        switch (cmd) {
                   1209:        case VHCI_IOC_GET_INFO:
                   1210:                return vhci_get_info(vfd, data);
                   1211:        case VHCI_IOC_SET_PORT:
                   1212:                return vhci_set_port(vfd, data);
1.10      maxv     1213:        case VHCI_IOC_SET_ADDR:
                   1214:                return vhci_set_addr(vfd, data);
1.1       maxv     1215:        case VHCI_IOC_USB_ATTACH:
1.12      maxv     1216:                return vhci_usb_attach(vfd);
1.1       maxv     1217:        case VHCI_IOC_USB_DETACH:
1.12      maxv     1218:                return vhci_usb_detach(vfd);
1.1       maxv     1219:        default:
                   1220:                return EINVAL;
                   1221:        }
                   1222: }
                   1223:
                   1224: /* -------------------------------------------------------------------------- */
                   1225:
                   1226: static int vhci_match(device_t, cfdata_t, void *);
                   1227: static void vhci_attach(device_t, device_t, void *);
1.3       maxv     1228: static int vhci_activate(device_t, enum devact);
1.1       maxv     1229:
                   1230: CFATTACH_DECL_NEW(vhci, sizeof(vhci_softc_t), vhci_match, vhci_attach,
1.3       maxv     1231:     NULL, vhci_activate);
1.1       maxv     1232:
                   1233: void
                   1234: vhciattach(int nunits)
                   1235: {
                   1236:        static struct cfdata vhci_cfdata = {
                   1237:                .cf_name = "vhci",
                   1238:                .cf_atname = "vhci",
                   1239:                .cf_unit = 0,
                   1240:                .cf_fstate = FSTATE_STAR,
                   1241:        };
                   1242:        int error;
                   1243:
                   1244:        error = config_cfattach_attach(vhci_cd.cd_name, &vhci_ca);
                   1245:        if (error) {
                   1246:                aprint_error("%s: unable to register cfattach\n",
                   1247:                    vhci_cd.cd_name);
                   1248:                (void)config_cfdriver_detach(&vhci_cd);
                   1249:                return;
                   1250:        }
                   1251:
                   1252:        config_attach_pseudo(&vhci_cfdata);
                   1253: }
                   1254:
                   1255: static int
1.3       maxv     1256: vhci_activate(device_t self, enum devact act)
                   1257: {
                   1258:        vhci_softc_t *sc = device_private(self);
                   1259:
                   1260:        switch (act) {
                   1261:        case DVACT_DEACTIVATE:
                   1262:                sc->sc_dying = 1;
                   1263:                return 0;
                   1264:        default:
                   1265:                return EOPNOTSUPP;
                   1266:        }
                   1267: }
                   1268:
                   1269: static int
1.1       maxv     1270: vhci_match(device_t parent, cfdata_t match, void *aux)
                   1271: {
                   1272:        return 1;
                   1273: }
                   1274:
                   1275: static void
                   1276: vhci_attach(device_t parent, device_t self, void *aux)
                   1277: {
                   1278:        vhci_softc_t *sc = device_private(self);
                   1279:        vhci_port_t *port;
1.10      maxv     1280:        uint8_t addr;
1.1       maxv     1281:        size_t i;
                   1282:
                   1283:        sc->sc_dev = self;
                   1284:        sc->sc_bus.ub_revision = USBREV_2_0;
                   1285:        sc->sc_bus.ub_usedma = false;
                   1286:        sc->sc_bus.ub_methods = &vhci_bus_methods;
                   1287:        sc->sc_bus.ub_pipesize = sizeof(vhci_pipe_t);
                   1288:        sc->sc_bus.ub_hcpriv = sc;
                   1289:        sc->sc_dying = false;
                   1290:        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
                   1291:
                   1292:        sc->sc_nports = VHCI_NPORTS;
                   1293:        for (i = 0; i < sc->sc_nports; i++) {
                   1294:                port = &sc->sc_port[i];
                   1295:                mutex_init(&port->lock, MUTEX_DEFAULT, IPL_SOFTUSB);
1.10      maxv     1296:                for (addr = 0; addr < VHCI_NADDRS; addr++) {
                   1297:                        TAILQ_INIT(&port->endpoints[addr].usb_to_host);
                   1298:                        TAILQ_INIT(&port->endpoints[addr].host_to_usb);
                   1299:                }
1.1       maxv     1300:        }
                   1301:
                   1302:        sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
                   1303: }

CVSweb <webmaster@jp.NetBSD.org>