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 /** 212 * usb_decode_ctrl - Returns human readable representation of control request. 213 * @str: buffer to return a human-readable representation of control request. 214 * This buffer should have about 200 bytes. 215 * @size: size of str buffer. 216 * @bRequestType: matches the USB bmRequestType field 217 * @bRequest: matches the USB bRequest field 218 * @wValue: matches the USB wValue field (CPU byte order) 219 * @wIndex: matches the USB wIndex field (CPU byte order) 220 * @wLength: matches the USB wLength field (CPU byte order) 221 * 222 * Function returns decoded, formatted and human-readable description of 223 * control request packet. 224 * 225 * The usage scenario for this is for tracepoints, so function as a return 226 * use the same value as in parameters. This approach allows to use this 227 * function in TP_printk 228 * 229 * Important: wValue, wIndex, wLength parameters before invoking this function 230 * should be processed by le16_to_cpu macro. 231 */ 232 const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, 233 __u8 bRequest, __u16 wValue, __u16 wIndex, 234 __u16 wLength) 235 { 236 switch (bRequest) { 237 case USB_REQ_GET_STATUS: 238 usb_decode_get_status(bRequestType, wIndex, wLength, str, size); 239 break; 240 case USB_REQ_CLEAR_FEATURE: 241 case USB_REQ_SET_FEATURE: 242 usb_decode_set_clear_feature(bRequestType, bRequest, wValue, 243 wIndex, str, size); 244 break; 245 case USB_REQ_SET_ADDRESS: 246 usb_decode_set_address(wValue, str, size); 247 break; 248 case USB_REQ_GET_DESCRIPTOR: 249 case USB_REQ_SET_DESCRIPTOR: 250 usb_decode_get_set_descriptor(bRequestType, bRequest, wValue, 251 wIndex, wLength, str, size); 252 break; 253 case USB_REQ_GET_CONFIGURATION: 254 usb_decode_get_configuration(wLength, str, size); 255 break; 256 case USB_REQ_SET_CONFIGURATION: 257 usb_decode_set_configuration(wValue, str, size); 258 break; 259 case USB_REQ_GET_INTERFACE: 260 usb_decode_get_intf(wIndex, wLength, str, size); 261 break; 262 case USB_REQ_SET_INTERFACE: 263 usb_decode_set_intf(wValue, wIndex, str, size); 264 break; 265 case USB_REQ_SYNCH_FRAME: 266 usb_decode_synch_frame(wIndex, wLength, str, size); 267 break; 268 case USB_REQ_SET_SEL: 269 usb_decode_set_sel(wLength, str, size); 270 break; 271 case USB_REQ_SET_ISOCH_DELAY: 272 usb_decode_set_isoch_delay(wValue, str, size); 273 break; 274 default: 275 snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x", 276 bRequestType, bRequest, 277 (u8)(cpu_to_le16(wValue) & 0xff), 278 (u8)(cpu_to_le16(wValue) >> 8), 279 (u8)(cpu_to_le16(wIndex) & 0xff), 280 (u8)(cpu_to_le16(wIndex) >> 8), 281 (u8)(cpu_to_le16(wLength) & 0xff), 282 (u8)(cpu_to_le16(wLength) >> 8)); 283 } 284 285 return str; 286 } 287 EXPORT_SYMBOL_GPL(usb_decode_ctrl); 288