18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drivers/usb/core/usb.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * (C) Copyright Linus Torvalds 1999 68c2ecf20Sopenharmony_ci * (C) Copyright Johannes Erdfelt 1999-2001 78c2ecf20Sopenharmony_ci * (C) Copyright Andreas Gal 1999 88c2ecf20Sopenharmony_ci * (C) Copyright Gregory P. Smith 1999 98c2ecf20Sopenharmony_ci * (C) Copyright Deti Fliegl 1999 (new USB architecture) 108c2ecf20Sopenharmony_ci * (C) Copyright Randy Dunlap 2000 118c2ecf20Sopenharmony_ci * (C) Copyright David Brownell 2000-2004 128c2ecf20Sopenharmony_ci * (C) Copyright Yggdrasil Computing, Inc. 2000 138c2ecf20Sopenharmony_ci * (usb_device_id matching changes by Adam J. Richter) 148c2ecf20Sopenharmony_ci * (C) Copyright Greg Kroah-Hartman 2002-2003 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Released under the GPLv2 only. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * NOTE! This is not actually a driver at all, rather this is 198c2ecf20Sopenharmony_ci * just a collection of helper routines that implement the 208c2ecf20Sopenharmony_ci * generic USB things that the real drivers can use.. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Think of this as a "USB library" rather than anything else, 238c2ecf20Sopenharmony_ci * with no callbacks. Callbacks are evil. 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <linux/module.h> 278c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 288c2ecf20Sopenharmony_ci#include <linux/string.h> 298c2ecf20Sopenharmony_ci#include <linux/bitops.h> 308c2ecf20Sopenharmony_ci#include <linux/slab.h> 318c2ecf20Sopenharmony_ci#include <linux/interrupt.h> /* for in_interrupt() */ 328c2ecf20Sopenharmony_ci#include <linux/kmod.h> 338c2ecf20Sopenharmony_ci#include <linux/init.h> 348c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 358c2ecf20Sopenharmony_ci#include <linux/errno.h> 368c2ecf20Sopenharmony_ci#include <linux/usb.h> 378c2ecf20Sopenharmony_ci#include <linux/usb/hcd.h> 388c2ecf20Sopenharmony_ci#include <linux/mutex.h> 398c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 408c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 418c2ecf20Sopenharmony_ci#include <linux/usb/of.h> 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#include <asm/io.h> 448c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 458c2ecf20Sopenharmony_ci#include <linux/mm.h> 468c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include "hub.h" 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ciconst char *usbcore_name = "usbcore"; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic bool nousb; /* Disable USB when built into kernel image */ 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cimodule_param(nousb, bool, 0444); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* 578c2ecf20Sopenharmony_ci * for external read access to <nousb> 588c2ecf20Sopenharmony_ci */ 598c2ecf20Sopenharmony_ciint usb_disabled(void) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci return nousb; 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_disabled); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 668c2ecf20Sopenharmony_ci/* Default delay value, in seconds */ 678c2ecf20Sopenharmony_cistatic int usb_autosuspend_delay = CONFIG_USB_AUTOSUSPEND_DELAY; 688c2ecf20Sopenharmony_cimodule_param_named(autosuspend, usb_autosuspend_delay, int, 0644); 698c2ecf20Sopenharmony_ciMODULE_PARM_DESC(autosuspend, "default autosuspend delay"); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#else 728c2ecf20Sopenharmony_ci#define usb_autosuspend_delay 0 738c2ecf20Sopenharmony_ci#endif 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic bool match_endpoint(struct usb_endpoint_descriptor *epd, 768c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **bulk_in, 778c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **bulk_out, 788c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **int_in, 798c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **int_out) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci switch (usb_endpoint_type(epd)) { 828c2ecf20Sopenharmony_ci case USB_ENDPOINT_XFER_BULK: 838c2ecf20Sopenharmony_ci if (usb_endpoint_dir_in(epd)) { 848c2ecf20Sopenharmony_ci if (bulk_in && !*bulk_in) { 858c2ecf20Sopenharmony_ci *bulk_in = epd; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci } else { 898c2ecf20Sopenharmony_ci if (bulk_out && !*bulk_out) { 908c2ecf20Sopenharmony_ci *bulk_out = epd; 918c2ecf20Sopenharmony_ci break; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci return false; 968c2ecf20Sopenharmony_ci case USB_ENDPOINT_XFER_INT: 978c2ecf20Sopenharmony_ci if (usb_endpoint_dir_in(epd)) { 988c2ecf20Sopenharmony_ci if (int_in && !*int_in) { 998c2ecf20Sopenharmony_ci *int_in = epd; 1008c2ecf20Sopenharmony_ci break; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci } else { 1038c2ecf20Sopenharmony_ci if (int_out && !*int_out) { 1048c2ecf20Sopenharmony_ci *int_out = epd; 1058c2ecf20Sopenharmony_ci break; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return false; 1108c2ecf20Sopenharmony_ci default: 1118c2ecf20Sopenharmony_ci return false; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return (!bulk_in || *bulk_in) && (!bulk_out || *bulk_out) && 1158c2ecf20Sopenharmony_ci (!int_in || *int_in) && (!int_out || *int_out); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/** 1198c2ecf20Sopenharmony_ci * usb_find_common_endpoints() -- look up common endpoint descriptors 1208c2ecf20Sopenharmony_ci * @alt: alternate setting to search 1218c2ecf20Sopenharmony_ci * @bulk_in: pointer to descriptor pointer, or NULL 1228c2ecf20Sopenharmony_ci * @bulk_out: pointer to descriptor pointer, or NULL 1238c2ecf20Sopenharmony_ci * @int_in: pointer to descriptor pointer, or NULL 1248c2ecf20Sopenharmony_ci * @int_out: pointer to descriptor pointer, or NULL 1258c2ecf20Sopenharmony_ci * 1268c2ecf20Sopenharmony_ci * Search the alternate setting's endpoint descriptors for the first bulk-in, 1278c2ecf20Sopenharmony_ci * bulk-out, interrupt-in and interrupt-out endpoints and return them in the 1288c2ecf20Sopenharmony_ci * provided pointers (unless they are NULL). 1298c2ecf20Sopenharmony_ci * 1308c2ecf20Sopenharmony_ci * If a requested endpoint is not found, the corresponding pointer is set to 1318c2ecf20Sopenharmony_ci * NULL. 1328c2ecf20Sopenharmony_ci * 1338c2ecf20Sopenharmony_ci * Return: Zero if all requested descriptors were found, or -ENXIO otherwise. 1348c2ecf20Sopenharmony_ci */ 1358c2ecf20Sopenharmony_ciint usb_find_common_endpoints(struct usb_host_interface *alt, 1368c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **bulk_in, 1378c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **bulk_out, 1388c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **int_in, 1398c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **int_out) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor *epd; 1428c2ecf20Sopenharmony_ci int i; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci if (bulk_in) 1458c2ecf20Sopenharmony_ci *bulk_in = NULL; 1468c2ecf20Sopenharmony_ci if (bulk_out) 1478c2ecf20Sopenharmony_ci *bulk_out = NULL; 1488c2ecf20Sopenharmony_ci if (int_in) 1498c2ecf20Sopenharmony_ci *int_in = NULL; 1508c2ecf20Sopenharmony_ci if (int_out) 1518c2ecf20Sopenharmony_ci *int_out = NULL; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci for (i = 0; i < alt->desc.bNumEndpoints; ++i) { 1548c2ecf20Sopenharmony_ci epd = &alt->endpoint[i].desc; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (match_endpoint(epd, bulk_in, bulk_out, int_in, int_out)) 1578c2ecf20Sopenharmony_ci return 0; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci return -ENXIO; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_find_common_endpoints); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/** 1658c2ecf20Sopenharmony_ci * usb_find_common_endpoints_reverse() -- look up common endpoint descriptors 1668c2ecf20Sopenharmony_ci * @alt: alternate setting to search 1678c2ecf20Sopenharmony_ci * @bulk_in: pointer to descriptor pointer, or NULL 1688c2ecf20Sopenharmony_ci * @bulk_out: pointer to descriptor pointer, or NULL 1698c2ecf20Sopenharmony_ci * @int_in: pointer to descriptor pointer, or NULL 1708c2ecf20Sopenharmony_ci * @int_out: pointer to descriptor pointer, or NULL 1718c2ecf20Sopenharmony_ci * 1728c2ecf20Sopenharmony_ci * Search the alternate setting's endpoint descriptors for the last bulk-in, 1738c2ecf20Sopenharmony_ci * bulk-out, interrupt-in and interrupt-out endpoints and return them in the 1748c2ecf20Sopenharmony_ci * provided pointers (unless they are NULL). 1758c2ecf20Sopenharmony_ci * 1768c2ecf20Sopenharmony_ci * If a requested endpoint is not found, the corresponding pointer is set to 1778c2ecf20Sopenharmony_ci * NULL. 1788c2ecf20Sopenharmony_ci * 1798c2ecf20Sopenharmony_ci * Return: Zero if all requested descriptors were found, or -ENXIO otherwise. 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_ciint usb_find_common_endpoints_reverse(struct usb_host_interface *alt, 1828c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **bulk_in, 1838c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **bulk_out, 1848c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **int_in, 1858c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor **int_out) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor *epd; 1888c2ecf20Sopenharmony_ci int i; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (bulk_in) 1918c2ecf20Sopenharmony_ci *bulk_in = NULL; 1928c2ecf20Sopenharmony_ci if (bulk_out) 1938c2ecf20Sopenharmony_ci *bulk_out = NULL; 1948c2ecf20Sopenharmony_ci if (int_in) 1958c2ecf20Sopenharmony_ci *int_in = NULL; 1968c2ecf20Sopenharmony_ci if (int_out) 1978c2ecf20Sopenharmony_ci *int_out = NULL; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci for (i = alt->desc.bNumEndpoints - 1; i >= 0; --i) { 2008c2ecf20Sopenharmony_ci epd = &alt->endpoint[i].desc; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (match_endpoint(epd, bulk_in, bulk_out, int_in, int_out)) 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci return -ENXIO; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_find_common_endpoints_reverse); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci/** 2118c2ecf20Sopenharmony_ci * usb_find_endpoint() - Given an endpoint address, search for the endpoint's 2128c2ecf20Sopenharmony_ci * usb_host_endpoint structure in an interface's current altsetting. 2138c2ecf20Sopenharmony_ci * @intf: the interface whose current altsetting should be searched 2148c2ecf20Sopenharmony_ci * @ep_addr: the endpoint address (number and direction) to find 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * Search the altsetting's list of endpoints for one with the specified address. 2178c2ecf20Sopenharmony_ci * 2188c2ecf20Sopenharmony_ci * Return: Pointer to the usb_host_endpoint if found, %NULL otherwise. 2198c2ecf20Sopenharmony_ci */ 2208c2ecf20Sopenharmony_cistatic const struct usb_host_endpoint *usb_find_endpoint( 2218c2ecf20Sopenharmony_ci const struct usb_interface *intf, unsigned int ep_addr) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci int n; 2248c2ecf20Sopenharmony_ci const struct usb_host_endpoint *ep; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci n = intf->cur_altsetting->desc.bNumEndpoints; 2278c2ecf20Sopenharmony_ci ep = intf->cur_altsetting->endpoint; 2288c2ecf20Sopenharmony_ci for (; n > 0; (--n, ++ep)) { 2298c2ecf20Sopenharmony_ci if (ep->desc.bEndpointAddress == ep_addr) 2308c2ecf20Sopenharmony_ci return ep; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci return NULL; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci/** 2368c2ecf20Sopenharmony_ci * usb_check_bulk_endpoints - Check whether an interface's current altsetting 2378c2ecf20Sopenharmony_ci * contains a set of bulk endpoints with the given addresses. 2388c2ecf20Sopenharmony_ci * @intf: the interface whose current altsetting should be searched 2398c2ecf20Sopenharmony_ci * @ep_addrs: 0-terminated array of the endpoint addresses (number and 2408c2ecf20Sopenharmony_ci * direction) to look for 2418c2ecf20Sopenharmony_ci * 2428c2ecf20Sopenharmony_ci * Search for endpoints with the specified addresses and check their types. 2438c2ecf20Sopenharmony_ci * 2448c2ecf20Sopenharmony_ci * Return: %true if all the endpoints are found and are bulk, %false otherwise. 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_cibool usb_check_bulk_endpoints( 2478c2ecf20Sopenharmony_ci const struct usb_interface *intf, const u8 *ep_addrs) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci const struct usb_host_endpoint *ep; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci for (; *ep_addrs; ++ep_addrs) { 2528c2ecf20Sopenharmony_ci ep = usb_find_endpoint(intf, *ep_addrs); 2538c2ecf20Sopenharmony_ci if (!ep || !usb_endpoint_xfer_bulk(&ep->desc)) 2548c2ecf20Sopenharmony_ci return false; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci return true; 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_check_bulk_endpoints); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci/** 2618c2ecf20Sopenharmony_ci * usb_check_int_endpoints - Check whether an interface's current altsetting 2628c2ecf20Sopenharmony_ci * contains a set of interrupt endpoints with the given addresses. 2638c2ecf20Sopenharmony_ci * @intf: the interface whose current altsetting should be searched 2648c2ecf20Sopenharmony_ci * @ep_addrs: 0-terminated array of the endpoint addresses (number and 2658c2ecf20Sopenharmony_ci * direction) to look for 2668c2ecf20Sopenharmony_ci * 2678c2ecf20Sopenharmony_ci * Search for endpoints with the specified addresses and check their types. 2688c2ecf20Sopenharmony_ci * 2698c2ecf20Sopenharmony_ci * Return: %true if all the endpoints are found and are interrupt, 2708c2ecf20Sopenharmony_ci * %false otherwise. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_cibool usb_check_int_endpoints( 2738c2ecf20Sopenharmony_ci const struct usb_interface *intf, const u8 *ep_addrs) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci const struct usb_host_endpoint *ep; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci for (; *ep_addrs; ++ep_addrs) { 2788c2ecf20Sopenharmony_ci ep = usb_find_endpoint(intf, *ep_addrs); 2798c2ecf20Sopenharmony_ci if (!ep || !usb_endpoint_xfer_int(&ep->desc)) 2808c2ecf20Sopenharmony_ci return false; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci return true; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_check_int_endpoints); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci/** 2878c2ecf20Sopenharmony_ci * usb_find_alt_setting() - Given a configuration, find the alternate setting 2888c2ecf20Sopenharmony_ci * for the given interface. 2898c2ecf20Sopenharmony_ci * @config: the configuration to search (not necessarily the current config). 2908c2ecf20Sopenharmony_ci * @iface_num: interface number to search in 2918c2ecf20Sopenharmony_ci * @alt_num: alternate interface setting number to search for. 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * Search the configuration's interface cache for the given alt setting. 2948c2ecf20Sopenharmony_ci * 2958c2ecf20Sopenharmony_ci * Return: The alternate setting, if found. %NULL otherwise. 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_cistruct usb_host_interface *usb_find_alt_setting( 2988c2ecf20Sopenharmony_ci struct usb_host_config *config, 2998c2ecf20Sopenharmony_ci unsigned int iface_num, 3008c2ecf20Sopenharmony_ci unsigned int alt_num) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci struct usb_interface_cache *intf_cache = NULL; 3038c2ecf20Sopenharmony_ci int i; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (!config) 3068c2ecf20Sopenharmony_ci return NULL; 3078c2ecf20Sopenharmony_ci for (i = 0; i < config->desc.bNumInterfaces; i++) { 3088c2ecf20Sopenharmony_ci if (config->intf_cache[i]->altsetting[0].desc.bInterfaceNumber 3098c2ecf20Sopenharmony_ci == iface_num) { 3108c2ecf20Sopenharmony_ci intf_cache = config->intf_cache[i]; 3118c2ecf20Sopenharmony_ci break; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci if (!intf_cache) 3158c2ecf20Sopenharmony_ci return NULL; 3168c2ecf20Sopenharmony_ci for (i = 0; i < intf_cache->num_altsetting; i++) 3178c2ecf20Sopenharmony_ci if (intf_cache->altsetting[i].desc.bAlternateSetting == alt_num) 3188c2ecf20Sopenharmony_ci return &intf_cache->altsetting[i]; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Did not find alt setting %u for intf %u, " 3218c2ecf20Sopenharmony_ci "config %u\n", alt_num, iface_num, 3228c2ecf20Sopenharmony_ci config->desc.bConfigurationValue); 3238c2ecf20Sopenharmony_ci return NULL; 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_find_alt_setting); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci/** 3288c2ecf20Sopenharmony_ci * usb_ifnum_to_if - get the interface object with a given interface number 3298c2ecf20Sopenharmony_ci * @dev: the device whose current configuration is considered 3308c2ecf20Sopenharmony_ci * @ifnum: the desired interface 3318c2ecf20Sopenharmony_ci * 3328c2ecf20Sopenharmony_ci * This walks the device descriptor for the currently active configuration 3338c2ecf20Sopenharmony_ci * to find the interface object with the particular interface number. 3348c2ecf20Sopenharmony_ci * 3358c2ecf20Sopenharmony_ci * Note that configuration descriptors are not required to assign interface 3368c2ecf20Sopenharmony_ci * numbers sequentially, so that it would be incorrect to assume that 3378c2ecf20Sopenharmony_ci * the first interface in that descriptor corresponds to interface zero. 3388c2ecf20Sopenharmony_ci * This routine helps device drivers avoid such mistakes. 3398c2ecf20Sopenharmony_ci * However, you should make sure that you do the right thing with any 3408c2ecf20Sopenharmony_ci * alternate settings available for this interfaces. 3418c2ecf20Sopenharmony_ci * 3428c2ecf20Sopenharmony_ci * Don't call this function unless you are bound to one of the interfaces 3438c2ecf20Sopenharmony_ci * on this device or you have locked the device! 3448c2ecf20Sopenharmony_ci * 3458c2ecf20Sopenharmony_ci * Return: A pointer to the interface that has @ifnum as interface number, 3468c2ecf20Sopenharmony_ci * if found. %NULL otherwise. 3478c2ecf20Sopenharmony_ci */ 3488c2ecf20Sopenharmony_cistruct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, 3498c2ecf20Sopenharmony_ci unsigned ifnum) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci struct usb_host_config *config = dev->actconfig; 3528c2ecf20Sopenharmony_ci int i; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci if (!config) 3558c2ecf20Sopenharmony_ci return NULL; 3568c2ecf20Sopenharmony_ci for (i = 0; i < config->desc.bNumInterfaces; i++) 3578c2ecf20Sopenharmony_ci if (config->interface[i]->altsetting[0] 3588c2ecf20Sopenharmony_ci .desc.bInterfaceNumber == ifnum) 3598c2ecf20Sopenharmony_ci return config->interface[i]; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return NULL; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_ifnum_to_if); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci/** 3668c2ecf20Sopenharmony_ci * usb_altnum_to_altsetting - get the altsetting structure with a given alternate setting number. 3678c2ecf20Sopenharmony_ci * @intf: the interface containing the altsetting in question 3688c2ecf20Sopenharmony_ci * @altnum: the desired alternate setting number 3698c2ecf20Sopenharmony_ci * 3708c2ecf20Sopenharmony_ci * This searches the altsetting array of the specified interface for 3718c2ecf20Sopenharmony_ci * an entry with the correct bAlternateSetting value. 3728c2ecf20Sopenharmony_ci * 3738c2ecf20Sopenharmony_ci * Note that altsettings need not be stored sequentially by number, so 3748c2ecf20Sopenharmony_ci * it would be incorrect to assume that the first altsetting entry in 3758c2ecf20Sopenharmony_ci * the array corresponds to altsetting zero. This routine helps device 3768c2ecf20Sopenharmony_ci * drivers avoid such mistakes. 3778c2ecf20Sopenharmony_ci * 3788c2ecf20Sopenharmony_ci * Don't call this function unless you are bound to the intf interface 3798c2ecf20Sopenharmony_ci * or you have locked the device! 3808c2ecf20Sopenharmony_ci * 3818c2ecf20Sopenharmony_ci * Return: A pointer to the entry of the altsetting array of @intf that 3828c2ecf20Sopenharmony_ci * has @altnum as the alternate setting number. %NULL if not found. 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_cistruct usb_host_interface *usb_altnum_to_altsetting( 3858c2ecf20Sopenharmony_ci const struct usb_interface *intf, 3868c2ecf20Sopenharmony_ci unsigned int altnum) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci int i; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci for (i = 0; i < intf->num_altsetting; i++) { 3918c2ecf20Sopenharmony_ci if (intf->altsetting[i].desc.bAlternateSetting == altnum) 3928c2ecf20Sopenharmony_ci return &intf->altsetting[i]; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci return NULL; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_altnum_to_altsetting); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistruct find_interface_arg { 3998c2ecf20Sopenharmony_ci int minor; 4008c2ecf20Sopenharmony_ci struct device_driver *drv; 4018c2ecf20Sopenharmony_ci}; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic int __find_interface(struct device *dev, const void *data) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci const struct find_interface_arg *arg = data; 4068c2ecf20Sopenharmony_ci struct usb_interface *intf; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (!is_usb_interface(dev)) 4098c2ecf20Sopenharmony_ci return 0; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (dev->driver != arg->drv) 4128c2ecf20Sopenharmony_ci return 0; 4138c2ecf20Sopenharmony_ci intf = to_usb_interface(dev); 4148c2ecf20Sopenharmony_ci return intf->minor == arg->minor; 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci/** 4188c2ecf20Sopenharmony_ci * usb_find_interface - find usb_interface pointer for driver and device 4198c2ecf20Sopenharmony_ci * @drv: the driver whose current configuration is considered 4208c2ecf20Sopenharmony_ci * @minor: the minor number of the desired device 4218c2ecf20Sopenharmony_ci * 4228c2ecf20Sopenharmony_ci * This walks the bus device list and returns a pointer to the interface 4238c2ecf20Sopenharmony_ci * with the matching minor and driver. Note, this only works for devices 4248c2ecf20Sopenharmony_ci * that share the USB major number. 4258c2ecf20Sopenharmony_ci * 4268c2ecf20Sopenharmony_ci * Return: A pointer to the interface with the matching major and @minor. 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_cistruct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci struct find_interface_arg argb; 4318c2ecf20Sopenharmony_ci struct device *dev; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci argb.minor = minor; 4348c2ecf20Sopenharmony_ci argb.drv = &drv->drvwrap.driver; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci dev = bus_find_device(&usb_bus_type, NULL, &argb, __find_interface); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /* Drop reference count from bus_find_device */ 4398c2ecf20Sopenharmony_ci put_device(dev); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci return dev ? to_usb_interface(dev) : NULL; 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_find_interface); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistruct each_dev_arg { 4468c2ecf20Sopenharmony_ci void *data; 4478c2ecf20Sopenharmony_ci int (*fn)(struct usb_device *, void *); 4488c2ecf20Sopenharmony_ci}; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int __each_dev(struct device *dev, void *data) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci struct each_dev_arg *arg = (struct each_dev_arg *)data; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /* There are struct usb_interface on the same bus, filter them out */ 4558c2ecf20Sopenharmony_ci if (!is_usb_device(dev)) 4568c2ecf20Sopenharmony_ci return 0; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci return arg->fn(to_usb_device(dev), arg->data); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci/** 4628c2ecf20Sopenharmony_ci * usb_for_each_dev - iterate over all USB devices in the system 4638c2ecf20Sopenharmony_ci * @data: data pointer that will be handed to the callback function 4648c2ecf20Sopenharmony_ci * @fn: callback function to be called for each USB device 4658c2ecf20Sopenharmony_ci * 4668c2ecf20Sopenharmony_ci * Iterate over all USB devices and call @fn for each, passing it @data. If it 4678c2ecf20Sopenharmony_ci * returns anything other than 0, we break the iteration prematurely and return 4688c2ecf20Sopenharmony_ci * that value. 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_ciint usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *)) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci struct each_dev_arg arg = {data, fn}; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci return bus_for_each_dev(&usb_bus_type, NULL, &arg, __each_dev); 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_for_each_dev); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci/** 4798c2ecf20Sopenharmony_ci * usb_release_dev - free a usb device structure when all users of it are finished. 4808c2ecf20Sopenharmony_ci * @dev: device that's been disconnected 4818c2ecf20Sopenharmony_ci * 4828c2ecf20Sopenharmony_ci * Will be called only by the device core when all users of this usb device are 4838c2ecf20Sopenharmony_ci * done. 4848c2ecf20Sopenharmony_ci */ 4858c2ecf20Sopenharmony_cistatic void usb_release_dev(struct device *dev) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci struct usb_device *udev; 4888c2ecf20Sopenharmony_ci struct usb_hcd *hcd; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci udev = to_usb_device(dev); 4918c2ecf20Sopenharmony_ci hcd = bus_to_hcd(udev->bus); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci usb_destroy_configuration(udev); 4948c2ecf20Sopenharmony_ci usb_release_bos_descriptor(udev); 4958c2ecf20Sopenharmony_ci of_node_put(dev->of_node); 4968c2ecf20Sopenharmony_ci usb_put_hcd(hcd); 4978c2ecf20Sopenharmony_ci kfree(udev->product); 4988c2ecf20Sopenharmony_ci kfree(udev->manufacturer); 4998c2ecf20Sopenharmony_ci kfree(udev->serial); 5008c2ecf20Sopenharmony_ci kfree(udev); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci struct usb_device *usb_dev; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci usb_dev = to_usb_device(dev); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum)) 5108c2ecf20Sopenharmony_ci return -ENOMEM; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum)) 5138c2ecf20Sopenharmony_ci return -ENOMEM; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci return 0; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci/* USB device Power-Management thunks. 5218c2ecf20Sopenharmony_ci * There's no need to distinguish here between quiescing a USB device 5228c2ecf20Sopenharmony_ci * and powering it down; the generic_suspend() routine takes care of 5238c2ecf20Sopenharmony_ci * it by skipping the usb_port_suspend() call for a quiesce. And for 5248c2ecf20Sopenharmony_ci * USB interfaces there's no difference at all. 5258c2ecf20Sopenharmony_ci */ 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_cistatic int usb_dev_prepare(struct device *dev) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci return 0; /* Implement eventually? */ 5308c2ecf20Sopenharmony_ci} 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_cistatic void usb_dev_complete(struct device *dev) 5338c2ecf20Sopenharmony_ci{ 5348c2ecf20Sopenharmony_ci /* Currently used only for rebinding interfaces */ 5358c2ecf20Sopenharmony_ci usb_resume_complete(dev); 5368c2ecf20Sopenharmony_ci} 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic int usb_dev_suspend(struct device *dev) 5398c2ecf20Sopenharmony_ci{ 5408c2ecf20Sopenharmony_ci return usb_suspend(dev, PMSG_SUSPEND); 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic int usb_dev_resume(struct device *dev) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci return usb_resume(dev, PMSG_RESUME); 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic int usb_dev_freeze(struct device *dev) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci return usb_suspend(dev, PMSG_FREEZE); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic int usb_dev_thaw(struct device *dev) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci return usb_resume(dev, PMSG_THAW); 5568c2ecf20Sopenharmony_ci} 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cistatic int usb_dev_poweroff(struct device *dev) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci return usb_suspend(dev, PMSG_HIBERNATE); 5618c2ecf20Sopenharmony_ci} 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_cistatic int usb_dev_restore(struct device *dev) 5648c2ecf20Sopenharmony_ci{ 5658c2ecf20Sopenharmony_ci return usb_resume(dev, PMSG_RESTORE); 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic const struct dev_pm_ops usb_device_pm_ops = { 5698c2ecf20Sopenharmony_ci .prepare = usb_dev_prepare, 5708c2ecf20Sopenharmony_ci .complete = usb_dev_complete, 5718c2ecf20Sopenharmony_ci .suspend = usb_dev_suspend, 5728c2ecf20Sopenharmony_ci .resume = usb_dev_resume, 5738c2ecf20Sopenharmony_ci .freeze = usb_dev_freeze, 5748c2ecf20Sopenharmony_ci .thaw = usb_dev_thaw, 5758c2ecf20Sopenharmony_ci .poweroff = usb_dev_poweroff, 5768c2ecf20Sopenharmony_ci .restore = usb_dev_restore, 5778c2ecf20Sopenharmony_ci .runtime_suspend = usb_runtime_suspend, 5788c2ecf20Sopenharmony_ci .runtime_resume = usb_runtime_resume, 5798c2ecf20Sopenharmony_ci .runtime_idle = usb_runtime_idle, 5808c2ecf20Sopenharmony_ci}; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */ 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic char *usb_devnode(struct device *dev, 5868c2ecf20Sopenharmony_ci umode_t *mode, kuid_t *uid, kgid_t *gid) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci struct usb_device *usb_dev; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci usb_dev = to_usb_device(dev); 5918c2ecf20Sopenharmony_ci return kasprintf(GFP_KERNEL, "bus/usb/%03d/%03d", 5928c2ecf20Sopenharmony_ci usb_dev->bus->busnum, usb_dev->devnum); 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_cistruct device_type usb_device_type = { 5968c2ecf20Sopenharmony_ci .name = "usb_device", 5978c2ecf20Sopenharmony_ci .release = usb_release_dev, 5988c2ecf20Sopenharmony_ci .uevent = usb_dev_uevent, 5998c2ecf20Sopenharmony_ci .devnode = usb_devnode, 6008c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 6018c2ecf20Sopenharmony_ci .pm = &usb_device_pm_ops, 6028c2ecf20Sopenharmony_ci#endif 6038c2ecf20Sopenharmony_ci}; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci/* Returns 1 if @usb_bus is WUSB, 0 otherwise */ 6078c2ecf20Sopenharmony_cistatic unsigned usb_bus_is_wusb(struct usb_bus *bus) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci struct usb_hcd *hcd = bus_to_hcd(bus); 6108c2ecf20Sopenharmony_ci return hcd->wireless; 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cistatic bool usb_dev_authorized(struct usb_device *dev, struct usb_hcd *hcd) 6148c2ecf20Sopenharmony_ci{ 6158c2ecf20Sopenharmony_ci struct usb_hub *hub; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci if (!dev->parent) 6188c2ecf20Sopenharmony_ci return true; /* Root hub always ok [and always wired] */ 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci switch (hcd->dev_policy) { 6218c2ecf20Sopenharmony_ci case USB_DEVICE_AUTHORIZE_NONE: 6228c2ecf20Sopenharmony_ci default: 6238c2ecf20Sopenharmony_ci return false; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci case USB_DEVICE_AUTHORIZE_ALL: 6268c2ecf20Sopenharmony_ci return true; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci case USB_DEVICE_AUTHORIZE_INTERNAL: 6298c2ecf20Sopenharmony_ci hub = usb_hub_to_struct_hub(dev->parent); 6308c2ecf20Sopenharmony_ci return hub->ports[dev->portnum - 1]->connect_type == 6318c2ecf20Sopenharmony_ci USB_PORT_CONNECT_TYPE_HARD_WIRED; 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci/** 6368c2ecf20Sopenharmony_ci * usb_alloc_dev - usb device constructor (usbcore-internal) 6378c2ecf20Sopenharmony_ci * @parent: hub to which device is connected; null to allocate a root hub 6388c2ecf20Sopenharmony_ci * @bus: bus used to access the device 6398c2ecf20Sopenharmony_ci * @port1: one-based index of port; ignored for root hubs 6408c2ecf20Sopenharmony_ci * Context: !in_interrupt() 6418c2ecf20Sopenharmony_ci * 6428c2ecf20Sopenharmony_ci * Only hub drivers (including virtual root hub drivers for host 6438c2ecf20Sopenharmony_ci * controllers) should ever call this. 6448c2ecf20Sopenharmony_ci * 6458c2ecf20Sopenharmony_ci * This call may not be used in a non-sleeping context. 6468c2ecf20Sopenharmony_ci * 6478c2ecf20Sopenharmony_ci * Return: On success, a pointer to the allocated usb device. %NULL on 6488c2ecf20Sopenharmony_ci * failure. 6498c2ecf20Sopenharmony_ci */ 6508c2ecf20Sopenharmony_cistruct usb_device *usb_alloc_dev(struct usb_device *parent, 6518c2ecf20Sopenharmony_ci struct usb_bus *bus, unsigned port1) 6528c2ecf20Sopenharmony_ci{ 6538c2ecf20Sopenharmony_ci struct usb_device *dev; 6548c2ecf20Sopenharmony_ci struct usb_hcd *usb_hcd = bus_to_hcd(bus); 6558c2ecf20Sopenharmony_ci unsigned root_hub = 0; 6568c2ecf20Sopenharmony_ci unsigned raw_port = port1; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci dev = kzalloc(sizeof(*dev), GFP_KERNEL); 6598c2ecf20Sopenharmony_ci if (!dev) 6608c2ecf20Sopenharmony_ci return NULL; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci if (!usb_get_hcd(usb_hcd)) { 6638c2ecf20Sopenharmony_ci kfree(dev); 6648c2ecf20Sopenharmony_ci return NULL; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci /* Root hubs aren't true devices, so don't allocate HCD resources */ 6678c2ecf20Sopenharmony_ci if (usb_hcd->driver->alloc_dev && parent && 6688c2ecf20Sopenharmony_ci !usb_hcd->driver->alloc_dev(usb_hcd, dev)) { 6698c2ecf20Sopenharmony_ci usb_put_hcd(bus_to_hcd(bus)); 6708c2ecf20Sopenharmony_ci kfree(dev); 6718c2ecf20Sopenharmony_ci return NULL; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci device_initialize(&dev->dev); 6758c2ecf20Sopenharmony_ci dev->dev.bus = &usb_bus_type; 6768c2ecf20Sopenharmony_ci dev->dev.type = &usb_device_type; 6778c2ecf20Sopenharmony_ci dev->dev.groups = usb_device_groups; 6788c2ecf20Sopenharmony_ci set_dev_node(&dev->dev, dev_to_node(bus->sysdev)); 6798c2ecf20Sopenharmony_ci dev->state = USB_STATE_ATTACHED; 6808c2ecf20Sopenharmony_ci dev->lpm_disable_count = 1; 6818c2ecf20Sopenharmony_ci atomic_set(&dev->urbnum, 0); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dev->ep0.urb_list); 6848c2ecf20Sopenharmony_ci dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; 6858c2ecf20Sopenharmony_ci dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; 6868c2ecf20Sopenharmony_ci /* ep0 maxpacket comes later, from device descriptor */ 6878c2ecf20Sopenharmony_ci usb_enable_endpoint(dev, &dev->ep0, false); 6888c2ecf20Sopenharmony_ci dev->can_submit = 1; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci /* Save readable and stable topology id, distinguishing devices 6918c2ecf20Sopenharmony_ci * by location for diagnostics, tools, driver model, etc. The 6928c2ecf20Sopenharmony_ci * string is a path along hub ports, from the root. Each device's 6938c2ecf20Sopenharmony_ci * dev->devpath will be stable until USB is re-cabled, and hubs 6948c2ecf20Sopenharmony_ci * are often labeled with these port numbers. The name isn't 6958c2ecf20Sopenharmony_ci * as stable: bus->busnum changes easily from modprobe order, 6968c2ecf20Sopenharmony_ci * cardbus or pci hotplugging, and so on. 6978c2ecf20Sopenharmony_ci */ 6988c2ecf20Sopenharmony_ci if (unlikely(!parent)) { 6998c2ecf20Sopenharmony_ci dev->devpath[0] = '0'; 7008c2ecf20Sopenharmony_ci dev->route = 0; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci dev->dev.parent = bus->controller; 7038c2ecf20Sopenharmony_ci device_set_of_node_from_dev(&dev->dev, bus->sysdev); 7048c2ecf20Sopenharmony_ci dev_set_name(&dev->dev, "usb%d", bus->busnum); 7058c2ecf20Sopenharmony_ci root_hub = 1; 7068c2ecf20Sopenharmony_ci } else { 7078c2ecf20Sopenharmony_ci /* match any labeling on the hubs; it's one-based */ 7088c2ecf20Sopenharmony_ci if (parent->devpath[0] == '0') { 7098c2ecf20Sopenharmony_ci snprintf(dev->devpath, sizeof dev->devpath, 7108c2ecf20Sopenharmony_ci "%d", port1); 7118c2ecf20Sopenharmony_ci /* Root ports are not counted in route string */ 7128c2ecf20Sopenharmony_ci dev->route = 0; 7138c2ecf20Sopenharmony_ci } else { 7148c2ecf20Sopenharmony_ci snprintf(dev->devpath, sizeof dev->devpath, 7158c2ecf20Sopenharmony_ci "%s.%d", parent->devpath, port1); 7168c2ecf20Sopenharmony_ci /* Route string assumes hubs have less than 16 ports */ 7178c2ecf20Sopenharmony_ci if (port1 < 15) 7188c2ecf20Sopenharmony_ci dev->route = parent->route + 7198c2ecf20Sopenharmony_ci (port1 << ((parent->level - 1)*4)); 7208c2ecf20Sopenharmony_ci else 7218c2ecf20Sopenharmony_ci dev->route = parent->route + 7228c2ecf20Sopenharmony_ci (15 << ((parent->level - 1)*4)); 7238c2ecf20Sopenharmony_ci } 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci dev->dev.parent = &parent->dev; 7268c2ecf20Sopenharmony_ci dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath); 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci if (!parent->parent) { 7298c2ecf20Sopenharmony_ci /* device under root hub's port */ 7308c2ecf20Sopenharmony_ci raw_port = usb_hcd_find_raw_port_number(usb_hcd, 7318c2ecf20Sopenharmony_ci port1); 7328c2ecf20Sopenharmony_ci } 7338c2ecf20Sopenharmony_ci dev->dev.of_node = usb_of_get_device_node(parent, raw_port); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci /* hub driver sets up TT records */ 7368c2ecf20Sopenharmony_ci } 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci dev->portnum = port1; 7398c2ecf20Sopenharmony_ci dev->bus = bus; 7408c2ecf20Sopenharmony_ci dev->parent = parent; 7418c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dev->filelist); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 7448c2ecf20Sopenharmony_ci pm_runtime_set_autosuspend_delay(&dev->dev, 7458c2ecf20Sopenharmony_ci usb_autosuspend_delay * 1000); 7468c2ecf20Sopenharmony_ci dev->connect_time = jiffies; 7478c2ecf20Sopenharmony_ci dev->active_duration = -jiffies; 7488c2ecf20Sopenharmony_ci#endif 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci dev->authorized = usb_dev_authorized(dev, usb_hcd); 7518c2ecf20Sopenharmony_ci if (!root_hub) 7528c2ecf20Sopenharmony_ci dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci return dev; 7558c2ecf20Sopenharmony_ci} 7568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_alloc_dev); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci/** 7598c2ecf20Sopenharmony_ci * usb_get_dev - increments the reference count of the usb device structure 7608c2ecf20Sopenharmony_ci * @dev: the device being referenced 7618c2ecf20Sopenharmony_ci * 7628c2ecf20Sopenharmony_ci * Each live reference to a device should be refcounted. 7638c2ecf20Sopenharmony_ci * 7648c2ecf20Sopenharmony_ci * Drivers for USB interfaces should normally record such references in 7658c2ecf20Sopenharmony_ci * their probe() methods, when they bind to an interface, and release 7668c2ecf20Sopenharmony_ci * them by calling usb_put_dev(), in their disconnect() methods. 7678c2ecf20Sopenharmony_ci * 7688c2ecf20Sopenharmony_ci * Return: A pointer to the device with the incremented reference counter. 7698c2ecf20Sopenharmony_ci */ 7708c2ecf20Sopenharmony_cistruct usb_device *usb_get_dev(struct usb_device *dev) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci if (dev) 7738c2ecf20Sopenharmony_ci get_device(&dev->dev); 7748c2ecf20Sopenharmony_ci return dev; 7758c2ecf20Sopenharmony_ci} 7768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_get_dev); 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci/** 7798c2ecf20Sopenharmony_ci * usb_put_dev - release a use of the usb device structure 7808c2ecf20Sopenharmony_ci * @dev: device that's been disconnected 7818c2ecf20Sopenharmony_ci * 7828c2ecf20Sopenharmony_ci * Must be called when a user of a device is finished with it. When the last 7838c2ecf20Sopenharmony_ci * user of the device calls this function, the memory of the device is freed. 7848c2ecf20Sopenharmony_ci */ 7858c2ecf20Sopenharmony_civoid usb_put_dev(struct usb_device *dev) 7868c2ecf20Sopenharmony_ci{ 7878c2ecf20Sopenharmony_ci if (dev) 7888c2ecf20Sopenharmony_ci put_device(&dev->dev); 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_put_dev); 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci/** 7938c2ecf20Sopenharmony_ci * usb_get_intf - increments the reference count of the usb interface structure 7948c2ecf20Sopenharmony_ci * @intf: the interface being referenced 7958c2ecf20Sopenharmony_ci * 7968c2ecf20Sopenharmony_ci * Each live reference to a interface must be refcounted. 7978c2ecf20Sopenharmony_ci * 7988c2ecf20Sopenharmony_ci * Drivers for USB interfaces should normally record such references in 7998c2ecf20Sopenharmony_ci * their probe() methods, when they bind to an interface, and release 8008c2ecf20Sopenharmony_ci * them by calling usb_put_intf(), in their disconnect() methods. 8018c2ecf20Sopenharmony_ci * 8028c2ecf20Sopenharmony_ci * Return: A pointer to the interface with the incremented reference counter. 8038c2ecf20Sopenharmony_ci */ 8048c2ecf20Sopenharmony_cistruct usb_interface *usb_get_intf(struct usb_interface *intf) 8058c2ecf20Sopenharmony_ci{ 8068c2ecf20Sopenharmony_ci if (intf) 8078c2ecf20Sopenharmony_ci get_device(&intf->dev); 8088c2ecf20Sopenharmony_ci return intf; 8098c2ecf20Sopenharmony_ci} 8108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_get_intf); 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci/** 8138c2ecf20Sopenharmony_ci * usb_put_intf - release a use of the usb interface structure 8148c2ecf20Sopenharmony_ci * @intf: interface that's been decremented 8158c2ecf20Sopenharmony_ci * 8168c2ecf20Sopenharmony_ci * Must be called when a user of an interface is finished with it. When the 8178c2ecf20Sopenharmony_ci * last user of the interface calls this function, the memory of the interface 8188c2ecf20Sopenharmony_ci * is freed. 8198c2ecf20Sopenharmony_ci */ 8208c2ecf20Sopenharmony_civoid usb_put_intf(struct usb_interface *intf) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci if (intf) 8238c2ecf20Sopenharmony_ci put_device(&intf->dev); 8248c2ecf20Sopenharmony_ci} 8258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_put_intf); 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci/** 8288c2ecf20Sopenharmony_ci * usb_intf_get_dma_device - acquire a reference on the usb interface's DMA endpoint 8298c2ecf20Sopenharmony_ci * @intf: the usb interface 8308c2ecf20Sopenharmony_ci * 8318c2ecf20Sopenharmony_ci * While a USB device cannot perform DMA operations by itself, many USB 8328c2ecf20Sopenharmony_ci * controllers can. A call to usb_intf_get_dma_device() returns the DMA endpoint 8338c2ecf20Sopenharmony_ci * for the given USB interface, if any. The returned device structure must be 8348c2ecf20Sopenharmony_ci * released with put_device(). 8358c2ecf20Sopenharmony_ci * 8368c2ecf20Sopenharmony_ci * See also usb_get_dma_device(). 8378c2ecf20Sopenharmony_ci * 8388c2ecf20Sopenharmony_ci * Returns: A reference to the usb interface's DMA endpoint; or NULL if none 8398c2ecf20Sopenharmony_ci * exists. 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_cistruct device *usb_intf_get_dma_device(struct usb_interface *intf) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(intf); 8448c2ecf20Sopenharmony_ci struct device *dmadev; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci if (!udev->bus) 8478c2ecf20Sopenharmony_ci return NULL; 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci dmadev = get_device(udev->bus->sysdev); 8508c2ecf20Sopenharmony_ci if (!dmadev || !dmadev->dma_mask) { 8518c2ecf20Sopenharmony_ci put_device(dmadev); 8528c2ecf20Sopenharmony_ci return NULL; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci return dmadev; 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_intf_get_dma_device); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci/* USB device locking 8608c2ecf20Sopenharmony_ci * 8618c2ecf20Sopenharmony_ci * USB devices and interfaces are locked using the semaphore in their 8628c2ecf20Sopenharmony_ci * embedded struct device. The hub driver guarantees that whenever a 8638c2ecf20Sopenharmony_ci * device is connected or disconnected, drivers are called with the 8648c2ecf20Sopenharmony_ci * USB device locked as well as their particular interface. 8658c2ecf20Sopenharmony_ci * 8668c2ecf20Sopenharmony_ci * Complications arise when several devices are to be locked at the same 8678c2ecf20Sopenharmony_ci * time. Only hub-aware drivers that are part of usbcore ever have to 8688c2ecf20Sopenharmony_ci * do this; nobody else needs to worry about it. The rule for locking 8698c2ecf20Sopenharmony_ci * is simple: 8708c2ecf20Sopenharmony_ci * 8718c2ecf20Sopenharmony_ci * When locking both a device and its parent, always lock the 8728c2ecf20Sopenharmony_ci * the parent first. 8738c2ecf20Sopenharmony_ci */ 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci/** 8768c2ecf20Sopenharmony_ci * usb_lock_device_for_reset - cautiously acquire the lock for a usb device structure 8778c2ecf20Sopenharmony_ci * @udev: device that's being locked 8788c2ecf20Sopenharmony_ci * @iface: interface bound to the driver making the request (optional) 8798c2ecf20Sopenharmony_ci * 8808c2ecf20Sopenharmony_ci * Attempts to acquire the device lock, but fails if the device is 8818c2ecf20Sopenharmony_ci * NOTATTACHED or SUSPENDED, or if iface is specified and the interface 8828c2ecf20Sopenharmony_ci * is neither BINDING nor BOUND. Rather than sleeping to wait for the 8838c2ecf20Sopenharmony_ci * lock, the routine polls repeatedly. This is to prevent deadlock with 8848c2ecf20Sopenharmony_ci * disconnect; in some drivers (such as usb-storage) the disconnect() 8858c2ecf20Sopenharmony_ci * or suspend() method will block waiting for a device reset to complete. 8868c2ecf20Sopenharmony_ci * 8878c2ecf20Sopenharmony_ci * Return: A negative error code for failure, otherwise 0. 8888c2ecf20Sopenharmony_ci */ 8898c2ecf20Sopenharmony_ciint usb_lock_device_for_reset(struct usb_device *udev, 8908c2ecf20Sopenharmony_ci const struct usb_interface *iface) 8918c2ecf20Sopenharmony_ci{ 8928c2ecf20Sopenharmony_ci unsigned long jiffies_expire = jiffies + HZ; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (udev->state == USB_STATE_NOTATTACHED) 8958c2ecf20Sopenharmony_ci return -ENODEV; 8968c2ecf20Sopenharmony_ci if (udev->state == USB_STATE_SUSPENDED) 8978c2ecf20Sopenharmony_ci return -EHOSTUNREACH; 8988c2ecf20Sopenharmony_ci if (iface && (iface->condition == USB_INTERFACE_UNBINDING || 8998c2ecf20Sopenharmony_ci iface->condition == USB_INTERFACE_UNBOUND)) 9008c2ecf20Sopenharmony_ci return -EINTR; 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci while (!usb_trylock_device(udev)) { 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci /* If we can't acquire the lock after waiting one second, 9058c2ecf20Sopenharmony_ci * we're probably deadlocked */ 9068c2ecf20Sopenharmony_ci if (time_after(jiffies, jiffies_expire)) 9078c2ecf20Sopenharmony_ci return -EBUSY; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci msleep(15); 9108c2ecf20Sopenharmony_ci if (udev->state == USB_STATE_NOTATTACHED) 9118c2ecf20Sopenharmony_ci return -ENODEV; 9128c2ecf20Sopenharmony_ci if (udev->state == USB_STATE_SUSPENDED) 9138c2ecf20Sopenharmony_ci return -EHOSTUNREACH; 9148c2ecf20Sopenharmony_ci if (iface && (iface->condition == USB_INTERFACE_UNBINDING || 9158c2ecf20Sopenharmony_ci iface->condition == USB_INTERFACE_UNBOUND)) 9168c2ecf20Sopenharmony_ci return -EINTR; 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci return 0; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_lock_device_for_reset); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci/** 9238c2ecf20Sopenharmony_ci * usb_get_current_frame_number - return current bus frame number 9248c2ecf20Sopenharmony_ci * @dev: the device whose bus is being queried 9258c2ecf20Sopenharmony_ci * 9268c2ecf20Sopenharmony_ci * Return: The current frame number for the USB host controller used 9278c2ecf20Sopenharmony_ci * with the given USB device. This can be used when scheduling 9288c2ecf20Sopenharmony_ci * isochronous requests. 9298c2ecf20Sopenharmony_ci * 9308c2ecf20Sopenharmony_ci * Note: Different kinds of host controller have different "scheduling 9318c2ecf20Sopenharmony_ci * horizons". While one type might support scheduling only 32 frames 9328c2ecf20Sopenharmony_ci * into the future, others could support scheduling up to 1024 frames 9338c2ecf20Sopenharmony_ci * into the future. 9348c2ecf20Sopenharmony_ci * 9358c2ecf20Sopenharmony_ci */ 9368c2ecf20Sopenharmony_ciint usb_get_current_frame_number(struct usb_device *dev) 9378c2ecf20Sopenharmony_ci{ 9388c2ecf20Sopenharmony_ci return usb_hcd_get_frame_number(dev); 9398c2ecf20Sopenharmony_ci} 9408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_get_current_frame_number); 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------*/ 9438c2ecf20Sopenharmony_ci/* 9448c2ecf20Sopenharmony_ci * __usb_get_extra_descriptor() finds a descriptor of specific type in the 9458c2ecf20Sopenharmony_ci * extra field of the interface and endpoint descriptor structs. 9468c2ecf20Sopenharmony_ci */ 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ciint __usb_get_extra_descriptor(char *buffer, unsigned size, 9498c2ecf20Sopenharmony_ci unsigned char type, void **ptr, size_t minsize) 9508c2ecf20Sopenharmony_ci{ 9518c2ecf20Sopenharmony_ci struct usb_descriptor_header *header; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci while (size >= sizeof(struct usb_descriptor_header)) { 9548c2ecf20Sopenharmony_ci header = (struct usb_descriptor_header *)buffer; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci if (header->bLength < 2 || header->bLength > size) { 9578c2ecf20Sopenharmony_ci printk(KERN_ERR 9588c2ecf20Sopenharmony_ci "%s: bogus descriptor, type %d length %d\n", 9598c2ecf20Sopenharmony_ci usbcore_name, 9608c2ecf20Sopenharmony_ci header->bDescriptorType, 9618c2ecf20Sopenharmony_ci header->bLength); 9628c2ecf20Sopenharmony_ci return -1; 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci if (header->bDescriptorType == type && header->bLength >= minsize) { 9668c2ecf20Sopenharmony_ci *ptr = header; 9678c2ecf20Sopenharmony_ci return 0; 9688c2ecf20Sopenharmony_ci } 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci buffer += header->bLength; 9718c2ecf20Sopenharmony_ci size -= header->bLength; 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci return -1; 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__usb_get_extra_descriptor); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci/** 9788c2ecf20Sopenharmony_ci * usb_alloc_coherent - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP 9798c2ecf20Sopenharmony_ci * @dev: device the buffer will be used with 9808c2ecf20Sopenharmony_ci * @size: requested buffer size 9818c2ecf20Sopenharmony_ci * @mem_flags: affect whether allocation may block 9828c2ecf20Sopenharmony_ci * @dma: used to return DMA address of buffer 9838c2ecf20Sopenharmony_ci * 9848c2ecf20Sopenharmony_ci * Return: Either null (indicating no buffer could be allocated), or the 9858c2ecf20Sopenharmony_ci * cpu-space pointer to a buffer that may be used to perform DMA to the 9868c2ecf20Sopenharmony_ci * specified device. Such cpu-space buffers are returned along with the DMA 9878c2ecf20Sopenharmony_ci * address (through the pointer provided). 9888c2ecf20Sopenharmony_ci * 9898c2ecf20Sopenharmony_ci * Note: 9908c2ecf20Sopenharmony_ci * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags 9918c2ecf20Sopenharmony_ci * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU 9928c2ecf20Sopenharmony_ci * hardware during URB completion/resubmit. The implementation varies between 9938c2ecf20Sopenharmony_ci * platforms, depending on details of how DMA will work to this device. 9948c2ecf20Sopenharmony_ci * Using these buffers also eliminates cacheline sharing problems on 9958c2ecf20Sopenharmony_ci * architectures where CPU caches are not DMA-coherent. On systems without 9968c2ecf20Sopenharmony_ci * bus-snooping caches, these buffers are uncached. 9978c2ecf20Sopenharmony_ci * 9988c2ecf20Sopenharmony_ci * When the buffer is no longer used, free it with usb_free_coherent(). 9998c2ecf20Sopenharmony_ci */ 10008c2ecf20Sopenharmony_civoid *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags, 10018c2ecf20Sopenharmony_ci dma_addr_t *dma) 10028c2ecf20Sopenharmony_ci{ 10038c2ecf20Sopenharmony_ci if (!dev || !dev->bus) 10048c2ecf20Sopenharmony_ci return NULL; 10058c2ecf20Sopenharmony_ci return hcd_buffer_alloc(dev->bus, size, mem_flags, dma); 10068c2ecf20Sopenharmony_ci} 10078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_alloc_coherent); 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci/** 10108c2ecf20Sopenharmony_ci * usb_free_coherent - free memory allocated with usb_alloc_coherent() 10118c2ecf20Sopenharmony_ci * @dev: device the buffer was used with 10128c2ecf20Sopenharmony_ci * @size: requested buffer size 10138c2ecf20Sopenharmony_ci * @addr: CPU address of buffer 10148c2ecf20Sopenharmony_ci * @dma: DMA address of buffer 10158c2ecf20Sopenharmony_ci * 10168c2ecf20Sopenharmony_ci * This reclaims an I/O buffer, letting it be reused. The memory must have 10178c2ecf20Sopenharmony_ci * been allocated using usb_alloc_coherent(), and the parameters must match 10188c2ecf20Sopenharmony_ci * those provided in that allocation request. 10198c2ecf20Sopenharmony_ci */ 10208c2ecf20Sopenharmony_civoid usb_free_coherent(struct usb_device *dev, size_t size, void *addr, 10218c2ecf20Sopenharmony_ci dma_addr_t dma) 10228c2ecf20Sopenharmony_ci{ 10238c2ecf20Sopenharmony_ci if (!dev || !dev->bus) 10248c2ecf20Sopenharmony_ci return; 10258c2ecf20Sopenharmony_ci if (!addr) 10268c2ecf20Sopenharmony_ci return; 10278c2ecf20Sopenharmony_ci hcd_buffer_free(dev->bus, size, addr, dma); 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_free_coherent); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci/* 10328c2ecf20Sopenharmony_ci * Notifications of device and interface registration 10338c2ecf20Sopenharmony_ci */ 10348c2ecf20Sopenharmony_cistatic int usb_bus_notify(struct notifier_block *nb, unsigned long action, 10358c2ecf20Sopenharmony_ci void *data) 10368c2ecf20Sopenharmony_ci{ 10378c2ecf20Sopenharmony_ci struct device *dev = data; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci switch (action) { 10408c2ecf20Sopenharmony_ci case BUS_NOTIFY_ADD_DEVICE: 10418c2ecf20Sopenharmony_ci if (dev->type == &usb_device_type) 10428c2ecf20Sopenharmony_ci (void) usb_create_sysfs_dev_files(to_usb_device(dev)); 10438c2ecf20Sopenharmony_ci else if (dev->type == &usb_if_device_type) 10448c2ecf20Sopenharmony_ci usb_create_sysfs_intf_files(to_usb_interface(dev)); 10458c2ecf20Sopenharmony_ci break; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci case BUS_NOTIFY_DEL_DEVICE: 10488c2ecf20Sopenharmony_ci if (dev->type == &usb_device_type) 10498c2ecf20Sopenharmony_ci usb_remove_sysfs_dev_files(to_usb_device(dev)); 10508c2ecf20Sopenharmony_ci else if (dev->type == &usb_if_device_type) 10518c2ecf20Sopenharmony_ci usb_remove_sysfs_intf_files(to_usb_interface(dev)); 10528c2ecf20Sopenharmony_ci break; 10538c2ecf20Sopenharmony_ci } 10548c2ecf20Sopenharmony_ci return 0; 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_cistatic struct notifier_block usb_bus_nb = { 10588c2ecf20Sopenharmony_ci .notifier_call = usb_bus_notify, 10598c2ecf20Sopenharmony_ci}; 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_cistatic struct dentry *usb_devices_root; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_cistatic void usb_debugfs_init(void) 10648c2ecf20Sopenharmony_ci{ 10658c2ecf20Sopenharmony_ci usb_devices_root = debugfs_create_file("devices", 0444, usb_debug_root, 10668c2ecf20Sopenharmony_ci NULL, &usbfs_devices_fops); 10678c2ecf20Sopenharmony_ci} 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_cistatic void usb_debugfs_cleanup(void) 10708c2ecf20Sopenharmony_ci{ 10718c2ecf20Sopenharmony_ci debugfs_remove(usb_devices_root); 10728c2ecf20Sopenharmony_ci} 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci/* 10758c2ecf20Sopenharmony_ci * Init 10768c2ecf20Sopenharmony_ci */ 10778c2ecf20Sopenharmony_cistatic int __init usb_init(void) 10788c2ecf20Sopenharmony_ci{ 10798c2ecf20Sopenharmony_ci int retval; 10808c2ecf20Sopenharmony_ci if (usb_disabled()) { 10818c2ecf20Sopenharmony_ci pr_info("%s: USB support disabled\n", usbcore_name); 10828c2ecf20Sopenharmony_ci return 0; 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci usb_init_pool_max(); 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci usb_debugfs_init(); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci usb_acpi_register(); 10898c2ecf20Sopenharmony_ci retval = bus_register(&usb_bus_type); 10908c2ecf20Sopenharmony_ci if (retval) 10918c2ecf20Sopenharmony_ci goto bus_register_failed; 10928c2ecf20Sopenharmony_ci retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); 10938c2ecf20Sopenharmony_ci if (retval) 10948c2ecf20Sopenharmony_ci goto bus_notifier_failed; 10958c2ecf20Sopenharmony_ci retval = usb_major_init(); 10968c2ecf20Sopenharmony_ci if (retval) 10978c2ecf20Sopenharmony_ci goto major_init_failed; 10988c2ecf20Sopenharmony_ci retval = usb_register(&usbfs_driver); 10998c2ecf20Sopenharmony_ci if (retval) 11008c2ecf20Sopenharmony_ci goto driver_register_failed; 11018c2ecf20Sopenharmony_ci retval = usb_devio_init(); 11028c2ecf20Sopenharmony_ci if (retval) 11038c2ecf20Sopenharmony_ci goto usb_devio_init_failed; 11048c2ecf20Sopenharmony_ci retval = usb_hub_init(); 11058c2ecf20Sopenharmony_ci if (retval) 11068c2ecf20Sopenharmony_ci goto hub_init_failed; 11078c2ecf20Sopenharmony_ci retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE); 11088c2ecf20Sopenharmony_ci if (!retval) 11098c2ecf20Sopenharmony_ci goto out; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci usb_hub_cleanup(); 11128c2ecf20Sopenharmony_cihub_init_failed: 11138c2ecf20Sopenharmony_ci usb_devio_cleanup(); 11148c2ecf20Sopenharmony_ciusb_devio_init_failed: 11158c2ecf20Sopenharmony_ci usb_deregister(&usbfs_driver); 11168c2ecf20Sopenharmony_cidriver_register_failed: 11178c2ecf20Sopenharmony_ci usb_major_cleanup(); 11188c2ecf20Sopenharmony_cimajor_init_failed: 11198c2ecf20Sopenharmony_ci bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); 11208c2ecf20Sopenharmony_cibus_notifier_failed: 11218c2ecf20Sopenharmony_ci bus_unregister(&usb_bus_type); 11228c2ecf20Sopenharmony_cibus_register_failed: 11238c2ecf20Sopenharmony_ci usb_acpi_unregister(); 11248c2ecf20Sopenharmony_ci usb_debugfs_cleanup(); 11258c2ecf20Sopenharmony_ciout: 11268c2ecf20Sopenharmony_ci return retval; 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci/* 11308c2ecf20Sopenharmony_ci * Cleanup 11318c2ecf20Sopenharmony_ci */ 11328c2ecf20Sopenharmony_cistatic void __exit usb_exit(void) 11338c2ecf20Sopenharmony_ci{ 11348c2ecf20Sopenharmony_ci /* This will matter if shutdown/reboot does exitcalls. */ 11358c2ecf20Sopenharmony_ci if (usb_disabled()) 11368c2ecf20Sopenharmony_ci return; 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci usb_release_quirk_list(); 11398c2ecf20Sopenharmony_ci usb_deregister_device_driver(&usb_generic_driver); 11408c2ecf20Sopenharmony_ci usb_major_cleanup(); 11418c2ecf20Sopenharmony_ci usb_deregister(&usbfs_driver); 11428c2ecf20Sopenharmony_ci usb_devio_cleanup(); 11438c2ecf20Sopenharmony_ci usb_hub_cleanup(); 11448c2ecf20Sopenharmony_ci bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); 11458c2ecf20Sopenharmony_ci bus_unregister(&usb_bus_type); 11468c2ecf20Sopenharmony_ci usb_acpi_unregister(); 11478c2ecf20Sopenharmony_ci usb_debugfs_cleanup(); 11488c2ecf20Sopenharmony_ci idr_destroy(&usb_bus_idr); 11498c2ecf20Sopenharmony_ci} 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_cisubsys_initcall(usb_init); 11528c2ecf20Sopenharmony_cimodule_exit(usb_exit); 11538c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1154