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

Annotation of src/sys/dev/usb/usbdi_util.c, Revision 1.77

1.77    ! maxv        1: /*     $NetBSD: usbdi_util.c,v 1.76 2020/02/08 07:53:23 maxv Exp $     */
1.1       augustss    2:
                      3: /*
1.57      mrg         4:  * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
1.1       augustss    5:  * All rights reserved.
                      6:  *
1.5       augustss    7:  * This code is derived from software contributed to The NetBSD Foundation
1.30      augustss    8:  * by Lennart Augustsson (lennart@augustsson.net) at
1.57      mrg         9:  * Carlstedt Research & Technology and Matthew R. Green (mrg@eterna.com.au).
1.1       augustss   10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
                     31:  */
1.36      lukem      32:
                     33: #include <sys/cdefs.h>
1.77    ! maxv       34: __KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.76 2020/02/08 07:53:23 maxv Exp $");
1.63      skrll      35:
                     36: #ifdef _KERNEL_OPT
                     37: #include "opt_usb.h"
                     38: #endif
1.1       augustss   39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/kernel.h>
1.65      skrll      43: #include <sys/kmem.h>
1.1       augustss   44: #include <sys/proc.h>
1.14      augustss   45: #include <sys/device.h>
1.57      mrg        46: #include <sys/bus.h>
1.1       augustss   47:
                     48: #include <dev/usb/usb.h>
                     49: #include <dev/usb/usbhid.h>
                     50: #include <dev/usb/usbdi.h>
1.57      mrg        51: #include <dev/usb/usbdivar.h>
1.1       augustss   52: #include <dev/usb/usbdi_util.h>
1.72      manu       53: #include <dev/usb/usb_quirks.h>
1.63      skrll      54: #include <dev/usb/usbhist.h>
1.1       augustss   55:
1.65      skrll      56: #define        DPRINTF(FMT,A,B,C,D)    USBHIST_LOGN(usbdebug,1,FMT,A,B,C,D)
                     57: #define        DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(usbdebug,N,FMT,A,B,C,D)
1.1       augustss   58:
                     59: usbd_status
1.65      skrll      60: usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void *desc)
1.1       augustss   61: {
                     62:        usb_device_request_t req;
1.72      manu       63:        usbd_status err;
1.1       augustss   64:
1.75      mrg        65:        USBHIST_FUNC();
                     66:        USBHIST_CALLARGS(usbdebug, "type=%jd, index=%jd, len=%jd",
                     67:            type, index, len, 0);
1.26      augustss   68:
1.72      manu       69:        /*
                     70:         * Provide hard-coded configuration descriptors
                     71:         * for devices that may corrupt it. This cannot
                     72:         * be done for device descriptors which are used
                     73:         * to identify the device.
                     74:         */
                     75:        if (type != UDESC_DEVICE &&
                     76:            dev->ud_quirks->uq_flags & UQ_DESC_CORRUPT) {
                     77:                err = usbd_get_desc_fake(dev, type, index, len, desc);
                     78:                goto out;
                     79:        }
                     80:
1.1       augustss   81:        req.bmRequestType = UT_READ_DEVICE;
                     82:        req.bRequest = UR_GET_DESCRIPTOR;
                     83:        USETW2(req.wValue, type, index);
                     84:        USETW(req.wIndex, 0);
                     85:        USETW(req.wLength, len);
1.72      manu       86:        err = usbd_do_request(dev, &req, desc);
                     87:
                     88: out:
                     89:        return err;
1.1       augustss   90: }
                     91:
                     92: usbd_status
1.65      skrll      93: usbd_get_config_desc(struct usbd_device *dev, int confidx,
1.31      augustss   94:                     usb_config_descriptor_t *d)
1.1       augustss   95: {
1.75      mrg        96:        USBHIST_FUNC();
                     97:        USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0);
