[BACK]Return to ugenhc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / rump / dev / lib / libugenhc

Annotation of src/sys/rump/dev/lib/libugenhc/ugenhc.c, Revision 1.18

1.18    ! christos    1: /*     $NetBSD: ugenhc.c,v 1.17 2014/03/13 01:38:11 pooka Exp $        */
1.1       pooka       2:
                      3: /*
1.7       pooka       4:  * Copyright (c) 2009, 2010 Antti Kantee.  All Rights Reserved.
1.1       pooka       5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     18:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  */
                     27:
                     28: /*
                     29:  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
                     30:  * All rights reserved.
                     31:  *
                     32:  * This code is derived from software contributed to The NetBSD Foundation
                     33:  * by Lennart Augustsson (lennart@augustsson.net) at
                     34:  * Carlstedt Research & Technology.
                     35:  *
                     36:  * Redistribution and use in source and binary forms, with or without
                     37:  * modification, are permitted provided that the following conditions
                     38:  * are met:
                     39:  * 1. Redistributions of source code must retain the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer.
                     41:  * 2. Redistributions in binary form must reproduce the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer in the
                     43:  *    documentation and/or other materials provided with the distribution.
                     44:  *
                     45:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     46:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     47:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     48:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     49:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     50:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     51:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     52:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     53:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     54:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     55:  * POSSIBILITY OF SUCH DAMAGE.
                     56:  */
                     57:
                     58: /*
                     59:  * This rump driver attaches ugen as a kernel usb host controller.
                     60:  * It's still somewhat under the hammer ....
                     61:  */
                     62:
                     63: #include <sys/cdefs.h>
1.18    ! christos   64: __KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.17 2014/03/13 01:38:11 pooka Exp $");
1.1       pooka      65:
                     66: #include <sys/param.h>
                     67: #include <sys/bus.h>
                     68: #include <sys/conf.h>
                     69: #include <sys/device.h>
                     70: #include <sys/fcntl.h>
                     71: #include <sys/kmem.h>
                     72: #include <sys/kernel.h>
                     73: #include <sys/kthread.h>
                     74:
                     75: #include <dev/usb/usb.h>
                     76: #include <dev/usb/usbdi.h>
                     77: #include <dev/usb/usbhid.h>
                     78: #include <dev/usb/usbdivar.h>
                     79: #include <dev/usb/usb_mem.h>
                     80: #include <dev/usb/usbroothub_subr.h>
                     81:
                     82: #include <rump/rumpuser.h>
                     83:
1.17      pooka      84: #include "ugenhc_user.h"
1.13      pooka      85:
1.1       pooka      86: #include "rump_private.h"
                     87: #include "rump_dev_private.h"
                     88:
                     89: #define UGEN_NEPTS 16
                     90: #define UGEN_EPT_CTRL 0 /* ugenx.00 is the control endpoint */
                     91:
                     92: struct ugenhc_softc {
                     93:        struct usbd_bus sc_bus;
                     94:        int sc_devnum;
                     95:
                     96:        int sc_ugenfd[UGEN_NEPTS];
                     97:        int sc_fdmodes[UGEN_NEPTS];
                     98:
                     99:        int sc_port_status;
                    100:        int sc_port_change;
                    101:        int sc_addr;
                    102:        int sc_conf;
1.3       pooka     103:
                    104:        struct lwp *sc_rhintr;
                    105:        usbd_xfer_handle sc_intrxfer;
1.1       pooka     106: };
                    107:
1.12      chs       108: static int     ugenhc_probe(device_t, cfdata_t, void *);
                    109: static void    ugenhc_attach(device_t, device_t, void *);
1.1       pooka     110:
                    111: CFATTACH_DECL_NEW(ugenhc, sizeof(struct ugenhc_softc),
                    112:        ugenhc_probe, ugenhc_attach, NULL, NULL);
                    113:
                    114: struct rusb_xfer {
                    115:        struct usbd_xfer rusb_xfer;
                    116:        int rusb_status; /* now this is a cheap trick */
                    117: };
                    118: #define RUSB(x) ((struct rusb_xfer *)x)
                    119:
                    120: #define UGENDEV_BASESTR "/dev/ugen"
                    121: #define UGENDEV_BUFSIZE 32
                    122: static void
