usb_device.c revision 224777
1285809Sscottl/* $FreeBSD: head/sys/dev/usb/usb_device.c 224777 2011-08-11 11:30:21Z hselasky $ */ 2285809Sscottl/*- 3285809Sscottl * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4285809Sscottl * 5285809Sscottl * Redistribution and use in source and binary forms, with or without 6285809Sscottl * modification, are permitted provided that the following conditions 7285809Sscottl * are met: 8285809Sscottl * 1. Redistributions of source code must retain the above copyright 9285809Sscottl * notice, this list of conditions and the following disclaimer. 10285809Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11285809Sscottl * notice, this list of conditions and the following disclaimer in the 12285809Sscottl * documentation and/or other materials provided with the distribution. 13285809Sscottl * 14285809Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15285809Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16285809Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17285809Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18285809Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19285809Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20285809Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21285809Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22285809Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23285809Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24285809Sscottl * SUCH DAMAGE. 25285809Sscottl */ 26285809Sscottl 27285809Sscottl#include <sys/stdint.h> 28285809Sscottl#include <sys/stddef.h> 29285809Sscottl#include <sys/param.h> 30285809Sscottl#include <sys/queue.h> 31285809Sscottl#include <sys/types.h> 32285809Sscottl#include <sys/systm.h> 33285809Sscottl#include <sys/kernel.h> 34285809Sscottl#include <sys/bus.h> 35285809Sscottl#include <sys/module.h> 36285809Sscottl#include <sys/lock.h> 37285809Sscottl#include <sys/mutex.h> 38285809Sscottl#include <sys/condvar.h> 39285809Sscottl#include <sys/sysctl.h> 40285809Sscottl#include <sys/sx.h> 41285809Sscottl#include <sys/unistd.h> 42285809Sscottl#include <sys/callout.h> 43285809Sscottl#include <sys/malloc.h> 44285809Sscottl#include <sys/priv.h> 45285809Sscottl#include <sys/conf.h> 46285809Sscottl#include <sys/fcntl.h> 47285809Sscottl 48285809Sscottl#include <dev/usb/usb.h> 49285809Sscottl#include <dev/usb/usbdi.h> 50285809Sscottl#include <dev/usb/usbdi_util.h> 51285809Sscottl#include <dev/usb/usb_ioctl.h> 52285809Sscottl 53285809Sscottl#if USB_HAVE_UGEN 54285809Sscottl#include <sys/sbuf.h> 55285809Sscottl#endif 56285809Sscottl 57285809Sscottl#include "usbdevs.h" 58285809Sscottl 59285809Sscottl#define USB_DEBUG_VAR usb_debug 60285809Sscottl 61285809Sscottl#include <dev/usb/usb_core.h> 62285809Sscottl#include <dev/usb/usb_debug.h> 63285809Sscottl#include <dev/usb/usb_process.h> 64285809Sscottl#include <dev/usb/usb_device.h> 65285809Sscottl#include <dev/usb/usb_busdma.h> 66285809Sscottl#include <dev/usb/usb_transfer.h> 67285809Sscottl#include <dev/usb/usb_request.h> 68285809Sscottl#include <dev/usb/usb_dynamic.h> 69285809Sscottl#include <dev/usb/usb_hub.h> 70285809Sscottl#include <dev/usb/usb_util.h> 71285809Sscottl#include <dev/usb/usb_msctest.h> 72285809Sscottl#if USB_HAVE_UGEN 73285809Sscottl#include <dev/usb/usb_dev.h> 74285809Sscottl#include <dev/usb/usb_generic.h> 75285809Sscottl#endif 76285809Sscottl 77285809Sscottl#include <dev/usb/quirk/usb_quirk.h> 78285809Sscottl 79285809Sscottl#include <dev/usb/usb_controller.h> 80285809Sscottl#include <dev/usb/usb_bus.h> 81285809Sscottl 82285809Sscottl/* function prototypes */ 83285809Sscottl 84285809Sscottlstatic void usb_init_endpoint(struct usb_device *, uint8_t, 85285809Sscottl struct usb_endpoint_descriptor *, 86285809Sscottl struct usb_endpoint_ss_comp_descriptor *, 87285809Sscottl struct usb_endpoint *); 88285809Sscottlstatic void usb_unconfigure(struct usb_device *, uint8_t); 89285809Sscottlstatic void usb_detach_device_sub(struct usb_device *, device_t *, 90285809Sscottl char **, uint8_t); 91285809Sscottlstatic uint8_t usb_probe_and_attach_sub(struct usb_device *, 92285809Sscottl struct usb_attach_arg *); 93285809Sscottlstatic void usb_init_attach_arg(struct usb_device *, 94285809Sscottl struct usb_attach_arg *); 95285809Sscottlstatic void usb_suspend_resume_sub(struct usb_device *, device_t, 96285809Sscottl uint8_t); 97285809Sscottlstatic void usbd_clear_stall_proc(struct usb_proc_msg *_pm); 98285809Sscottlstatic usb_error_t usb_config_parse(struct usb_device *, uint8_t, uint8_t); 99285809Sscottlstatic void usbd_set_device_strings(struct usb_device *); 100285809Sscottl#if USB_HAVE_DEVCTL 101285809Sscottlstatic void usb_notify_addq(const char *type, struct usb_device *); 102285809Sscottl#endif 103285809Sscottl#if USB_HAVE_UGEN 104285809Sscottlstatic void usb_fifo_free_wrap(struct usb_device *, uint8_t, uint8_t); 105285809Sscottlstatic void usb_cdev_create(struct usb_device *); 106285809Sscottlstatic void usb_cdev_free(struct usb_device *); 107285809Sscottl#endif 108285809Sscottl 109285809Sscottl/* This variable is global to allow easy access to it: */ 110285809Sscottl 111285809Sscottlint usb_template = 0; 112285809Sscottl 113285809SscottlTUNABLE_INT("hw.usb.usb_template", &usb_template); 114285809SscottlSYSCTL_INT(_hw_usb, OID_AUTO, template, CTLFLAG_RW, 115285809Sscottl &usb_template, 0, "Selected USB device side template"); 116285809Sscottl 117285809Sscottl/* English is default language */ 118285809Sscottl 119285809Sscottlstatic int usb_lang_id = 0x0009; 120285809Sscottlstatic int usb_lang_mask = 0x00FF; 121285809Sscottl 122285809SscottlTUNABLE_INT("hw.usb.usb_lang_id", &usb_lang_id); 123285809SscottlSYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_id, CTLFLAG_RW, 124285809Sscottl &usb_lang_id, 0, "Preferred USB language ID"); 125285809Sscottl 126285809SscottlTUNABLE_INT("hw.usb.usb_lang_mask", &usb_lang_mask); 127285809SscottlSYSCTL_INT(_hw_usb, OID_AUTO, usb_lang_mask, CTLFLAG_RW, 128285809Sscottl &usb_lang_mask, 0, "Preferred USB language mask"); 129285809Sscottl 130285809Sscottlstatic const char* statestr[USB_STATE_MAX] = { 131285809Sscottl [USB_STATE_DETACHED] = "DETACHED", 132285809Sscottl [USB_STATE_ATTACHED] = "ATTACHED", 133285809Sscottl [USB_STATE_POWERED] = "POWERED", 134285809Sscottl [USB_STATE_ADDRESSED] = "ADDRESSED", 135285809Sscottl [USB_STATE_CONFIGURED] = "CONFIGURED", 136285809Sscottl}; 137285809Sscottl 138285809Sscottlconst char * 139285809Sscottlusb_statestr(enum usb_dev_state state) 140285809Sscottl{ 141285809Sscottl return ((state < USB_STATE_MAX) ? statestr[state] : "UNKNOWN"); 142285809Sscottl} 143285809Sscottl 144285809Sscottlconst char * 145285809Sscottlusb_get_manufacturer(struct usb_device *udev) 146285809Sscottl{ 147285809Sscottl return (udev->manufacturer ? udev->manufacturer : "Unknown"); 148285809Sscottl} 149285809Sscottl 150285809Sscottlconst char * 151285809Sscottlusb_get_product(struct usb_device *udev) 152285809Sscottl{ 153285809Sscottl return (udev->product ? udev->product : ""); 154285809Sscottl} 155285809Sscottl 156285809Sscottlconst char * 157285809Sscottlusb_get_serial(struct usb_device *udev) 158285809Sscottl{ 159285809Sscottl return (udev->serial ? udev->serial : ""); 160285809Sscottl} 161285809Sscottl 162285809Sscottl/*------------------------------------------------------------------------* 163285809Sscottl * usbd_get_ep_by_addr 164285809Sscottl * 165285809Sscottl * This function searches for an USB ep by endpoint address and 166285809Sscottl * direction. 167285809Sscottl * 168285809Sscottl * Returns: 169285809Sscottl * NULL: Failure 170285809Sscottl * Else: Success 171285809Sscottl *------------------------------------------------------------------------*/ 172285809Sscottlstruct usb_endpoint * 173285809Sscottlusbd_get_ep_by_addr(struct usb_device *udev, uint8_t ea_val) 174285809Sscottl{ 175285809Sscottl struct usb_endpoint *ep = udev->endpoints; 176285809Sscottl struct usb_endpoint *ep_end = udev->endpoints + udev->endpoints_max; 177285809Sscottl enum { 178285809Sscottl EA_MASK = (UE_DIR_IN | UE_DIR_OUT | UE_ADDR), 179285809Sscottl }; 180285809Sscottl 181285809Sscottl /* 182285809Sscottl * According to the USB specification not all bits are used 183285809Sscottl * for the endpoint address. Keep defined bits only: 184285809Sscottl */ 185285809Sscottl ea_val &= EA_MASK; 186285809Sscottl 187285809Sscottl /* 188285809Sscottl * Iterate accross all the USB endpoints searching for a match 189285809Sscottl * based on the endpoint address: 190285809Sscottl */ 191285809Sscottl for (; ep != ep_end; ep++) { 192285809Sscottl 193285809Sscottl if (ep->edesc == NULL) { 194285809Sscottl continue; 195285809Sscottl } 196285809Sscottl /* do the mask and check the value */ 197285809Sscottl if ((ep->edesc->bEndpointAddress & EA_MASK) == ea_val) { 198285809Sscottl goto found; 199285809Sscottl } 200285809Sscottl } 201285809Sscottl 202285809Sscottl /* 203285809Sscottl * The default endpoint is always present and is checked separately: 204285809Sscottl */ 205285809Sscottl if ((udev->ctrl_ep.edesc) && 206285809Sscottl ((udev->ctrl_ep.edesc->bEndpointAddress & EA_MASK) == ea_val)) { 207285809Sscottl ep = &udev->ctrl_ep; 208285809Sscottl goto found; 209285809Sscottl } 210285809Sscottl return (NULL); 211285809Sscottl 212285809Sscottlfound: 213285809Sscottl return (ep); 214285809Sscottl} 215285809Sscottl 216285809Sscottl/*------------------------------------------------------------------------* 217285809Sscottl * usbd_get_endpoint 218285809Sscottl * 219285809Sscottl * This function searches for an USB endpoint based on the information 220285809Sscottl * given by the passed "struct usb_config" pointer. 221285809Sscottl * 222285809Sscottl * Return values: 223285809Sscottl * NULL: No match. 224285809Sscottl * Else: Pointer to "struct usb_endpoint". 225285809Sscottl *------------------------------------------------------------------------*/ 226285809Sscottlstruct usb_endpoint * 227285809Sscottlusbd_get_endpoint(struct usb_device *udev, uint8_t iface_index, 228285809Sscottl const struct usb_config *setup) 229285809Sscottl{ 230285809Sscottl struct usb_endpoint *ep = udev->endpoints; 231285809Sscottl struct usb_endpoint *ep_end = udev->endpoints + udev->endpoints_max; 232285809Sscottl uint8_t index = setup->ep_index; 233285809Sscottl uint8_t ea_mask; 234285809Sscottl uint8_t ea_val; 235285809Sscottl uint8_t type_mask; 236285809Sscottl uint8_t type_val; 237285809Sscottl 238285809Sscottl DPRINTFN(10, "udev=%p iface_index=%d address=0x%x " 239285809Sscottl "type=0x%x dir=0x%x index=%d\n", 240285809Sscottl udev, iface_index, setup->endpoint, 241285809Sscottl setup->type, setup->direction, setup->ep_index); 242285809Sscottl 243285809Sscottl /* check USB mode */ 244285809Sscottl 245285809Sscottl if (setup->usb_mode != USB_MODE_DUAL && 246285809Sscottl udev->flags.usb_mode != setup->usb_mode) { 247285809Sscottl /* wrong mode - no endpoint */ 248285809Sscottl return (NULL); 249285809Sscottl } 250285809Sscottl 251285809Sscottl /* setup expected endpoint direction mask and value */ 252285809Sscottl 253285809Sscottl if (setup->direction == UE_DIR_RX) { 254285809Sscottl ea_mask = (UE_DIR_IN | UE_DIR_OUT); 255285809Sscottl ea_val = (udev->flags.usb_mode == USB_MODE_DEVICE) ? 256285809Sscottl UE_DIR_OUT : UE_DIR_IN; 257285809Sscottl } else if (setup->direction == UE_DIR_TX) { 258285809Sscottl ea_mask = (UE_DIR_IN | UE_DIR_OUT); 259285809Sscottl ea_val = (udev->flags.usb_mode == USB_MODE_DEVICE) ? 260285809Sscottl UE_DIR_IN : UE_DIR_OUT; 261285809Sscottl } else if (setup->direction == UE_DIR_ANY) { 262285809Sscottl /* match any endpoint direction */ 263285809Sscottl ea_mask = 0; 264285809Sscottl ea_val = 0; 265285809Sscottl } else { 266285809Sscottl /* match the given endpoint direction */ 267285809Sscottl ea_mask = (UE_DIR_IN | UE_DIR_OUT); 268285809Sscottl ea_val = (setup->direction & (UE_DIR_IN | UE_DIR_OUT)); 269285809Sscottl } 270285809Sscottl 271285809Sscottl /* setup expected endpoint address */ 272285809Sscottl 273285809Sscottl if (setup->endpoint == UE_ADDR_ANY) { 274285809Sscottl /* match any endpoint address */ 275285809Sscottl } else { 276285809Sscottl /* match the given endpoint address */ 277285809Sscottl ea_mask |= UE_ADDR; 278285809Sscottl ea_val |= (setup->endpoint & UE_ADDR); 279285809Sscottl } 280285809Sscottl 281285809Sscottl /* setup expected endpoint type */ 282285809Sscottl 283285809Sscottl if (setup->type == UE_BULK_INTR) { 284285809Sscottl /* this will match BULK and INTERRUPT endpoints */ 285285809Sscottl type_mask = 2; 286285809Sscottl type_val = 2; 287285809Sscottl } else if (setup->type == UE_TYPE_ANY) { 288285809Sscottl /* match any endpoint type */ 289285809Sscottl type_mask = 0; 290285809Sscottl type_val = 0; 291285809Sscottl } else { 292285809Sscottl /* match the given endpoint type */ 293285809Sscottl type_mask = UE_XFERTYPE; 294285809Sscottl type_val = (setup->type & UE_XFERTYPE); 295285809Sscottl } 296285809Sscottl 297285809Sscottl /* 298285809Sscottl * Iterate accross all the USB endpoints searching for a match 299285809Sscottl * based on the endpoint address. Note that we are searching 300285809Sscottl * the endpoints from the beginning of the "udev->endpoints" array. 301285809Sscottl */ 302285809Sscottl for (; ep != ep_end; ep++) { 303285809Sscottl 304285809Sscottl if ((ep->edesc == NULL) || 305285809Sscottl (ep->iface_index != iface_index)) { 306285809Sscottl continue; 307285809Sscottl } 308285809Sscottl /* do the masks and check the values */ 309285809Sscottl 310285809Sscottl if (((ep->edesc->bEndpointAddress & ea_mask) == ea_val) && 311285809Sscottl ((ep->edesc->bmAttributes & type_mask) == type_val)) { 312285809Sscottl if (!index--) { 313285809Sscottl goto found; 314285809Sscottl } 315285809Sscottl } 316285809Sscottl } 317285809Sscottl 318285809Sscottl /* 319285809Sscottl * Match against default endpoint last, so that "any endpoint", "any 320285809Sscottl * address" and "any direction" returns the first endpoint of the 321285809Sscottl * interface. "iface_index" and "direction" is ignored: 322285809Sscottl */ 323285809Sscottl if ((udev->ctrl_ep.edesc) && 324285809Sscottl ((udev->ctrl_ep.edesc->bEndpointAddress & ea_mask) == ea_val) && 325285809Sscottl ((udev->ctrl_ep.edesc->bmAttributes & type_mask) == type_val) && 326285809Sscottl (!index)) { 327285809Sscottl ep = &udev->ctrl_ep; 328285809Sscottl goto found; 329285809Sscottl } 330285809Sscottl return (NULL); 331285809Sscottl 332285809Sscottlfound: 333285809Sscottl return (ep); 334285809Sscottl} 335285809Sscottl 336285809Sscottl/*------------------------------------------------------------------------* 337285809Sscottl * usbd_interface_count 338285809Sscottl * 339285809Sscottl * This function stores the number of USB interfaces excluding 340285809Sscottl * alternate settings, which the USB config descriptor reports into 341285809Sscottl * the unsigned 8-bit integer pointed to by "count". 342285809Sscottl * 343285809Sscottl * Returns: 344285809Sscottl * 0: Success 345285809Sscottl * Else: Failure 346285809Sscottl *------------------------------------------------------------------------*/ 347285809Sscottlusb_error_t 348285809Sscottlusbd_interface_count(struct usb_device *udev, uint8_t *count) 349285809Sscottl{ 350285809Sscottl if (udev->cdesc == NULL) { 351285809Sscottl *count = 0; 352285809Sscottl return (USB_ERR_NOT_CONFIGURED); 353285809Sscottl } 354285809Sscottl *count = udev->ifaces_max; 355285809Sscottl return (USB_ERR_NORMAL_COMPLETION); 356285809Sscottl} 357285809Sscottl 358285809Sscottl 359285809Sscottl/*------------------------------------------------------------------------* 360285809Sscottl * usb_init_endpoint 361285809Sscottl * 362285809Sscottl * This function will initialise the USB endpoint structure pointed to by 363285809Sscottl * the "endpoint" argument. The structure pointed to by "endpoint" must be 364285809Sscottl * zeroed before calling this function. 365285809Sscottl *------------------------------------------------------------------------*/ 366285809Sscottlstatic void 367285809Sscottlusb_init_endpoint(struct usb_device *udev, uint8_t iface_index, 368285809Sscottl struct usb_endpoint_descriptor *edesc, 369285809Sscottl struct usb_endpoint_ss_comp_descriptor *ecomp, 370285809Sscottl struct usb_endpoint *ep) 371285809Sscottl{ 372285809Sscottl struct usb_bus_methods *methods; 373285809Sscottl 374285809Sscottl methods = udev->bus->methods; 375285809Sscottl 376285809Sscottl (methods->endpoint_init) (udev, edesc, ep); 377285809Sscottl 378285809Sscottl /* initialise USB endpoint structure */ 379285809Sscottl ep->edesc = edesc; 380285809Sscottl ep->ecomp = ecomp; 381285809Sscottl ep->iface_index = iface_index; 382285809Sscottl TAILQ_INIT(&ep->endpoint_q.head); 383285809Sscottl ep->endpoint_q.command = &usbd_pipe_start; 384285809Sscottl 385285809Sscottl /* the pipe is not supported by the hardware */ 386285809Sscottl if (ep->methods == NULL) 387285809Sscottl return; 388285809Sscottl 389285809Sscottl /* clear stall, if any */ 390285809Sscottl if (methods->clear_stall != NULL) { 391285809Sscottl USB_BUS_LOCK(udev->bus); 392285809Sscottl (methods->clear_stall) (udev, ep); 393285809Sscottl USB_BUS_UNLOCK(udev->bus); 394285809Sscottl } 395285809Sscottl} 396285809Sscottl 397285809Sscottl/*-----------------------------------------------------------------------* 398285809Sscottl * usb_endpoint_foreach 399285809Sscottl * 400285809Sscottl * This function will iterate all the USB endpoints except the control 401285809Sscottl * endpoint. This function is NULL safe. 402285809Sscottl * 403285809Sscottl * Return values: 404285809Sscottl * NULL: End of USB endpoints 405285809Sscottl * Else: Pointer to next USB endpoint 406285809Sscottl *------------------------------------------------------------------------*/ 407285809Sscottlstruct usb_endpoint * 408285809Sscottlusb_endpoint_foreach(struct usb_device *udev, struct usb_endpoint *ep) 409285809Sscottl{ 410285809Sscottl struct usb_endpoint *ep_end; 411285809Sscottl 412285809Sscottl /* be NULL safe */ 413285809Sscottl if (udev == NULL) 414285809Sscottl return (NULL); 415285809Sscottl 416285809Sscottl ep_end = udev->endpoints + udev->endpoints_max; 417285809Sscottl 418285809Sscottl /* get next endpoint */ 419285809Sscottl if (ep == NULL) 420285809Sscottl ep = udev->endpoints; 421285809Sscottl else 422285809Sscottl ep++; 423285809Sscottl 424285809Sscottl /* find next allocated ep */ 425285809Sscottl while (ep != ep_end) { 426285809Sscottl if (ep->edesc != NULL) 427285809Sscottl return (ep); 428285809Sscottl ep++; 429285809Sscottl } 430285809Sscottl return (NULL); 431285809Sscottl} 432285809Sscottl 433285809Sscottl/*------------------------------------------------------------------------* 434285809Sscottl * usb_unconfigure 435285809Sscottl * 436285809Sscottl * This function will free all USB interfaces and USB endpoints belonging 437285809Sscottl * to an USB device. 438285809Sscottl * 439285809Sscottl * Flag values, see "USB_UNCFG_FLAG_XXX". 440285809Sscottl *------------------------------------------------------------------------*/ 441285809Sscottlstatic void 442285809Sscottlusb_unconfigure(struct usb_device *udev, uint8_t flag) 443285809Sscottl{ 444285809Sscottl uint8_t do_unlock; 445285809Sscottl 446285809Sscottl /* automatic locking */ 447285809Sscottl if (usbd_enum_is_locked(udev)) { 448285809Sscottl do_unlock = 0; 449285809Sscottl } else { 450285809Sscottl do_unlock = 1; 451285809Sscottl usbd_enum_lock(udev); 452285809Sscottl } 453285809Sscottl 454285809Sscottl /* detach all interface drivers */ 455285809Sscottl usb_detach_device(udev, USB_IFACE_INDEX_ANY, flag); 456285809Sscottl 457285809Sscottl#if USB_HAVE_UGEN 458285809Sscottl /* free all FIFOs except control endpoint FIFOs */ 459285809Sscottl usb_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, flag); 460285809Sscottl 461285809Sscottl /* 462285809Sscottl * Free all cdev's, if any. 463285809Sscottl */ 464285809Sscottl usb_cdev_free(udev); 465285809Sscottl#endif 466285809Sscottl 467285809Sscottl#if USB_HAVE_COMPAT_LINUX 468285809Sscottl /* free Linux compat device, if any */ 469285809Sscottl if (udev->linux_endpoint_start) { 470285809Sscottl usb_linux_free_device(udev); 471285809Sscottl udev->linux_endpoint_start = NULL; 472285809Sscottl } 473285809Sscottl#endif 474285809Sscottl 475285809Sscottl usb_config_parse(udev, USB_IFACE_INDEX_ANY, USB_CFG_FREE); 476285809Sscottl 477285809Sscottl /* free "cdesc" after "ifaces" and "endpoints", if any */ 478285809Sscottl if (udev->cdesc != NULL) { 479285809Sscottl if (udev->flags.usb_mode != USB_MODE_DEVICE) 480285809Sscottl free(udev->cdesc, M_USB); 481285809Sscottl udev->cdesc = NULL; 482285809Sscottl } 483285809Sscottl /* set unconfigured state */ 484285809Sscottl udev->curr_config_no = USB_UNCONFIG_NO; 485285809Sscottl udev->curr_config_index = USB_UNCONFIG_INDEX; 486285809Sscottl 487285809Sscottl if (do_unlock) 488285809Sscottl usbd_enum_unlock(udev); 489285809Sscottl} 490285809Sscottl 491285809Sscottl/*------------------------------------------------------------------------* 492285809Sscottl * usbd_set_config_index 493285809Sscottl * 494285809Sscottl * This function selects configuration by index, independent of the 495285809Sscottl * actual configuration number. This function should not be used by 496285809Sscottl * USB drivers. 497285809Sscottl * 498285809Sscottl * Returns: 499285809Sscottl * 0: Success 500285809Sscottl * Else: Failure 501285809Sscottl *------------------------------------------------------------------------*/ 502285809Sscottlusb_error_t 503285809Sscottlusbd_set_config_index(struct usb_device *udev, uint8_t index) 504285809Sscottl{ 505285809Sscottl struct usb_status ds; 506285809Sscottl struct usb_config_descriptor *cdp; 507285809Sscottl uint16_t power; 508285809Sscottl uint16_t max_power; 509285809Sscottl uint8_t selfpowered; 510285809Sscottl uint8_t do_unlock; 511285809Sscottl usb_error_t err; 512285809Sscottl 513285809Sscottl DPRINTFN(6, "udev=%p index=%d\n", udev, index); 514285809Sscottl 515285809Sscottl /* automatic locking */ 516285809Sscottl if (usbd_enum_is_locked(udev)) { 517285809Sscottl do_unlock = 0; 518285809Sscottl } else { 519285809Sscottl do_unlock = 1; 520285809Sscottl usbd_enum_lock(udev); 521285809Sscottl } 522285809Sscottl 523285809Sscottl usb_unconfigure(udev, 0); 524285809Sscottl 525285809Sscottl if (index == USB_UNCONFIG_INDEX) { 526285809Sscottl /* 527285809Sscottl * Leave unallocated when unconfiguring the 528285809Sscottl * device. "usb_unconfigure()" will also reset 529285809Sscottl * the current config number and index. 530285809Sscottl */ 531285809Sscottl err = usbd_req_set_config(udev, NULL, USB_UNCONFIG_NO); 532285809Sscottl if (udev->state == USB_STATE_CONFIGURED) 533285809Sscottl usb_set_device_state(udev, USB_STATE_ADDRESSED); 534285809Sscottl goto done; 535285809Sscottl } 536285809Sscottl /* get the full config descriptor */ 537285809Sscottl if (udev->flags.usb_mode == USB_MODE_DEVICE) { 538285809Sscottl /* save some memory */ 539285809Sscottl err = usbd_req_get_descriptor_ptr(udev, &cdp, 540285809Sscottl (UDESC_CONFIG << 8) | index); 541285809Sscottl } else { 542285809Sscottl /* normal request */ 543285809Sscottl err = usbd_req_get_config_desc_full(udev, 544285809Sscottl NULL, &cdp, M_USB, index); 545285809Sscottl } 546285809Sscottl if (err) { 547285809Sscottl goto done; 548285809Sscottl } 549285809Sscottl /* set the new config descriptor */ 550285809Sscottl 551285809Sscottl udev->cdesc = cdp; 552285809Sscottl 553285809Sscottl /* Figure out if the device is self or bus powered. */ 554285809Sscottl selfpowered = 0; 555285809Sscottl if ((!udev->flags.uq_bus_powered) && 556285809Sscottl (cdp->bmAttributes & UC_SELF_POWERED) && 557285809Sscottl (udev->flags.usb_mode == USB_MODE_HOST)) { 558285809Sscottl /* May be self powered. */ 559285809Sscottl if (cdp->bmAttributes & UC_BUS_POWERED) { 560285809Sscottl /* Must ask device. */ 561285809Sscottl err = usbd_req_get_device_status(udev, NULL, &ds); 562285809Sscottl if (err) { 563285809Sscottl DPRINTFN(0, "could not read " 564285809Sscottl "device status: %s\n", 565285809Sscottl usbd_errstr(err)); 566285809Sscottl } else if (UGETW(ds.wStatus) & UDS_SELF_POWERED) { 567285809Sscottl selfpowered = 1; 568285809Sscottl } 569285809Sscottl DPRINTF("status=0x%04x \n", 570285809Sscottl UGETW(ds.wStatus)); 571285809Sscottl } else 572285809Sscottl selfpowered = 1; 573285809Sscottl } 574285809Sscottl DPRINTF("udev=%p cdesc=%p (addr %d) cno=%d attr=0x%02x, " 575285809Sscottl "selfpowered=%d, power=%d\n", 576285809Sscottl udev, cdp, 577285809Sscottl udev->address, cdp->bConfigurationValue, cdp->bmAttributes, 578285809Sscottl selfpowered, cdp->bMaxPower * 2); 579285809Sscottl 580285809Sscottl /* Check if we have enough power. */ 581285809Sscottl power = cdp->bMaxPower * 2; 582285809Sscottl 583285809Sscottl if (udev->parent_hub) { 584285809Sscottl max_power = udev->parent_hub->hub->portpower; 585285809Sscottl } else { 586285809Sscottl max_power = USB_MAX_POWER; 587285809Sscottl } 588285809Sscottl 589285809Sscottl if (power > max_power) { 590285809Sscottl DPRINTFN(0, "power exceeded %d > %d\n", power, max_power); 591285809Sscottl err = USB_ERR_NO_POWER; 592285809Sscottl goto done; 593285809Sscottl } 594285809Sscottl /* Only update "self_powered" in USB Host Mode */ 595285809Sscottl if (udev->flags.usb_mode == USB_MODE_HOST) { 596285809Sscottl udev->flags.self_powered = selfpowered; 597285809Sscottl } 598285809Sscottl udev->power = power; 599285809Sscottl udev->curr_config_no = cdp->bConfigurationValue; 600285809Sscottl udev->curr_config_index = index; 601285809Sscottl usb_set_device_state(udev, USB_STATE_CONFIGURED); 602285809Sscottl 603285809Sscottl /* Set the actual configuration value. */ 604285809Sscottl err = usbd_req_set_config(udev, NULL, cdp->bConfigurationValue); 605285809Sscottl if (err) { 606285809Sscottl goto done; 607285809Sscottl } 608285809Sscottl 609285809Sscottl err = usb_config_parse(udev, USB_IFACE_INDEX_ANY, USB_CFG_ALLOC); 610285809Sscottl if (err) { 611285809Sscottl goto done; 612285809Sscottl } 613285809Sscottl 614285809Sscottl err = usb_config_parse(udev, USB_IFACE_INDEX_ANY, USB_CFG_INIT); 615285809Sscottl if (err) { 616285809Sscottl goto done; 617285809Sscottl } 618285809Sscottl 619285809Sscottl#if USB_HAVE_UGEN 620285809Sscottl /* create device nodes for each endpoint */ 621285809Sscottl usb_cdev_create(udev); 622285809Sscottl#endif 623285809Sscottl 624285809Sscottldone: 625285809Sscottl DPRINTF("error=%s\n", usbd_errstr(err)); 626285809Sscottl if (err) { 627285809Sscottl usb_unconfigure(udev, 0); 628285809Sscottl } 629285809Sscottl if (do_unlock) 630285809Sscottl usbd_enum_unlock(udev); 631285809Sscottl return (err); 632285809Sscottl} 633285809Sscottl 634285809Sscottl/*------------------------------------------------------------------------* 635285809Sscottl * usb_config_parse 636285809Sscottl * 637285809Sscottl * This function will allocate and free USB interfaces and USB endpoints, 638285809Sscottl * parse the USB configuration structure and initialise the USB endpoints 639285809Sscottl * and interfaces. If "iface_index" is not equal to 640285809Sscottl * "USB_IFACE_INDEX_ANY" then the "cmd" parameter is the 641285809Sscottl * alternate_setting to be selected for the given interface. Else the 642285809Sscottl * "cmd" parameter is defined by "USB_CFG_XXX". "iface_index" can be 643285809Sscottl * "USB_IFACE_INDEX_ANY" or a valid USB interface index. This function 644285809Sscottl * is typically called when setting the configuration or when setting 645285809Sscottl * an alternate interface. 646285809Sscottl * 647285809Sscottl * Returns: 648285809Sscottl * 0: Success 649285809Sscottl * Else: Failure 650285809Sscottl *------------------------------------------------------------------------*/ 651285809Sscottlstatic usb_error_t 652285809Sscottlusb_config_parse(struct usb_device *udev, uint8_t iface_index, uint8_t cmd) 653285809Sscottl{ 654285809Sscottl struct usb_idesc_parse_state ips; 655285809Sscottl struct usb_interface_descriptor *id; 656285809Sscottl struct usb_endpoint_descriptor *ed; 657285809Sscottl struct usb_interface *iface; 658285809Sscottl struct usb_endpoint *ep; 659285809Sscottl usb_error_t err; 660285809Sscottl uint8_t ep_curr; 661285809Sscottl uint8_t ep_max; 662285809Sscottl uint8_t temp; 663285809Sscottl uint8_t do_init; 664285809Sscottl uint8_t alt_index; 665285809Sscottl 666285809Sscottl if (iface_index != USB_IFACE_INDEX_ANY) { 667285809Sscottl /* parameter overload */ 668285809Sscottl alt_index = cmd; 669285809Sscottl cmd = USB_CFG_INIT; 670285809Sscottl } else { 671285809Sscottl /* not used */ 672285809Sscottl alt_index = 0; 673285809Sscottl } 674285809Sscottl 675285809Sscottl err = 0; 676285809Sscottl 677285809Sscottl DPRINTFN(5, "iface_index=%d cmd=%d\n", 678285809Sscottl iface_index, cmd); 679285809Sscottl 680285809Sscottl if (cmd == USB_CFG_FREE) 681285809Sscottl goto cleanup; 682285809Sscottl 683285809Sscottl if (cmd == USB_CFG_INIT) { 684285809Sscottl sx_assert(&udev->enum_sx, SA_LOCKED); 685285809Sscottl 686285809Sscottl /* check for in-use endpoints */ 687285809Sscottl 688285809Sscottl ep = udev->endpoints; 689285809Sscottl ep_max = udev->endpoints_max; 690285809Sscottl while (ep_max--) { 691285809Sscottl /* look for matching endpoints */ 692285809Sscottl if ((iface_index == USB_IFACE_INDEX_ANY) || 693285809Sscottl (iface_index == ep->iface_index)) { 694285809Sscottl if (ep->refcount_alloc != 0) { 695285809Sscottl /* 696285809Sscottl * This typically indicates a 697285809Sscottl * more serious error. 698285809Sscottl */ 699285809Sscottl err = USB_ERR_IN_USE; 700285809Sscottl } else { 701285809Sscottl /* reset endpoint */ 702285809Sscottl memset(ep, 0, sizeof(*ep)); 703285809Sscottl /* make sure we don't zero the endpoint again */ 704285809Sscottl ep->iface_index = USB_IFACE_INDEX_ANY; 705285809Sscottl } 706285809Sscottl } 707285809Sscottl ep++; 708285809Sscottl } 709285809Sscottl 710285809Sscottl if (err) 711285809Sscottl return (err); 712285809Sscottl } 713285809Sscottl 714285809Sscottl memset(&ips, 0, sizeof(ips)); 715285809Sscottl 716285809Sscottl ep_curr = 0; 717285809Sscottl ep_max = 0; 718285809Sscottl 719285809Sscottl while ((id = usb_idesc_foreach(udev->cdesc, &ips))) { 720285809Sscottl 721285809Sscottl /* check for interface overflow */ 722285809Sscottl if (ips.iface_index == USB_IFACE_MAX) 723285809Sscottl break; /* crazy */ 724285809Sscottl 725285809Sscottl iface = udev->ifaces + ips.iface_index; 726285809Sscottl 727285809Sscottl /* check for specific interface match */ 728285809Sscottl 729285809Sscottl if (cmd == USB_CFG_INIT) { 730285809Sscottl if ((iface_index != USB_IFACE_INDEX_ANY) && 731285809Sscottl (iface_index != ips.iface_index)) { 732285809Sscottl /* wrong interface */ 733285809Sscottl do_init = 0; 734285809Sscottl } else if (alt_index != ips.iface_index_alt) { 735285809Sscottl /* wrong alternate setting */ 736285809Sscottl do_init = 0; 737285809Sscottl } else { 738285809Sscottl /* initialise interface */ 739285809Sscottl do_init = 1; 740285809Sscottl } 741285809Sscottl } else 742285809Sscottl do_init = 0; 743285809Sscottl 744285809Sscottl /* check for new interface */ 745285809Sscottl if (ips.iface_index_alt == 0) { 746285809Sscottl /* update current number of endpoints */ 747285809Sscottl ep_curr = ep_max; 748285809Sscottl } 749285809Sscottl /* check for init */ 750285809Sscottl if (do_init) { 751285809Sscottl /* setup the USB interface structure */ 752285809Sscottl iface->idesc = id; 753285809Sscottl /* default setting */ 754285809Sscottl iface->parent_iface_index = USB_IFACE_INDEX_ANY; 755285809Sscottl /* set alternate index */ 756285809Sscottl iface->alt_index = alt_index; 757285809Sscottl } 758285809Sscottl 759285809Sscottl DPRINTFN(5, "found idesc nendpt=%d\n", id->bNumEndpoints); 760285809Sscottl 761285809Sscottl ed = (struct usb_endpoint_descriptor *)id; 762285809Sscottl 763285809Sscottl temp = ep_curr; 764285809Sscottl 765285809Sscottl /* iterate all the endpoint descriptors */ 766285809Sscottl while ((ed = usb_edesc_foreach(udev->cdesc, ed))) { 767285809Sscottl 768285809Sscottl if (temp == USB_EP_MAX) 769285809Sscottl break; /* crazy */ 770285809Sscottl 771285809Sscottl ep = udev->endpoints + temp; 772285809Sscottl 773285809Sscottl if (do_init) { 774285809Sscottl void *ecomp; 775285809Sscottl 776285809Sscottl ecomp = usb_ed_comp_foreach(udev->cdesc, (void *)ed); 777285809Sscottl if (ecomp != NULL) 778285809Sscottl DPRINTFN(5, "Found endpoint companion descriptor\n"); 779285809Sscottl 780285809Sscottl usb_init_endpoint(udev, 781285809Sscottl ips.iface_index, ed, ecomp, ep); 782285809Sscottl } 783285809Sscottl 784285809Sscottl temp ++; 785285809Sscottl 786285809Sscottl /* find maximum number of endpoints */ 787285809Sscottl if (ep_max < temp) 788285809Sscottl ep_max = temp; 789285809Sscottl 790285809Sscottl /* optimalisation */ 791285809Sscottl id = (struct usb_interface_descriptor *)ed; 792285809Sscottl } 793285809Sscottl } 794285809Sscottl 795285809Sscottl /* NOTE: It is valid to have no interfaces and no endpoints! */ 796285809Sscottl 797285809Sscottl if (cmd == USB_CFG_ALLOC) { 798285809Sscottl udev->ifaces_max = ips.iface_index; 799285809Sscottl udev->ifaces = NULL; 800285809Sscottl if (udev->ifaces_max != 0) { 801285809Sscottl udev->ifaces = malloc(sizeof(*iface) * udev->ifaces_max, 802285809Sscottl M_USB, M_WAITOK | M_ZERO); 803285809Sscottl if (udev->ifaces == NULL) { 804285809Sscottl err = USB_ERR_NOMEM; 805285809Sscottl goto done; 806285809Sscottl } 807285809Sscottl } 808285809Sscottl if (ep_max != 0) { 809285809Sscottl udev->endpoints = malloc(sizeof(*ep) * ep_max, 810285809Sscottl M_USB, M_WAITOK | M_ZERO); 811285809Sscottl if (udev->endpoints == NULL) { 812285809Sscottl err = USB_ERR_NOMEM; 813285809Sscottl goto done; 814285809Sscottl } 815285809Sscottl } else { 816285809Sscottl udev->endpoints = NULL; 817285809Sscottl } 818285809Sscottl USB_BUS_LOCK(udev->bus); 819285809Sscottl udev->endpoints_max = ep_max; 820285809Sscottl /* reset any ongoing clear-stall */ 821285809Sscottl udev->ep_curr = NULL; 822285809Sscottl USB_BUS_UNLOCK(udev->bus); 823285809Sscottl } 824285809Sscottl 825285809Sscottldone: 826285809Sscottl if (err) { 827285809Sscottl if (cmd == USB_CFG_ALLOC) { 828285809Sscottlcleanup: 829285809Sscottl USB_BUS_LOCK(udev->bus); 830285809Sscottl udev->endpoints_max = 0; 831285809Sscottl /* reset any ongoing clear-stall */ 832285809Sscottl udev->ep_curr = NULL; 833285809Sscottl USB_BUS_UNLOCK(udev->bus); 834285809Sscottl 835285809Sscottl /* cleanup */ 836285809Sscottl if (udev->ifaces != NULL) 837285809Sscottl free(udev->ifaces, M_USB); 838285809Sscottl if (udev->endpoints != NULL) 839285809Sscottl free(udev->endpoints, M_USB); 840285809Sscottl 841285809Sscottl udev->ifaces = NULL; 842285809Sscottl udev->endpoints = NULL; 843285809Sscottl udev->ifaces_max = 0; 844285809Sscottl } 845285809Sscottl } 846285809Sscottl return (err); 847285809Sscottl} 848285809Sscottl 849285809Sscottl/*------------------------------------------------------------------------* 850285809Sscottl * usbd_set_alt_interface_index 851285809Sscottl * 852285809Sscottl * This function will select an alternate interface index for the 853285809Sscottl * given interface index. The interface should not be in use when this 854285809Sscottl * function is called. That means there should not be any open USB 855285809Sscottl * transfers. Else an error is returned. If the alternate setting is 856285809Sscottl * already set this function will simply return success. This function 857285809Sscottl * is called in Host mode and Device mode! 858285809Sscottl * 859285809Sscottl * Returns: 860285809Sscottl * 0: Success 861285809Sscottl * Else: Failure 862285809Sscottl *------------------------------------------------------------------------*/ 863285809Sscottlusb_error_t 864285809Sscottlusbd_set_alt_interface_index(struct usb_device *udev, 865285809Sscottl uint8_t iface_index, uint8_t alt_index) 866285809Sscottl{ 867285809Sscottl struct usb_interface *iface = usbd_get_iface(udev, iface_index); 868285809Sscottl usb_error_t err; 869285809Sscottl uint8_t do_unlock; 870285809Sscottl 871285809Sscottl /* automatic locking */ 872285809Sscottl if (usbd_enum_is_locked(udev)) { 873285809Sscottl do_unlock = 0; 874285809Sscottl } else { 875285809Sscottl do_unlock = 1; 876285809Sscottl usbd_enum_lock(udev); 877285809Sscottl } 878285809Sscottl if (iface == NULL) { 879285809Sscottl err = USB_ERR_INVAL; 880285809Sscottl goto done; 881285809Sscottl } 882285809Sscottl if (iface->alt_index == alt_index) { 883285809Sscottl /* 884285809Sscottl * Optimise away duplicate setting of 885285809Sscottl * alternate setting in USB Host Mode! 886285809Sscottl */ 887285809Sscottl err = 0; 888285809Sscottl goto done; 889285809Sscottl } 890285809Sscottl#if USB_HAVE_UGEN 891285809Sscottl /* 892285809Sscottl * Free all generic FIFOs for this interface, except control 893285809Sscottl * endpoint FIFOs: 894285809Sscottl */ 895285809Sscottl usb_fifo_free_wrap(udev, iface_index, 0); 896285809Sscottl#endif 897285809Sscottl 898285809Sscottl err = usb_config_parse(udev, iface_index, alt_index); 899285809Sscottl if (err) { 900285809Sscottl goto done; 901285809Sscottl } 902285809Sscottl if (iface->alt_index != alt_index) { 903285809Sscottl /* the alternate setting does not exist */ 904285809Sscottl err = USB_ERR_INVAL; 905285809Sscottl goto done; 906285809Sscottl } 907285809Sscottl 908285809Sscottl err = usbd_req_set_alt_interface_no(udev, NULL, iface_index, 909285809Sscottl iface->idesc->bAlternateSetting); 910285809Sscottl 911285809Sscottldone: 912285809Sscottl if (do_unlock) 913285809Sscottl usbd_enum_unlock(udev); 914285809Sscottl 915285809Sscottl return (err); 916285809Sscottl} 917285809Sscottl 918285809Sscottl/*------------------------------------------------------------------------* 919285809Sscottl * usbd_set_endpoint_stall 920285809Sscottl * 921285809Sscottl * This function is used to make a BULK or INTERRUPT endpoint send 922285809Sscottl * STALL tokens in USB device mode. 923285809Sscottl * 924285809Sscottl * Returns: 925285809Sscottl * 0: Success 926285809Sscottl * Else: Failure 927285809Sscottl *------------------------------------------------------------------------*/ 928285809Sscottlusb_error_t 929285809Sscottlusbd_set_endpoint_stall(struct usb_device *udev, struct usb_endpoint *ep, 930285809Sscottl uint8_t do_stall) 931285809Sscottl{ 932285809Sscottl struct usb_xfer *xfer; 933285809Sscottl uint8_t et; 934285809Sscottl uint8_t was_stalled; 935285809Sscottl 936285809Sscottl if (ep == NULL) { 937285809Sscottl /* nothing to do */ 938285809Sscottl DPRINTF("Cannot find endpoint\n"); 939285809Sscottl /* 940285809Sscottl * Pretend that the clear or set stall request is 941285809Sscottl * successful else some USB host stacks can do 942285809Sscottl * strange things, especially when a control endpoint 943285809Sscottl * stalls. 944285809Sscottl */ 945285809Sscottl return (0); 946285809Sscottl } 947285809Sscottl et = (ep->edesc->bmAttributes & UE_XFERTYPE); 948285809Sscottl 949285809Sscottl if ((et != UE_BULK) && 950285809Sscottl (et != UE_INTERRUPT)) { 951285809Sscottl /* 952285809Sscottl * Should not stall control 953285809Sscottl * nor isochronous endpoints. 954285809Sscottl */ 955285809Sscottl DPRINTF("Invalid endpoint\n"); 956285809Sscottl return (0); 957285809Sscottl } 958285809Sscottl USB_BUS_LOCK(udev->bus); 959285809Sscottl 960285809Sscottl /* store current stall state */ 961285809Sscottl was_stalled = ep->is_stalled; 962285809Sscottl 963285809Sscottl /* check for no change */ 964285809Sscottl if (was_stalled && do_stall) { 965285809Sscottl /* if the endpoint is already stalled do nothing */ 966285809Sscottl USB_BUS_UNLOCK(udev->bus); 967285809Sscottl DPRINTF("No change\n"); 968285809Sscottl return (0); 969285809Sscottl } 970285809Sscottl /* set stalled state */ 971285809Sscottl ep->is_stalled = 1; 972285809Sscottl 973285809Sscottl if (do_stall || (!was_stalled)) { 974285809Sscottl if (!was_stalled) { 975285809Sscottl /* lookup the current USB transfer, if any */ 976285809Sscottl xfer = ep->endpoint_q.curr; 977285809Sscottl } else { 978285809Sscottl xfer = NULL; 979285809Sscottl } 980285809Sscottl 981285809Sscottl /* 982285809Sscottl * If "xfer" is non-NULL the "set_stall" method will 983285809Sscottl * complete the USB transfer like in case of a timeout 984285809Sscottl * setting the error code "USB_ERR_STALLED". 985285809Sscottl */ 986285809Sscottl (udev->bus->methods->set_stall) (udev, xfer, ep, &do_stall); 987285809Sscottl } 988285809Sscottl if (!do_stall) { 989285809Sscottl ep->toggle_next = 0; /* reset data toggle */ 990285809Sscottl ep->is_stalled = 0; /* clear stalled state */ 991285809Sscottl 992285809Sscottl (udev->bus->methods->clear_stall) (udev, ep); 993285809Sscottl 994285809Sscottl /* start up the current or next transfer, if any */ 995285809Sscottl usb_command_wrapper(&ep->endpoint_q, ep->endpoint_q.curr); 996285809Sscottl } 997285809Sscottl USB_BUS_UNLOCK(udev->bus); 998285809Sscottl return (0); 999285809Sscottl} 1000285809Sscottl 1001285809Sscottl/*------------------------------------------------------------------------* 1002285809Sscottl * usb_reset_iface_endpoints - used in USB device side mode 1003285809Sscottl *------------------------------------------------------------------------*/ 1004285809Sscottlusb_error_t 1005285809Sscottlusb_reset_iface_endpoints(struct usb_device *udev, uint8_t iface_index) 1006285809Sscottl{ 1007285809Sscottl struct usb_endpoint *ep; 1008285809Sscottl struct usb_endpoint *ep_end; 1009285809Sscottl 1010285809Sscottl ep = udev->endpoints; 1011285809Sscottl ep_end = udev->endpoints + udev->endpoints_max; 1012285809Sscottl 1013285809Sscottl for (; ep != ep_end; ep++) { 1014285809Sscottl 1015285809Sscottl if ((ep->edesc == NULL) || 1016285809Sscottl (ep->iface_index != iface_index)) { 1017285809Sscottl continue; 1018285809Sscottl } 1019285809Sscottl /* simulate a clear stall from the peer */ 1020285809Sscottl usbd_set_endpoint_stall(udev, ep, 0); 1021285809Sscottl } 1022285809Sscottl return (0); 1023285809Sscottl} 1024285809Sscottl 1025285809Sscottl/*------------------------------------------------------------------------* 1026285809Sscottl * usb_detach_device_sub 1027285809Sscottl * 1028285809Sscottl * This function will try to detach an USB device. If it fails a panic 1029285809Sscottl * will result. 1030285809Sscottl * 1031285809Sscottl * Flag values, see "USB_UNCFG_FLAG_XXX". 1032285809Sscottl *------------------------------------------------------------------------*/ 1033285809Sscottlstatic void 1034285809Sscottlusb_detach_device_sub(struct usb_device *udev, device_t *ppdev, 1035285809Sscottl char **ppnpinfo, uint8_t flag) 1036285809Sscottl{ 1037285809Sscottl device_t dev; 1038285809Sscottl char *pnpinfo; 1039285809Sscottl int err; 1040285809Sscottl 1041285809Sscottl dev = *ppdev; 1042285809Sscottl if (dev) { 1043285809Sscottl /* 1044285809Sscottl * NOTE: It is important to clear "*ppdev" before deleting 1045285809Sscottl * the child due to some device methods being called late 1046285809Sscottl * during the delete process ! 1047285809Sscottl */ 1048285809Sscottl *ppdev = NULL; 1049285809Sscottl 1050285809Sscottl device_printf(dev, "at %s, port %d, addr %d " 1051285809Sscottl "(disconnected)\n", 1052285809Sscottl device_get_nameunit(udev->parent_dev), 1053285809Sscottl udev->port_no, udev->address); 1054285809Sscottl 1055285809Sscottl if (device_is_attached(dev)) { 1056285809Sscottl if (udev->flags.peer_suspended) { 1057285809Sscottl err = DEVICE_RESUME(dev); 1058285809Sscottl if (err) { 1059285809Sscottl device_printf(dev, "Resume failed\n"); 1060285809Sscottl } 1061285809Sscottl } 1062285809Sscottl if (device_detach(dev)) { 1063285809Sscottl goto error; 1064285809Sscottl } 1065285809Sscottl } 1066285809Sscottl if (device_delete_child(udev->parent_dev, dev)) { 1067285809Sscottl goto error; 1068285809Sscottl } 1069285809Sscottl } 1070285809Sscottl 1071285809Sscottl pnpinfo = *ppnpinfo; 1072285809Sscottl if (pnpinfo != NULL) { 1073285809Sscottl *ppnpinfo = NULL; 1074285809Sscottl free(pnpinfo, M_USBDEV); 1075285809Sscottl } 1076285809Sscottl return; 1077285809Sscottl 1078285809Sscottlerror: 1079285809Sscottl /* Detach is not allowed to fail in the USB world */ 1080285809Sscottl panic("usb_detach_device_sub: A USB driver would not detach\n"); 1081285809Sscottl} 1082285809Sscottl 1083285809Sscottl/*------------------------------------------------------------------------* 1084285809Sscottl * usb_detach_device 1085285809Sscottl * 1086285809Sscottl * The following function will detach the matching interfaces. 1087285809Sscottl * This function is NULL safe. 1088285809Sscottl * 1089285809Sscottl * Flag values, see "USB_UNCFG_FLAG_XXX". 1090285809Sscottl *------------------------------------------------------------------------*/ 1091285809Sscottlvoid 1092285809Sscottlusb_detach_device(struct usb_device *udev, uint8_t iface_index, 1093285809Sscottl uint8_t flag) 1094285809Sscottl{ 1095285809Sscottl struct usb_interface *iface; 1096285809Sscottl uint8_t i; 1097285809Sscottl 1098285809Sscottl if (udev == NULL) { 1099285809Sscottl /* nothing to do */ 1100285809Sscottl return; 1101285809Sscottl } 1102285809Sscottl DPRINTFN(4, "udev=%p\n", udev); 1103285809Sscottl 1104285809Sscottl sx_assert(&udev->enum_sx, SA_LOCKED); 1105285809Sscottl 1106285809Sscottl /* 1107285809Sscottl * First detach the child to give the child's detach routine a 1108285809Sscottl * chance to detach the sub-devices in the correct order. 1109285809Sscottl * Then delete the child using "device_delete_child()" which 1110285809Sscottl * will detach all sub-devices from the bottom and upwards! 1111285809Sscottl */ 1112285809Sscottl if (iface_index != USB_IFACE_INDEX_ANY) { 1113285809Sscottl i = iface_index; 1114285809Sscottl iface_index = i + 1; 1115285809Sscottl } else { 1116285809Sscottl i = 0; 1117285809Sscottl iface_index = USB_IFACE_MAX; 1118285809Sscottl } 1119285809Sscottl 1120285809Sscottl /* do the detach */ 1121285809Sscottl 1122285809Sscottl for (; i != iface_index; i++) { 1123285809Sscottl 1124285809Sscottl iface = usbd_get_iface(udev, i); 1125285809Sscottl if (iface == NULL) { 1126285809Sscottl /* looks like the end of the USB interfaces */ 1127285809Sscottl break; 1128285809Sscottl } 1129285809Sscottl usb_detach_device_sub(udev, &iface->subdev, 1130285809Sscottl &iface->pnpinfo, flag); 1131285809Sscottl } 1132285809Sscottl} 1133285809Sscottl 1134285809Sscottl/*------------------------------------------------------------------------* 1135285809Sscottl * usb_probe_and_attach_sub 1136285809Sscottl * 1137285809Sscottl * Returns: 1138285809Sscottl * 0: Success 1139285809Sscottl * Else: Failure 1140285809Sscottl *------------------------------------------------------------------------*/ 1141285809Sscottlstatic uint8_t 1142285809Sscottlusb_probe_and_attach_sub(struct usb_device *udev, 1143285809Sscottl struct usb_attach_arg *uaa) 1144285809Sscottl{ 1145285809Sscottl struct usb_interface *iface; 1146285809Sscottl device_t dev; 1147285809Sscottl int err; 1148285809Sscottl 1149285809Sscottl iface = uaa->iface; 1150285809Sscottl if (iface->parent_iface_index != USB_IFACE_INDEX_ANY) { 1151285809Sscottl /* leave interface alone */ 1152285809Sscottl return (0); 1153285809Sscottl } 1154285809Sscottl dev = iface->subdev; 1155285809Sscottl if (dev) { 1156285809Sscottl 1157285809Sscottl /* clean up after module unload */ 1158285809Sscottl 1159285809Sscottl if (device_is_attached(dev)) { 1160285809Sscottl /* already a device there */ 1161285809Sscottl return (0); 1162285809Sscottl } 1163285809Sscottl /* clear "iface->subdev" as early as possible */ 1164285809Sscottl 1165285809Sscottl iface->subdev = NULL; 1166285809Sscottl 1167285809Sscottl if (device_delete_child(udev->parent_dev, dev)) { 1168285809Sscottl 1169285809Sscottl /* 1170285809Sscottl * Panic here, else one can get a double call 1171285809Sscottl * to device_detach(). USB devices should 1172285809Sscottl * never fail on detach! 1173285809Sscottl */ 1174285809Sscottl panic("device_delete_child() failed\n"); 1175285809Sscottl } 1176285809Sscottl } 1177285809Sscottl if (uaa->temp_dev == NULL) { 1178285809Sscottl 1179285809Sscottl /* create a new child */ 1180285809Sscottl uaa->temp_dev = device_add_child(udev->parent_dev, NULL, -1); 1181285809Sscottl if (uaa->temp_dev == NULL) { 1182285809Sscottl device_printf(udev->parent_dev, 1183285809Sscottl "Device creation failed\n"); 1184285809Sscottl return (1); /* failure */ 1185285809Sscottl } 1186285809Sscottl device_set_ivars(uaa->temp_dev, uaa); 1187285809Sscottl device_quiet(uaa->temp_dev); 1188285809Sscottl } 1189285809Sscottl /* 1190285809Sscottl * Set "subdev" before probe and attach so that "devd" gets 1191285809Sscottl * the information it needs. 1192285809Sscottl */ 1193285809Sscottl iface->subdev = uaa->temp_dev; 1194285809Sscottl 1195285809Sscottl if (device_probe_and_attach(iface->subdev) == 0) { 1196285809Sscottl /* 1197285809Sscottl * The USB attach arguments are only available during probe 1198285809Sscottl * and attach ! 1199285809Sscottl */ 1200285809Sscottl uaa->temp_dev = NULL; 1201285809Sscottl device_set_ivars(iface->subdev, NULL); 1202285809Sscottl 1203285809Sscottl if (udev->flags.peer_suspended) { 1204285809Sscottl err = DEVICE_SUSPEND(iface->subdev); 1205285809Sscottl if (err) 1206285809Sscottl device_printf(iface->subdev, "Suspend failed\n"); 1207285809Sscottl } 1208285809Sscottl return (0); /* success */ 1209285809Sscottl } else { 1210285809Sscottl /* No USB driver found */ 1211285809Sscottl iface->subdev = NULL; 1212285809Sscottl } 1213285809Sscottl return (1); /* failure */ 1214285809Sscottl} 1215285809Sscottl 1216285809Sscottl/*------------------------------------------------------------------------* 1217285809Sscottl * usbd_set_parent_iface 1218285809Sscottl * 1219285809Sscottl * Using this function will lock the alternate interface setting on an 1220285809Sscottl * interface. It is typically used for multi interface drivers. In USB 1221285809Sscottl * device side mode it is assumed that the alternate interfaces all 1222285809Sscottl * have the same endpoint descriptors. The default parent index value 1223285809Sscottl * is "USB_IFACE_INDEX_ANY". Then the alternate setting value is not 1224285809Sscottl * locked. 1225285809Sscottl *------------------------------------------------------------------------*/ 1226285809Sscottlvoid 1227285809Sscottlusbd_set_parent_iface(struct usb_device *udev, uint8_t iface_index, 1228285809Sscottl uint8_t parent_index) 1229285809Sscottl{ 1230285809Sscottl struct usb_interface *iface; 1231285809Sscottl 1232285809Sscottl iface = usbd_get_iface(udev, iface_index); 1233285809Sscottl if (iface) { 1234285809Sscottl iface->parent_iface_index = parent_index; 1235285809Sscottl } 1236285809Sscottl} 1237285809Sscottl 1238285809Sscottlstatic void 1239285809Sscottlusb_init_attach_arg(struct usb_device *udev, 1240285809Sscottl struct usb_attach_arg *uaa) 1241285809Sscottl{ 1242285809Sscottl bzero(uaa, sizeof(*uaa)); 1243285809Sscottl 1244285809Sscottl uaa->device = udev; 1245285809Sscottl uaa->usb_mode = udev->flags.usb_mode; 1246285809Sscottl uaa->port = udev->port_no; 1247285809Sscottl uaa->dev_state = UAA_DEV_READY; 1248285809Sscottl 1249285809Sscottl uaa->info.idVendor = UGETW(udev->ddesc.idVendor); 1250285809Sscottl uaa->info.idProduct = UGETW(udev->ddesc.idProduct); 1251285809Sscottl uaa->info.bcdDevice = UGETW(udev->ddesc.bcdDevice); 1252285809Sscottl uaa->info.bDeviceClass = udev->ddesc.bDeviceClass; 1253285809Sscottl uaa->info.bDeviceSubClass = udev->ddesc.bDeviceSubClass; 1254285809Sscottl uaa->info.bDeviceProtocol = udev->ddesc.bDeviceProtocol; 1255285809Sscottl uaa->info.bConfigIndex = udev->curr_config_index; 1256285809Sscottl uaa->info.bConfigNum = udev->curr_config_no; 1257285809Sscottl} 1258285809Sscottl 1259285809Sscottl/*------------------------------------------------------------------------* 1260285809Sscottl * usb_probe_and_attach 1261285809Sscottl * 1262285809Sscottl * This function is called from "uhub_explore_sub()", 1263285809Sscottl * "usb_handle_set_config()" and "usb_handle_request()". 1264285809Sscottl * 1265285809Sscottl * Returns: 1266285809Sscottl * 0: Success 1267285809Sscottl * Else: A control transfer failed 1268285809Sscottl *------------------------------------------------------------------------*/ 1269285809Sscottlusb_error_t 1270285809Sscottlusb_probe_and_attach(struct usb_device *udev, uint8_t iface_index) 1271285809Sscottl{ 1272285809Sscottl struct usb_attach_arg uaa; 1273285809Sscottl struct usb_interface *iface; 1274285809Sscottl uint8_t i; 1275285809Sscottl uint8_t j; 1276285809Sscottl uint8_t do_unlock; 1277285809Sscottl 1278285809Sscottl if (udev == NULL) { 1279285809Sscottl DPRINTF("udev == NULL\n"); 1280285809Sscottl return (USB_ERR_INVAL); 1281285809Sscottl } 1282285809Sscottl /* automatic locking */ 1283285809Sscottl if (usbd_enum_is_locked(udev)) { 1284285809Sscottl do_unlock = 0; 1285285809Sscottl } else { 1286285809Sscottl do_unlock = 1; 1287285809Sscottl usbd_enum_lock(udev); 1288285809Sscottl } 1289285809Sscottl 1290285809Sscottl if (udev->curr_config_index == USB_UNCONFIG_INDEX) { 1291285809Sscottl /* do nothing - no configuration has been set */ 1292285809Sscottl goto done; 1293285809Sscottl } 1294285809Sscottl /* setup USB attach arguments */ 1295285809Sscottl 1296285809Sscottl usb_init_attach_arg(udev, &uaa); 1297285809Sscottl 1298285809Sscottl /* 1299285809Sscottl * If the whole USB device is targeted, invoke the USB event 1300285809Sscottl * handler(s): 1301285809Sscottl */ 1302285809Sscottl if (iface_index == USB_IFACE_INDEX_ANY) { 1303285809Sscottl 1304285809Sscottl EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa); 1305285809Sscottl 1306285809Sscottl if (uaa.dev_state != UAA_DEV_READY) { 1307285809Sscottl /* leave device unconfigured */ 1308285809Sscottl usb_unconfigure(udev, 0); 1309285809Sscottl goto done; 1310285809Sscottl } 1311285809Sscottl } 1312285809Sscottl 1313285809Sscottl /* Check if only one interface should be probed: */ 1314285809Sscottl if (iface_index != USB_IFACE_INDEX_ANY) { 1315285809Sscottl i = iface_index; 1316285809Sscottl j = i + 1; 1317285809Sscottl } else { 1318285809Sscottl i = 0; 1319285809Sscottl j = USB_IFACE_MAX; 1320285809Sscottl } 1321285809Sscottl 1322285809Sscottl /* Do the probe and attach */ 1323285809Sscottl for (; i != j; i++) { 1324285809Sscottl 1325285809Sscottl iface = usbd_get_iface(udev, i); 1326285809Sscottl if (iface == NULL) { 1327285809Sscottl /* 1328285809Sscottl * Looks like the end of the USB 1329285809Sscottl * interfaces ! 1330285809Sscottl */ 1331285809Sscottl DPRINTFN(2, "end of interfaces " 1332285809Sscottl "at %u\n", i); 1333285809Sscottl break; 1334285809Sscottl } 1335285809Sscottl if (iface->idesc == NULL) { 1336285809Sscottl /* no interface descriptor */ 1337285809Sscottl continue; 1338285809Sscottl } 1339285809Sscottl uaa.iface = iface; 1340285809Sscottl 1341285809Sscottl uaa.info.bInterfaceClass = 1342285809Sscottl iface->idesc->bInterfaceClass; 1343285809Sscottl uaa.info.bInterfaceSubClass = 1344285809Sscottl iface->idesc->bInterfaceSubClass; 1345285809Sscottl uaa.info.bInterfaceProtocol = 1346285809Sscottl iface->idesc->bInterfaceProtocol; 1347285809Sscottl uaa.info.bIfaceIndex = i; 1348285809Sscottl uaa.info.bIfaceNum = 1349285809Sscottl iface->idesc->bInterfaceNumber; 1350285809Sscottl uaa.driver_info = 0; /* reset driver_info */ 1351285809Sscottl 1352285809Sscottl DPRINTFN(2, "iclass=%u/%u/%u iindex=%u/%u\n", 1353285809Sscottl uaa.info.bInterfaceClass, 1354285809Sscottl uaa.info.bInterfaceSubClass, 1355285809Sscottl uaa.info.bInterfaceProtocol, 1356285809Sscottl uaa.info.bIfaceIndex, 1357285809Sscottl uaa.info.bIfaceNum); 1358285809Sscottl 1359285809Sscottl usb_probe_and_attach_sub(udev, &uaa); 1360285809Sscottl 1361285809Sscottl /* 1362285809Sscottl * Remove the leftover child, if any, to enforce that 1363285809Sscottl * a new nomatch devd event is generated for the next 1364285809Sscottl * interface if no driver is found: 1365285809Sscottl */ 1366285809Sscottl if (uaa.temp_dev == NULL) 1367285809Sscottl continue; 1368285809Sscottl if (device_delete_child(udev->parent_dev, uaa.temp_dev)) 1369285809Sscottl DPRINTFN(0, "device delete child failed\n"); 1370285809Sscottl uaa.temp_dev = NULL; 1371285809Sscottl } 1372285809Sscottldone: 1373285809Sscottl if (do_unlock) 1374285809Sscottl usbd_enum_unlock(udev); 1375285809Sscottl 1376285809Sscottl return (0); 1377285809Sscottl} 1378285809Sscottl 1379285809Sscottl/*------------------------------------------------------------------------* 1380285809Sscottl * usb_suspend_resume_sub 1381285809Sscottl * 1382285809Sscottl * This function is called when the suspend or resume methods should 1383285809Sscottl * be executed on an USB device. 1384285809Sscottl *------------------------------------------------------------------------*/ 1385285809Sscottlstatic void 1386285809Sscottlusb_suspend_resume_sub(struct usb_device *udev, device_t dev, uint8_t do_suspend) 1387285809Sscottl{ 1388285809Sscottl int err; 1389285809Sscottl 1390285809Sscottl if (dev == NULL) { 1391285809Sscottl return; 1392285809Sscottl } 1393285809Sscottl if (!device_is_attached(dev)) { 1394285809Sscottl return; 1395285809Sscottl } 1396285809Sscottl if (do_suspend) { 1397285809Sscottl err = DEVICE_SUSPEND(dev); 1398285809Sscottl } else { 1399285809Sscottl err = DEVICE_RESUME(dev); 1400285809Sscottl } 1401285809Sscottl if (err) { 1402285809Sscottl device_printf(dev, "%s failed\n", 1403285809Sscottl do_suspend ? "Suspend" : "Resume"); 1404285809Sscottl } 1405285809Sscottl} 1406285809Sscottl 1407285809Sscottl/*------------------------------------------------------------------------* 1408285809Sscottl * usb_suspend_resume 1409285809Sscottl * 1410285809Sscottl * The following function will suspend or resume the USB device. 1411285809Sscottl * 1412285809Sscottl * Returns: 1413285809Sscottl * 0: Success 1414285809Sscottl * Else: Failure 1415285809Sscottl *------------------------------------------------------------------------*/ 1416285809Sscottlusb_error_t 1417285809Sscottlusb_suspend_resume(struct usb_device *udev, uint8_t do_suspend) 1418285809Sscottl{ 1419285809Sscottl struct usb_interface *iface; 1420285809Sscottl uint8_t i; 1421285809Sscottl 1422285809Sscottl if (udev == NULL) { 1423285809Sscottl /* nothing to do */ 1424285809Sscottl return (0); 1425285809Sscottl } 1426285809Sscottl DPRINTFN(4, "udev=%p do_suspend=%d\n", udev, do_suspend); 1427285809Sscottl 1428285809Sscottl sx_assert(&udev->sr_sx, SA_LOCKED); 1429285809Sscottl 1430285809Sscottl USB_BUS_LOCK(udev->bus); 1431285809Sscottl /* filter the suspend events */ 1432285809Sscottl if (udev->flags.peer_suspended == do_suspend) { 1433285809Sscottl USB_BUS_UNLOCK(udev->bus); 1434285809Sscottl /* nothing to do */ 1435285809Sscottl return (0); 1436285809Sscottl } 1437285809Sscottl udev->flags.peer_suspended = do_suspend; 1438285809Sscottl USB_BUS_UNLOCK(udev->bus); 1439285809Sscottl 1440285809Sscottl /* do the suspend or resume */ 1441285809Sscottl 1442285809Sscottl for (i = 0; i != USB_IFACE_MAX; i++) { 1443285809Sscottl 1444285809Sscottl iface = usbd_get_iface(udev, i); 1445285809Sscottl if (iface == NULL) { 1446285809Sscottl /* looks like the end of the USB interfaces */ 1447285809Sscottl break; 1448285809Sscottl } 1449285809Sscottl usb_suspend_resume_sub(udev, iface->subdev, do_suspend); 1450285809Sscottl } 1451285809Sscottl return (0); 1452285809Sscottl} 1453285809Sscottl 1454285809Sscottl/*------------------------------------------------------------------------* 1455285809Sscottl * usbd_clear_stall_proc 1456285809Sscottl * 1457285809Sscottl * This function performs generic USB clear stall operations. 1458285809Sscottl *------------------------------------------------------------------------*/ 1459285809Sscottlstatic void 1460285809Sscottlusbd_clear_stall_proc(struct usb_proc_msg *_pm) 1461285809Sscottl{ 1462285809Sscottl struct usb_clear_stall_msg *pm = (void *)_pm; 1463285809Sscottl struct usb_device *udev = pm->udev; 1464285809Sscottl 1465285809Sscottl /* Change lock */ 1466285809Sscottl USB_BUS_UNLOCK(udev->bus); 1467285809Sscottl mtx_lock(&udev->device_mtx); 1468285809Sscottl 1469285809Sscottl /* Start clear stall callback */ 1470285809Sscottl usbd_transfer_start(udev->ctrl_xfer[1]); 1471285809Sscottl 1472285809Sscottl /* Change lock */ 1473285809Sscottl mtx_unlock(&udev->device_mtx); 1474285809Sscottl USB_BUS_LOCK(udev->bus); 1475285809Sscottl} 1476285809Sscottl 1477285809Sscottl/*------------------------------------------------------------------------* 1478285809Sscottl * usb_alloc_device 1479285809Sscottl * 1480285809Sscottl * This function allocates a new USB device. This function is called 1481285809Sscottl * when a new device has been put in the powered state, but not yet in 1482285809Sscottl * the addressed state. Get initial descriptor, set the address, get 1483285809Sscottl * full descriptor and get strings. 1484285809Sscottl * 1485285809Sscottl * Return values: 1486285809Sscottl * 0: Failure 1487285809Sscottl * Else: Success 1488285809Sscottl *------------------------------------------------------------------------*/ 1489285809Sscottlstruct usb_device * 1490285809Sscottlusb_alloc_device(device_t parent_dev, struct usb_bus *bus, 1491285809Sscottl struct usb_device *parent_hub, uint8_t depth, uint8_t port_index, 1492285809Sscottl uint8_t port_no, enum usb_dev_speed speed, enum usb_hc_mode mode) 1493285809Sscottl{ 1494285809Sscottl struct usb_attach_arg uaa; 1495285809Sscottl struct usb_device *udev; 1496285809Sscottl struct usb_device *adev; 1497285809Sscottl struct usb_device *hub; 1498285809Sscottl uint8_t *scratch_ptr; 1499285809Sscottl size_t scratch_size; 1500285809Sscottl usb_error_t err; 1501285809Sscottl uint8_t device_index; 1502285809Sscottl uint8_t config_index; 1503285809Sscottl uint8_t config_quirk; 1504285809Sscottl uint8_t set_config_failed; 1505285809Sscottl 1506285809Sscottl DPRINTF("parent_dev=%p, bus=%p, parent_hub=%p, depth=%u, " 1507285809Sscottl "port_index=%u, port_no=%u, speed=%u, usb_mode=%u\n", 1508285809Sscottl parent_dev, bus, parent_hub, depth, port_index, port_no, 1509285809Sscottl speed, mode); 1510285809Sscottl 1511285809Sscottl /* 1512285809Sscottl * Find an unused device index. In USB Host mode this is the 1513285809Sscottl * same as the device address. 1514285809Sscottl * 1515285809Sscottl * Device index zero is not used and device index 1 should 1516285809Sscottl * always be the root hub. 1517285809Sscottl */ 1518285809Sscottl for (device_index = USB_ROOT_HUB_ADDR; 1519285809Sscottl (device_index != bus->devices_max) && 1520285809Sscottl (bus->devices[device_index] != NULL); 1521285809Sscottl device_index++) /* nop */; 1522285809Sscottl 1523285809Sscottl if (device_index == bus->devices_max) { 1524285809Sscottl device_printf(bus->bdev, 1525285809Sscottl "No free USB device index for new device\n"); 1526285809Sscottl return (NULL); 1527285809Sscottl } 1528285809Sscottl 1529285809Sscottl if (depth > 0x10) { 1530285809Sscottl device_printf(bus->bdev, 1531285809Sscottl "Invalid device depth\n"); 1532285809Sscottl return (NULL); 1533285809Sscottl } 1534285809Sscottl udev = malloc(sizeof(*udev), M_USB, M_WAITOK | M_ZERO); 1535285809Sscottl if (udev == NULL) { 1536285809Sscottl return (NULL); 1537285809Sscottl } 1538285809Sscottl /* initialise our SX-lock */ 1539285809Sscottl sx_init_flags(&udev->ctrl_sx, "USB device SX lock", SX_DUPOK); 1540285809Sscottl 1541285809Sscottl /* initialise our SX-lock */ 1542285809Sscottl sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK); 1543285809Sscottl sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS); 1544285809Sscottl 1545285809Sscottl cv_init(&udev->ctrlreq_cv, "WCTRL"); 1546285809Sscottl cv_init(&udev->ref_cv, "UGONE"); 1547285809Sscottl 1548285809Sscottl /* initialise our mutex */ 1549285809Sscottl mtx_init(&udev->device_mtx, "USB device mutex", NULL, MTX_DEF); 1550285809Sscottl 1551285809Sscottl /* initialise generic clear stall */ 1552285809Sscottl udev->cs_msg[0].hdr.pm_callback = &usbd_clear_stall_proc; 1553285809Sscottl udev->cs_msg[0].udev = udev; 1554285809Sscottl udev->cs_msg[1].hdr.pm_callback = &usbd_clear_stall_proc; 1555285809Sscottl udev->cs_msg[1].udev = udev; 1556285809Sscottl 1557285809Sscottl /* initialise some USB device fields */ 1558285809Sscottl udev->parent_hub = parent_hub; 1559285809Sscottl udev->parent_dev = parent_dev; 1560285809Sscottl udev->port_index = port_index; 1561285809Sscottl udev->port_no = port_no; 1562285809Sscottl udev->depth = depth; 1563285809Sscottl udev->bus = bus; 1564285809Sscottl udev->address = USB_START_ADDR; /* default value */ 1565285809Sscottl udev->plugtime = (usb_ticks_t)ticks; 1566285809Sscottl /* 1567285809Sscottl * We need to force the power mode to "on" because there are plenty 1568285809Sscottl * of USB devices out there that do not work very well with 1569285809Sscottl * automatic suspend and resume! 1570285809Sscottl */ 1571285809Sscottl udev->power_mode = usbd_filter_power_mode(udev, USB_POWER_MODE_ON); 1572285809Sscottl udev->pwr_save.last_xfer_time = ticks; 1573285809Sscottl /* we are not ready yet */ 1574285809Sscottl udev->refcount = 1; 1575285809Sscottl 1576285809Sscottl /* set up default endpoint descriptor */ 1577285809Sscottl udev->ctrl_ep_desc.bLength = sizeof(udev->ctrl_ep_desc); 1578285809Sscottl udev->ctrl_ep_desc.bDescriptorType = UDESC_ENDPOINT; 1579285809Sscottl udev->ctrl_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT; 1580285809Sscottl udev->ctrl_ep_desc.bmAttributes = UE_CONTROL; 1581285809Sscottl udev->ctrl_ep_desc.wMaxPacketSize[0] = USB_MAX_IPACKET; 1582285809Sscottl udev->ctrl_ep_desc.wMaxPacketSize[1] = 0; 1583285809Sscottl udev->ctrl_ep_desc.bInterval = 0; 1584285809Sscottl 1585285809Sscottl /* set up default endpoint companion descriptor */ 1586285809Sscottl udev->ctrl_ep_comp_desc.bLength = sizeof(udev->ctrl_ep_comp_desc); 1587285809Sscottl udev->ctrl_ep_comp_desc.bDescriptorType = UDESC_ENDPOINT_SS_COMP; 1588285809Sscottl 1589285809Sscottl udev->ddesc.bMaxPacketSize = USB_MAX_IPACKET; 1590285809Sscottl 1591285809Sscottl udev->speed = speed; 1592285809Sscottl udev->flags.usb_mode = mode; 1593285809Sscottl 1594285809Sscottl /* search for our High Speed USB HUB, if any */ 1595285809Sscottl 1596285809Sscottl adev = udev; 1597285809Sscottl hub = udev->parent_hub; 1598285809Sscottl 1599285809Sscottl while (hub) { 1600285809Sscottl if (hub->speed == USB_SPEED_HIGH) { 1601285809Sscottl udev->hs_hub_addr = hub->address; 1602285809Sscottl udev->parent_hs_hub = hub; 1603285809Sscottl udev->hs_port_no = adev->port_no; 1604285809Sscottl break; 1605285809Sscottl } 1606285809Sscottl adev = hub; 1607285809Sscottl hub = hub->parent_hub; 1608285809Sscottl } 1609285809Sscottl 1610285809Sscottl /* init the default endpoint */ 1611285809Sscottl usb_init_endpoint(udev, 0, 1612285809Sscottl &udev->ctrl_ep_desc, 1613285809Sscottl &udev->ctrl_ep_comp_desc, 1614285809Sscottl &udev->ctrl_ep); 1615285809Sscottl 1616285809Sscottl /* set device index */ 1617285809Sscottl udev->device_index = device_index; 1618285809Sscottl 1619285809Sscottl#if USB_HAVE_UGEN 1620285809Sscottl /* Create ugen name */ 1621285809Sscottl snprintf(udev->ugen_name, sizeof(udev->ugen_name), 1622285809Sscottl USB_GENERIC_NAME "%u.%u", device_get_unit(bus->bdev), 1623285809Sscottl device_index); 1624285809Sscottl LIST_INIT(&udev->pd_list); 1625285809Sscottl 1626285809Sscottl /* Create the control endpoint device */ 1627285809Sscottl udev->ctrl_dev = usb_make_dev(udev, NULL, 0, 0, 1628285809Sscottl FREAD|FWRITE, UID_ROOT, GID_OPERATOR, 0600); 1629285809Sscottl 1630285809Sscottl /* Create a link from /dev/ugenX.X to the default endpoint */ 1631285809Sscottl if (udev->ctrl_dev != NULL) 1632285809Sscottl make_dev_alias(udev->ctrl_dev->cdev, "%s", udev->ugen_name); 1633285809Sscottl#endif 1634285809Sscottl /* Initialise device */ 1635285809Sscottl if (bus->methods->device_init != NULL) { 1636285809Sscottl err = (bus->methods->device_init) (udev); 1637285809Sscottl if (err != 0) { 1638285809Sscottl DPRINTFN(0, "device init %d failed " 1639285809Sscottl "(%s, ignored)\n", device_index, 1640285809Sscottl usbd_errstr(err)); 1641285809Sscottl goto done; 1642285809Sscottl } 1643285809Sscottl } 1644285809Sscottl /* set powered device state after device init is complete */ 1645285809Sscottl usb_set_device_state(udev, USB_STATE_POWERED); 1646285809Sscottl 1647285809Sscottl if (udev->flags.usb_mode == USB_MODE_HOST) { 1648285809Sscottl 1649285809Sscottl err = usbd_req_set_address(udev, NULL, device_index); 1650285809Sscottl 1651285809Sscottl /* 1652285809Sscottl * This is the new USB device address from now on, if 1653285809Sscottl * the set address request didn't set it already. 1654285809Sscottl */ 1655285809Sscottl if (udev->address == USB_START_ADDR) 1656285809Sscottl udev->address = device_index; 1657285809Sscottl 1658285809Sscottl /* 1659285809Sscottl * We ignore any set-address errors, hence there are 1660285809Sscottl * buggy USB devices out there that actually receive 1661285809Sscottl * the SETUP PID, but manage to set the address before 1662285809Sscottl * the STATUS stage is ACK'ed. If the device responds 1663285809Sscottl * to the subsequent get-descriptor at the new 1664285809Sscottl * address, then we know that the set-address command 1665285809Sscottl * was successful. 1666285809Sscottl */ 1667285809Sscottl if (err) { 1668285809Sscottl DPRINTFN(0, "set address %d failed " 1669285809Sscottl "(%s, ignored)\n", udev->address, 1670285809Sscottl usbd_errstr(err)); 1671285809Sscottl } 1672285809Sscottl } else { 1673285809Sscottl /* We are not self powered */ 1674285809Sscottl udev->flags.self_powered = 0; 1675285809Sscottl 1676285809Sscottl /* Set unconfigured state */ 1677285809Sscottl udev->curr_config_no = USB_UNCONFIG_NO; 1678285809Sscottl udev->curr_config_index = USB_UNCONFIG_INDEX; 1679285809Sscottl 1680285809Sscottl /* Setup USB descriptors */ 1681285809Sscottl err = (usb_temp_setup_by_index_p) (udev, usb_template); 1682285809Sscottl if (err) { 1683285809Sscottl DPRINTFN(0, "setting up USB template failed maybe the USB " 1684285809Sscottl "template module has not been loaded\n"); 1685285809Sscottl goto done; 1686285809Sscottl } 1687285809Sscottl } 1688285809Sscottl usb_set_device_state(udev, USB_STATE_ADDRESSED); 1689285809Sscottl 1690285809Sscottl /* setup the device descriptor and the initial "wMaxPacketSize" */ 1691285809Sscottl err = usbd_setup_device_desc(udev, NULL); 1692285809Sscottl 1693285809Sscottl if (err != 0) { 1694285809Sscottl /* XXX try to re-enumerate the device */ 1695285809Sscottl err = usbd_req_re_enumerate(udev, NULL); 1696285809Sscottl if (err) 1697285809Sscottl goto done; 1698285809Sscottl } 1699285809Sscottl 1700285809Sscottl /* 1701285809Sscottl * Setup temporary USB attach args so that we can figure out some 1702285809Sscottl * basic quirks for this device. 1703285809Sscottl */ 1704285809Sscottl usb_init_attach_arg(udev, &uaa); 1705285809Sscottl 1706285809Sscottl if (usb_test_quirk(&uaa, UQ_BUS_POWERED)) { 1707285809Sscottl udev->flags.uq_bus_powered = 1; 1708285809Sscottl } 1709285809Sscottl if (usb_test_quirk(&uaa, UQ_NO_STRINGS)) { 1710285809Sscottl udev->flags.no_strings = 1; 1711285809Sscottl } 1712285809Sscottl /* 1713285809Sscottl * Workaround for buggy USB devices. 1714285809Sscottl * 1715285809Sscottl * It appears that some string-less USB chips will crash and 1716285809Sscottl * disappear if any attempts are made to read any string 1717285809Sscottl * descriptors. 1718285809Sscottl * 1719285809Sscottl * Try to detect such chips by checking the strings in the USB 1720285809Sscottl * device descriptor. If no strings are present there we 1721285809Sscottl * simply disable all USB strings. 1722285809Sscottl */ 1723285809Sscottl scratch_ptr = udev->bus->scratch[0].data; 1724285809Sscottl scratch_size = sizeof(udev->bus->scratch[0].data); 1725285809Sscottl 1726285809Sscottl if (udev->ddesc.iManufacturer || 1727285809Sscottl udev->ddesc.iProduct || 1728285809Sscottl udev->ddesc.iSerialNumber) { 1729285809Sscottl /* read out the language ID string */ 1730285809Sscottl err = usbd_req_get_string_desc(udev, NULL, 1731285809Sscottl (char *)scratch_ptr, 4, 0, USB_LANGUAGE_TABLE); 1732285809Sscottl } else { 1733285809Sscottl err = USB_ERR_INVAL; 1734285809Sscottl } 1735285809Sscottl 1736285809Sscottl if (err || (scratch_ptr[0] < 4)) { 1737285809Sscottl udev->flags.no_strings = 1; 1738285809Sscottl } else { 1739285809Sscottl uint16_t langid; 1740285809Sscottl uint16_t pref; 1741285809Sscottl uint16_t mask; 1742285809Sscottl uint8_t x; 1743285809Sscottl 1744285809Sscottl /* load preferred value and mask */ 1745285809Sscottl pref = usb_lang_id; 1746285809Sscottl mask = usb_lang_mask; 1747285809Sscottl 1748285809Sscottl /* align length correctly */ 1749285809Sscottl scratch_ptr[0] &= ~1; 1750285809Sscottl 1751285809Sscottl /* fix compiler warning */ 1752285809Sscottl langid = 0; 1753285809Sscottl 1754285809Sscottl /* search for preferred language */ 1755285809Sscottl for (x = 2; (x < scratch_ptr[0]); x += 2) { 1756285809Sscottl langid = UGETW(scratch_ptr + x); 1757285809Sscottl if ((langid & mask) == pref) 1758285809Sscottl break; 1759285809Sscottl } 1760285809Sscottl if (x >= scratch_ptr[0]) { 1761285809Sscottl /* pick the first language as the default */ 1762285809Sscottl DPRINTFN(1, "Using first language\n"); 1763285809Sscottl langid = UGETW(scratch_ptr + 2); 1764285809Sscottl } 1765285809Sscottl 1766285809Sscottl DPRINTFN(1, "Language selected: 0x%04x\n", langid); 1767285809Sscottl udev->langid = langid; 1768285809Sscottl } 1769285809Sscottl 1770285809Sscottl /* assume 100mA bus powered for now. Changed when configured. */ 1771285809Sscottl udev->power = USB_MIN_POWER; 1772285809Sscottl /* fetch the vendor and product strings from the device */ 1773285809Sscottl usbd_set_device_strings(udev); 1774285809Sscottl 1775285809Sscottl if (udev->flags.usb_mode == USB_MODE_DEVICE) { 1776285809Sscottl /* USB device mode setup is complete */ 1777285809Sscottl err = 0; 1778285809Sscottl goto config_done; 1779285809Sscottl } 1780285809Sscottl 1781285809Sscottl /* 1782285809Sscottl * Most USB devices should attach to config index 0 by 1783285809Sscottl * default 1784285809Sscottl */ 1785285809Sscottl if (usb_test_quirk(&uaa, UQ_CFG_INDEX_0)) { 1786285809Sscottl config_index = 0; 1787285809Sscottl config_quirk = 1; 1788285809Sscottl } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_1)) { 1789285809Sscottl config_index = 1; 1790285809Sscottl config_quirk = 1; 1791285809Sscottl } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_2)) { 1792285809Sscottl config_index = 2; 1793285809Sscottl config_quirk = 1; 1794285809Sscottl } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_3)) { 1795285809Sscottl config_index = 3; 1796285809Sscottl config_quirk = 1; 1797285809Sscottl } else if (usb_test_quirk(&uaa, UQ_CFG_INDEX_4)) { 1798285809Sscottl config_index = 4; 1799285809Sscottl config_quirk = 1; 1800285809Sscottl } else { 1801285809Sscottl config_index = 0; 1802285809Sscottl config_quirk = 0; 1803285809Sscottl } 1804285809Sscottl 1805285809Sscottl set_config_failed = 0; 1806285809Sscottlrepeat_set_config: 1807285809Sscottl 1808285809Sscottl DPRINTF("setting config %u\n", config_index); 1809285809Sscottl 1810285809Sscottl /* get the USB device configured */ 1811285809Sscottl err = usbd_set_config_index(udev, config_index); 1812285809Sscottl if (err) { 1813285809Sscottl if (udev->ddesc.bNumConfigurations != 0) { 1814285809Sscottl if (!set_config_failed) { 1815285809Sscottl set_config_failed = 1; 1816285809Sscottl /* XXX try to re-enumerate the device */ 1817285809Sscottl err = usbd_req_re_enumerate(udev, NULL); 1818285809Sscottl if (err == 0) 1819285809Sscottl goto repeat_set_config; 1820285809Sscottl } 1821285809Sscottl DPRINTFN(0, "Failure selecting configuration index %u:" 1822285809Sscottl "%s, port %u, addr %u (ignored)\n", 1823285809Sscottl config_index, usbd_errstr(err), udev->port_no, 1824285809Sscottl udev->address); 1825285809Sscottl } 1826285809Sscottl /* 1827285809Sscottl * Some USB devices do not have any configurations. Ignore any 1828285809Sscottl * set config failures! 1829285809Sscottl */ 1830285809Sscottl err = 0; 1831285809Sscottl goto config_done; 1832285809Sscottl } 1833285809Sscottl if (!config_quirk && config_index + 1 < udev->ddesc.bNumConfigurations) { 1834285809Sscottl if ((udev->cdesc->bNumInterface < 2) && 1835285809Sscottl usbd_get_no_descriptors(udev->cdesc, UDESC_ENDPOINT) == 0) { 1836285809Sscottl DPRINTFN(0, "Found no endpoints, trying next config\n"); 1837285809Sscottl config_index++; 1838285809Sscottl goto repeat_set_config; 1839285809Sscottl } 1840285809Sscottl if (config_index == 0) { 1841285809Sscottl /* 1842285809Sscottl * Try to figure out if we have an 1843285809Sscottl * auto-install disk there: 1844285809Sscottl */ 1845285809Sscottl if (usb_iface_is_cdrom(udev, 0)) { 1846285809Sscottl DPRINTFN(0, "Found possible auto-install " 1847285809Sscottl "disk (trying next config)\n"); 1848285809Sscottl config_index++; 1849285809Sscottl goto repeat_set_config; 1850285809Sscottl } 1851285809Sscottl } 1852285809Sscottl } 1853285809Sscottl 1854285809Sscottlconfig_done: 1855285809Sscottl DPRINTF("new dev (addr %d), udev=%p, parent_hub=%p\n", 1856285809Sscottl udev->address, udev, udev->parent_hub); 1857285809Sscottl 1858285809Sscottl /* register our device - we are ready */ 1859285809Sscottl usb_bus_port_set_device(bus, parent_hub ? 1860285809Sscottl parent_hub->hub->ports + port_index : NULL, udev, device_index); 1861285809Sscottl 1862285809Sscottl#if USB_HAVE_UGEN 1863285809Sscottl /* Symlink the ugen device name */ 1864285809Sscottl udev->ugen_symlink = usb_alloc_symlink(udev->ugen_name); 1865285809Sscottl 1866285809Sscottl /* Announce device */ 1867285809Sscottl printf("%s: <%s> at %s\n", udev->ugen_name, 1868285809Sscottl usb_get_manufacturer(udev), 1869285809Sscottl device_get_nameunit(udev->bus->bdev)); 1870285809Sscottl#endif 1871285809Sscottl 1872285809Sscottl#if USB_HAVE_DEVCTL 1873285809Sscottl usb_notify_addq("ATTACH", udev); 1874285809Sscottl#endif 1875285809Sscottldone: 1876285809Sscottl if (err) { 1877285809Sscottl /* 1878285809Sscottl * Free USB device and all subdevices, if any. 1879285809Sscottl */ 1880285809Sscottl usb_free_device(udev, 0); 1881285809Sscottl udev = NULL; 1882285809Sscottl } 1883285809Sscottl return (udev); 1884285809Sscottl} 1885285809Sscottl 1886285809Sscottl#if USB_HAVE_UGEN 1887285809Sscottlstruct usb_fs_privdata * 1888285809Sscottlusb_make_dev(struct usb_device *udev, const char *devname, int ep, 1889285809Sscottl int fi, int rwmode, uid_t uid, gid_t gid, int mode) 1890285809Sscottl{ 1891285809Sscottl struct usb_fs_privdata* pd; 1892285809Sscottl char buffer[32]; 1893285809Sscottl 1894285809Sscottl /* Store information to locate ourselves again later */ 1895285809Sscottl pd = malloc(sizeof(struct usb_fs_privdata), M_USBDEV, 1896285809Sscottl M_WAITOK | M_ZERO); 1897285809Sscottl pd->bus_index = device_get_unit(udev->bus->bdev); 1898285809Sscottl pd->dev_index = udev->device_index; 1899285809Sscottl pd->ep_addr = ep; 1900285809Sscottl pd->fifo_index = fi; 1901285809Sscottl pd->mode = rwmode; 1902285809Sscottl 1903285809Sscottl /* Now, create the device itself */ 1904285809Sscottl if (devname == NULL) { 1905285809Sscottl devname = buffer; 1906285809Sscottl snprintf(buffer, sizeof(buffer), USB_DEVICE_DIR "/%u.%u.%u", 1907285809Sscottl pd->bus_index, pd->dev_index, pd->ep_addr); 1908285809Sscottl } 1909285809Sscottl 1910285809Sscottl pd->cdev = make_dev(&usb_devsw, 0, uid, gid, mode, "%s", devname); 1911285809Sscottl 1912285809Sscottl if (pd->cdev == NULL) { 1913285809Sscottl DPRINTFN(0, "Failed to create device %s\n", devname); 1914285809Sscottl free(pd, M_USBDEV); 1915285809Sscottl return (NULL); 1916285809Sscottl } 1917285809Sscottl 1918285809Sscottl /* XXX setting si_drv1 and creating the device is not atomic! */ 1919285809Sscottl pd->cdev->si_drv1 = pd; 1920285809Sscottl 1921285809Sscottl return (pd); 1922285809Sscottl} 1923285809Sscottl 1924285809Sscottlvoid 1925285809Sscottlusb_destroy_dev(struct usb_fs_privdata *pd) 1926285809Sscottl{ 1927285809Sscottl if (pd == NULL) 1928285809Sscottl return; 1929285809Sscottl 1930285809Sscottl destroy_dev(pd->cdev); 1931285809Sscottl 1932285809Sscottl free(pd, M_USBDEV); 1933285809Sscottl} 1934285809Sscottl 1935285809Sscottlstatic void 1936285809Sscottlusb_cdev_create(struct usb_device *udev) 1937285809Sscottl{ 1938285809Sscottl struct usb_config_descriptor *cd; 1939285809Sscottl struct usb_endpoint_descriptor *ed; 1940285809Sscottl struct usb_descriptor *desc; 1941285809Sscottl struct usb_fs_privdata* pd; 1942285809Sscottl int inmode, outmode, inmask, outmask, mode; 1943285809Sscottl uint8_t ep; 1944285809Sscottl 1945285809Sscottl KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("stale cdev entries")); 1946285809Sscottl 1947285809Sscottl DPRINTFN(2, "Creating device nodes\n"); 1948285809Sscottl 1949285809Sscottl if (usbd_get_mode(udev) == USB_MODE_DEVICE) { 1950285809Sscottl inmode = FWRITE; 1951285809Sscottl outmode = FREAD; 1952285809Sscottl } else { /* USB_MODE_HOST */ 1953285809Sscottl inmode = FREAD; 1954285809Sscottl outmode = FWRITE; 1955285809Sscottl } 1956285809Sscottl 1957285809Sscottl inmask = 0; 1958285809Sscottl outmask = 0; 1959285809Sscottl desc = NULL; 1960285809Sscottl 1961285809Sscottl /* 1962285809Sscottl * Collect all used endpoint numbers instead of just 1963285809Sscottl * generating 16 static endpoints. 1964285809Sscottl */ 1965285809Sscottl cd = usbd_get_config_descriptor(udev); 1966285809Sscottl while ((desc = usb_desc_foreach(cd, desc))) { 1967285809Sscottl /* filter out all endpoint descriptors */ 1968285809Sscottl if ((desc->bDescriptorType == UDESC_ENDPOINT) && 1969285809Sscottl (desc->bLength >= sizeof(*ed))) { 1970285809Sscottl ed = (struct usb_endpoint_descriptor *)desc; 1971285809Sscottl 1972285809Sscottl /* update masks */ 1973285809Sscottl ep = ed->bEndpointAddress; 1974285809Sscottl if (UE_GET_DIR(ep) == UE_DIR_OUT) 1975285809Sscottl outmask |= 1 << UE_GET_ADDR(ep); 1976285809Sscottl else 1977285809Sscottl inmask |= 1 << UE_GET_ADDR(ep); 1978285809Sscottl } 1979285809Sscottl } 1980285809Sscottl 1981285809Sscottl /* Create all available endpoints except EP0 */ 1982285809Sscottl for (ep = 1; ep < 16; ep++) { 1983285809Sscottl mode = (inmask & (1 << ep)) ? inmode : 0; 1984285809Sscottl mode |= (outmask & (1 << ep)) ? outmode : 0; 1985285809Sscottl if (mode == 0) 1986285809Sscottl continue; /* no IN or OUT endpoint */ 1987285809Sscottl 1988285809Sscottl pd = usb_make_dev(udev, NULL, ep, 0, 1989285809Sscottl mode, UID_ROOT, GID_OPERATOR, 0600); 1990285809Sscottl 1991285809Sscottl if (pd != NULL) 1992285809Sscottl LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next); 1993285809Sscottl } 1994285809Sscottl} 1995285809Sscottl 1996285809Sscottlstatic void 1997285809Sscottlusb_cdev_free(struct usb_device *udev) 1998285809Sscottl{ 1999285809Sscottl struct usb_fs_privdata* pd; 2000285809Sscottl 2001285809Sscottl DPRINTFN(2, "Freeing device nodes\n"); 2002285809Sscottl 2003285809Sscottl while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) { 2004285809Sscottl KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt")); 2005285809Sscottl 2006285809Sscottl LIST_REMOVE(pd, pd_next); 2007285809Sscottl 2008285809Sscottl usb_destroy_dev(pd); 2009285809Sscottl } 2010285809Sscottl} 2011285809Sscottl#endif 2012285809Sscottl 2013285809Sscottl/*------------------------------------------------------------------------* 2014285809Sscottl * usb_free_device 2015285809Sscottl * 2016285809Sscottl * This function is NULL safe and will free an USB device and its 2017285809Sscottl * children devices, if any. 2018285809Sscottl * 2019285809Sscottl * Flag values: Reserved, set to zero. 2020285809Sscottl *------------------------------------------------------------------------*/ 2021285809Sscottlvoid 2022285809Sscottlusb_free_device(struct usb_device *udev, uint8_t flag) 2023285809Sscottl{ 2024285809Sscottl struct usb_bus *bus; 2025285809Sscottl 2026285809Sscottl if (udev == NULL) 2027285809Sscottl return; /* already freed */ 2028285809Sscottl 2029285809Sscottl DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no); 2030285809Sscottl 2031285809Sscottl bus = udev->bus; 2032285809Sscottl usb_set_device_state(udev, USB_STATE_DETACHED); 2033285809Sscottl 2034285809Sscottl#if USB_HAVE_DEVCTL 2035285809Sscottl usb_notify_addq("DETACH", udev); 2036285809Sscottl#endif 2037285809Sscottl 2038285809Sscottl#if USB_HAVE_UGEN 2039285809Sscottl printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name, 2040285809Sscottl usb_get_manufacturer(udev), device_get_nameunit(bus->bdev)); 2041285809Sscottl 2042285809Sscottl /* Destroy UGEN symlink, if any */ 2043285809Sscottl if (udev->ugen_symlink) { 2044285809Sscottl usb_free_symlink(udev->ugen_symlink); 2045285809Sscottl udev->ugen_symlink = NULL; 2046285809Sscottl } 2047285809Sscottl#endif 2048285809Sscottl /* 2049285809Sscottl * Unregister our device first which will prevent any further 2050285809Sscottl * references: 2051285809Sscottl */ 2052285809Sscottl usb_bus_port_set_device(bus, udev->parent_hub ? 2053285809Sscottl udev->parent_hub->hub->ports + udev->port_index : NULL, 2054285809Sscottl NULL, USB_ROOT_HUB_ADDR); 2055285809Sscottl 2056285809Sscottl#if USB_HAVE_UGEN 2057285809Sscottl /* wait for all pending references to go away: */ 2058285809Sscottl mtx_lock(&usb_ref_lock); 2059285809Sscottl udev->refcount--; 2060285809Sscottl while (udev->refcount != 0) { 2061285809Sscottl cv_wait(&udev->ref_cv, &usb_ref_lock); 2062285809Sscottl } 2063285809Sscottl mtx_unlock(&usb_ref_lock); 2064285809Sscottl 2065285809Sscottl usb_destroy_dev(udev->ctrl_dev); 2066285809Sscottl#endif 2067285809Sscottl 2068285809Sscottl if (udev->flags.usb_mode == USB_MODE_DEVICE) { 2069285809Sscottl /* stop receiving any control transfers (Device Side Mode) */ 2070285809Sscottl usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX); 2071285809Sscottl } 2072285809Sscottl 2073285809Sscottl /* the following will get the device unconfigured in software */ 2074285809Sscottl usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_EP0); 2075285809Sscottl 2076285809Sscottl /* unsetup any leftover default USB transfers */ 2077285809Sscottl usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX); 2078285809Sscottl 2079285809Sscottl /* template unsetup, if any */ 2080285809Sscottl (usb_temp_unsetup_p) (udev); 2081285809Sscottl 2082285809Sscottl /* 2083285809Sscottl * Make sure that our clear-stall messages are not queued 2084285809Sscottl * anywhere: 2085285809Sscottl */ 2086285809Sscottl USB_BUS_LOCK(udev->bus); 2087285809Sscottl usb_proc_mwait(&udev->bus->non_giant_callback_proc, 2088285809Sscottl &udev->cs_msg[0], &udev->cs_msg[1]); 2089285809Sscottl USB_BUS_UNLOCK(udev->bus); 2090285809Sscottl 2091285809Sscottl sx_destroy(&udev->ctrl_sx); 2092285809Sscottl sx_destroy(&udev->enum_sx); 2093285809Sscottl sx_destroy(&udev->sr_sx); 2094285809Sscottl 2095285809Sscottl cv_destroy(&udev->ctrlreq_cv); 2096285809Sscottl cv_destroy(&udev->ref_cv); 2097285809Sscottl 2098285809Sscottl mtx_destroy(&udev->device_mtx); 2099285809Sscottl#if USB_HAVE_UGEN 2100285809Sscottl KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("leaked cdev entries")); 2101285809Sscottl#endif 2102285809Sscottl 2103285809Sscottl /* Uninitialise device */ 2104285809Sscottl if (bus->methods->device_uninit != NULL) 2105285809Sscottl (bus->methods->device_uninit) (udev); 2106285809Sscottl 2107285809Sscottl /* free device */ 2108285809Sscottl free(udev->serial, M_USB); 2109285809Sscottl free(udev->manufacturer, M_USB); 2110285809Sscottl free(udev->product, M_USB); 2111285809Sscottl free(udev, M_USB); 2112285809Sscottl} 2113285809Sscottl 2114285809Sscottl/*------------------------------------------------------------------------* 2115285809Sscottl * usbd_get_iface 2116285809Sscottl * 2117285809Sscottl * This function is the safe way to get the USB interface structure 2118285809Sscottl * pointer by interface index. 2119285809Sscottl * 2120285809Sscottl * Return values: 2121285809Sscottl * NULL: Interface not present. 2122285809Sscottl * Else: Pointer to USB interface structure. 2123285809Sscottl *------------------------------------------------------------------------*/ 2124285809Sscottlstruct usb_interface * 2125285809Sscottlusbd_get_iface(struct usb_device *udev, uint8_t iface_index) 2126285809Sscottl{ 2127285809Sscottl struct usb_interface *iface = udev->ifaces + iface_index; 2128285809Sscottl 2129285809Sscottl if (iface_index >= udev->ifaces_max) 2130285809Sscottl return (NULL); 2131285809Sscottl return (iface); 2132285809Sscottl} 2133285809Sscottl 2134285809Sscottl/*------------------------------------------------------------------------* 2135285809Sscottl * usbd_find_descriptor 2136285809Sscottl * 2137285809Sscottl * This function will lookup the first descriptor that matches the 2138285809Sscottl * criteria given by the arguments "type" and "subtype". Descriptors 2139285809Sscottl * will only be searched within the interface having the index 2140285809Sscottl * "iface_index". If the "id" argument points to an USB descriptor, 2141285809Sscottl * it will be skipped before the search is started. This allows 2142285809Sscottl * searching for multiple descriptors using the same criteria. Else 2143285809Sscottl * the search is started after the interface descriptor. 2144285809Sscottl * 2145285809Sscottl * Return values: 2146285809Sscottl * NULL: End of descriptors 2147285809Sscottl * Else: A descriptor matching the criteria 2148285809Sscottl *------------------------------------------------------------------------*/ 2149285809Sscottlvoid * 2150285809Sscottlusbd_find_descriptor(struct usb_device *udev, void *id, uint8_t iface_index, 2151285809Sscottl uint8_t type, uint8_t type_mask, 2152285809Sscottl uint8_t subtype, uint8_t subtype_mask) 2153285809Sscottl{ 2154285809Sscottl struct usb_descriptor *desc; 2155285809Sscottl struct usb_config_descriptor *cd; 2156285809Sscottl struct usb_interface *iface; 2157285809Sscottl 2158285809Sscottl cd = usbd_get_config_descriptor(udev); 2159285809Sscottl if (cd == NULL) { 2160285809Sscottl return (NULL); 2161285809Sscottl } 2162285809Sscottl if (id == NULL) { 2163285809Sscottl iface = usbd_get_iface(udev, iface_index); 2164285809Sscottl if (iface == NULL) { 2165285809Sscottl return (NULL); 2166285809Sscottl } 2167285809Sscottl id = usbd_get_interface_descriptor(iface); 2168285809Sscottl if (id == NULL) { 2169285809Sscottl return (NULL); 2170 } 2171 } 2172 desc = (void *)id; 2173 2174 while ((desc = usb_desc_foreach(cd, desc))) { 2175 2176 if (desc->bDescriptorType == UDESC_INTERFACE) { 2177 break; 2178 } 2179 if (((desc->bDescriptorType & type_mask) == type) && 2180 ((desc->bDescriptorSubtype & subtype_mask) == subtype)) { 2181 return (desc); 2182 } 2183 } 2184 return (NULL); 2185} 2186 2187/*------------------------------------------------------------------------* 2188 * usb_devinfo 2189 * 2190 * This function will dump information from the device descriptor 2191 * belonging to the USB device pointed to by "udev", to the string 2192 * pointed to by "dst_ptr" having a maximum length of "dst_len" bytes 2193 * including the terminating zero. 2194 *------------------------------------------------------------------------*/ 2195void 2196usb_devinfo(struct usb_device *udev, char *dst_ptr, uint16_t dst_len) 2197{ 2198 struct usb_device_descriptor *udd = &udev->ddesc; 2199 uint16_t bcdDevice; 2200 uint16_t bcdUSB; 2201 2202 bcdUSB = UGETW(udd->bcdUSB); 2203 bcdDevice = UGETW(udd->bcdDevice); 2204 2205 if (udd->bDeviceClass != 0xFF) { 2206 snprintf(dst_ptr, dst_len, "%s %s, class %d/%d, rev %x.%02x/" 2207 "%x.%02x, addr %d", 2208 usb_get_manufacturer(udev), 2209 usb_get_product(udev), 2210 udd->bDeviceClass, udd->bDeviceSubClass, 2211 (bcdUSB >> 8), bcdUSB & 0xFF, 2212 (bcdDevice >> 8), bcdDevice & 0xFF, 2213 udev->address); 2214 } else { 2215 snprintf(dst_ptr, dst_len, "%s %s, rev %x.%02x/" 2216 "%x.%02x, addr %d", 2217 usb_get_manufacturer(udev), 2218 usb_get_product(udev), 2219 (bcdUSB >> 8), bcdUSB & 0xFF, 2220 (bcdDevice >> 8), bcdDevice & 0xFF, 2221 udev->address); 2222 } 2223} 2224 2225#ifdef USB_VERBOSE 2226/* 2227 * Descriptions of of known vendors and devices ("products"). 2228 */ 2229struct usb_knowndev { 2230 uint16_t vendor; 2231 uint16_t product; 2232 uint32_t flags; 2233 const char *vendorname; 2234 const char *productname; 2235}; 2236 2237#define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */ 2238 2239#include "usbdevs.h" 2240#include "usbdevs_data.h" 2241#endif /* USB_VERBOSE */ 2242 2243static void 2244usbd_set_device_strings(struct usb_device *udev) 2245{ 2246 struct usb_device_descriptor *udd = &udev->ddesc; 2247#ifdef USB_VERBOSE 2248 const struct usb_knowndev *kdp; 2249#endif 2250 char *temp_ptr; 2251 size_t temp_size; 2252 uint16_t vendor_id; 2253 uint16_t product_id; 2254 2255 temp_ptr = (char *)udev->bus->scratch[0].data; 2256 temp_size = sizeof(udev->bus->scratch[0].data); 2257 2258 vendor_id = UGETW(udd->idVendor); 2259 product_id = UGETW(udd->idProduct); 2260 2261 /* get serial number string */ 2262 usbd_req_get_string_any(udev, NULL, temp_ptr, temp_size, 2263 udev->ddesc.iSerialNumber); 2264 udev->serial = strdup(temp_ptr, M_USB); 2265 2266 /* get manufacturer string */ 2267 usbd_req_get_string_any(udev, NULL, temp_ptr, temp_size, 2268 udev->ddesc.iManufacturer); 2269 usb_trim_spaces(temp_ptr); 2270 if (temp_ptr[0] != '\0') 2271 udev->manufacturer = strdup(temp_ptr, M_USB); 2272 2273 /* get product string */ 2274 usbd_req_get_string_any(udev, NULL, temp_ptr, temp_size, 2275 udev->ddesc.iProduct); 2276 usb_trim_spaces(temp_ptr); 2277 if (temp_ptr[0] != '\0') 2278 udev->product = strdup(temp_ptr, M_USB); 2279 2280#ifdef USB_VERBOSE 2281 if (udev->manufacturer == NULL || udev->product == NULL) { 2282 for (kdp = usb_knowndevs; kdp->vendorname != NULL; kdp++) { 2283 if (kdp->vendor == vendor_id && 2284 (kdp->product == product_id || 2285 (kdp->flags & USB_KNOWNDEV_NOPROD) != 0)) 2286 break; 2287 } 2288 if (kdp->vendorname != NULL) { 2289 /* XXX should use pointer to knowndevs string */ 2290 if (udev->manufacturer == NULL) { 2291 udev->manufacturer = strdup(kdp->vendorname, 2292 M_USB); 2293 } 2294 if (udev->product == NULL && 2295 (kdp->flags & USB_KNOWNDEV_NOPROD) == 0) { 2296 udev->product = strdup(kdp->productname, 2297 M_USB); 2298 } 2299 } 2300 } 2301#endif 2302 /* Provide default strings if none were found */ 2303 if (udev->manufacturer == NULL) { 2304 snprintf(temp_ptr, temp_size, "vendor 0x%04x", vendor_id); 2305 udev->manufacturer = strdup(temp_ptr, M_USB); 2306 } 2307 if (udev->product == NULL) { 2308 snprintf(temp_ptr, temp_size, "product 0x%04x", product_id); 2309 udev->product = strdup(temp_ptr, M_USB); 2310 } 2311} 2312 2313/* 2314 * Returns: 2315 * See: USB_MODE_XXX 2316 */ 2317enum usb_hc_mode 2318usbd_get_mode(struct usb_device *udev) 2319{ 2320 return (udev->flags.usb_mode); 2321} 2322 2323/* 2324 * Returns: 2325 * See: USB_SPEED_XXX 2326 */ 2327enum usb_dev_speed 2328usbd_get_speed(struct usb_device *udev) 2329{ 2330 return (udev->speed); 2331} 2332 2333uint32_t 2334usbd_get_isoc_fps(struct usb_device *udev) 2335{ 2336 ; /* indent fix */ 2337 switch (udev->speed) { 2338 case USB_SPEED_LOW: 2339 case USB_SPEED_FULL: 2340 return (1000); 2341 default: 2342 return (8000); 2343 } 2344} 2345 2346struct usb_device_descriptor * 2347usbd_get_device_descriptor(struct usb_device *udev) 2348{ 2349 if (udev == NULL) 2350 return (NULL); /* be NULL safe */ 2351 return (&udev->ddesc); 2352} 2353 2354struct usb_config_descriptor * 2355usbd_get_config_descriptor(struct usb_device *udev) 2356{ 2357 if (udev == NULL) 2358 return (NULL); /* be NULL safe */ 2359 return (udev->cdesc); 2360} 2361 2362/*------------------------------------------------------------------------* 2363 * usb_test_quirk - test a device for a given quirk 2364 * 2365 * Return values: 2366 * 0: The USB device does not have the given quirk. 2367 * Else: The USB device has the given quirk. 2368 *------------------------------------------------------------------------*/ 2369uint8_t 2370usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk) 2371{ 2372 uint8_t found; 2373 2374 found = (usb_test_quirk_p) (&uaa->info, quirk); 2375 return (found); 2376} 2377 2378struct usb_interface_descriptor * 2379usbd_get_interface_descriptor(struct usb_interface *iface) 2380{ 2381 if (iface == NULL) 2382 return (NULL); /* be NULL safe */ 2383 return (iface->idesc); 2384} 2385 2386uint8_t 2387usbd_get_interface_altindex(struct usb_interface *iface) 2388{ 2389 return (iface->alt_index); 2390} 2391 2392uint8_t 2393usbd_get_bus_index(struct usb_device *udev) 2394{ 2395 return ((uint8_t)device_get_unit(udev->bus->bdev)); 2396} 2397 2398uint8_t 2399usbd_get_device_index(struct usb_device *udev) 2400{ 2401 return (udev->device_index); 2402} 2403 2404#if USB_HAVE_DEVCTL 2405static void 2406usb_notify_addq(const char *type, struct usb_device *udev) 2407{ 2408 struct usb_interface *iface; 2409 struct sbuf *sb; 2410 int i; 2411 2412 /* announce the device */ 2413 sb = sbuf_new_auto(); 2414 sbuf_printf(sb, 2415#if USB_HAVE_UGEN 2416 "ugen=%s " 2417 "cdev=%s " 2418#endif 2419 "vendor=0x%04x " 2420 "product=0x%04x " 2421 "devclass=0x%02x " 2422 "devsubclass=0x%02x " 2423 "sernum=\"%s\" " 2424 "release=0x%04x " 2425 "mode=%s " 2426 "port=%u " 2427#if USB_HAVE_UGEN 2428 "parent=%s" 2429#endif 2430 "", 2431#if USB_HAVE_UGEN 2432 udev->ugen_name, 2433 udev->ugen_name, 2434#endif 2435 UGETW(udev->ddesc.idVendor), 2436 UGETW(udev->ddesc.idProduct), 2437 udev->ddesc.bDeviceClass, 2438 udev->ddesc.bDeviceSubClass, 2439 usb_get_serial(udev), 2440 UGETW(udev->ddesc.bcdDevice), 2441 (udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device", 2442 udev->port_no 2443#if USB_HAVE_UGEN 2444 , udev->parent_hub != NULL ? 2445 udev->parent_hub->ugen_name : 2446 device_get_nameunit(device_get_parent(udev->bus->bdev)) 2447#endif 2448 ); 2449 sbuf_finish(sb); 2450 devctl_notify("USB", "DEVICE", type, sbuf_data(sb)); 2451 sbuf_delete(sb); 2452 2453 /* announce each interface */ 2454 for (i = 0; i < USB_IFACE_MAX; i++) { 2455 iface = usbd_get_iface(udev, i); 2456 if (iface == NULL) 2457 break; /* end of interfaces */ 2458 if (iface->idesc == NULL) 2459 continue; /* no interface descriptor */ 2460 2461 sb = sbuf_new_auto(); 2462 sbuf_printf(sb, 2463#if USB_HAVE_UGEN 2464 "ugen=%s " 2465 "cdev=%s " 2466#endif 2467 "vendor=0x%04x " 2468 "product=0x%04x " 2469 "devclass=0x%02x " 2470 "devsubclass=0x%02x " 2471 "sernum=\"%s\" " 2472 "release=0x%04x " 2473 "mode=%s " 2474 "interface=%d " 2475 "endpoints=%d " 2476 "intclass=0x%02x " 2477 "intsubclass=0x%02x " 2478 "intprotocol=0x%02x", 2479#if USB_HAVE_UGEN 2480 udev->ugen_name, 2481 udev->ugen_name, 2482#endif 2483 UGETW(udev->ddesc.idVendor), 2484 UGETW(udev->ddesc.idProduct), 2485 udev->ddesc.bDeviceClass, 2486 udev->ddesc.bDeviceSubClass, 2487 usb_get_serial(udev), 2488 UGETW(udev->ddesc.bcdDevice), 2489 (udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device", 2490 iface->idesc->bInterfaceNumber, 2491 iface->idesc->bNumEndpoints, 2492 iface->idesc->bInterfaceClass, 2493 iface->idesc->bInterfaceSubClass, 2494 iface->idesc->bInterfaceProtocol); 2495 sbuf_finish(sb); 2496 devctl_notify("USB", "INTERFACE", type, sbuf_data(sb)); 2497 sbuf_delete(sb); 2498 } 2499} 2500#endif 2501 2502#if USB_HAVE_UGEN 2503/*------------------------------------------------------------------------* 2504 * usb_fifo_free_wrap 2505 * 2506 * This function will free the FIFOs. 2507 * 2508 * Description of "flag" argument: If the USB_UNCFG_FLAG_FREE_EP0 flag 2509 * is set and "iface_index" is set to "USB_IFACE_INDEX_ANY", we free 2510 * all FIFOs. If the USB_UNCFG_FLAG_FREE_EP0 flag is not set and 2511 * "iface_index" is set to "USB_IFACE_INDEX_ANY", we free all non 2512 * control endpoint FIFOs. If "iface_index" is not set to 2513 * "USB_IFACE_INDEX_ANY" the flag has no effect. 2514 *------------------------------------------------------------------------*/ 2515static void 2516usb_fifo_free_wrap(struct usb_device *udev, 2517 uint8_t iface_index, uint8_t flag) 2518{ 2519 struct usb_fifo *f; 2520 uint16_t i; 2521 2522 /* 2523 * Free any USB FIFOs on the given interface: 2524 */ 2525 for (i = 0; i != USB_FIFO_MAX; i++) { 2526 f = udev->fifo[i]; 2527 if (f == NULL) { 2528 continue; 2529 } 2530 /* Check if the interface index matches */ 2531 if (iface_index == f->iface_index) { 2532 if (f->methods != &usb_ugen_methods) { 2533 /* 2534 * Don't free any non-generic FIFOs in 2535 * this case. 2536 */ 2537 continue; 2538 } 2539 if ((f->dev_ep_index == 0) && 2540 (f->fs_xfer == NULL)) { 2541 /* no need to free this FIFO */ 2542 continue; 2543 } 2544 } else if (iface_index == USB_IFACE_INDEX_ANY) { 2545 if ((f->methods == &usb_ugen_methods) && 2546 (f->dev_ep_index == 0) && 2547 (!(flag & USB_UNCFG_FLAG_FREE_EP0)) && 2548 (f->fs_xfer == NULL)) { 2549 /* no need to free this FIFO */ 2550 continue; 2551 } 2552 } else { 2553 /* no need to free this FIFO */ 2554 continue; 2555 } 2556 /* free this FIFO */ 2557 usb_fifo_free(f); 2558 } 2559} 2560#endif 2561 2562/*------------------------------------------------------------------------* 2563 * usb_peer_can_wakeup 2564 * 2565 * Return values: 2566 * 0: Peer cannot do resume signalling. 2567 * Else: Peer can do resume signalling. 2568 *------------------------------------------------------------------------*/ 2569uint8_t 2570usb_peer_can_wakeup(struct usb_device *udev) 2571{ 2572 const struct usb_config_descriptor *cdp; 2573 2574 cdp = udev->cdesc; 2575 if ((cdp != NULL) && (udev->flags.usb_mode == USB_MODE_HOST)) { 2576 return (cdp->bmAttributes & UC_REMOTE_WAKEUP); 2577 } 2578 return (0); /* not supported */ 2579} 2580 2581void 2582usb_set_device_state(struct usb_device *udev, enum usb_dev_state state) 2583{ 2584 2585 KASSERT(state < USB_STATE_MAX, ("invalid udev state")); 2586 2587 DPRINTF("udev %p state %s -> %s\n", udev, 2588 usb_statestr(udev->state), usb_statestr(state)); 2589 udev->state = state; 2590 2591 if (udev->bus->methods->device_state_change != NULL) 2592 (udev->bus->methods->device_state_change) (udev); 2593} 2594 2595enum usb_dev_state 2596usb_get_device_state(struct usb_device *udev) 2597{ 2598 if (udev == NULL) 2599 return (USB_STATE_DETACHED); 2600 return (udev->state); 2601} 2602 2603uint8_t 2604usbd_device_attached(struct usb_device *udev) 2605{ 2606 return (udev->state > USB_STATE_DETACHED); 2607} 2608 2609/* The following function locks enumerating the given USB device. */ 2610 2611void 2612usbd_enum_lock(struct usb_device *udev) 2613{ 2614 sx_xlock(&udev->enum_sx); 2615 sx_xlock(&udev->sr_sx); 2616 /* 2617 * NEWBUS LOCK NOTE: We should check if any parent SX locks 2618 * are locked before locking Giant. Else the lock can be 2619 * locked multiple times. 2620 */ 2621 mtx_lock(&Giant); 2622} 2623 2624/* The following function unlocks enumerating the given USB device. */ 2625 2626void 2627usbd_enum_unlock(struct usb_device *udev) 2628{ 2629 mtx_unlock(&Giant); 2630 sx_xunlock(&udev->enum_sx); 2631 sx_xunlock(&udev->sr_sx); 2632} 2633 2634/* The following function locks suspend and resume. */ 2635 2636void 2637usbd_sr_lock(struct usb_device *udev) 2638{ 2639 sx_xlock(&udev->sr_sx); 2640 /* 2641 * NEWBUS LOCK NOTE: We should check if any parent SX locks 2642 * are locked before locking Giant. Else the lock can be 2643 * locked multiple times. 2644 */ 2645 mtx_lock(&Giant); 2646} 2647 2648/* The following function unlocks suspend and resume. */ 2649 2650void 2651usbd_sr_unlock(struct usb_device *udev) 2652{ 2653 mtx_unlock(&Giant); 2654 sx_xunlock(&udev->sr_sx); 2655} 2656 2657/* 2658 * The following function checks the enumerating lock for the given 2659 * USB device. 2660 */ 2661 2662uint8_t 2663usbd_enum_is_locked(struct usb_device *udev) 2664{ 2665 return (sx_xlocked(&udev->enum_sx)); 2666} 2667 2668/* 2669 * The following function is used to set the per-interface specific 2670 * plug and play information. The string referred to by the pnpinfo 2671 * argument can safely be freed after calling this function. The 2672 * pnpinfo of an interface will be reset at device detach or when 2673 * passing a NULL argument to this function. This function 2674 * returns zero on success, else a USB_ERR_XXX failure code. 2675 */ 2676 2677usb_error_t 2678usbd_set_pnpinfo(struct usb_device *udev, uint8_t iface_index, const char *pnpinfo) 2679{ 2680 struct usb_interface *iface; 2681 2682 iface = usbd_get_iface(udev, iface_index); 2683 if (iface == NULL) 2684 return (USB_ERR_INVAL); 2685 2686 if (iface->pnpinfo != NULL) { 2687 free(iface->pnpinfo, M_USBDEV); 2688 iface->pnpinfo = NULL; 2689 } 2690 2691 if (pnpinfo == NULL || pnpinfo[0] == 0) 2692 return (0); /* success */ 2693 2694 iface->pnpinfo = strdup(pnpinfo, M_USBDEV); 2695 if (iface->pnpinfo == NULL) 2696 return (USB_ERR_NOMEM); 2697 2698 return (0); /* success */ 2699} 2700 2701