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 13 static 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 33 static 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 53 static 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 71 static 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 99 static void usb_decode_set_address(__u16 wValue, char *str, size_t size) 100 { 101 snprintf(str, size, "Set Address(Addr = %02x)", wValue); 102 } 103 104 static 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 169 static void usb_decode_get_configuration(__u16 wLength, char *str, size_t size) 170 { 171 snprintf(str, size, "Get Configuration(Length = %d)", wLength); 172 } 173 174 static void usb_decode_set_configuration(__u8 wValue, char *str, size_t size) 175 { 176 snprintf(str, size, "Set Configuration(Config = %d)", wValue); 177 } 178 179 static 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 186 static 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 193 static 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 200 static void usb_decode_set_sel(__u16 wLength, char *str, size_t size) 201 { 202 snprintf(str, size, "Set SEL(Length = %d)", wLength); 203 } 204 205 static 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 210 /* 211 * usb_decode_ctrl - returns a string representation of ctrl request 212 */ 213 const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, 214 __u8 bRequest, __u16 wValue, __u16 wIndex, 215 __u16 wLength) 216 { 217 switch (bRequest) { 218 case USB_REQ_GET_STATUS: 219 usb_decode_get_status(bRequestType, wIndex, wLength, str, size); 220 break; 221 case USB_REQ_CLEAR_FEATURE: 222 case USB_REQ_SET_FEATURE: 223 usb_decode_set_clear_feature(bRequestType, bRequest, wValue, 224 wIndex, str, size); 225 break; 226 case USB_REQ_SET_ADDRESS: 227 usb_decode_set_address(wValue, str, size); 228 break; 229 case USB_REQ_GET_DESCRIPTOR: 230 case USB_REQ_SET_DESCRIPTOR: 231 usb_decode_get_set_descriptor(bRequestType, bRequest, wValue, 232 wIndex, wLength, str, size); 233 break; 234 case USB_REQ_GET_CONFIGURATION: 235 usb_decode_get_configuration(wLength, str, size); 236 break; 237 case USB_REQ_SET_CONFIGURATION: 238 usb_decode_set_configuration(wValue, str, size); 239 break; 240 case USB_REQ_GET_INTERFACE: 241 usb_decode_get_intf(wIndex, wLength, str, size); 242 break; 243 case USB_REQ_SET_INTERFACE: 244 usb_decode_set_intf(wValue, wIndex, str, size); 245 break; 246 case USB_REQ_SYNCH_FRAME: 247 usb_decode_synch_frame(wIndex, wLength, str, size); 248 break; 249 case USB_REQ_SET_SEL: 250 usb_decode_set_sel(wLength, str, size); 251 break; 252 case USB_REQ_SET_ISOCH_DELAY: 253 usb_decode_set_isoch_delay(wValue, str, size); 254 break; 255 default: 256 snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x", 257 bRequestType, bRequest, 258 (u8)(cpu_to_le16(wValue) & 0xff), 259 (u8)(cpu_to_le16(wValue) >> 8), 260 (u8)(cpu_to_le16(wIndex) & 0xff), 261 (u8)(cpu_to_le16(wIndex) >> 8), 262 (u8)(cpu_to_le16(wLength) & 0xff), 263 (u8)(cpu_to_le16(wLength) >> 8)); 264 } 265 266 return str; 267 } 268 EXPORT_SYMBOL_GPL(usb_decode_ctrl); 269