]>
Commit | Line | Data |
---|---|---|
91f255a2 | 1 | // SPDX-License-Identifier: GPL-2.0 |
3e682e6f | 2 | /* |
91f255a2 PL |
3 | * Common USB debugging functions |
4 | * | |
ffeb1e9e | 5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com |
91f255a2 PL |
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 | ||
010665b4 PL |
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) { | |
62fb45d3 | 56 | case USB_TEST_J: |
010665b4 | 57 | return ": TEST_J"; |
62fb45d3 | 58 | case USB_TEST_K: |
010665b4 | 59 | return ": TEST_K"; |
62fb45d3 | 60 | case USB_TEST_SE0_NAK: |
010665b4 | 61 | return ": TEST_SE0_NAK"; |
62fb45d3 | 62 | case USB_TEST_PACKET: |
010665b4 | 63 | return ": TEST_PACKET"; |
62fb45d3 | 64 | case USB_TEST_FORCE_ENABLE: |
010665b4 PL |
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) | |
91f255a2 PL |
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", | |
010665b4 | 79 | usb_decode_device_feature(wValue), |
91f255a2 | 80 | wValue == USB_DEVICE_TEST_MODE ? |
010665b4 | 81 | usb_decode_test_mode(wIndex) : ""); |
91f255a2 PL |
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 | { | |
f72429fc PL |
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 | ||
91f255a2 | 164 | snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)", |
f72429fc PL |
165 | bRequest == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set", |
166 | s, wValue & 0xff, wLength); | |
91f255a2 PL |
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 | ||
3e682e6f | 210 | /* |
91f255a2 PL |
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); |