1.23      augustss   98:        usbd_status err;
1.9       augustss   99:
1.40      augustss  100:        err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
1.26      augustss  101:                            USB_CONFIG_DESCRIPTOR_SIZE, d);
1.23      augustss  102:        if (err)
1.65      skrll     103:                return err;
1.9       augustss  104:        if (d->bDescriptorType != UDESC_CONFIG) {
1.70      pgoyette  105:                DPRINTFN(1, "confidx=%jd, bad desc len=%d type=%d",
1.65      skrll     106:                    confidx, d->bLength, d->bDescriptorType, 0);
                    107:                return USBD_INVAL;
1.9       augustss  108:        }
1.65      skrll     109:        return USBD_NORMAL_COMPLETION;
1.1       augustss  110: }
                    111:
                    112: usbd_status
1.65      skrll     113: usbd_get_config_desc_full(struct usbd_device *dev, int conf, void *d, int size)
1.4       augustss  114: {
1.75      mrg       115:        USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "conf=%jd", conf, 0, 0, 0);
1.65      skrll     116:
                    117:        return usbd_get_desc(dev, UDESC_CONFIG, conf, size, d);
1.4       augustss  118: }
                    119:
                    120: usbd_status
1.65      skrll     121: usbd_get_bos_desc(struct usbd_device *dev, int confidx,
1.64      skrll     122:                     usb_bos_descriptor_t *d)
                    123: {
1.75      mrg       124:        USBHIST_FUNC();
                    125:        USBHIST_CALLARGS(usbdebug, "confidx=%jd", confidx, 0, 0, 0);
1.64      skrll     126:        usbd_status err;
                    127:
                    128:        err = usbd_get_desc(dev, UDESC_BOS, confidx,
                    129:                            USB_BOS_DESCRIPTOR_SIZE, d);
                    130:        if (err)
1.69      skrll     131:                return err;
1.64      skrll     132:        if (d->bDescriptorType != UDESC_BOS) {
1.70      pgoyette  133:                DPRINTFN(1, "confidx=%jd, bad desc len=%d type=%d",
1.65      skrll     134:                    confidx, d->bLength, d->bDescriptorType, 0);
                    135:                return USBD_INVAL;
1.64      skrll     136:        }
1.65      skrll     137:        return USBD_NORMAL_COMPLETION;
1.64      skrll     138: }
                    139:
                    140: usbd_status
1.65      skrll     141: usbd_get_bos_desc_full(struct usbd_device *dev, int conf, void *d, int size)
1.64      skrll     142: {
1.75      mrg       143:        USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "conf=%jd", conf, 0, 0, 0);
1.65      skrll     144:
                    145:        return usbd_get_desc(dev, UDESC_BOS, conf, size, d);
1.64      skrll     146: }
                    147:
                    148: usbd_status
1.65      skrll     149: usbd_get_device_desc(struct usbd_device *dev, usb_device_descriptor_t *d)
1.1       augustss  150: {
1.65      skrll     151:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
                    152:
1.69      skrll     153:        return usbd_get_desc(dev, UDESC_DEVICE,
                    154:                             0, USB_DEVICE_DESCRIPTOR_SIZE, d);
1.1       augustss  155: }
                    156:
1.77    ! maxv      157: /* -------------------------------------------------------------------------- */
        !           158:
1.1       augustss  159: usbd_status
1.65      skrll     160: usbd_get_device_status(struct usbd_device *dev, usb_status_t *st)
1.1       augustss  161: {
1.65      skrll     162:        USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
1.1       augustss  163:        usb_device_request_t req;
                    164:
                    165:        req.bmRequestType = UT_READ_DEVICE;
                    166:        req.bRequest = UR_GET_STATUS;
                    167:        USETW(req.wValue, 0);
                    168:        USETW(req.wIndex, 0);
                    169:        USETW(req.wLength, sizeof(usb_status_t));
1.65      skrll     170:        return usbd_do_request(dev, &req, st);
1.40      augustss  171: }
1.1       augustss  172:
                    173: usbd_status
1.65      skrll     174: usbd_get_hub_status(struct usbd_device *dev, usb_hub_status_t *st)
1.1       augustss  175: {
1.75      mrg       176:        USBHIST_FUNC();
                    177:        USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0);
1.1       augustss  178:        usb_device_request_t req;
                    179:
                    180:        req.bmRequestType = UT_READ_CLASS_DEVICE;
                    181:        req.bRequest = UR_GET_STATUS;
                    182:        USETW(req.wValue, 0);
                    183:        USETW(req.wIndex, 0);
                    184:        USETW(req.wLength, sizeof(usb_hub_status_t));
