18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * USB device quirk handling logic and table 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2007 Oliver Neukum 68c2ecf20Sopenharmony_ci * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 108c2ecf20Sopenharmony_ci#include <linux/usb.h> 118c2ecf20Sopenharmony_ci#include <linux/usb/quirks.h> 128c2ecf20Sopenharmony_ci#include <linux/usb/hcd.h> 138c2ecf20Sopenharmony_ci#include "usb.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistruct quirk_entry { 168c2ecf20Sopenharmony_ci u16 vid; 178c2ecf20Sopenharmony_ci u16 pid; 188c2ecf20Sopenharmony_ci u32 flags; 198c2ecf20Sopenharmony_ci}; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(quirk_mutex); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic struct quirk_entry *quirk_list; 248c2ecf20Sopenharmony_cistatic unsigned int quirk_count; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic char quirks_param[128]; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic int quirks_param_set(const char *value, const struct kernel_param *kp) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci char *val, *p, *field; 318c2ecf20Sopenharmony_ci u16 vid, pid; 328c2ecf20Sopenharmony_ci u32 flags; 338c2ecf20Sopenharmony_ci size_t i; 348c2ecf20Sopenharmony_ci int err; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci val = kstrdup(value, GFP_KERNEL); 378c2ecf20Sopenharmony_ci if (!val) 388c2ecf20Sopenharmony_ci return -ENOMEM; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci err = param_set_copystring(val, kp); 418c2ecf20Sopenharmony_ci if (err) { 428c2ecf20Sopenharmony_ci kfree(val); 438c2ecf20Sopenharmony_ci return err; 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci mutex_lock(&quirk_mutex); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (!*val) { 498c2ecf20Sopenharmony_ci quirk_count = 0; 508c2ecf20Sopenharmony_ci kfree(quirk_list); 518c2ecf20Sopenharmony_ci quirk_list = NULL; 528c2ecf20Sopenharmony_ci goto unlock; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci for (quirk_count = 1, i = 0; val[i]; i++) 568c2ecf20Sopenharmony_ci if (val[i] == ',') 578c2ecf20Sopenharmony_ci quirk_count++; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (quirk_list) { 608c2ecf20Sopenharmony_ci kfree(quirk_list); 618c2ecf20Sopenharmony_ci quirk_list = NULL; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry), 658c2ecf20Sopenharmony_ci GFP_KERNEL); 668c2ecf20Sopenharmony_ci if (!quirk_list) { 678c2ecf20Sopenharmony_ci quirk_count = 0; 688c2ecf20Sopenharmony_ci mutex_unlock(&quirk_mutex); 698c2ecf20Sopenharmony_ci kfree(val); 708c2ecf20Sopenharmony_ci return -ENOMEM; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci for (i = 0, p = val; p && *p;) { 748c2ecf20Sopenharmony_ci /* Each entry consists of VID:PID:flags */ 758c2ecf20Sopenharmony_ci field = strsep(&p, ":"); 768c2ecf20Sopenharmony_ci if (!field) 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (kstrtou16(field, 16, &vid)) 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci field = strsep(&p, ":"); 838c2ecf20Sopenharmony_ci if (!field) 848c2ecf20Sopenharmony_ci break; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (kstrtou16(field, 16, &pid)) 878c2ecf20Sopenharmony_ci break; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci field = strsep(&p, ","); 908c2ecf20Sopenharmony_ci if (!field || !*field) 918c2ecf20Sopenharmony_ci break; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Collect the flags */ 948c2ecf20Sopenharmony_ci for (flags = 0; *field; field++) { 958c2ecf20Sopenharmony_ci switch (*field) { 968c2ecf20Sopenharmony_ci case 'a': 978c2ecf20Sopenharmony_ci flags |= USB_QUIRK_STRING_FETCH_255; 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci case 'b': 1008c2ecf20Sopenharmony_ci flags |= USB_QUIRK_RESET_RESUME; 1018c2ecf20Sopenharmony_ci break; 1028c2ecf20Sopenharmony_ci case 'c': 1038c2ecf20Sopenharmony_ci flags |= USB_QUIRK_NO_SET_INTF; 1048c2ecf20Sopenharmony_ci break; 1058c2ecf20Sopenharmony_ci case 'd': 1068c2ecf20Sopenharmony_ci flags |= USB_QUIRK_CONFIG_INTF_STRINGS; 1078c2ecf20Sopenharmony_ci break; 1088c2ecf20Sopenharmony_ci case 'e': 1098c2ecf20Sopenharmony_ci flags |= USB_QUIRK_RESET; 1108c2ecf20Sopenharmony_ci break; 1118c2ecf20Sopenharmony_ci case 'f': 1128c2ecf20Sopenharmony_ci flags |= USB_QUIRK_HONOR_BNUMINTERFACES; 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci case 'g': 1158c2ecf20Sopenharmony_ci flags |= USB_QUIRK_DELAY_INIT; 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci case 'h': 1188c2ecf20Sopenharmony_ci flags |= USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL; 1198c2ecf20Sopenharmony_ci break; 1208c2ecf20Sopenharmony_ci case 'i': 1218c2ecf20Sopenharmony_ci flags |= USB_QUIRK_DEVICE_QUALIFIER; 1228c2ecf20Sopenharmony_ci break; 1238c2ecf20Sopenharmony_ci case 'j': 1248c2ecf20Sopenharmony_ci flags |= USB_QUIRK_IGNORE_REMOTE_WAKEUP; 1258c2ecf20Sopenharmony_ci break; 1268c2ecf20Sopenharmony_ci case 'k': 1278c2ecf20Sopenharmony_ci flags |= USB_QUIRK_NO_LPM; 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci case 'l': 1308c2ecf20Sopenharmony_ci flags |= USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL; 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci case 'm': 1338c2ecf20Sopenharmony_ci flags |= USB_QUIRK_DISCONNECT_SUSPEND; 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci case 'n': 1368c2ecf20Sopenharmony_ci flags |= USB_QUIRK_DELAY_CTRL_MSG; 1378c2ecf20Sopenharmony_ci break; 1388c2ecf20Sopenharmony_ci case 'o': 1398c2ecf20Sopenharmony_ci flags |= USB_QUIRK_HUB_SLOW_RESET; 1408c2ecf20Sopenharmony_ci break; 1418c2ecf20Sopenharmony_ci /* Ignore unrecognized flag characters */ 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci quirk_list[i++] = (struct quirk_entry) 1468c2ecf20Sopenharmony_ci { .vid = vid, .pid = pid, .flags = flags }; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci if (i < quirk_count) 1508c2ecf20Sopenharmony_ci quirk_count = i; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciunlock: 1538c2ecf20Sopenharmony_ci mutex_unlock(&quirk_mutex); 1548c2ecf20Sopenharmony_ci kfree(val); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return 0; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic const struct kernel_param_ops quirks_param_ops = { 1608c2ecf20Sopenharmony_ci .set = quirks_param_set, 1618c2ecf20Sopenharmony_ci .get = param_get_string, 1628c2ecf20Sopenharmony_ci}; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic struct kparam_string quirks_param_string = { 1658c2ecf20Sopenharmony_ci .maxlen = sizeof(quirks_param), 1668c2ecf20Sopenharmony_ci .string = quirks_param, 1678c2ecf20Sopenharmony_ci}; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cidevice_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644); 1708c2ecf20Sopenharmony_ciMODULE_PARM_DESC(quirks, "Add/modify USB quirks by specifying quirks=vendorID:productID:quirks"); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* Lists of quirky USB devices, split in device quirks and interface quirks. 1738c2ecf20Sopenharmony_ci * Device quirks are applied at the very beginning of the enumeration process, 1748c2ecf20Sopenharmony_ci * right after reading the device descriptor. They can thus only match on device 1758c2ecf20Sopenharmony_ci * information. 1768c2ecf20Sopenharmony_ci * 1778c2ecf20Sopenharmony_ci * Interface quirks are applied after reading all the configuration descriptors. 1788c2ecf20Sopenharmony_ci * They can match on both device and interface information. 1798c2ecf20Sopenharmony_ci * 1808c2ecf20Sopenharmony_ci * Note that the DELAY_INIT and HONOR_BNUMINTERFACES quirks do not make sense as 1818c2ecf20Sopenharmony_ci * interface quirks, as they only influence the enumeration process which is run 1828c2ecf20Sopenharmony_ci * before processing the interface quirks. 1838c2ecf20Sopenharmony_ci * 1848c2ecf20Sopenharmony_ci * Please keep the lists ordered by: 1858c2ecf20Sopenharmony_ci * 1) Vendor ID 1868c2ecf20Sopenharmony_ci * 2) Product ID 1878c2ecf20Sopenharmony_ci * 3) Class ID 1888c2ecf20Sopenharmony_ci */ 1898c2ecf20Sopenharmony_cistatic const struct usb_device_id usb_quirk_list[] = { 1908c2ecf20Sopenharmony_ci /* CBM - Flash disk */ 1918c2ecf20Sopenharmony_ci { USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME }, 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* WORLDE Controller KS49 or Prodipe MIDI 49C USB controller */ 1948c2ecf20Sopenharmony_ci { USB_DEVICE(0x0218, 0x0201), .driver_info = 1958c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* WORLDE easy key (easykey.25) MIDI controller */ 1988c2ecf20Sopenharmony_ci { USB_DEVICE(0x0218, 0x0401), .driver_info = 1998c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* HP 5300/5370C scanner */ 2028c2ecf20Sopenharmony_ci { USB_DEVICE(0x03f0, 0x0701), .driver_info = 2038c2ecf20Sopenharmony_ci USB_QUIRK_STRING_FETCH_255 }, 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci /* HP v222w 16GB Mini USB Drive */ 2068c2ecf20Sopenharmony_ci { USB_DEVICE(0x03f0, 0x3f40), .driver_info = USB_QUIRK_DELAY_INIT }, 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* Creative SB Audigy 2 NX */ 2098c2ecf20Sopenharmony_ci { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* USB3503 */ 2128c2ecf20Sopenharmony_ci { USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME }, 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* Microsoft Wireless Laser Mouse 6000 Receiver */ 2158c2ecf20Sopenharmony_ci { USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME }, 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci /* Microsoft LifeCam-VX700 v2.0 */ 2188c2ecf20Sopenharmony_ci { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci /* Microsoft Surface Dock Ethernet (RTL8153 GigE) */ 2218c2ecf20Sopenharmony_ci { USB_DEVICE(0x045e, 0x07c6), .driver_info = USB_QUIRK_NO_LPM }, 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */ 2248c2ecf20Sopenharmony_ci { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci /* Logitech HD Webcam C270 */ 2278c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */ 2308c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, 2318c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, 2328c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT }, 2338c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x085b), .driver_info = USB_QUIRK_DELAY_INIT }, 2348c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x085c), .driver_info = USB_QUIRK_DELAY_INIT }, 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* Logitech ConferenceCam CC3000e */ 2378c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT }, 2388c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x0848), .driver_info = USB_QUIRK_DELAY_INIT }, 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* Logitech PTZ Pro Camera */ 2418c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT }, 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Logitech Screen Share */ 2448c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x086c), .driver_info = USB_QUIRK_NO_LPM }, 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* Logitech Quickcam Fusion */ 2478c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* Logitech Quickcam Orbit MP */ 2508c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x08c2), .driver_info = USB_QUIRK_RESET_RESUME }, 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* Logitech Quickcam Pro for Notebook */ 2538c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x08c3), .driver_info = USB_QUIRK_RESET_RESUME }, 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* Logitech Quickcam Pro 5000 */ 2568c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x08c5), .driver_info = USB_QUIRK_RESET_RESUME }, 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* Logitech Quickcam OEM Dell Notebook */ 2598c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x08c6), .driver_info = USB_QUIRK_RESET_RESUME }, 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* Logitech Quickcam OEM Cisco VT Camera II */ 2628c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0x08c7), .driver_info = USB_QUIRK_RESET_RESUME }, 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* Logitech Harmony 700-series */ 2658c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* Philips PSC805 audio device */ 2688c2ecf20Sopenharmony_ci { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /* Plantronic Audio 655 DSP */ 2718c2ecf20Sopenharmony_ci { USB_DEVICE(0x047f, 0xc008), .driver_info = USB_QUIRK_RESET_RESUME }, 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* Plantronic Audio 648 USB */ 2748c2ecf20Sopenharmony_ci { USB_DEVICE(0x047f, 0xc013), .driver_info = USB_QUIRK_RESET_RESUME }, 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Artisman Watchdog Dongle */ 2778c2ecf20Sopenharmony_ci { USB_DEVICE(0x04b4, 0x0526), .driver_info = 2788c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci /* Microchip Joss Optical infrared touchboard device */ 2818c2ecf20Sopenharmony_ci { USB_DEVICE(0x04d8, 0x000c), .driver_info = 2828c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* CarrolTouch 4000U */ 2858c2ecf20Sopenharmony_ci { USB_DEVICE(0x04e7, 0x0009), .driver_info = USB_QUIRK_RESET_RESUME }, 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci /* CarrolTouch 4500U */ 2888c2ecf20Sopenharmony_ci { USB_DEVICE(0x04e7, 0x0030), .driver_info = USB_QUIRK_RESET_RESUME }, 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* Samsung Android phone modem - ID conflict with SPH-I500 */ 2918c2ecf20Sopenharmony_ci { USB_DEVICE(0x04e8, 0x6601), .driver_info = 2928c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* Elan Touchscreen */ 2958c2ecf20Sopenharmony_ci { USB_DEVICE(0x04f3, 0x0089), .driver_info = 2968c2ecf20Sopenharmony_ci USB_QUIRK_DEVICE_QUALIFIER }, 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci { USB_DEVICE(0x04f3, 0x009b), .driver_info = 2998c2ecf20Sopenharmony_ci USB_QUIRK_DEVICE_QUALIFIER }, 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci { USB_DEVICE(0x04f3, 0x010c), .driver_info = 3028c2ecf20Sopenharmony_ci USB_QUIRK_DEVICE_QUALIFIER }, 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci { USB_DEVICE(0x04f3, 0x0125), .driver_info = 3058c2ecf20Sopenharmony_ci USB_QUIRK_DEVICE_QUALIFIER }, 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci { USB_DEVICE(0x04f3, 0x016f), .driver_info = 3088c2ecf20Sopenharmony_ci USB_QUIRK_DEVICE_QUALIFIER }, 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci { USB_DEVICE(0x04f3, 0x0381), .driver_info = 3118c2ecf20Sopenharmony_ci USB_QUIRK_NO_LPM }, 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci { USB_DEVICE(0x04f3, 0x21b8), .driver_info = 3148c2ecf20Sopenharmony_ci USB_QUIRK_DEVICE_QUALIFIER }, 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* Roland SC-8820 */ 3178c2ecf20Sopenharmony_ci { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME }, 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* Edirol SD-20 */ 3208c2ecf20Sopenharmony_ci { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* Alcor Micro Corp. Hub */ 3238c2ecf20Sopenharmony_ci { USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME }, 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* appletouch */ 3268c2ecf20Sopenharmony_ci { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Genesys Logic hub, internally used by KY-688 USB 3.1 Type-C Hub */ 3298c2ecf20Sopenharmony_ci { USB_DEVICE(0x05e3, 0x0612), .driver_info = USB_QUIRK_NO_LPM }, 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* ELSA MicroLink 56K */ 3328c2ecf20Sopenharmony_ci { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_RESET_RESUME }, 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci /* Genesys Logic hub, internally used by Moshi USB to Ethernet Adapter */ 3358c2ecf20Sopenharmony_ci { USB_DEVICE(0x05e3, 0x0616), .driver_info = USB_QUIRK_NO_LPM }, 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* Avision AV600U */ 3388c2ecf20Sopenharmony_ci { USB_DEVICE(0x0638, 0x0a13), .driver_info = 3398c2ecf20Sopenharmony_ci USB_QUIRK_STRING_FETCH_255 }, 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* Saitek Cyborg Gold Joystick */ 3428c2ecf20Sopenharmony_ci { USB_DEVICE(0x06a3, 0x0006), .driver_info = 3438c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* Agfa SNAPSCAN 1212U */ 3468c2ecf20Sopenharmony_ci { USB_DEVICE(0x06bd, 0x0001), .driver_info = USB_QUIRK_RESET_RESUME }, 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */ 3498c2ecf20Sopenharmony_ci { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* Guillemot Webcam Hercules Dualpix Exchange*/ 3528c2ecf20Sopenharmony_ci { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME }, 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* Guillemot Hercules DJ Console audio card (BZ 208357) */ 3558c2ecf20Sopenharmony_ci { USB_DEVICE(0x06f8, 0xb000), .driver_info = 3568c2ecf20Sopenharmony_ci USB_QUIRK_ENDPOINT_IGNORE }, 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* Midiman M-Audio Keystation 88es */ 3598c2ecf20Sopenharmony_ci { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME }, 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* SanDisk Ultra Fit and Ultra Flair */ 3628c2ecf20Sopenharmony_ci { USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM }, 3638c2ecf20Sopenharmony_ci { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /* Realforce 87U Keyboard */ 3668c2ecf20Sopenharmony_ci { USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM }, 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* M-Systems Flash Disk Pioneers */ 3698c2ecf20Sopenharmony_ci { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci /* Baum Vario Ultra */ 3728c2ecf20Sopenharmony_ci { USB_DEVICE(0x0904, 0x6101), .driver_info = 3738c2ecf20Sopenharmony_ci USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, 3748c2ecf20Sopenharmony_ci { USB_DEVICE(0x0904, 0x6102), .driver_info = 3758c2ecf20Sopenharmony_ci USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, 3768c2ecf20Sopenharmony_ci { USB_DEVICE(0x0904, 0x6103), .driver_info = 3778c2ecf20Sopenharmony_ci USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci /* Sound Devices USBPre2 */ 3808c2ecf20Sopenharmony_ci { USB_DEVICE(0x0926, 0x0202), .driver_info = 3818c2ecf20Sopenharmony_ci USB_QUIRK_ENDPOINT_IGNORE }, 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* Sound Devices MixPre-D */ 3848c2ecf20Sopenharmony_ci { USB_DEVICE(0x0926, 0x0208), .driver_info = 3858c2ecf20Sopenharmony_ci USB_QUIRK_ENDPOINT_IGNORE }, 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* Keytouch QWERTY Panel keyboard */ 3888c2ecf20Sopenharmony_ci { USB_DEVICE(0x0926, 0x3333), .driver_info = 3898c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* Kingston DataTraveler 3.0 */ 3928c2ecf20Sopenharmony_ci { USB_DEVICE(0x0951, 0x1666), .driver_info = USB_QUIRK_NO_LPM }, 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* NVIDIA Jetson devices in Force Recovery mode */ 3958c2ecf20Sopenharmony_ci { USB_DEVICE(0x0955, 0x7018), .driver_info = USB_QUIRK_RESET_RESUME }, 3968c2ecf20Sopenharmony_ci { USB_DEVICE(0x0955, 0x7019), .driver_info = USB_QUIRK_RESET_RESUME }, 3978c2ecf20Sopenharmony_ci { USB_DEVICE(0x0955, 0x7418), .driver_info = USB_QUIRK_RESET_RESUME }, 3988c2ecf20Sopenharmony_ci { USB_DEVICE(0x0955, 0x7721), .driver_info = USB_QUIRK_RESET_RESUME }, 3998c2ecf20Sopenharmony_ci { USB_DEVICE(0x0955, 0x7c18), .driver_info = USB_QUIRK_RESET_RESUME }, 4008c2ecf20Sopenharmony_ci { USB_DEVICE(0x0955, 0x7e19), .driver_info = USB_QUIRK_RESET_RESUME }, 4018c2ecf20Sopenharmony_ci { USB_DEVICE(0x0955, 0x7f21), .driver_info = USB_QUIRK_RESET_RESUME }, 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */ 4048c2ecf20Sopenharmony_ci { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF }, 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci /* ELMO L-12F document camera */ 4078c2ecf20Sopenharmony_ci { USB_DEVICE(0x09a1, 0x0028), .driver_info = USB_QUIRK_DELAY_CTRL_MSG }, 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci /* Broadcom BCM92035DGROM BT dongle */ 4108c2ecf20Sopenharmony_ci { USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME }, 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* MAYA44USB sound device */ 4138c2ecf20Sopenharmony_ci { USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME }, 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* ASUS Base Station(T100) */ 4168c2ecf20Sopenharmony_ci { USB_DEVICE(0x0b05, 0x17e0), .driver_info = 4178c2ecf20Sopenharmony_ci USB_QUIRK_IGNORE_REMOTE_WAKEUP }, 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci /* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/ 4208c2ecf20Sopenharmony_ci { USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* Realtek hub in Dell WD19 (Type-C) */ 4238c2ecf20Sopenharmony_ci { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM }, 4248c2ecf20Sopenharmony_ci { USB_DEVICE(0x0bda, 0x5487), .driver_info = USB_QUIRK_RESET_RESUME }, 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* Generic RTL8153 based ethernet adapters */ 4278c2ecf20Sopenharmony_ci { USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM }, 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci /* SONiX USB DEVICE Touchpad */ 4308c2ecf20Sopenharmony_ci { USB_DEVICE(0x0c45, 0x7056), .driver_info = 4318c2ecf20Sopenharmony_ci USB_QUIRK_IGNORE_REMOTE_WAKEUP }, 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* Action Semiconductor flash disk */ 4348c2ecf20Sopenharmony_ci { USB_DEVICE(0x10d6, 0x2200), .driver_info = 4358c2ecf20Sopenharmony_ci USB_QUIRK_STRING_FETCH_255 }, 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci /* novation SoundControl XL */ 4388c2ecf20Sopenharmony_ci { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME }, 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci /* Focusrite Scarlett Solo USB */ 4418c2ecf20Sopenharmony_ci { USB_DEVICE(0x1235, 0x8211), .driver_info = 4428c2ecf20Sopenharmony_ci USB_QUIRK_DISCONNECT_SUSPEND }, 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* Huawei 4G LTE module */ 4458c2ecf20Sopenharmony_ci { USB_DEVICE(0x12d1, 0x15bb), .driver_info = 4468c2ecf20Sopenharmony_ci USB_QUIRK_DISCONNECT_SUSPEND }, 4478c2ecf20Sopenharmony_ci { USB_DEVICE(0x12d1, 0x15c3), .driver_info = 4488c2ecf20Sopenharmony_ci USB_QUIRK_DISCONNECT_SUSPEND }, 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci /* SKYMEDI USB_DRIVE */ 4518c2ecf20Sopenharmony_ci { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME }, 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* Razer - Razer Blade Keyboard */ 4548c2ecf20Sopenharmony_ci { USB_DEVICE(0x1532, 0x0116), .driver_info = 4558c2ecf20Sopenharmony_ci USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /* Lenovo ThinkPad OneLink+ Dock twin hub controllers (VIA Labs VL812) */ 4588c2ecf20Sopenharmony_ci { USB_DEVICE(0x17ef, 0x1018), .driver_info = USB_QUIRK_RESET_RESUME }, 4598c2ecf20Sopenharmony_ci { USB_DEVICE(0x17ef, 0x1019), .driver_info = USB_QUIRK_RESET_RESUME }, 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci /* Lenovo USB-C to Ethernet Adapter RTL8153-04 */ 4628c2ecf20Sopenharmony_ci { USB_DEVICE(0x17ef, 0x720c), .driver_info = USB_QUIRK_NO_LPM }, 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /* Lenovo Powered USB-C Travel Hub (4X90S92381, RTL8153 GigE) */ 4658c2ecf20Sopenharmony_ci { USB_DEVICE(0x17ef, 0x721e), .driver_info = USB_QUIRK_NO_LPM }, 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci /* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */ 4688c2ecf20Sopenharmony_ci { USB_DEVICE(0x17ef, 0xa012), .driver_info = 4698c2ecf20Sopenharmony_ci USB_QUIRK_DISCONNECT_SUSPEND }, 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* Lenovo ThinkPad USB-C Dock Gen2 Ethernet (RTL8153 GigE) */ 4728c2ecf20Sopenharmony_ci { USB_DEVICE(0x17ef, 0xa387), .driver_info = USB_QUIRK_NO_LPM }, 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci /* BUILDWIN Photo Frame */ 4758c2ecf20Sopenharmony_ci { USB_DEVICE(0x1908, 0x1315), .driver_info = 4768c2ecf20Sopenharmony_ci USB_QUIRK_HONOR_BNUMINTERFACES }, 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci /* Protocol and OTG Electrical Test Device */ 4798c2ecf20Sopenharmony_ci { USB_DEVICE(0x1a0a, 0x0200), .driver_info = 4808c2ecf20Sopenharmony_ci USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* Terminus Technology Inc. Hub */ 4838c2ecf20Sopenharmony_ci { USB_DEVICE(0x1a40, 0x0101), .driver_info = USB_QUIRK_HUB_SLOW_RESET }, 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* Corsair K70 RGB */ 4868c2ecf20Sopenharmony_ci { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT | 4878c2ecf20Sopenharmony_ci USB_QUIRK_DELAY_CTRL_MSG }, 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci /* Corsair Strafe */ 4908c2ecf20Sopenharmony_ci { USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT | 4918c2ecf20Sopenharmony_ci USB_QUIRK_DELAY_CTRL_MSG }, 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci /* Corsair Strafe RGB */ 4948c2ecf20Sopenharmony_ci { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT | 4958c2ecf20Sopenharmony_ci USB_QUIRK_DELAY_CTRL_MSG }, 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci /* Corsair K70 LUX RGB */ 4988c2ecf20Sopenharmony_ci { USB_DEVICE(0x1b1c, 0x1b33), .driver_info = USB_QUIRK_DELAY_INIT }, 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci /* Corsair K70 LUX */ 5018c2ecf20Sopenharmony_ci { USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT }, 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci /* Corsair K70 RGB RAPDIFIRE */ 5048c2ecf20Sopenharmony_ci { USB_DEVICE(0x1b1c, 0x1b38), .driver_info = USB_QUIRK_DELAY_INIT | 5058c2ecf20Sopenharmony_ci USB_QUIRK_DELAY_CTRL_MSG }, 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci /* MIDI keyboard WORLDE MINI */ 5088c2ecf20Sopenharmony_ci { USB_DEVICE(0x1c75, 0x0204), .driver_info = 5098c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci /* Acer C120 LED Projector */ 5128c2ecf20Sopenharmony_ci { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM }, 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci /* Blackmagic Design Intensity Shuttle */ 5158c2ecf20Sopenharmony_ci { USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM }, 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* Blackmagic Design UltraStudio SDI */ 5188c2ecf20Sopenharmony_ci { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* Hauppauge HVR-950q */ 5218c2ecf20Sopenharmony_ci { USB_DEVICE(0x2040, 0x7200), .driver_info = 5228c2ecf20Sopenharmony_ci USB_QUIRK_CONFIG_INTF_STRINGS }, 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci /* Raydium Touchscreen */ 5258c2ecf20Sopenharmony_ci { USB_DEVICE(0x2386, 0x3114), .driver_info = USB_QUIRK_NO_LPM }, 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci { USB_DEVICE(0x2386, 0x3119), .driver_info = USB_QUIRK_NO_LPM }, 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM }, 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci /* DJI CineSSD */ 5328c2ecf20Sopenharmony_ci { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci /* Alcor Link AK9563 SC Reader used in 2022 Lenovo ThinkPads */ 5358c2ecf20Sopenharmony_ci { USB_DEVICE(0x2ce3, 0x9563), .driver_info = USB_QUIRK_NO_LPM }, 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* DELL USB GEN2 */ 5388c2ecf20Sopenharmony_ci { USB_DEVICE(0x413c, 0xb062), .driver_info = USB_QUIRK_NO_LPM | USB_QUIRK_RESET_RESUME }, 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci /* VCOM device */ 5418c2ecf20Sopenharmony_ci { USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci /* INTEL VALUE SSD */ 5448c2ecf20Sopenharmony_ci { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci { } /* terminating entry must be last */ 5478c2ecf20Sopenharmony_ci}; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic const struct usb_device_id usb_interface_quirk_list[] = { 5508c2ecf20Sopenharmony_ci /* Logitech UVC Cameras */ 5518c2ecf20Sopenharmony_ci { USB_VENDOR_AND_INTERFACE_INFO(0x046d, USB_CLASS_VIDEO, 1, 0), 5528c2ecf20Sopenharmony_ci .driver_info = USB_QUIRK_RESET_RESUME }, 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci { } /* terminating entry must be last */ 5558c2ecf20Sopenharmony_ci}; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic const struct usb_device_id usb_amd_resume_quirk_list[] = { 5588c2ecf20Sopenharmony_ci /* Lenovo Mouse with Pixart controller */ 5598c2ecf20Sopenharmony_ci { USB_DEVICE(0x17ef, 0x602e), .driver_info = USB_QUIRK_RESET_RESUME }, 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* Pixart Mouse */ 5628c2ecf20Sopenharmony_ci { USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME }, 5638c2ecf20Sopenharmony_ci { USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME }, 5648c2ecf20Sopenharmony_ci { USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME }, 5658c2ecf20Sopenharmony_ci { USB_DEVICE(0x03f0, 0x2b4a), .driver_info = USB_QUIRK_RESET_RESUME }, 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci /* Logitech Optical Mouse M90/M100 */ 5688c2ecf20Sopenharmony_ci { USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME }, 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci { } /* terminating entry must be last */ 5718c2ecf20Sopenharmony_ci}; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci/* 5748c2ecf20Sopenharmony_ci * Entries for endpoints that should be ignored when parsing configuration 5758c2ecf20Sopenharmony_ci * descriptors. 5768c2ecf20Sopenharmony_ci * 5778c2ecf20Sopenharmony_ci * Matched for devices with USB_QUIRK_ENDPOINT_IGNORE. 5788c2ecf20Sopenharmony_ci */ 5798c2ecf20Sopenharmony_cistatic const struct usb_device_id usb_endpoint_ignore[] = { 5808c2ecf20Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x01 }, 5818c2ecf20Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x81 }, 5828c2ecf20Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 }, 5838c2ecf20Sopenharmony_ci { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 }, 5848c2ecf20Sopenharmony_ci { } 5858c2ecf20Sopenharmony_ci}; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cibool usb_endpoint_is_ignored(struct usb_device *udev, 5888c2ecf20Sopenharmony_ci struct usb_host_interface *intf, 5898c2ecf20Sopenharmony_ci struct usb_endpoint_descriptor *epd) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci const struct usb_device_id *id; 5928c2ecf20Sopenharmony_ci unsigned int address; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci for (id = usb_endpoint_ignore; id->match_flags; ++id) { 5958c2ecf20Sopenharmony_ci if (!usb_match_device(udev, id)) 5968c2ecf20Sopenharmony_ci continue; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci if (!usb_match_one_id_intf(udev, intf, id)) 5998c2ecf20Sopenharmony_ci continue; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci address = id->driver_info; 6028c2ecf20Sopenharmony_ci if (address == epd->bEndpointAddress) 6038c2ecf20Sopenharmony_ci return true; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci return false; 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_cistatic bool usb_match_any_interface(struct usb_device *udev, 6108c2ecf20Sopenharmony_ci const struct usb_device_id *id) 6118c2ecf20Sopenharmony_ci{ 6128c2ecf20Sopenharmony_ci unsigned int i; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci for (i = 0; i < udev->descriptor.bNumConfigurations; ++i) { 6158c2ecf20Sopenharmony_ci struct usb_host_config *cfg = &udev->config[i]; 6168c2ecf20Sopenharmony_ci unsigned int j; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci for (j = 0; j < cfg->desc.bNumInterfaces; ++j) { 6198c2ecf20Sopenharmony_ci struct usb_interface_cache *cache; 6208c2ecf20Sopenharmony_ci struct usb_host_interface *intf; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci cache = cfg->intf_cache[j]; 6238c2ecf20Sopenharmony_ci if (cache->num_altsetting == 0) 6248c2ecf20Sopenharmony_ci continue; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci intf = &cache->altsetting[0]; 6278c2ecf20Sopenharmony_ci if (usb_match_one_id_intf(udev, intf, id)) 6288c2ecf20Sopenharmony_ci return true; 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci } 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci return false; 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_cistatic int usb_amd_resume_quirk(struct usb_device *udev) 6368c2ecf20Sopenharmony_ci{ 6378c2ecf20Sopenharmony_ci struct usb_hcd *hcd; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci hcd = bus_to_hcd(udev->bus); 6408c2ecf20Sopenharmony_ci /* The device should be attached directly to root hub */ 6418c2ecf20Sopenharmony_ci if (udev->level == 1 && hcd->amd_resume_bug == 1) 6428c2ecf20Sopenharmony_ci return 1; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci return 0; 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic u32 usb_detect_static_quirks(struct usb_device *udev, 6488c2ecf20Sopenharmony_ci const struct usb_device_id *id) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci u32 quirks = 0; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci for (; id->match_flags; id++) { 6538c2ecf20Sopenharmony_ci if (!usb_match_device(udev, id)) 6548c2ecf20Sopenharmony_ci continue; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) && 6578c2ecf20Sopenharmony_ci !usb_match_any_interface(udev, id)) 6588c2ecf20Sopenharmony_ci continue; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci quirks |= (u32)(id->driver_info); 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci return quirks; 6648c2ecf20Sopenharmony_ci} 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_cistatic u32 usb_detect_dynamic_quirks(struct usb_device *udev) 6678c2ecf20Sopenharmony_ci{ 6688c2ecf20Sopenharmony_ci u16 vid = le16_to_cpu(udev->descriptor.idVendor); 6698c2ecf20Sopenharmony_ci u16 pid = le16_to_cpu(udev->descriptor.idProduct); 6708c2ecf20Sopenharmony_ci int i, flags = 0; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci mutex_lock(&quirk_mutex); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci for (i = 0; i < quirk_count; i++) { 6758c2ecf20Sopenharmony_ci if (vid == quirk_list[i].vid && pid == quirk_list[i].pid) { 6768c2ecf20Sopenharmony_ci flags = quirk_list[i].flags; 6778c2ecf20Sopenharmony_ci break; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci mutex_unlock(&quirk_mutex); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci return flags; 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci/* 6878c2ecf20Sopenharmony_ci * Detect any quirks the device has, and do any housekeeping for it if needed. 6888c2ecf20Sopenharmony_ci */ 6898c2ecf20Sopenharmony_civoid usb_detect_quirks(struct usb_device *udev) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci udev->quirks = usb_detect_static_quirks(udev, usb_quirk_list); 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci /* 6948c2ecf20Sopenharmony_ci * Pixart-based mice would trigger remote wakeup issue on AMD 6958c2ecf20Sopenharmony_ci * Yangtze chipset, so set them as RESET_RESUME flag. 6968c2ecf20Sopenharmony_ci */ 6978c2ecf20Sopenharmony_ci if (usb_amd_resume_quirk(udev)) 6988c2ecf20Sopenharmony_ci udev->quirks |= usb_detect_static_quirks(udev, 6998c2ecf20Sopenharmony_ci usb_amd_resume_quirk_list); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci udev->quirks ^= usb_detect_dynamic_quirks(udev); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (udev->quirks) 7048c2ecf20Sopenharmony_ci dev_dbg(&udev->dev, "USB quirks for this device: %x\n", 7058c2ecf20Sopenharmony_ci udev->quirks); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_DEFAULT_PERSIST 7088c2ecf20Sopenharmony_ci if (!(udev->quirks & USB_QUIRK_RESET)) 7098c2ecf20Sopenharmony_ci udev->persist_enabled = 1; 7108c2ecf20Sopenharmony_ci#else 7118c2ecf20Sopenharmony_ci /* Hubs are automatically enabled for USB-PERSIST */ 7128c2ecf20Sopenharmony_ci if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) 7138c2ecf20Sopenharmony_ci udev->persist_enabled = 1; 7148c2ecf20Sopenharmony_ci#endif /* CONFIG_USB_DEFAULT_PERSIST */ 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_civoid usb_detect_interface_quirks(struct usb_device *udev) 7188c2ecf20Sopenharmony_ci{ 7198c2ecf20Sopenharmony_ci u32 quirks; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci quirks = usb_detect_static_quirks(udev, usb_interface_quirk_list); 7228c2ecf20Sopenharmony_ci if (quirks == 0) 7238c2ecf20Sopenharmony_ci return; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci dev_dbg(&udev->dev, "USB interface quirks for this device: %x\n", 7268c2ecf20Sopenharmony_ci quirks); 7278c2ecf20Sopenharmony_ci udev->quirks |= quirks; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_civoid usb_release_quirk_list(void) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci mutex_lock(&quirk_mutex); 7338c2ecf20Sopenharmony_ci kfree(quirk_list); 7348c2ecf20Sopenharmony_ci quirk_list = NULL; 7358c2ecf20Sopenharmony_ci mutex_unlock(&quirk_mutex); 7368c2ecf20Sopenharmony_ci} 737