1.18    ! christos  123: makeugendevstr(int devnum, int endpoint, char *buf, size_t len)
1.1       pooka     124: {
                    125:
                    126:        CTASSERT(UGENDEV_BUFSIZE > sizeof(UGENDEV_BASESTR)+sizeof("0.00")+1);
1.18    ! christos  127:        snprintf(buf, len, "%s%d.%02d", UGENDEV_BASESTR, devnum, endpoint);
1.1       pooka     128: }
                    129:
                    130: /*
                    131:  * Our fictional hubbie.
                    132:  */
                    133:
                    134: static const usb_device_descriptor_t rumphub_udd = {
                    135:        .bLength                = USB_DEVICE_DESCRIPTOR_SIZE,
                    136:        .bDescriptorType        = UDESC_DEVICE,
                    137:        .bDeviceClass           = UDCLASS_HUB,
                    138:        .bDeviceSubClass        = UDSUBCLASS_HUB,
                    139:        .bDeviceProtocol        = UDPROTO_FSHUB,
                    140:        .bMaxPacketSize         = 64,
1.8       pooka     141:        .idVendor               = { 0x75, 0x72 },
                    142:        .idProduct              = { 0x70, 0x6d },
1.1       pooka     143:        .bNumConfigurations     = 1,
                    144: };
                    145:
                    146: static const usb_config_descriptor_t rumphub_ucd = {
                    147:        .bLength                = USB_CONFIG_DESCRIPTOR_SIZE,
                    148:        .bDescriptorType        = UDESC_CONFIG,
                    149:        .wTotalLength           = { USB_CONFIG_DESCRIPTOR_SIZE
                    150:                                  + USB_INTERFACE_DESCRIPTOR_SIZE
                    151:                                  + USB_ENDPOINT_DESCRIPTOR_SIZE },
                    152:        .bNumInterface          = 1,
                    153:        .bmAttributes           = UC_SELF_POWERED | UC_ATTR_MBO,
                    154: };
                    155: /* XXX: spec says UC_ATTR_MBO is reserved and set to one.  required? */
                    156:
                    157: static const usb_interface_descriptor_t rumphub_uid = {
                    158:        .bLength                = USB_INTERFACE_DESCRIPTOR_SIZE,
                    159:        .bDescriptorType        = UDESC_INTERFACE,
                    160:        .bInterfaceNumber       = 0,
                    161:        .bNumEndpoints          = 1,
                    162:        .bInterfaceClass        = UICLASS_HUB,
                    163:        .bInterfaceSubClass     = UISUBCLASS_HUB,
                    164:        .bInterfaceProtocol     = UIPROTO_FSHUB,
                    165: };
                    166:
                    167: static const usb_endpoint_descriptor_t rumphub_epd = {
                    168:        .bLength                = USB_ENDPOINT_DESCRIPTOR_SIZE,
                    169:        .bDescriptorType        = UDESC_ENDPOINT,
                    170:        .bmAttributes           = UE_INTERRUPT,
                    171:        .wMaxPacketSize         = {64, 0},
                    172: };
                    173:
                    174: static const usb_hub_descriptor_t rumphub_hdd = {
                    175:        .bDescLength            = USB_HUB_DESCRIPTOR_SIZE,
                    176:        .bDescriptorType        = UDESC_HUB,
                    177:        .bNbrPorts              = 1,
                    178: };
                    179:
                    180: static usbd_status
                    181: rumpusb_root_ctrl_start(usbd_xfer_handle xfer)
                    182: {
                    183:        usb_device_request_t *req = &xfer->request;
                    184:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
                    185:        int len, totlen, value, curlen, err;
                    186:        uint8_t *buf = NULL;
                    187:
                    188:        len = totlen = UGETW(req->wLength);
                    189:        if (len)
                    190:                buf = KERNADDR(&xfer->dmabuf, 0);
                    191:        value = UGETW(req->wValue);
                    192:
                    193: #define C(x,y) ((x) | ((y) << 8))
                    194:        switch(C(req->bRequest, req->bmRequestType)) {
                    195:
                    196:        case C(UR_GET_CONFIG, UT_READ_DEVICE):
                    197:                if (len > 0) {
                    198:                        *buf = sc->sc_conf;
                    199:                        totlen = 1;
                    200:                }
                    201:                break;
                    202:
                    203:        case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
                    204:                switch (value >> 8) {
                    205:                case UDESC_DEVICE:
                    206:                        totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
                    207:                        memcpy(buf, &rumphub_udd, totlen);
                    208:                        break;
                    209:
                    210:                case UDESC_CONFIG:
                    211:                        totlen = 0;
                    212:                        curlen = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
                    213:                        memcpy(buf, &rumphub_ucd, curlen);
                    214:                        len -= curlen;
                    215:                        buf += curlen;
                    216:                        totlen += curlen;
                    217:
                    218:                        curlen = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
                    219:                        memcpy(buf, &rumphub_uid, curlen);
                    220:                        len -= curlen;
                    221:                        buf += curlen;
                    222:                        totlen += curlen;
                    223:
                    224:                        curlen = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
                    225:                        memcpy(buf, &rumphub_epd, curlen);
                    226:                        len -= curlen;
                    227:                        buf += curlen;
                    228:                        totlen += curlen;
                    229:                        break;
                    230:
                    231:                case UDESC_STRING:
                    232: #define sd ((usb_string_descriptor_t *)buf)
                    233:                        switch (value & 0xff) {
                    234:                        case 0: /* Language table */
                    235:                                totlen = usb_makelangtbl(sd, len);
                    236:                                break;
                    237:                        case 1: /* Vendor */
                    238:                                totlen = usb_makestrdesc(sd, len, "rod nevada");
                    239:                                break;
                    240:                        case 2: /* Product */
                    241:                                totlen = usb_makestrdesc(sd, len,
                    242:                                    "RUMPUSBHC root hub");
                    243:                                break;
                    244:                        }
                    245: #undef sd
                    246:                        break;
                    247:
                    248:                default:
                    249:                        panic("unhandled read device request");
                    250:                        break;
                    251:                }
                    252:                break;
                    253:
                    254:        case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
                    255:                if (value >= USB_MAX_DEVICES) {
                    256:                        err = USBD_IOERROR;
                    257:                        goto ret;
                    258:                }
                    259:                sc->sc_addr = value;
                    260:                break;
                    261:
                    262:        case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
                    263:                if (value != 0 && value != 1) {
                    264:                        err = USBD_IOERROR;
                    265:                        goto ret;
                    266:                }
                    267:                sc->sc_conf = value;
                    268:                break;
                    269:
                    270:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
                    271:                switch (value) {
                    272:                case UHF_PORT_RESET:
                    273:                        sc->sc_port_change |= UPS_C_PORT_RESET;
                    274:                        break;
                    275:                case UHF_PORT_POWER:
                    276:                        break;
                    277:                default:
                    278:                        panic("unhandled");
                    279:                }
                    280:                break;
                    281:
                    282:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
                    283:                sc->sc_port_change &= ~value;
                    284:                break;
                    285:
                    286:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                    287:                totlen = min(len, USB_HUB_DESCRIPTOR_SIZE);
                    288:                memcpy(buf, &rumphub_hdd, totlen);
                    289:                break;
                    290:
                    291:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                    292:                /* huh?  other hc's do this */
                    293:                memset(buf, 0, len);
                    294:                totlen = len;
                    295:                break;
                    296:
                    297:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
                    298:                {
                    299:                usb_port_status_t ps;
                    300:
                    301:                USETW(ps.wPortStatus, sc->sc_port_status);
                    302:                USETW(ps.wPortChange, sc->sc_port_change);
                    303:                totlen = min(len, sizeof(ps));
                    304:                memcpy(buf, &ps, totlen);
                    305:                break;
                    306:                }
                    307:
                    308:        default:
                    309:                panic("unhandled request");
                    310:                break;
                    311:        }
                    312:        err = USBD_NORMAL_COMPLETION;
                    313:        xfer->actlen = totlen;
                    314:
                    315: ret:
                    316:        xfer->status = err;
1.10      mrg       317:        /* XXX locking */
1.1       pooka     318:        usb_transfer_complete(xfer);
                    319:        return (USBD_IN_PROGRESS);
                    320: }
                    321:
                    322: static usbd_status
                    323: rumpusb_root_ctrl_transfer(usbd_xfer_handle xfer)
                    324: {
                    325:        usbd_status err;
                    326:
                    327:        err = usb_insert_transfer(xfer);
                    328:        if (err)
                    329:                return (err);
                    330:
                    331:        return (rumpusb_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
                    332: }
                    333:
                    334: static void
                    335: rumpusb_root_ctrl_abort(usbd_xfer_handle xfer)
                    336: {
                    337:
                    338: }
                    339:
                    340: static void
                    341: rumpusb_root_ctrl_close(usbd_pipe_handle pipe)
                    342: {
                    343:
                    344: }
                    345:
                    346: static void
                    347: rumpusb_root_ctrl_cleartoggle(usbd_pipe_handle pipe)
                    348: {
                    349:
                    350: }
                    351:
                    352: static void
                    353: rumpusb_root_ctrl_done(usbd_xfer_handle xfer)
                    354: {
                    355:
                    356: }
                    357:
                    358: static const struct usbd_pipe_methods rumpusb_root_ctrl_methods = {
                    359:        .transfer =     rumpusb_root_ctrl_transfer,
                    360:        .start =        rumpusb_root_ctrl_start,
                    361:        .abort =        rumpusb_root_ctrl_abort,
                    362:        .close =        rumpusb_root_ctrl_close,
                    363:        .cleartoggle =  rumpusb_root_ctrl_cleartoggle,
                    364:        .done =         rumpusb_root_ctrl_done,
                    365: };
                    366:
                    367: static usbd_status
                    368: rumpusb_device_ctrl_start(usbd_xfer_handle xfer)
                    369: {
                    370:        usb_device_request_t *req = &xfer->request;
                    371:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
                    372:        uint8_t *buf = NULL;
                    373:        int len, totlen;
                    374:        int value;
                    375:        int err = 0;
                    376:        int ru_error, mightfail = 0;
                    377:
                    378:        len = totlen = UGETW(req->wLength);
                    379:        if (len)
                    380:                buf = KERNADDR(&xfer->dmabuf, 0);
                    381:        value = UGETW(req->wValue);
                    382:
                    383: #define C(x,y) ((x) | ((y) << 8))
                    384:        switch(C(req->bRequest, req->bmRequestType)) {
                    385:        case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
                    386:                switch (value>>8) {
                    387:                case UDESC_DEVICE:
                    388:                        {
                    389:                        usb_device_descriptor_t uddesc;
                    390:                        totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
                    391:                        memset(buf, 0, totlen);
1.13      pooka     392:                        if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.3       pooka     393:                            USB_GET_DEVICE_DESC, &uddesc, &ru_error) == -1) {
                    394:                                err = EIO;
                    395:                                goto ret;
                    396:                        }
1.1       pooka     397:                        memcpy(buf, &uddesc, totlen);
                    398:                        }
                    399:
                    400:                        break;
                    401:                case UDESC_CONFIG:
                    402:                        {
                    403:                        struct usb_full_desc ufdesc;
1.7       pooka     404:                        ufdesc.ufd_config_index = value & 0xff;
1.1       pooka     405:                        ufdesc.ufd_size = len;
                    406:                        ufdesc.ufd_data = buf;
1.7       pooka     407:                        memset(buf, 0, len);
1.13      pooka     408:                        if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.7       pooka     409:                            USB_GET_FULL_DESC, &ufdesc, &ru_error) == -1) {
                    410:                                err = USBD_IOERROR;
                    411:                                goto ret;
                    412:                        }
                    413:                        totlen = ufdesc.ufd_size;
1.1       pooka     414:                        }
                    415:                        break;
                    416:
                    417:                case UDESC_STRING:
                    418:                        {
                    419:                        struct usb_device_info udi;
                    420:
1.13      pooka     421:                        if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.1       pooka     422:                            USB_GET_DEVICEINFO, &udi, &ru_error) == -1) {
                    423:                                printf("ugenhc: get dev info failed: %d\n",
                    424:                                    ru_error);
                    425:                                err = USBD_IOERROR;
                    426:                                goto ret;
                    427:                        }
                    428:
                    429:                        switch (value & 0xff) {
                    430: #define sd ((usb_string_descriptor_t *)buf)
                    431:                        case 0: /* language table */
                    432:                                break;
                    433:                        case 1: /* vendor */
                    434:                                totlen = usb_makestrdesc(sd, len,
                    435:                                    udi.udi_vendor);
                    436:                                break;
                    437:                        case 2: /* product */
                    438:                                totlen = usb_makestrdesc(sd, len,
                    439:                                    udi.udi_product);
                    440:                                break;
                    441:                        }
                    442: #undef sd
                    443:                        }
                    444:                        break;
                    445:
                    446:                default:
                    447:                        panic("not handled");
                    448:                }
                    449:                break;
                    450:
                    451:        case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
                    452:                /* ignored, ugen won't let us */
                    453:                break;
                    454:
                    455:        case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
