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