1.65      skrll     185:        return usbd_do_request(dev, &req, st);
1.40      augustss  186: }
1.1       augustss  187:
                    188: usbd_status
1.65      skrll     189: usbd_get_port_status(struct usbd_device *dev, int port, usb_port_status_t *ps)
1.1       augustss  190: {
1.75      mrg       191:        USBHIST_FUNC();
                    192:        USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd",
                    193:            (uintptr_t)dev, port, 0, 0);
1.1       augustss  194:        usb_device_request_t req;
                    195:
                    196:        req.bmRequestType = UT_READ_CLASS_OTHER;
                    197:        req.bRequest = UR_GET_STATUS;
                    198:        USETW(req.wValue, 0);
                    199:        USETW(req.wIndex, port);
1.65      skrll     200:        USETW(req.wLength, sizeof(*ps));
                    201:        return usbd_do_request(dev, &req, ps);
                    202: }
                    203:
                    204: /* USB 3.1 10.16.2.6, 10.16.2.6.3 */
                    205: usbd_status
                    206: usbd_get_port_status_ext(struct usbd_device *dev, int port,
                    207:     usb_port_status_ext_t *pse)
                    208: {
1.75      mrg       209:        USBHIST_FUNC();
                    210:        USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd",
                    211:            (uintptr_t)dev, port, 0, 0);
1.65      skrll     212:        usb_device_request_t req;
                    213:
                    214:        req.bmRequestType = UT_READ_CLASS_OTHER;
                    215:        req.bRequest = UR_GET_STATUS;
                    216:        USETW2(req.wValue, 0, UR_PST_EXT_PORT_STATUS);
                    217:        USETW(req.wIndex, port);
                    218:        USETW(req.wLength, sizeof(*pse));
1.69      skrll     219:        return usbd_do_request(dev, &req, pse);
1.16      augustss  220: }
                    221:
1.77    ! maxv      222: /* -------------------------------------------------------------------------- */
        !           223:
1.16      augustss  224: usbd_status
1.65      skrll     225: usbd_clear_hub_feature(struct usbd_device *dev, int sel)
1.16      augustss  226: {
1.75      mrg       227:        USBHIST_FUNC();
                    228:        USBHIST_CALLARGS(usbdebug, "dev %#jx sel %jd",
                    229:            (uintptr_t)dev, sel, 0, 0);
1.16      augustss  230:        usb_device_request_t req;
                    231:
                    232:        req.bmRequestType = UT_WRITE_CLASS_DEVICE;
                    233:        req.bRequest = UR_CLEAR_FEATURE;
                    234:        USETW(req.wValue, sel);
                    235:        USETW(req.wIndex, 0);
                    236:        USETW(req.wLength, 0);
1.65      skrll     237:        return usbd_do_request(dev, &req, 0);
1.16      augustss  238: }
                    239:
                    240: usbd_status
1.65      skrll     241: usbd_set_hub_feature(struct usbd_device *dev, int sel)
1.16      augustss  242: {
1.75      mrg       243:        USBHIST_FUNC();
                    244:        USBHIST_CALLARGS(usbdebug,
                    245:            "dev %#jx sel %jd", (uintptr_t)dev, sel, 0, 0);
1.16      augustss  246:        usb_device_request_t req;
                    247:
                    248:        req.bmRequestType = UT_WRITE_CLASS_DEVICE;
                    249:        req.bRequest = UR_SET_FEATURE;
                    250:        USETW(req.wValue, sel);
                    251:        USETW(req.wIndex, 0);
                    252:        USETW(req.wLength, 0);
1.65      skrll     253:        return usbd_do_request(dev, &req, 0);
1.1       augustss  254: }
                    255:
                    256: usbd_status
1.65      skrll     257: usbd_clear_port_feature(struct usbd_device *dev, int port, int sel)
1.1       augustss  258: {
1.75      mrg       259:        USBHIST_FUNC();
                    260:        USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %jd",
                    261:            (uintptr_t)dev, port, sel, 0);