1.13      pooka     456:                if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.7       pooka     457:                    USB_SET_CONFIG, &value, &ru_error) == -1) {
                    458:                        printf("ugenhc: set config failed: %d\n",
                    459:                            ru_error);
                    460:                        err = USBD_IOERROR;
                    461:                        goto ret;
                    462:                }
1.1       pooka     463:                break;
                    464:
                    465:        case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
                    466:                {
                    467:                struct usb_alt_interface uai;
                    468:
                    469:                totlen = 0;
                    470:                uai.uai_interface_index = UGETW(req->wIndex);
                    471:                uai.uai_alt_no = value;
1.13      pooka     472:                if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.1       pooka     473:                    USB_SET_ALTINTERFACE, &uai, &ru_error) == -1) {
                    474:                        printf("ugenhc: set alt interface failed: %d\n",
                    475:                            ru_error);
                    476:                        err = USBD_IOERROR;
                    477:                        goto ret;
                    478:                }
                    479:                break;
                    480:                }
                    481:
                    482:        /*
                    483:         * This request might fail unknown reasons.  "EIO" doesn't
                    484:         * give much help, and debugging the host ugen would be
                    485:         * necessary.  However, since it doesn't seem to really
                    486:         * affect anything, just let it fail for now.
                    487:         */
                    488:        case C(0x00, UT_WRITE_CLASS_INTERFACE):
                    489:                mightfail = 1;
                    490:                /*FALLTHROUGH*/
                    491:
                    492:        /*
                    493:         * XXX: don't wildcard these yet.  I want to better figure
                    494:         * out what to trap here.  This is kinda silly, though ...
                    495:         */
                    496:
                    497:        case C(0x01, UT_WRITE_VENDOR_DEVICE):
                    498:        case C(0x06, UT_WRITE_VENDOR_DEVICE):
                    499:        case C(0x07, UT_READ_VENDOR_DEVICE):
                    500:        case C(0x09, UT_READ_VENDOR_DEVICE):
                    501:        case C(0xfe, UT_READ_CLASS_INTERFACE):
                    502:        case C(0x01, UT_READ_CLASS_INTERFACE):
                    503:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
                    504:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                    505:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                    506:        case C(UR_GET_DESCRIPTOR, UT_READ_INTERFACE):
                    507:        case C(0xff, UT_WRITE_CLASS_INTERFACE):
                    508:        case C(0x20, UT_WRITE_CLASS_INTERFACE):
                    509:        case C(0x22, UT_WRITE_CLASS_INTERFACE):
                    510:        case C(0x0a, UT_WRITE_CLASS_INTERFACE):
                    511:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
