File:  [DragonFly] / src / sys / bus / usb / usbdi_util.c
Revision 1.6: download - view: text, annotated - select for diffs
Wed Feb 11 15:17:26 2004 UTC (10 years, 7 months ago) by joerg
Branches: MAIN
CVS tags: HEAD
Add defined(__FreeBSD__) and defined(__DragonFly__) where appropriate

    1: /*
    2:  * $NetBSD: usbdi_util.c,v 1.24 1999/11/17 23:00:50 augustss Exp $
    3:  * $NetBSD: usbdi_util.c,v 1.36 2001/11/13 06:24:57 lukem Exp $
    4:  * $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.31 2003/08/24 17:55:55 obrien Exp $
    5:  * $DragonFly: src/sys/bus/usb/usbdi_util.c,v 1.6 2004/02/11 15:17:26 joerg Exp $
    6:  */
    7: 
    8: /*
    9:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
   10:  * All rights reserved.
   11:  *
   12:  * This code is derived from software contributed to The NetBSD Foundation
   13:  * by Lennart Augustsson (lennart@augustsson.net) at
   14:  * Carlstedt Research & Technology.
   15:  *
   16:  * Redistribution and use in source and binary forms, with or without
   17:  * modification, are permitted provided that the following conditions
   18:  * are met:
   19:  * 1. Redistributions of source code must retain the above copyright
   20:  *    notice, this list of conditions and the following disclaimer.
   21:  * 2. Redistributions in binary form must reproduce the above copyright
   22:  *    notice, this list of conditions and the following disclaimer in the
   23:  *    documentation and/or other materials provided with the distribution.
   24:  * 3. All advertising materials mentioning features or use of this software
   25:  *    must display the following acknowledgement:
   26:  *        This product includes software developed by the NetBSD
   27:  *        Foundation, Inc. and its contributors.
   28:  * 4. Neither the name of The NetBSD Foundation nor the names of its
   29:  *    contributors may be used to endorse or promote products derived
   30:  *    from this software without specific prior written permission.
   31:  *
   32:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   33:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   34:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   35:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   36:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   37:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   38:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   39:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   40:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   41:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   42:  * POSSIBILITY OF SUCH DAMAGE.
   43:  */
   44: 
   45: #include <sys/param.h>
   46: #include <sys/systm.h>
   47: #include <sys/kernel.h>
   48: #include <sys/malloc.h>
   49: #if defined(__NetBSD__) || defined(__OpenBSD__)
   50: #include <sys/proc.h>
   51: #include <sys/device.h>
   52: #elif defined(__FreeBSD__) || defined(__DragonFly__)
   53: #include <sys/bus.h>
   54: #endif
   55: 
   56: #include "usb.h"
   57: #include "usbhid.h"
   58: 
   59: #include "usbdi.h"
   60: #include "usbdi_util.h"
   61: 
   62: #ifdef USB_DEBUG
   63: #define DPRINTF(x)	if (usbdebug) logprintf x
   64: #define DPRINTFN(n,x)	if (usbdebug>(n)) logprintf x
   65: extern int usbdebug;
   66: #else
   67: #define DPRINTF(x)
   68: #define DPRINTFN(n,x)
   69: #endif
   70: 
   71: usbd_status
   72: usbd_get_desc(usbd_device_handle dev, int type, int index, int len, void *desc)
   73: {
   74: 	usb_device_request_t req;
   75: 
   76: 	DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n",
   77: 		    type, index, len));
   78: 
   79: 	req.bmRequestType = UT_READ_DEVICE;
   80: 	req.bRequest = UR_GET_DESCRIPTOR;
   81: 	USETW2(req.wValue, type, index);
   82: 	USETW(req.wIndex, 0);
   83: 	USETW(req.wLength, len);
   84: 	return (usbd_do_request(dev, &req, desc));
   85: }
   86: 
   87: usbd_status
   88: usbd_get_config_desc(usbd_device_handle dev, int confidx,
   89: 		     usb_config_descriptor_t *d)
   90: {
   91: 	usbd_status err;
   92: 
   93: 	DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx));
   94: 	err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
   95: 			    USB_CONFIG_DESCRIPTOR_SIZE, d);
   96: 	if (err)
   97: 		return (err);
   98: 	if (d->bDescriptorType != UDESC_CONFIG) {
   99: 		DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc "
  100: 			     "len=%d type=%d\n",
  101: 			     confidx, d->bLength, d->bDescriptorType));
  102: 		return (USBD_INVAL);
  103: 	}
  104: 	return (USBD_NORMAL_COMPLETION);
  105: }
  106: 
  107: usbd_status
  108: usbd_get_config_desc_full(usbd_device_handle dev, int conf, void *d, int size)
  109: {
  110: 	DPRINTFN(3,("usbd_get_config_desc_full: conf=%d\n", conf));
  111: 	return (usbd_get_desc(dev, UDESC_CONFIG, conf, size, d));
  112: }
  113: 
  114: usbd_status
  115: usbd_get_device_desc(usbd_device_handle dev, usb_device_descriptor_t *d)
  116: {
  117: 	DPRINTFN(3,("usbd_get_device_desc:\n"));
  118: 	return (usbd_get_desc(dev, UDESC_DEVICE,
  119: 			     0, USB_DEVICE_DESCRIPTOR_SIZE, d));
  120: }
  121: 
  122: usbd_status
  123: usbd_get_device_status(usbd_device_handle dev, usb_status_t *st)
  124: {
  125: 	usb_device_request_t req;
  126: 
  127: 	req.bmRequestType = UT_READ_DEVICE;
  128: 	req.bRequest = UR_GET_STATUS;
  129: 	USETW(req.wValue, 0);
  130: 	USETW(req.wIndex, 0);
  131: 	USETW(req.wLength, sizeof(usb_status_t));
  132: 	return (usbd_do_request(dev, &req, st));
  133: }
  134: 
  135: usbd_status
  136: usbd_get_hub_status(usbd_device_handle dev, usb_hub_status_t *st)
  137: {
  138: 	usb_device_request_t req;
  139: 
  140: 	req.bmRequestType = UT_READ_CLASS_DEVICE;
  141: 	req.bRequest = UR_GET_STATUS;
  142: 	USETW(req.wValue, 0);
  143: 	USETW(req.wIndex, 0);
  144: 	USETW(req.wLength, sizeof(usb_hub_status_t));
  145: 	return (usbd_do_request(dev, &req, st));
  146: }
  147: 
  148: usbd_status
  149: usbd_set_address(usbd_device_handle dev, int addr)
  150: {
  151: 	usb_device_request_t req;
  152: 
  153: 	req.bmRequestType = UT_WRITE_DEVICE;
  154: 	req.bRequest = UR_SET_ADDRESS;
  155: 	USETW(req.wValue, addr);
  156: 	USETW(req.wIndex, 0);
  157: 	USETW(req.wLength, 0);
  158: 	return usbd_do_request(dev, &req, 0);
  159: }
  160: 
  161: usbd_status
  162: usbd_get_port_status(usbd_device_handle dev, int port, usb_port_status_t *ps)
  163: {
  164: 	usb_device_request_t req;
  165: 
  166: 	req.bmRequestType = UT_READ_CLASS_OTHER;
  167: 	req.bRequest = UR_GET_STATUS;
  168: 	USETW(req.wValue, 0);
  169: 	USETW(req.wIndex, port);
  170: 	USETW(req.wLength, sizeof *ps);
  171: 	return (usbd_do_request(dev, &req, ps));
  172: }
  173: 
  174: usbd_status
  175: usbd_clear_hub_feature(usbd_device_handle dev, int sel)
  176: {
  177: 	usb_device_request_t req;
  178: 
  179: 	req.bmRequestType = UT_WRITE_CLASS_DEVICE;
  180: 	req.bRequest = UR_CLEAR_FEATURE;
  181: 	USETW(req.wValue, sel);
  182: 	USETW(req.wIndex, 0);
  183: 	USETW(req.wLength, 0);
  184: 	return (usbd_do_request(dev, &req, 0));
  185: }
  186: 
  187: usbd_status
  188: usbd_set_hub_feature(usbd_device_handle dev, int sel)
  189: {
  190: 	usb_device_request_t req;
  191: 
  192: 	req.bmRequestType = UT_WRITE_CLASS_DEVICE;
  193: 	req.bRequest = UR_SET_FEATURE;
  194: 	USETW(req.wValue, sel);
  195: 	USETW(req.wIndex, 0);
  196: 	USETW(req.wLength, 0);
  197: 	return (usbd_do_request(dev, &req, 0));
  198: }
  199: 
  200: usbd_status
  201: usbd_clear_port_feature(usbd_device_handle dev, int port, int sel)
  202: {
  203: 	usb_device_request_t req;
  204: 
  205: 	req.bmRequestType = UT_WRITE_CLASS_OTHER;
  206: 	req.bRequest = UR_CLEAR_FEATURE;
  207: 	USETW(req.wValue, sel);
  208: 	USETW(req.wIndex, port);
  209: 	USETW(req.wLength, 0);
  210: 	return (usbd_do_request(dev, &req, 0));
  211: }
  212: 
  213: usbd_status
  214: usbd_set_port_feature(usbd_device_handle dev, int port, int sel)
  215: {
  216: 	usb_device_request_t req;
  217: 
  218: 	req.bmRequestType = UT_WRITE_CLASS_OTHER;
  219: 	req.bRequest = UR_SET_FEATURE;
  220: 	USETW(req.wValue, sel);
  221: 	USETW(req.wIndex, port);
  222: 	USETW(req.wLength, 0);
  223: 	return (usbd_do_request(dev, &req, 0));
  224: }
  225: 
  226: 
  227: usbd_status
  228: usbd_set_protocol(usbd_interface_handle iface, int report)
  229: {
  230: 	usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
  231: 	usbd_device_handle dev;
  232: 	usb_device_request_t req;
  233: 
  234: 	DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n",
  235: 		     iface, report, id->bInterfaceNumber));
  236: 	if (id == NULL)
  237: 		return (USBD_IOERROR);
  238: 	usbd_interface2device_handle(iface, &dev);
  239: 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  240: 	req.bRequest = UR_SET_PROTOCOL;
  241: 	USETW(req.wValue, report);
  242: 	USETW(req.wIndex, id->bInterfaceNumber);
  243: 	USETW(req.wLength, 0);
  244: 	return (usbd_do_request(dev, &req, 0));
  245: }
  246: 
  247: usbd_status
  248: usbd_set_report(usbd_interface_handle iface, int type, int id, void *data,
  249: 		int len)
  250: {
  251: 	usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  252: 	usbd_device_handle dev;
  253: 	usb_device_request_t req;
  254: 
  255: 	DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
  256: 	if (ifd == NULL)
  257: 		return (USBD_IOERROR);
  258: 	usbd_interface2device_handle(iface, &dev);
  259: 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  260: 	req.bRequest = UR_SET_REPORT;
  261: 	USETW2(req.wValue, type, id);
  262: 	USETW(req.wIndex, ifd->bInterfaceNumber);
  263: 	USETW(req.wLength, len);
  264: 	return (usbd_do_request(dev, &req, data));
  265: }
  266: 
  267: usbd_status
  268: usbd_set_report_async(usbd_interface_handle iface, int type, int id, void *data,
  269: 		      int len)
  270: {
  271: 	usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  272: 	usbd_device_handle dev;
  273: 	usb_device_request_t req;
  274: 
  275: 	DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
  276: 	if (ifd == NULL)
  277: 		return (USBD_IOERROR);
  278: 	usbd_interface2device_handle(iface, &dev);
  279: 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  280: 	req.bRequest = UR_SET_REPORT;
  281: 	USETW2(req.wValue, type, id);
  282: 	USETW(req.wIndex, ifd->bInterfaceNumber);
  283: 	USETW(req.wLength, len);
  284: 	return (usbd_do_request_async(dev, &req, data));
  285: }
  286: 
  287: usbd_status
  288: usbd_get_report(usbd_interface_handle iface, int type, int id, void *data,
  289: 		int len)
  290: {
  291: 	usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  292: 	usbd_device_handle dev;
  293: 	usb_device_request_t req;
  294: 
  295: 	DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
  296: 	if (id == 0)
  297: 		return (USBD_IOERROR);
  298: 	usbd_interface2device_handle(iface, &dev);
  299: 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
  300: 	req.bRequest = UR_GET_REPORT;
  301: 	USETW2(req.wValue, type, id);
  302: 	USETW(req.wIndex, ifd->bInterfaceNumber);
  303: 	USETW(req.wLength, len);
  304: 	return (usbd_do_request(dev, &req, data));
  305: }
  306: 
  307: usbd_status
  308: usbd_set_idle(usbd_interface_handle iface, int duration, int id)
  309: {
  310: 	usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  311: 	usbd_device_handle dev;
  312: 	usb_device_request_t req;
  313: 
  314: 	DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id));
  315: 	if (ifd == NULL)
  316: 		return (USBD_IOERROR);
  317: 	usbd_interface2device_handle(iface, &dev);
  318: 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  319: 	req.bRequest = UR_SET_IDLE;
  320: 	USETW2(req.wValue, duration, id);
  321: 	USETW(req.wIndex, ifd->bInterfaceNumber);
  322: 	USETW(req.wLength, 0);
  323: 	return (usbd_do_request(dev, &req, 0));
  324: }
  325: 
  326: usbd_status
  327: usbd_get_report_descriptor(usbd_device_handle dev, int ifcno,
  328: 			   int size, void *d)
  329: {
  330: 	usb_device_request_t req;
  331: 
  332: 	req.bmRequestType = UT_READ_INTERFACE;
  333: 	req.bRequest = UR_GET_DESCRIPTOR;
  334: 	USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */
  335: 	USETW(req.wIndex, ifcno);
  336: 	USETW(req.wLength, size);
  337: 	return (usbd_do_request(dev, &req, d));
  338: }
  339: 
  340: usb_hid_descriptor_t *
  341: usbd_get_hid_descriptor(usbd_interface_handle ifc)
  342: {
  343: 	usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc);
  344: 	usbd_device_handle dev;
  345: 	usb_config_descriptor_t *cdesc;
  346: 	usb_hid_descriptor_t *hd;
  347: 	char *p, *end;
  348: 
  349: 	if (idesc == NULL)
  350: 		return (0);
  351: 	usbd_interface2device_handle(ifc, &dev);
  352: 	cdesc = usbd_get_config_descriptor(dev);
  353: 
  354: 	p = (char *)idesc + idesc->bLength;
  355: 	end = (char *)cdesc + UGETW(cdesc->wTotalLength);
  356: 
  357: 	for (; p < end; p += hd->bLength) {
  358: 		hd = (usb_hid_descriptor_t *)p;
  359: 		if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID)
  360: 			return (hd);
  361: 		if (hd->bDescriptorType == UDESC_INTERFACE)
  362: 			break;
  363: 	}
  364: 	return (0);
  365: }
  366: 
  367: usbd_status
  368: usbd_read_report_desc(usbd_interface_handle ifc, void **descp, int *sizep,
  369: 		      usb_malloc_type mem)
  370: {
  371: 	usb_interface_descriptor_t *id;
  372: 	usb_hid_descriptor_t *hid;
  373: 	usbd_device_handle dev;
  374: 	usbd_status err;
  375: 
  376: 	usbd_interface2device_handle(ifc, &dev);
  377: 	id = usbd_get_interface_descriptor(ifc);
  378: 	if (id == NULL)
  379: 		return (USBD_INVAL);
  380: 	hid = usbd_get_hid_descriptor(ifc);
  381: 	if (hid == NULL)
  382: 		return (USBD_IOERROR);
  383: 	*sizep = UGETW(hid->descrs[0].wDescriptorLength);
  384: 	*descp = malloc(*sizep, mem, M_NOWAIT);
  385: 	if (*descp == NULL)
  386: 		return (USBD_NOMEM);
  387: 	err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
  388: 					 *sizep, *descp);
  389: 	if (err) {
  390: 		free(*descp, mem);
  391: 		*descp = NULL;
  392: 		return (err);
  393: 	}
  394: 	return (USBD_NORMAL_COMPLETION);
  395: }
  396: 
  397: usbd_status
  398: usbd_get_config(usbd_device_handle dev, u_int8_t *conf)
  399: {
  400: 	usb_device_request_t req;
  401: 
  402: 	req.bmRequestType = UT_READ_DEVICE;
  403: 	req.bRequest = UR_GET_CONFIG;
  404: 	USETW(req.wValue, 0);
  405: 	USETW(req.wIndex, 0);
  406: 	USETW(req.wLength, 1);
  407: 	return (usbd_do_request(dev, &req, conf));
  408: }
  409: 
  410: Static void usbd_bulk_transfer_cb(usbd_xfer_handle xfer,
  411: 				  usbd_private_handle priv, usbd_status status);
  412: Static void
  413: usbd_bulk_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  414: 		      usbd_status status)
  415: {
  416: 	wakeup(xfer);
  417: }
  418: 
  419: usbd_status
  420: usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
  421: 		   u_int16_t flags, u_int32_t timeout, void *buf,
  422: 		   u_int32_t *size, char *lbl)
  423: {
  424: 	usbd_status err;
  425: 	int s, error;
  426: 
  427: 	usbd_setup_xfer(xfer, pipe, 0, buf, *size,
  428: 			flags, timeout, usbd_bulk_transfer_cb);
  429: 	DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
  430: 	s = splusb();		/* don't want callback until tsleep() */
  431: 	err = usbd_transfer(xfer);
  432: 	if (err != USBD_IN_PROGRESS) {
  433: 		splx(s);
  434: 		return (err);
  435: 	}
  436: 	error = tsleep((caddr_t)xfer, PCATCH, lbl, 0);
  437: 	splx(s);
  438: 	if (error) {
  439: 		DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
  440: 		usbd_abort_pipe(pipe);
  441: 		return (USBD_INTERRUPTED);
  442: 	}
  443: 	usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
  444: 	DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
  445: 	if (err) {
  446: 		DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
  447: 		usbd_clear_endpoint_stall(pipe);
  448: 	}
  449: 	return (err);
  450: }
  451: 
  452: Static void usbd_intr_transfer_cb(usbd_xfer_handle xfer,
  453: 				  usbd_private_handle priv, usbd_status status);
  454: Static void
  455: usbd_intr_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  456: 		      usbd_status status)
  457: {
  458: 	wakeup(xfer);
  459: }
  460: 
  461: usbd_status
  462: usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
  463: 		   u_int16_t flags, u_int32_t timeout, void *buf,
  464: 		   u_int32_t *size, char *lbl)
  465: {
  466: 	usbd_status err;
  467: 	int s, error;
  468: 
  469: 	usbd_setup_xfer(xfer, pipe, 0, buf, *size,
  470: 			flags, timeout, usbd_intr_transfer_cb);
  471: 	DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size));
  472: 	s = splusb();		/* don't want callback until tsleep() */
  473: 	err = usbd_transfer(xfer);
  474: 	if (err != USBD_IN_PROGRESS) {
  475: 		splx(s);
  476: 		return (err);
  477: 	}
  478: 	error = tsleep(xfer, PCATCH, lbl, 0);
  479: 	splx(s);
  480: 	if (error) {
  481: 		DPRINTF(("usbd_intr_transfer: tsleep=%d\n", error));
  482: 		usbd_abort_pipe(pipe);
  483: 		return (USBD_INTERRUPTED);
  484: 	}
  485: 	usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
  486: 	DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size));
  487: 	if (err) {
  488: 		DPRINTF(("usbd_intr_transfer: error=%d\n", err));
  489: 		usbd_clear_endpoint_stall(pipe);
  490: 	}
  491: 	return (err);
  492: }
  493: 
  494: void
  495: usb_detach_wait(device_ptr_t dv)
  496: {
  497: 	DPRINTF(("usb_detach_wait: waiting for %s\n", USBDEVPTRNAME(dv)));
  498: 	if (tsleep(dv, 0, "usbdet", hz * 60))
  499: 		printf("usb_detach_wait: %s didn't detach\n",
  500: 		        USBDEVPTRNAME(dv));
  501: 	DPRINTF(("usb_detach_wait: %s done\n", USBDEVPTRNAME(dv)));
  502: }
  503: 
  504: void
  505: usb_detach_wakeup(device_ptr_t dv)
  506: {
  507: 	DPRINTF(("usb_detach_wakeup: for %s\n", USBDEVPTRNAME(dv)));
  508: 	wakeup(dv);
  509: }