1.1       augustss  262:        usb_device_request_t req;
                    263:
                    264:        req.bmRequestType = UT_WRITE_CLASS_OTHER;
                    265:        req.bRequest = UR_CLEAR_FEATURE;
                    266:        USETW(req.wValue, sel);
                    267:        USETW(req.wIndex, port);
                    268:        USETW(req.wLength, 0);
1.65      skrll     269:        return usbd_do_request(dev, &req, 0);
1.1       augustss  270: }
                    271:
                    272: usbd_status
1.65      skrll     273: usbd_set_port_feature(struct usbd_device *dev, int port, int sel)
1.1       augustss  274: {
1.75      mrg       275:        USBHIST_FUNC();
                    276:        USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd sel %.d",
                    277:            (uintptr_t)dev, sel, 0, 0);
1.1       augustss  278:        usb_device_request_t req;
                    279:
                    280:        req.bmRequestType = UT_WRITE_CLASS_OTHER;
                    281:        req.bRequest = UR_SET_FEATURE;
                    282:        USETW(req.wValue, sel);
                    283:        USETW(req.wIndex, port);
                    284:        USETW(req.wLength, 0);
1.65      skrll     285:        return usbd_do_request(dev, &req, 0);
1.1       augustss  286: }
                    287:
1.39      augustss  288: usbd_status
1.65      skrll     289: usbd_set_port_u1_timeout(struct usbd_device *dev, int port, int timeout)
                    290: {
1.75      mrg       291:        USBHIST_FUNC();
                    292:        USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %.d",
                    293:            (uintptr_t)dev, port, timeout, 0);
1.65      skrll     294:        usb_device_request_t req;
                    295:
                    296:        req.bmRequestType = UT_WRITE_CLASS_OTHER;
                    297:        req.bRequest = UR_SET_FEATURE;
                    298:        USETW(req.wValue, UHF_PORT_U1_TIMEOUT);
                    299:        USETW2(req.wIndex, timeout, port);
                    300:        USETW(req.wLength, 0);
                    301:        return usbd_do_request(dev, &req, 0);
                    302: }
                    303:
                    304: usbd_status
                    305: usbd_set_port_u2_timeout(struct usbd_device *dev, int port, int timeout)
                    306: {
1.75      mrg       307:        USBHIST_FUNC();
                    308:        USBHIST_CALLARGS(usbdebug, "dev %#jx port %jd timeout %jd",
                    309:            (uintptr_t)dev, port, timeout, 0);
1.65      skrll     310:        usb_device_request_t req;
                    311:
                    312:        req.bmRequestType = UT_WRITE_CLASS_OTHER;
                    313:        req.bRequest = UR_SET_FEATURE;
                    314:        USETW(req.wValue, UHF_PORT_U2_TIMEOUT);
                    315:        USETW2(req.wIndex, timeout, port);
                    316:        USETW(req.wLength, 0);
                    317:        return usbd_do_request(dev, &req, 0);
                    318: }
                    319:
                    320: usbd_status
1.76      maxv      321: usbd_clear_endpoint_feature(struct usbd_device *dev, int epaddr, int sel)
                    322: {
                    323:        USBHIST_FUNC();
                    324:        usb_device_request_t req;
                    325:
                    326:        req.bmRequestType = UT_WRITE_ENDPOINT;
                    327:        req.bRequest = UR_CLEAR_FEATURE;
                    328:        USETW(req.wValue, sel);
                    329:        USETW(req.wIndex, epaddr);
                    330:        USETW(req.wLength, 0);
                    331:        return usbd_do_request(dev, &req, 0);
                    332: }
                    333:
1.77    ! maxv      334: /* -------------------------------------------------------------------------- */
        !           335:
        !           336: usbd_status
        !           337: usbd_get_config(struct usbd_device *dev, uint8_t *conf)
        !           338: {
        !           339:        USBHIST_FUNC();
        !           340:        USBHIST_CALLARGS(usbdebug, "dev %#jx", (uintptr_t)dev, 0, 0, 0);
        !           341:        usb_device_request_t req;
        !           342:
        !           343:        req.bmRequestType = UT_READ_DEVICE;
        !           344:        req.bRequest = UR_GET_CONFIG;
        !           345:        USETW(req.wValue, 0);
        !           346:        USETW(req.wIndex, 0);
        !           347:        USETW(req.wLength, 1);
        !           348:        return usbd_do_request(dev, &req, conf);
        !           349: }
        !           350:
        !           351: usbd_status
        !           352: usbd_set_address(struct usbd_device *dev, int addr)
        !           353: {
        !           354:        USBHIST_FUNC();
        !           355:        USBHIST_CALLARGS(usbdebug, "dev %#jx addr %jd",
        !           356:            (uintptr_t)dev, addr, 0, 0);
        !           357:        usb_device_request_t req;
        !           358:
        !           359:        req.bmRequestType = UT_WRITE_DEVICE;
        !           360:        req.bRequest = UR_SET_ADDRESS;
        !           361:        USETW(req.wValue, addr);
        !           362:        USETW(req.wIndex, 0);
        !           363:        USETW(req.wLength, 0);
        !           364:        return usbd_do_request(dev, &req, 0);
        !           365: }
        !           366:
        !           367: usbd_status
        !           368: usbd_set_idle(struct usbd_interface *iface, int duration, int id)
        !           369: {
        !           370:        usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
        !           371:        struct usbd_device *dev;
        !           372:        usb_device_request_t req;
        !           373:
        !           374:        USBHIST_FUNC();
        !           375:        USBHIST_CALLARGS(usbdebug, "duration %jd id %jd", duration, id, 0, 0);
        !           376:
        !           377:        if (ifd == NULL)
        !           378:                return USBD_IOERROR;
        !           379:        usbd_interface2device_handle(iface, &dev);
        !           380:        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
        !           381:        req.bRequest = UR_SET_IDLE;
        !           382:        USETW2(req.wValue, duration, id);
        !           383:        USETW(req.wIndex, ifd->bInterfaceNumber);
        !           384:        USETW(req.wLength, 0);
        !           385:        return usbd_do_request(dev, &req, 0);
        !           386: }
        !           387:
        !           388: /* -------------------------------------------------------------------------- */
        !           389:
1.76      maxv      390: usbd_status
1.65      skrll     391: usbd_get_protocol(struct usbd_interface *iface, uint8_t *report)
1.39      augustss  392: {
                    393:        usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
1.65      skrll     394:        struct usbd_device *dev;
1.39      augustss  395:        usb_device_request_t req;
                    396:
1.75      mrg       397:        USBHIST_FUNC();
                    398:        USBHIST_CALLARGS(usbdebug, "iface=%#jx, endpt=%jd",
                    399:            (uintptr_t)iface, id->bInterfaceNumber, 0, 0);
1.65      skrll     400:
1.39      augustss  401:        if (id == NULL)
1.65      skrll     402:                return USBD_IOERROR;
1.68      maya      403:
1.39      augustss  404:        usbd_interface2device_handle(iface, &dev);
                    405:        req.bmRequestType = UT_READ_CLASS_INTERFACE;
                    406:        req.bRequest = UR_GET_PROTOCOL;
                    407:        USETW(req.wValue, 0);
                    408:        USETW(req.wIndex, id->bInterfaceNumber);
                    409:        USETW(req.wLength, 1);
1.65      skrll     410:        return usbd_do_request(dev, &req, report);
1.39      augustss  411: }
1.1       augustss  412:
                    413: usbd_status
1.65      skrll     414: usbd_set_protocol(struct usbd_interface *iface, int report)
1.1       augustss  415: {
                    416:        usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
1.65      skrll     417:        struct usbd_device *dev;
1.1       augustss  418:        usb_device_request_t req;
                    419:
1.75      mrg       420:        USBHIST_FUNC();
                    421:        USBHIST_CALLARGS(usbdebug, "iface=%#jx, report=%jd, endpt=%jd",
                    422:            (uintptr_t)iface, report, id->bInterfaceNumber, 0);
1.65      skrll     423:
1.67      maya      424:        if (id == NULL)
                    425:                return USBD_IOERROR;
                    426:
1.37      augustss  427:        usbd_interface2device_handle(iface, &dev);
1.1       augustss  428:        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
                    429:        req.bRequest = UR_SET_PROTOCOL;
                    430:        USETW(req.wValue, report);
                    431:        USETW(req.wIndex, id->bInterfaceNumber);
                    432:        USETW(req.wLength, 0);
1.65      skrll     433:        return usbd_do_request(dev, &req, 0);
1.1       augustss  434: }
                    435:
1.77    ! maxv      436: /* -------------------------------------------------------------------------- */
        !           437:
1.1       augustss  438: usbd_status
1.65      skrll     439: usbd_set_report(struct usbd_interface *iface, int type, int id, void *data,
1.31      augustss  440:                int len)
1.1       augustss  441: {
                    442:        usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
1.65      skrll     443:        struct usbd_device *dev;
1.1       augustss  444:        usb_device_request_t req;
                    445:
1.75      mrg       446:        USBHIST_FUNC();
                    447:        USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0);
1.65      skrll     448:
1.23      augustss  449:        if (ifd == NULL)
1.65      skrll     450:                return USBD_IOERROR;
1.37      augustss  451:        usbd_interface2device_handle(iface, &dev);
1.1       augustss  452:        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
                    453:        req.bRequest = UR_SET_REPORT;
1.2       augustss  454:        USETW2(req.wValue, type, id);
                    455:        USETW(req.wIndex, ifd->bInterfaceNumber);
                    456:        USETW(req.wLength, len);
1.65      skrll     457:        return usbd_do_request(dev, &req, data);
1.3       augustss  458: }
                    459:
                    460: usbd_status
1.65      skrll     461: usbd_get_report(struct usbd_interface *iface, int type, int id, void *data,
1.31      augustss  462:                int len)
1.2       augustss  463: {
                    464:        usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
1.65      skrll     465:        struct usbd_device *dev;
1.2       augustss  466:        usb_device_request_t req;
                    467:
1.75      mrg       468:        USBHIST_FUNC(); USBHIST_CALLARGS(usbdebug, "len=%jd", len, 0, 0, 0);
1.65      skrll     469:
1.28      augustss  470:        if (ifd == NULL)
1.65      skrll     471:                return USBD_IOERROR;
1.37      augustss  472:        usbd_interface2device_handle(iface, &dev);
1.2       augustss  473:        req.bmRequestType = UT_READ_CLASS_INTERFACE;
                    474:        req.bRequest = UR_GET_REPORT;
1.1       augustss  475:        USETW2(req.wValue, type, id);
                    476:        USETW(req.wIndex, ifd->bInterfaceNumber);
                    477:        USETW(req.wLength, len);
1.65      skrll     478:        return usbd_do_request(dev, &req, data);
1.1       augustss  479: }
                    480:
                    481: usbd_status
1.65      skrll     482: usbd_get_report_descriptor(struct usbd_device *dev, int ifcno,
1.31      augustss  483:                           int size, void *d)
1.1       augustss  484: {
1.75      mrg       485:        USBHIST_FUNC();
                    486:        USBHIST_CALLARGS(usbdebug, "dev %#jx ifcno %jd size %jd",
                    487:            (uintptr_t)dev, ifcno, size, 0);
1.1       augustss  488:        usb_device_request_t req;
                    489:
                    490:        req.bmRequestType = UT_READ_INTERFACE;
                    491:        req.bRequest = UR_GET_DESCRIPTOR;
1.35      augustss  492:        USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */
1.6       augustss  493:        USETW(req.wIndex, ifcno);
1.1       augustss  494:        USETW(req.wLength, size);
1.65      skrll     495:        return usbd_do_request(dev, &req, d);
1.1       augustss  496: }
                    497:
1.77    ! maxv      498: /* -------------------------------------------------------------------------- */
        !           499:
1.1       augustss  500: usb_hid_descriptor_t *
1.65      skrll     501: usbd_get_hid_descriptor(struct usbd_interface *ifc)
1.1       augustss  502: {
                    503:        usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc);
1.65      skrll     504:        struct usbd_device *dev;
1.1       augustss  505:        usb_config_descriptor_t *cdesc;
                    506:        usb_hid_descriptor_t *hd;
                    507:        char *p, *end;
                    508:
1.23      augustss  509:        if (idesc == NULL)
1.65      skrll     510:                return NULL;
1.41      augustss  511:        usbd_interface2device_handle(ifc, &dev);
1.1       augustss  512:        cdesc = usbd_get_config_descriptor(dev);
                    513:
                    514:        p = (char *)idesc + idesc->bLength;
                    515:        end = (char *)cdesc + UGETW(cdesc->wTotalLength);
                    516:
                    517:        for (; p < end; p += hd->bLength) {
                    518:                hd = (usb_hid_descriptor_t *)p;
1.74      maxv      519:                if (p + hd->bLength <= end &&
                    520:                    hd->bLength >= USB_HID_DESCRIPTOR_SIZE(0) &&
                    521:                    hd->bDescriptorType == UDESC_HID)
1.65      skrll     522:                        return hd;
1.1       augustss  523:                if (hd->bDescriptorType == UDESC_INTERFACE)
                    524:                        break;
                    525:        }
1.65      skrll     526:        return NULL;
1.1       augustss  527: }
                    528:
                    529: usbd_status
1.65      skrll     530: usbd_read_report_desc(struct usbd_interface *ifc, void **descp, int *sizep)
1.1       augustss  531: {
1.6       augustss  532:        usb_interface_descriptor_t *id;
1.1       augustss  533:        usb_hid_descriptor_t *hid;
1.65      skrll     534:        struct usbd_device *dev;
1.23      augustss  535:        usbd_status err;
1.1       augustss  536:
1.37      augustss  537:        usbd_interface2device_handle(ifc, &dev);
1.6       augustss  538:        id = usbd_get_interface_descriptor(ifc);
1.23      augustss  539:        if (id == NULL)
1.65      skrll     540:                return USBD_INVAL;
1.1       augustss  541:        hid = usbd_get_hid_descriptor(ifc);
1.25      augustss  542:        if (hid == NULL)
1.65      skrll     543:                return USBD_IOERROR;
1.1       augustss  544:        *sizep = UGETW(hid->descrs[0].wDescriptorLength);
1.74      maxv      545:        if (*sizep == 0)
                    546:                return USBD_INVAL;
1.65      skrll     547:        *descp = kmem_alloc(*sizep, KM_SLEEP);
1.35      augustss  548:        err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
                    549:                                         *sizep, *descp);
1.23      augustss  550:        if (err) {
1.65      skrll     551:                kmem_free(*descp, *sizep);
1.34      augustss  552:                *descp = NULL;
1.65      skrll     553:                return err;
1.1       augustss  554:        }
1.65      skrll     555:        return USBD_NORMAL_COMPLETION;
1.7       augustss  556: }
                    557:
1.40      augustss  558: usbd_status
1.65      skrll     559: usbd_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
                    560:     uint16_t flags, uint32_t timeout, void *buf, uint32_t *size)
1.10      augustss  561: {
1.23      augustss  562:        usbd_status err;
1.10      augustss  563:
1.75      mrg       564:        USBHIST_FUNC();
                    565:        USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0);
1.63      skrll     566:
1.65      skrll     567:        usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL);
1.61      skrll     568:        err = usbd_sync_transfer_sig(xfer);
1.57      mrg       569:
                    570:        usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
1.70      pgoyette  571:        DPRINTFN(1, "transferred %jd", *size, 0, 0, 0);
1.23      augustss  572:        if (err) {
1.10      augustss  573:                usbd_clear_endpoint_stall(pipe);
                    574:        }
1.70      pgoyette  575:        USBHIST_LOG(usbdebug, "<- done xfer %#jx err %d", (uintptr_t)xfer,
                    576:            err, 0, 0);
1.61      skrll     577:
1.65      skrll     578:        return err;
1.10      augustss  579: }
                    580:
1.42      augustss  581: usbd_status
1.65      skrll     582: usbd_intr_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
                    583:     uint16_t flags, uint32_t timeout, void *buf, uint32_t *size)
1.42      augustss  584: {
                    585:        usbd_status err;
                    586:
1.75      mrg       587:        USBHIST_FUNC();
                    588:        USBHIST_CALLARGS(usbdebug, "start transfer %jd bytes", *size, 0, 0, 0);
1.63      skrll     589:
1.65      skrll     590:        usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL);
1.61      skrll     591:
1.57      mrg       592:        err = usbd_sync_transfer_sig(xfer);
1.61      skrll     593:
1.57      mrg       594:        usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
1.61      skrll     595:
1.70      pgoyette  596:        DPRINTFN(1, "transferred %jd", *size, 0, 0, 0);
1.42      augustss  597:        if (err) {
                    598:                usbd_clear_endpoint_stall(pipe);
                    599:        }