1.9       pooka     512:        case C(0x00, UT_WRITE_CLASS_DEVICE):
1.2       pooka     513:        case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
1.1       pooka     514:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
                    515:        case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE):
                    516:        case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
                    517:                {
                    518:                struct usb_ctl_request ucr;
                    519:
                    520:                memcpy(&ucr.ucr_request, req, sizeof(ucr.ucr_request));
                    521:                ucr.ucr_data = buf;
1.13      pooka     522:                if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.1       pooka     523:                    USB_DO_REQUEST, &ucr, &ru_error) == -1) {
1.2       pooka     524:                        if (!mightfail) {
1.1       pooka     525:                                panic("request failed: %d", ru_error);
1.2       pooka     526:                        } else {
1.1       pooka     527:                                err = ru_error;
1.2       pooka     528:                        }
1.1       pooka     529:                }
                    530:                }
                    531:                break;
                    532:
                    533:        default:
                    534:                panic("unhandled request");
                    535:                break;
                    536:        }
                    537:        xfer->actlen = totlen;
                    538:        err = USBD_NORMAL_COMPLETION;
                    539:
                    540:  ret:
                    541:        xfer->status = err;
                    542:        usb_transfer_complete(xfer);
                    543:        return (USBD_IN_PROGRESS);
                    544: }
                    545:
                    546: static usbd_status
                    547: rumpusb_device_ctrl_transfer(usbd_xfer_handle xfer)
                    548: {
                    549:        usbd_status err;
                    550:
                    551:        err = usb_insert_transfer(xfer);
                    552:        if (err)
                    553:                return (err);
                    554:
                    555:        return (rumpusb_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
                    556: }
                    557:
                    558: static void
                    559: rumpusb_device_ctrl_abort(usbd_xfer_handle xfer)
                    560: {
                    561:
                    562: }
                    563:
                    564: static void
                    565: rumpusb_device_ctrl_close(usbd_pipe_handle pipe)
                    566: {
                    567:
                    568: }
                    569:
                    570: static void
                    571: rumpusb_device_ctrl_cleartoggle(usbd_pipe_handle pipe)
                    572: {
                    573:
                    574: }
                    575:
                    576: static void
                    577: rumpusb_device_ctrl_done(usbd_xfer_handle xfer)
                    578: {
                    579:
                    580: }
                    581:
                    582: static const struct usbd_pipe_methods rumpusb_device_ctrl_methods = {
                    583:        .transfer =     rumpusb_device_ctrl_transfer,
                    584:        .start =        rumpusb_device_ctrl_start,
                    585:        .abort =        rumpusb_device_ctrl_abort,
                    586:        .close =        rumpusb_device_ctrl_close,
                    587:        .cleartoggle =  rumpusb_device_ctrl_cleartoggle,
                    588:        .done =         rumpusb_device_ctrl_done,
                    589: };
                    590:
1.3       pooka     591: static void
                    592: rhscintr(void *arg)
                    593: {
                    594:        char buf[UGENDEV_BUFSIZE];
                    595:        struct ugenhc_softc *sc = arg;
1.1       pooka     596:        usbd_xfer_handle xfer;
1.3       pooka     597:        int fd, error;
                    598:
1.18    ! christos  599:        makeugendevstr(sc->sc_devnum, 0, buf, sizeof(buf));
1.4       pooka     600:
1.3       pooka     601:        for (;;) {
1.4       pooka     602:                /*
                    603:                 * Detect device attach.
                    604:                 */
                    605:
                    606:                for (;;) {
1.15      pooka     607:                        error = rumpuser_open(buf, RUMPUSER_OPEN_RDWR, &fd);
                    608:                        if (error != 0)
1.4       pooka     609:                                break;
                    610:                        kpause("ugwait", false, hz/4, NULL);
                    611:                }
                    612:
                    613:                sc->sc_ugenfd[UGEN_EPT_CTRL] = fd;
                    614:                sc->sc_port_status = UPS_CURRENT_CONNECT_STATUS
                    615:                    | UPS_PORT_ENABLED | UPS_PORT_POWER;
1.7       pooka     616:                sc->sc_port_change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
1.4       pooka     617:
                    618:                xfer = sc->sc_intrxfer;
1.7       pooka     619:                memset(xfer->buffer, 0xff, xfer->length);
                    620:                xfer->actlen = xfer->length;
1.4       pooka     621:                xfer->status = USBD_NORMAL_COMPLETION;
1.7       pooka     622:
1.4       pooka     623:                usb_transfer_complete(xfer);
                    624:
1.7       pooka     625:                kpause("ugwait2", false, hz, NULL);
                    626:
1.4       pooka     627:                /*
                    628:                 * Detect device detach.
                    629:                 */
                    630:
                    631:                for (;;) {
1.11      pooka     632:                        fd = rumpuser_open(buf, RUMPUSER_OPEN_RDWR, &error);
1.4       pooka     633:                        if (fd == -1)
                    634:                                break;
1.7       pooka     635:
1.15      pooka     636:                        error = rumpuser_close(fd);
1.4       pooka     637:                        kpause("ugwait2", false, hz/4, NULL);
                    638:                }
1.1       pooka     639:
1.4       pooka     640:                sc->sc_port_status = ~(UPS_CURRENT_CONNECT_STATUS
                    641:                    | UPS_PORT_ENABLED | UPS_PORT_POWER);
1.7       pooka     642:                sc->sc_port_change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
1.5       pooka     643:
1.15      pooka     644:                error = rumpuser_close(sc->sc_ugenfd[UGEN_EPT_CTRL]);
1.4       pooka     645:                sc->sc_ugenfd[UGEN_EPT_CTRL] = -1;
1.1       pooka     646:
1.4       pooka     647:                xfer = sc->sc_intrxfer;
1.7       pooka     648:                memset(xfer->buffer, 0xff, xfer->length);
                    649:                xfer->actlen = xfer->length;
1.4       pooka     650:                xfer->status = USBD_NORMAL_COMPLETION;
                    651:                usb_transfer_complete(xfer);
1.7       pooka     652:
                    653:                kpause("ugwait3", false, hz, NULL);
1.4       pooka     654:        }
1.1       pooka     655:
1.3       pooka     656:        kthread_exit(0);
1.1       pooka     657: }
                    658:
                    659: static usbd_status
                    660: rumpusb_root_intr_start(usbd_xfer_handle xfer)
                    661: {
1.3       pooka     662:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
                    663:        int error;
1.1       pooka     664:
1.3       pooka     665:        sc->sc_intrxfer = xfer;
                    666:        if (!sc->sc_rhintr) {
                    667:                error = kthread_create(PRI_NONE, 0, NULL,
                    668:                    rhscintr, sc, &sc->sc_rhintr, "ugenrhi");
                    669:                if (error)
                    670:                        xfer->status = error;
                    671:        }
1.1       pooka     672:
                    673:        return (USBD_IN_PROGRESS);
                    674: }
                    675:
                    676: static usbd_status
                    677: rumpusb_root_intr_transfer(usbd_xfer_handle xfer)
                    678: {
                    679:        usbd_status err;
                    680:
                    681:        err = usb_insert_transfer(xfer);
                    682:        if (err)
                    683:                return (err);
                    684:
                    685:        return (rumpusb_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
                    686: }
                    687:
                    688: static void
                    689: rumpusb_root_intr_abort(usbd_xfer_handle xfer)
                    690: {
                    691:
                    692: }
                    693:
                    694: static void
                    695: rumpusb_root_intr_close(usbd_pipe_handle pipe)
                    696: {
                    697:
                    698: }
                    699:
                    700: static void
                    701: rumpusb_root_intr_cleartoggle(usbd_pipe_handle pipe)
                    702: {
                    703:
                    704: }
                    705:
                    706: static void
                    707: rumpusb_root_intr_done(usbd_xfer_handle xfer)
                    708: {
                    709:
                    710: }
                    711:
                    712: static const struct usbd_pipe_methods rumpusb_root_intr_methods = {
                    713:        .transfer =     rumpusb_root_intr_transfer,
                    714:        .start =        rumpusb_root_intr_start,
                    715:        .abort =        rumpusb_root_intr_abort,
                    716:        .close =        rumpusb_root_intr_close,
                    717:        .cleartoggle =  rumpusb_root_intr_cleartoggle,
                    718:        .done =         rumpusb_root_intr_done,
                    719: };
                    720:
                    721: static usbd_status
                    722: rumpusb_device_bulk_start(usbd_xfer_handle xfer)
                    723: {
                    724:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
1.9       pooka     725:        usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
1.15      pooka     726:        size_t n, done;
1.1       pooka     727:        bool isread;
                    728:        int len, error, endpt;
                    729:        uint8_t *buf;
1.6       pooka     730:        int xfererr = USBD_NORMAL_COMPLETION;
1.9       pooka     731:        int shortval, i;
1.1       pooka     732:
1.9       pooka     733:        ed = xfer->pipe->endpoint->edesc;
                    734:        endpt = ed->bEndpointAddress;
1.1       pooka     735:        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
                    736:        endpt = UE_GET_ADDR(endpt);
                    737:        KASSERT(endpt < UGEN_NEPTS);
                    738:
                    739:        buf = KERNADDR(&xfer->dmabuf, 0);
                    740:        done = 0;
1.9       pooka     741:        if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) {
                    742:                for (i = 0, len = 0; i < xfer->nframes; i++)
                    743:                        len += xfer->frlengths[i];
                    744:        } else {
                    745:                KASSERT(xfer->length);
                    746:                len = xfer->length;
                    747:        }
                    748:        shortval = (xfer->flags & USBD_SHORT_XFER_OK) != 0;
1.1       pooka     749:
                    750:        while (RUSB(xfer)->rusb_status == 0) {
                    751:                if (isread) {
1.14      pooka     752:                        struct rumpuser_iovec iov;
                    753:
1.13      pooka     754:                        rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[endpt],
1.9       pooka     755:                            USB_SET_SHORT_XFER, &shortval, &error);
1.14      pooka     756:                        iov.iov_base = buf+done;
                    757:                        iov.iov_len = len-done;
1.15      pooka     758:                        error = rumpuser_iovread(sc->sc_ugenfd[endpt], &iov, 1,
                    759:                            RUMPUSER_IOV_NOSEEK, &n);
                    760:                        if (error) {
1.1       pooka     761:                                n = 0;
1.9       pooka     762:                                if (done == 0) {
                    763:                                        if (error == ETIMEDOUT)
                    764:                                                continue;
                    765:                                        xfererr = USBD_IOERROR;
                    766:                                        goto out;
                    767:                                }
1.1       pooka     768:                        }
                    769:                        done += n;
                    770:                        if (done == len)
                    771:                                break;
                    772:                } else {
1.14      pooka     773:                        struct rumpuser_iovec iov;
                    774:
                    775:                        iov.iov_base = buf;
                    776:                        iov.iov_len = len;
1.15      pooka     777:                        error = rumpuser_iovwrite(sc->sc_ugenfd[endpt], &iov, 1,
                    778:                            RUMPUSER_IOV_NOSEEK, &n);
1.1       pooka     779:                        done = n;
                    780:                        if (done == len)
                    781:                                break;
1.15      pooka     782:                        else if (!error)
1.1       pooka     783:                                panic("short write");
1.6       pooka     784:
                    785:                        xfererr = USBD_IOERROR;
                    786:                        goto out;
1.1       pooka     787:                }
                    788:
1.9       pooka     789:                if (shortval) {
                    790:                        /*
                    791:                         * Holy XXX, bitman.  I get >16byte interrupt
                    792:                         * transfers from ugen in 16 byte chunks.
                    793:                         * Don't know how to better fix this for now.
                    794:                         * Of course this hack will fail e.g. if someone
                    795:                         * sports other magic values or if the transfer
                    796:                         * happens to be an integral multiple of 16
                    797:                         * in size ....
                    798:                         */
                    799:                        if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT
                    800:                            && n == 16) {
                    801:                                continue;
                    802:                        } else {
                    803:                                break;
                    804:                        }
                    805:                }
1.1       pooka     806:        }
                    807:
                    808:        if (RUSB(xfer)->rusb_status == 0) {
                    809:                xfer->actlen = done;
                    810:        } else {
1.6       pooka     811:                xfererr = USBD_CANCELLED;
1.1       pooka     812:                RUSB(xfer)->rusb_status = 2;
                    813:        }
                    814:  out:
