Loading...
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
210/*
211 * usb_decode_ctrl - returns a string representation of ctrl request
212 */
213const 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}
268EXPORT_SYMBOL_GPL(usb_decode_ctrl);
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
14static 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
34static 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
54static 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
72static 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
100static void usb_decode_set_address(__u16 wValue, char *str, size_t size)
101{
102 snprintf(str, size, "Set Address(Addr = %02x)", wValue);
103}
104
105static 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
170static void usb_decode_get_configuration(__u16 wLength, char *str, size_t size)
171{
172 snprintf(str, size, "Get Configuration(Length = %d)", wLength);
173}
174
175static void usb_decode_set_configuration(__u8 wValue, char *str, size_t size)
176{
177 snprintf(str, size, "Set Configuration(Config = %d)", wValue);
178}
179
180static 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
187static 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
194static 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
201static void usb_decode_set_sel(__u16 wLength, char *str, size_t size)
202{
203 snprintf(str, size, "Set SEL(Length = %d)", wLength);
204}
205
206static 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
211static 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
230static 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 */
300const 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}
319EXPORT_SYMBOL_GPL(usb_decode_ctrl);