1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2008-2022 Hans Petter Selasky
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include "implementation/global_implementation.h"
29 #ifdef LOSCFG_SHELL
30 #include "shcmd.h"
31 #endif
32
33
34 /*
35 * Define this unconditionally in case a kernel module is loaded that
36 * has been compiled with debugging options.
37 */
38 int usb_debug = 0;
39 #ifdef LOSCFG_USB_DEBUG
40 void
usb_debug_func(int level)41 usb_debug_func(int level)
42 {
43 usb_debug = level;
44 PRINTK("The level of usb other class debug is %d\n", level);
45 }
46 DEBUG_MODULE(other, usb_debug_func);
47 #endif
48
49 /*------------------------------------------------------------------------*
50 * usb_dump_iface
51 *
52 * This function dumps information about an USB interface.
53 *------------------------------------------------------------------------*/
54 void
usb_dump_iface(struct usb_interface * iface)55 usb_dump_iface(struct usb_interface *iface)
56 {
57 if (iface == NULL) {
58 return;
59 }
60 PRINTK(" iface=%p idesc=%p altindex=%d\n",
61 iface, iface->idesc, iface->alt_index);
62 }
63
64 /*------------------------------------------------------------------------*
65 * usb_dump_device
66 *
67 * This function dumps information about an USB device.
68 *------------------------------------------------------------------------*/
69 void
usb_dump_device(struct usb_device * udev)70 usb_dump_device(struct usb_device *udev)
71 {
72 if (udev == NULL) {
73 return;
74 }
75 PRINTK(" bus=%p \n"
76 " address=%d config=%d depth=%d speed=%d self_powered=%d\n"
77 " power=%d langid=%d\n",
78 udev->bus,
79 udev->address, udev->curr_config_no, udev->depth, udev->speed,
80 udev->flags.self_powered, udev->power, udev->langid);
81 }
82
83 /*------------------------------------------------------------------------*
84 * usb_dump_queue
85 *
86 * This function dumps the USB transfer that are queued up on an USB endpoint.
87 *------------------------------------------------------------------------*/
88 void
usb_dump_queue(struct usb_endpoint * ep)89 usb_dump_queue(struct usb_endpoint *ep)
90 {
91 struct usb_xfer *xfer;
92 usb_stream_t x;
93
94 PRINTK("usb_dump_queue: endpoint=%p xfer: ", ep);
95 for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
96 TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry)
97 PRINTK(" %p", xfer);
98 }
99 PRINTK("\n");
100 }
101
102 /*------------------------------------------------------------------------*
103 * usb_dump_endpoint
104 *
105 * This function dumps information about an USB endpoint.
106 *------------------------------------------------------------------------*/
107 void
usb_dump_endpoint(struct usb_endpoint * ep)108 usb_dump_endpoint(struct usb_endpoint *ep)
109 {
110 if (ep) {
111 PRINTK("usb_dump_endpoint: endpoint=%p", ep);
112
113 PRINTK(" edesc=%p isoc_next=%d toggle_next=%d",
114 ep->edesc, ep->isoc_next, ep->toggle_next);
115
116 if (ep->edesc) {
117 PRINTK(" bEndpointAddress=0x%02x",
118 ep->edesc->bEndpointAddress);
119 }
120 PRINTK("\n");
121 usb_dump_queue(ep);
122 } else {
123 PRINTK("usb_dump_endpoint: endpoint=NULL\n");
124 }
125 }
126
127 /*------------------------------------------------------------------------*
128 * usb_dump_xfer
129 *
130 * This function dumps information about an USB transfer.
131 *------------------------------------------------------------------------*/
132 void
usb_dump_xfer(struct usb_xfer * xfer)133 usb_dump_xfer(struct usb_xfer *xfer)
134 {
135 struct usb_device *udev;
136 PRINTK("usb_dump_xfer: xfer=%p\n", xfer);
137 if (xfer == NULL) {
138 return;
139 }
140 if (xfer->endpoint == NULL) {
141 PRINTK("xfer %p: endpoint=NULL\n",
142 xfer);
143 return;
144 }
145 udev = xfer->xroot->udev;
146 PRINTK("xfer %p: udev=%p vid=0x%04x pid=0x%04x addr=%d "
147 "endpoint=%p ep=0x%02x attr=0x%02x\n",
148 xfer, udev,
149 UGETW(udev->ddesc.idVendor),
150 UGETW(udev->ddesc.idProduct),
151 udev->address, xfer->endpoint,
152 xfer->endpoint->edesc->bEndpointAddress,
153 xfer->endpoint->edesc->bmAttributes);
154 }
155
156 #ifdef LOSCFG_USB_DEBUG
157 unsigned int usb_port_reset_delay = USB_PORT_RESET_DELAY;
158 unsigned int usb_port_root_reset_delay = USB_PORT_ROOT_RESET_DELAY;
159 unsigned int usb_port_reset_recovery = USB_PORT_RESET_RECOVERY;
160 unsigned int usb_port_powerup_delay = USB_PORT_POWERUP_DELAY;
161 unsigned int usb_port_resume_delay = USB_PORT_RESUME_DELAY;
162 unsigned int usb_set_address_settle = USB_SET_ADDRESS_SETTLE;
163 unsigned int usb_resume_delay = USB_RESUME_DELAY;
164 unsigned int usb_resume_wait = USB_RESUME_WAIT;
165 unsigned int usb_resume_recovery = USB_RESUME_RECOVERY;
166 unsigned int usb_extra_power_up_time = USB_EXTRA_POWER_UP_TIME;
167
168 #ifdef LOSCFG_DRIVERS_USB_HOST_EHCI
169 extern struct debug_module_data debug_ehci_mod;
170 #endif
171 #ifdef LOSCFG_DRIVERS_USB_ETHERNET
172 extern struct debug_module_data debug_axe_mod;
173 extern struct debug_module_data debug_axge_mod;
174 #endif
175 #ifdef LOSCFG_DRIVERS_USB_4G_MODEM
176 extern struct debug_module_data debug_cdce_mod;
177 #endif
178 #ifdef LOSCFG_DRIVERS_USB_RNDIS_HOST
179 extern struct debug_module_data debug_urndis_mod;
180 #endif
181 #if defined(LOSCFG_DRIVERS_USB_SERIAL) || defined(LOSCFG_DRIVERS_USB_4G_MODEM)
182 extern struct debug_module_data debug_u3g_mod;
183 extern struct debug_module_data debug_serial_mod;
184 #endif
185 #ifdef LOSCFG_DRIVERS_USB_MASS_STORAGE
186 extern struct debug_module_data debug_umass_mod;
187 #endif
188 #ifdef LOSCFG_DRIVERS_USB_HOST_DRIVER
189 extern struct debug_module_data debug_controller_mod;
190 extern struct debug_module_data debug_uhub_mod;
191 extern struct debug_module_data debug_process_mod;
192 #endif
193
194 static struct debug_module_data *debug_mode_list[] = {
195 #ifdef LOSCFG_DRIVERS_USB_HOST_EHCI
196 &debug_ehci_mod,
197 #endif
198 #ifdef LOSCFG_DRIVERS_USB_ETHERNET
199 &debug_axe_mod,
200 &debug_axge_mod,
201 #endif
202 #ifdef LOSCFG_DRIVERS_USB_4G_MODEM
203 &debug_cdce_mod,
204 #endif
205 #ifdef LOSCFG_DRIVERS_USB_RNDIS_HOST
206 &debug_urndis_mod,
207 #endif
208 #if defined(LOSCFG_DRIVERS_USB_SERIAL) || defined(LOSCFG_DRIVERS_USB_4G_MODEM)
209 &debug_u3g_mod,
210 &debug_serial_mod,
211 #endif
212 #ifdef LOSCFG_DRIVERS_USB_MASS_STORAGE
213 &debug_umass_mod,
214 #endif
215 #ifdef LOSCFG_DRIVERS_USB_HOST_DRIVER
216 &debug_controller_mod,
217 &debug_uhub_mod,
218 &debug_process_mod,
219 #endif
220 &debug_other_mod,
221 NULL
222 };
223
224 void
usb_debug_module_regsiter(void)225 usb_debug_module_regsiter(void)
226 {
227 uint32_t i;
228 struct debug_module_data* mod;
229 for (i = 0; (mod = debug_mode_list[i]) && (mod != NULL); i++) {
230 debug_module_register(mod);
231 }
232 }
233
234 void
usb_debug_module_unregsiter(void)235 usb_debug_module_unregsiter(void)
236 {
237 uint32_t i;
238 struct debug_module_data* mod;
239 for (i = 0; (mod = debug_mode_list[i]) && (mod != NULL); i++) {
240 debug_module_unregister(mod);
241 }
242 }
243
244 #ifdef LOSCFG_SHELL_CMD_DEBUG
245 void
usb_debug_shell_cmd(uint32_t argc,char ** argv)246 usb_debug_shell_cmd(uint32_t argc, char **argv)
247 {
248 uint32_t level = 0;
249 char *str;
250 struct debug_module_data* mod;
251
252 if (argc != 2) {
253 PRINTK("Usage: usb_debug module level\n");
254 PRINTK("Modules:\n");
255 debug_module_dump();
256 return;
257 }
258
259 str = argv[0];
260 level = strtoul(argv[1], 0, 0);
261
262 mod = get_debug_module(str);
263 if (mod == NULL) {
264 PRINTK("The module is not supported!\n");
265 return;
266 }
267
268 if (mod->callback)
269 mod->callback(level);
270 }
271
272 SHELLCMD_ENTRY(usb_debug_shellcmd, CMD_TYPE_EX, "usb_debug", 0, (CmdCallBackFunc)usb_debug_shell_cmd);
273 #endif
274 #endif
275