1.9       pooka     815:        if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS)
                    816:                if (done != len)
                    817:                        panic("lazy bum");
1.6       pooka     818:        xfer->status = xfererr;
1.1       pooka     819:        usb_transfer_complete(xfer);
                    820:        return (USBD_IN_PROGRESS);
                    821: }
                    822:
                    823: static void
                    824: doxfer_kth(void *arg)
                    825: {
                    826:        usbd_xfer_handle xfer = arg;
                    827:
                    828:        do {
                    829:                rumpusb_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
                    830:        } while (!SIMPLEQ_EMPTY(&xfer->pipe->queue));
                    831:        kthread_exit(0);
                    832: }
                    833:
                    834: static usbd_status
                    835: rumpusb_device_bulk_transfer(usbd_xfer_handle xfer)
                    836: {
                    837:        usbd_status err;
                    838:
                    839:        if (!rump_threads) {
                    840:                /* XXX: lie about supporting async transfers */
                    841:                if ((xfer->flags & USBD_SYNCHRONOUS) == 0) {
                    842:                        printf("non-threaded rump does not support "
                    843:                            "async transfers.\n");
                    844:                        return USBD_IN_PROGRESS;
                    845:                }
                    846:
                    847:                err = usb_insert_transfer(xfer);
                    848:                if (err)
                    849:                        return err;
                    850:
                    851:                return rumpusb_device_bulk_start(
                    852:                    SIMPLEQ_FIRST(&xfer->pipe->queue));
                    853:        } else {
                    854:                /* biglocked */
1.10      mrg       855:                /* XXX locking */
1.1       pooka     856:                err = usb_insert_transfer(xfer);
                    857:                if (err)
                    858:                        return err;
                    859:                kthread_create(PRI_NONE, 0, NULL, doxfer_kth, xfer, NULL,
                    860:                    "rusbhcxf");
                    861:
                    862:                return USBD_IN_PROGRESS;
                    863:        }
                    864: }
                    865:
                    866: /* wait for transfer to abort.  yea, this is cheesy (from a spray can) */
                    867: static void
                    868: rumpusb_device_bulk_abort(usbd_xfer_handle xfer)
                    869: {
                    870:        struct rusb_xfer *rx = RUSB(xfer);
                    871:
                    872:        rx->rusb_status = 1;
                    873:        while (rx->rusb_status < 2) {
                    874:                kpause("jopo", false, hz/10, NULL);
                    875:        }
                    876: }
                    877:
                    878: static void
                    879: rumpusb_device_bulk_close(usbd_pipe_handle pipe)
                    880: {
1.7       pooka     881:        struct ugenhc_softc *sc = pipe->device->bus->hci_private;
                    882:        int endpt = pipe->endpoint->edesc->bEndpointAddress;
                    883:        usbd_xfer_handle xfer;
1.1       pooka     884:
1.8       pooka     885:        endpt = UE_GET_ADDR(endpt);
                    886:
1.7       pooka     887:        while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL)
                    888:                rumpusb_device_bulk_abort(xfer);
                    889:
1.15      pooka     890:        rumpuser_close(sc->sc_ugenfd[endpt]);
1.7       pooka     891:        sc->sc_ugenfd[endpt] = -1;
                    892:        sc->sc_fdmodes[endpt] = -1;
1.1       pooka     893: }
                    894:
                    895: static void
                    896: rumpusb_device_bulk_cleartoggle(usbd_pipe_handle pipe)
                    897: {
                    898:
                    899: }
                    900:
                    901: static void
                    902: rumpusb_device_bulk_done(usbd_xfer_handle xfer)
                    903: {
                    904:
                    905: }
                    906:
                    907: static const struct usbd_pipe_methods rumpusb_device_bulk_methods = {
                    908:        .transfer =     rumpusb_device_bulk_transfer,
                    909:        .start =        rumpusb_device_bulk_start,
                    910:        .abort =        rumpusb_device_bulk_abort,
                    911:        .close =        rumpusb_device_bulk_close,
                    912:        .cleartoggle =  rumpusb_device_bulk_cleartoggle,
                    913:        .done =         rumpusb_device_bulk_done,
                    914: };
                    915:
                    916: static usbd_status
                    917: ugenhc_open(struct usbd_pipe *pipe)
                    918: {
                    919:        usbd_device_handle dev = pipe->device;
                    920:        struct ugenhc_softc *sc = dev->bus->hci_private;
                    921:        usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
                    922:        u_int8_t addr = dev->address;
                    923:        u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
                    924:        char buf[UGENDEV_BUFSIZE];
                    925:        int endpt, oflags, error;
                    926:        int fd, val;
                    927:
                    928:        if (addr == sc->sc_addr) {
                    929:                switch (xfertype) {
                    930:                case UE_CONTROL:
                    931:                        pipe->methods = &rumpusb_root_ctrl_methods;
                    932:                        break;
                    933:                case UE_INTERRUPT:
                    934:                        pipe->methods = &rumpusb_root_intr_methods;
                    935:                        break;
                    936:                default:
                    937:                        panic("%d not supported", xfertype);
                    938:                        break;
                    939:                }
                    940:        } else {
                    941:                switch (xfertype) {
                    942:                case UE_CONTROL:
                    943:                        pipe->methods = &rumpusb_device_ctrl_methods;
                    944:                        break;
                    945:                case UE_INTERRUPT:
                    946:                case UE_BULK:
1.9       pooka     947:                case UE_ISOCHRONOUS:
1.1       pooka     948:                        pipe->methods = &rumpusb_device_bulk_methods;
                    949:                        endpt = pipe->endpoint->edesc->bEndpointAddress;
                    950:                        if (UE_GET_DIR(endpt) == UE_DIR_IN) {
                    951:                                oflags = O_RDONLY;
                    952:                        } else {
                    953:                                oflags = O_WRONLY;
                    954:                        }
                    955:                        endpt = UE_GET_ADDR(endpt);
                    956:
1.9       pooka     957:                        if (oflags != O_RDONLY && xfertype == UE_ISOCHRONOUS) {
                    958:                                printf("WARNING: faking isoc write open\n");
                    959:                                oflags = O_RDONLY;
                    960:                        }
                    961:
1.1       pooka     962:                        if (sc->sc_fdmodes[endpt] == oflags
                    963:                            || sc->sc_fdmodes[endpt] == O_RDWR)
                    964:                                break;
                    965:
                    966:                        if (sc->sc_fdmodes[endpt] != -1) {
                    967:                                /* XXX: closing from under someone? */
1.15      pooka     968:                                error = rumpuser_close(sc->sc_ugenfd[endpt]);
1.1       pooka     969:                                oflags = O_RDWR;
                    970:                        }
                    971:
1.18    ! christos  972:                        makeugendevstr(sc->sc_devnum, endpt, buf, sizeof(buf));
1.11      pooka     973:                        /* XXX: theoretically should convert oflags */
1.15      pooka     974:                        error = rumpuser_open(buf, oflags, &fd);
                    975:                        if (error != 0) {
1.1       pooka     976:                                return USBD_INVAL; /* XXX: no mapping */
1.9       pooka     977:                        }
1.1       pooka     978:                        val = 100;
1.13      pooka     979:                        if (rumpcomp_ugenhc_ioctl(fd, USB_SET_TIMEOUT, &val,
1.1       pooka     980:                            &error) == -1)
                    981:                                panic("timeout set failed");
                    982:                        sc->sc_ugenfd[endpt] = fd;
                    983:                        sc->sc_fdmodes[endpt] = oflags;
1.9       pooka     984:
1.1       pooka     985:                        break;
                    986:                default:
                    987:                        panic("%d not supported", xfertype);
                    988:                        break;
                    989:
                    990:                }
                    991:        }
                    992:        return 0;
                    993: }
                    994:
                    995: static void
                    996: ugenhc_softint(void *arg)
                    997: {
                    998:
                    999: }
                   1000:
                   1001: static void
                   1002: ugenhc_poll(struct usbd_bus *ubus)
                   1003: {
                   1004:
                   1005: }
                   1006:
                   1007: static usbd_status
                   1008: ugenhc_allocm(struct usbd_bus *bus, usb_dma_t *dma, uint32_t size)
                   1009: {
                   1010:        struct ugenhc_softc *sc = bus->hci_private;
                   1011:
                   1012:        return usb_allocmem(&sc->sc_bus, size, 0, dma);
                   1013: }
                   1014:
                   1015: static void
