1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Common USB debugging functions 4 * 5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com 6 * 7 * Authors: Felipe Balbi <balbi@ti.com>, 8 * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 9 */ 10 11#include <linux/usb/ch9.h> 12 13static void usb_decode_get_status(__u8 bRequestType, __u16 wIndex, 14 __u16 wLength, char *str, size_t size) 15{ 16 switch (bRequestType & USB_RECIP_MASK) { 17 case USB_RECIP_DEVICE: 18 snprintf(str, size, "Get Device Status(Length = %d)", wLength); 19 break; 20 case USB_RECIP_INTERFACE: 21 snprintf(str, size, 22 "Get Interface Status(Intf = %d, Length = %d)", 23 wIndex, wLength); 24 break; 25 case USB_RECIP_ENDPOINT: 26 snprintf(str, size, "Get Endpoint Status(ep%d%s)", 27 wIndex & ~USB_DIR_IN, 28 wIndex & USB_DIR_IN ? "in" : "out"); 29 break; 30 } 31} 32 33static const char *usb_decode_device_feature(u16 wValue) 34{ 35 switch (wValue) { 36 case USB_DEVICE_SELF_POWERED: 37 return "Self Powered"; 38 case USB_DEVICE_REMOTE_WAKEUP: 39 return "Remote Wakeup"; 40 case USB_DEVICE_TEST_MODE: 41 return "Test Mode"; 42 case USB_DEVICE_U1_ENABLE: 43 return "U1 Enable"; 44 case USB_DEVICE_U2_ENABLE: 45 return "U2 Enable"; 46 case USB_DEVICE_LTM_ENABLE: 47 return "LTM Enable"; 48 default: 49 return "UNKNOWN"; 50 } 51} 52 53static const char *usb_decode_test_mode(u16 wIndex) 54{ 55 switch (wIndex) { 56 case USB_TEST_J: 57 return ": TEST_J"; 58 case USB_TEST_K: 59 return ": TEST_K"; 60 case USB_TEST_SE0_NAK: 61 return ": TEST_SE0_NAK"; 62 case USB_TEST_PACKET: 63 return ": TEST_PACKET"; 64 case USB_TEST_FORCE_ENABLE: 65 return ": TEST_FORCE_EN"; 66 default: 67 return ": UNKNOWN"; 68 } 69} 70 71static void usb_decode_set_clear_feature(__u8 bRequestType, 72 __u8 bRequest, __u16 wValue, 73 __u16 wIndex, char *str, size_t size) 74{ 75 switch (bRequestType & USB_RECIP_MASK) { 76 case USB_RECIP_DEVICE: 77 snprintf(str, size, "%s Device Feature(%s%s)", 78 bRequest == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", 79 usb_decode_device_feature(wValue), 80 wValue == USB_DEVICE_TEST_MODE ? 81 usb_decode_test_mode(wIndex) : ""); 82 break; 83 case USB_RECIP_INTERFACE: 84 snprintf(str, size, "%s Interface Feature(%s)", 85 bRequest == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", 86 wValue == USB_INTRF_FUNC_SUSPEND ? 87 "Function Suspend" : "UNKNOWN"); 88 break; 89 case USB_RECIP_ENDPOINT: 90 snprintf(str, size, "%s Endpoint Feature(%s ep%d%s)", 91 bRequest == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", 92 wValue == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN", 93 wIndex & ~USB_DIR_IN, 94 wIndex & USB_DIR_IN ? "in" : "out"); 95 break; 96 } 97} 98 99static void usb_decode_set_address(__u16 wValue, char *str, size_t size) 100{ 101 snprintf(str, size, "Set Address(Addr = %02x)", wValue); 102} 103 104static void usb_decode_get_set_descriptor(__u8 bRequestType, __u8 bRequest, 105 __u16 wValue, __u16 wIndex, 106 __u16 wLength, char *str, size_t size) 107{ 108 char *s; 109 110 switch (wValue >> 8) { 111 case USB_DT_DEVICE: 112 s = "Device"; 113 break; 114 case USB_DT_CONFIG: 115 s = "Configuration"; 116 break; 117 case USB_DT_STRING: 118 s = "String"; 119 break; 120 case USB_DT_INTERFACE: 121 s = "Interface"; 122 break; 123 case USB_DT_ENDPOINT: 124 s = "Endpoint"; 125 break; 126 case USB_DT_DEVICE_QUALIFIER: 127 s = "Device Qualifier"; 128 break; 129 case USB_DT_OTHER_SPEED_CONFIG: 130 s = "Other Speed Config"; 131 break; 132 case USB_DT_INTERFACE_POWER: 133 s = "Interface Power"; 134 break; 135 case USB_DT_OTG: 136 s = "OTG"; 137 break; 138 case USB_DT_DEBUG: 139 s = "Debug"; 140 break; 141 case USB_DT_INTERFACE_ASSOCIATION: 142 s = "Interface Association"; 143 break; 144 case USB_DT_BOS: 145 s = "BOS"; 146 break; 147 case USB_DT_DEVICE_CAPABILITY: 148 s = "Device Capability"; 149 break; 150 case USB_DT_PIPE_USAGE: 151 s = "Pipe Usage"; 152 break; 153 case USB_DT_SS_ENDPOINT_COMP: 154 s = "SS Endpoint Companion"; 155 break; 156 case USB_DT_SSP_ISOC_ENDPOINT_COMP: 157 s = "SSP Isochronous Endpoint Companion"; 158 break; 159 default: 160 s = "UNKNOWN"; 161 break; 162 } 163 164 snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)", 165 bRequest == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set", 166 s, wValue & 0xff, wLength); 167} 168 169static void usb_decode_get_configuration(__u16 wLength, char *str, size_t size) 170{ 171 snprintf(str, size, "Get Configuration(Length = %d)", wLength); 172} 173 174static void usb_decode_set_configuration(__u8 wValue, char *str, size_t size) 175{ 176 snprintf(str, size, "Set Configuration(Config = %d)", wValue); 177} 178 179static void usb_decode_get_intf(__u16 wIndex, __u16 wLength, char *str, 180 size_t size) 181{ 182 snprintf(str, size, "Get Interface(Intf = %d, Length = %d)", 183 wIndex, wLength); 184} 185 186static void usb_decode_set_intf(__u8 wValue, __u16 wIndex, char *str, 187 size_t size) 188{ 189 snprintf(str, size, "Set Interface(Intf = %d, Alt.Setting = %d)", 190 wIndex, wValue); 191} 192 193static void usb_decode_synch_frame(__u16 wIndex, __u16 wLength, 194 char *str, size_t size) 195{ 196 snprintf(str, size, "Synch Frame(Endpoint = %d, Length = %d)", 197 wIndex, wLength); 198} 199 200static void usb_decode_set_sel(__u16 wLength, char *str, size_t size) 201{ 202 snprintf(str, size, "Set SEL(Length = %d)", wLength); 203} 204 205static void usb_decode_set_isoch_delay(__u8 wValue, char *str, size_t size) 206{ 207 snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", wValue); 208} 209 210static void usb_decode_ctrl_generic(char *str, size_t size, __u8 bRequestType, 211 __u8 bRequest, __u16 wValue, __u16 wIndex, 212 __u16 wLength) 213{ 214 u8 recip = bRequestType & USB_RECIP_MASK; 215 u8 type = bRequestType & USB_TYPE_MASK; 216 217 snprintf(str, size, 218 "Type=%s Recipient=%s Dir=%s bRequest=%u wValue=%u wIndex=%u wLength=%u", 219 (type == USB_TYPE_STANDARD) ? "Standard" : 220 (type == USB_TYPE_VENDOR) ? "Vendor" : 221 (type == USB_TYPE_CLASS) ? "Class" : "Unknown", 222 (recip == USB_RECIP_DEVICE) ? "Device" : 223 (recip == USB_RECIP_INTERFACE) ? "Interface" : 224 (recip == USB_RECIP_ENDPOINT) ? "Endpoint" : "Unknown", 225 (bRequestType & USB_DIR_IN) ? "IN" : "OUT", 226 bRequest, wValue, wIndex, wLength); 227} 228 229static void usb_decode_ctrl_standard(char *str, size_t size, __u8 bRequestType, 230 __u8 bRequest, __u16 wValue, __u16 wIndex, 231 __u16 wLength) 232{ 233 switch (bRequest) { 234 case USB_REQ_GET_STATUS: 235 usb_decode_get_status(bRequestType, wIndex, wLength, str, size); 236 break; 237 case USB_REQ_CLEAR_FEATURE: 238 case USB_REQ_SET_FEATURE: 239 usb_decode_set_clear_feature(bRequestType, bRequest, wValue, 240 wIndex, str, size); 241 break; 242 case USB_REQ_SET_ADDRESS: 243 usb_decode_set_address(wValue, str, size); 244 break; 245 case USB_REQ_GET_DESCRIPTOR: 246 case USB_REQ_SET_DESCRIPTOR: 247 usb_decode_get_set_descriptor(bRequestType, bRequest, wValue, 248 wIndex, wLength, str, size); 249 break; 250 case USB_REQ_GET_CONFIGURATION: 251 usb_decode_get_configuration(wLength, str, size); 252 break; 253 case USB_REQ_SET_CONFIGURATION: 254 usb_decode_set_configuration(wValue, str, size); 255 break; 256 case USB_REQ_GET_INTERFACE: 257 usb_decode_get_intf(wIndex, wLength, str, size); 258 break; 259 case USB_REQ_SET_INTERFACE: 260 usb_decode_set_intf(wValue, wIndex, str, size); 261 break; 262 case USB_REQ_SYNCH_FRAME: 263 usb_decode_synch_frame(wIndex, wLength, str, size); 264 break; 265 case USB_REQ_SET_SEL: 266 usb_decode_set_sel(wLength, str, size); 267 break; 268 case USB_REQ_SET_ISOCH_DELAY: 269 usb_decode_set_isoch_delay(wValue, str, size); 270 break; 271 default: 272 usb_decode_ctrl_generic(str, size, bRequestType, bRequest, 273 wValue, wIndex, wLength); 274 break; 275 } 276} 277 278/** 279 * usb_decode_ctrl - Returns human readable representation of control request. 280 * @str: buffer to return a human-readable representation of control request. 281 * This buffer should have about 200 bytes. 282 * @size: size of str buffer. 283 * @bRequestType: matches the USB bmRequestType field 284 * @bRequest: matches the USB bRequest field 285 * @wValue: matches the USB wValue field (CPU byte order) 286 * @wIndex: matches the USB wIndex field (CPU byte order) 287 * @wLength: matches the USB wLength field (CPU byte order) 288 * 289 * Function returns decoded, formatted and human-readable description of 290 * control request packet. 291 * 292 * The usage scenario for this is for tracepoints, so function as a return 293 * use the same value as in parameters. This approach allows to use this 294 * function in TP_printk 295 * 296 * Important: wValue, wIndex, wLength parameters before invoking this function 297 * should be processed by le16_to_cpu macro. 298 */ 299const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, 300 __u8 bRequest, __u16 wValue, __u16 wIndex, 301 __u16 wLength) 302{ 303 switch (bRequestType & USB_TYPE_MASK) { 304 case USB_TYPE_STANDARD: 305 usb_decode_ctrl_standard(str, size, bRequestType, bRequest, 306 wValue, wIndex, wLength); 307 break; 308 case USB_TYPE_VENDOR: 309 case USB_TYPE_CLASS: 310 default: 311 usb_decode_ctrl_generic(str, size, bRequestType, bRequest, 312 wValue, wIndex, wLength); 313 break; 314 } 315 316 return str; 317} 318EXPORT_SYMBOL_GPL(usb_decode_ctrl); 319