1.70      pgoyette  600:        USBHIST_LOG(usbdebug, "<- done xfer %#jx err %jd", (uintptr_t)xfer,
                    601:            err, 0, 0);
1.63      skrll     602:
1.65      skrll     603:        return err;
1.42      augustss  604: }
                    605:
1.14      augustss  606: void
1.56      mrg       607: usb_detach_waitold(device_t dv)
1.14      augustss  608: {
1.75      mrg       609:        USBHIST_FUNC();
                    610:        USBHIST_CALLARGS(usbdebug, "waiting for dv %#jx",
                    611:            (uintptr_t)dv, 0, 0, 0);
1.65      skrll     612:
1.57      mrg       613:        if (tsleep(dv, PZERO, "usbdet", hz * 60)) /* XXXSMP ok */
1.71      msaitoh   614:                aprint_error_dev(dv, "usb_detach_waitold: didn't detach\n");
1.65      skrll     615:        DPRINTFN(1, "done", 0, 0, 0, 0);
1.40      augustss  616: }
1.14      augustss  617:
                    618: void
1.56      mrg       619: usb_detach_wakeupold(device_t dv)
1.14      augustss  620: {
1.75      mrg       621:        USBHIST_FUNC();
                    622:        USBHIST_CALLARGS(usbdebug, "for dv %#jx", (uintptr_t)dv, 0, 0, 0);
1.65      skrll     623:
1.57      mrg       624:        wakeup(dv); /* XXXSMP ok */
1.40      augustss  625: }
1.38      augustss  626:
1.48      drochner  627: const usb_cdc_descriptor_t *
1.65      skrll     628: usb_find_desc(struct usbd_device *dev, int type, int subtype)
1.38      augustss  629: {
1.41      augustss  630:        usbd_desc_iter_t iter;
1.48      drochner  631:        const usb_cdc_descriptor_t *desc;
1.41      augustss  632:
                    633:        usb_desc_iter_init(dev, &iter);
                    634:        for (;;) {
1.48      drochner  635:                desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter);
1.41      augustss  636:                if (!desc || (desc->bDescriptorType == type &&
1.48      drochner  637:                              (subtype == USBD_CDCSUBTYPE_ANY ||
1.41      augustss  638:                               subtype == desc->bDescriptorSubtype)))
                    639:                        break;
1.38      augustss  640:        }
1.41      augustss  641:        return desc;
1.38      augustss  642: }
1.43      itohy     643:
                    644: /* same as usb_find_desc(), but searches only in the specified interface. */
1.48      drochner  645: const usb_cdc_descriptor_t *
1.65      skrll     646: usb_find_desc_if(struct usbd_device *dev, int type, int subtype,
1.43      itohy     647:                 usb_interface_descriptor_t *id)
                    648: {
                    649:        usbd_desc_iter_t iter;
1.48      drochner  650:        const usb_cdc_descriptor_t *desc;
1.43      itohy     651:
1.54      christos  652:        if (id == NULL)
                    653:                return usb_find_desc(dev, type, subtype);
                    654:
1.43      itohy     655:        usb_desc_iter_init(dev, &iter);
                    656:
                    657:        iter.cur = (void *)id;          /* start from the interface desc */
                    658:        usb_desc_iter_next(&iter);      /* and skip it */
                    659:
1.48      drochner  660:        while ((desc = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter))
                    661:               != NULL) {
1.43      itohy     662:                if (desc->bDescriptorType == UDESC_INTERFACE) {
                    663:                        /* we ran into the next interface --- not found */
                    664:                        return NULL;
                    665:                }
                    666:                if (desc->bDescriptorType == type &&
1.48      drochner  667:                    (subtype == USBD_CDCSUBTYPE_ANY ||
1.43      itohy     668:                     subtype == desc->bDescriptorSubtype))
                    669:                        break;
                    670:        }
                    671:        return desc;
                    672: }

CVSweb <webmaster@jp.NetBSD.org>