1.8       pooka    1016: ugenhc_freem(struct usbd_bus *bus, usb_dma_t *dma)
1.1       pooka    1017: {
1.8       pooka    1018:        struct ugenhc_softc *sc = bus->hci_private;
1.1       pooka    1019:
1.8       pooka    1020:        usb_freemem(&sc->sc_bus, dma);
1.1       pooka    1021: }
                   1022:
                   1023: static struct usbd_xfer *
                   1024: ugenhc_allocx(struct usbd_bus *bus)
                   1025: {
                   1026:        usbd_xfer_handle xfer;
                   1027:
                   1028:        xfer = kmem_zalloc(sizeof(struct usbd_xfer), KM_SLEEP);
                   1029:        xfer->busy_free = XFER_BUSY;
                   1030:
                   1031:        return xfer;
                   1032: }
                   1033:
                   1034: static void
                   1035: ugenhc_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
                   1036: {
                   1037:
                   1038:        kmem_free(xfer, sizeof(struct usbd_xfer));
                   1039: }
                   1040:
                   1041: struct ugenhc_pipe {
                   1042:        struct usbd_pipe pipe;
                   1043: };
                   1044:
                   1045: static const struct usbd_bus_methods ugenhc_bus_methods = {
                   1046:        .open_pipe =    ugenhc_open,
                   1047:        .soft_intr =    ugenhc_softint,
                   1048:        .do_poll =      ugenhc_poll,
                   1049:        .allocm =       ugenhc_allocm,
                   1050:        .freem =        ugenhc_freem,
                   1051:        .allocx =       ugenhc_allocx,
                   1052:        .freex =        ugenhc_freex,
                   1053: };
                   1054:
                   1055: static int
