xref: /openbmc/linux/drivers/usb/common/debug.c (revision 0c6dfa75)
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