1.12      chs      1056: ugenhc_probe(device_t parent, cfdata_t match, void *aux)
1.1       pooka    1057: {
                   1058:        char buf[UGENDEV_BUFSIZE];
                   1059:
1.18    ! christos 1060:        makeugendevstr(match->cf_unit, 0, buf, sizeof(buf));
1.15      pooka    1061:        if (rumpuser_getfileinfo(buf, NULL, NULL) != 0)
1.1       pooka    1062:                return 0;
                   1063:
                   1064:        return 1;
                   1065: }
                   1066:
                   1067: static void
1.12      chs      1068: ugenhc_attach(device_t parent, device_t self, void *aux)
1.1       pooka    1069: {
                   1070:        struct mainbus_attach_args *maa = aux;
                   1071:        struct ugenhc_softc *sc = device_private(self);
                   1072:
                   1073:        aprint_normal("\n");
                   1074:
                   1075:        memset(sc, 0, sizeof(*sc));
                   1076:        memset(&sc->sc_ugenfd, -1, sizeof(sc->sc_ugenfd));
                   1077:        memset(&sc->sc_fdmodes, -1, sizeof(sc->sc_fdmodes));
                   1078:
                   1079:        sc->sc_bus.usbrev = USBREV_2_0;
                   1080:        sc->sc_bus.methods = &ugenhc_bus_methods;
                   1081:        sc->sc_bus.hci_private = sc;
                   1082:        sc->sc_bus.pipe_size = sizeof(struct ugenhc_pipe);
                   1083:        sc->sc_devnum = maa->maa_unit;
                   1084:
                   1085:        config_found(self, &sc->sc_bus, usbctlprint);
                   1086: }

CVSweb <webmaster@jp.NetBSD.org>