1 /* $FreeBSD$ */ 2 /*- 3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #ifdef USB_GLOBAL_INCLUDE_FILE 28 #include USB_GLOBAL_INCLUDE_FILE 29 #else 30 #include <sys/stdint.h> 31 #include <sys/stddef.h> 32 #include <sys/param.h> 33 #include <sys/queue.h> 34 #include <sys/types.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/bus.h> 38 #include <sys/module.h> 39 #include <sys/lock.h> 40 #include <sys/mutex.h> 41 #include <sys/condvar.h> 42 #include <sys/sysctl.h> 43 #include <sys/sx.h> 44 #include <sys/unistd.h> 45 #include <sys/callout.h> 46 #include <sys/malloc.h> 47 #include <sys/priv.h> 48 49 #include <dev/usb/usb.h> 50 #include <dev/usb/usbdi.h> 51 52 #include <dev/usb/usb_core.h> 53 #include <dev/usb/usb_debug.h> 54 #include <dev/usb/usb_process.h> 55 #include <dev/usb/usb_device.h> 56 #include <dev/usb/usb_busdma.h> 57 #include <dev/usb/usb_transfer.h> 58 59 #include <ddb/ddb.h> 60 #include <ddb/db_sym.h> 61 #endif /* USB_GLOBAL_INCLUDE_FILE */ 62 63 /* 64 * Define this unconditionally in case a kernel module is loaded that 65 * has been compiled with debugging options. 66 */ 67 int usb_debug = 0; 68 69 SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging"); 70 SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, 71 &usb_debug, 0, "Debug level"); 72 TUNABLE_INT("hw.usb.debug", &usb_debug); 73 74 #ifdef USB_DEBUG 75 /* 76 * Sysctls to modify timings/delays 77 */ 78 static SYSCTL_NODE(_hw_usb, OID_AUTO, timings, CTLFLAG_RW, 0, "Timings"); 79 static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS); 80 81 TUNABLE_INT("hw.usb.timings.port_reset_delay", (int *)&usb_port_reset_delay); 82 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 83 &usb_port_reset_delay, sizeof(usb_port_reset_delay), 84 usb_timings_sysctl_handler, "IU", "Port Reset Delay"); 85 TUNABLE_INT("hw.usb.timings.port_root_reset_delay", (int *)&usb_port_root_reset_delay); 86 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_root_reset_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 87 &usb_port_root_reset_delay, sizeof(usb_port_root_reset_delay), 88 usb_timings_sysctl_handler, "IU", "Root Port Reset Delay"); 89 TUNABLE_INT("hw.usb.timings.port_reset_recovery", (int *)&usb_port_reset_recovery); 90 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_recovery, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 91 &usb_port_reset_recovery, sizeof(usb_port_reset_recovery), 92 usb_timings_sysctl_handler, "IU", "Port Reset Recovery"); 93 TUNABLE_INT("hw.usb.timings.port_powerup_delay", (int *)&usb_port_powerup_delay); 94 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_powerup_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 95 &usb_port_powerup_delay, sizeof(usb_port_powerup_delay), 96 usb_timings_sysctl_handler, "IU", "Port PowerUp Delay"); 97 TUNABLE_INT("hw.usb.timings.port_resume_delay", (int *)&usb_port_resume_delay); 98 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_resume_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 99 &usb_port_resume_delay, sizeof(usb_port_resume_delay), 100 usb_timings_sysctl_handler, "IU", "Port Resume Delay"); 101 TUNABLE_INT("hw.usb.timings.set_address_settle", (int *)&usb_set_address_settle); 102 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, set_address_settle, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 103 &usb_set_address_settle, sizeof(usb_set_address_settle), 104 usb_timings_sysctl_handler, "IU", "Set Address Settle"); 105 TUNABLE_INT("hw.usb.timings.resume_delay", (int *)&usb_resume_delay); 106 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_delay, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 107 &usb_resume_delay, sizeof(usb_resume_delay), 108 usb_timings_sysctl_handler, "IU", "Resume Delay"); 109 TUNABLE_INT("hw.usb.timings.resume_wait", (int *)&usb_resume_wait); 110 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_wait, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 111 &usb_resume_wait, sizeof(usb_resume_wait), 112 usb_timings_sysctl_handler, "IU", "Resume Wait"); 113 TUNABLE_INT("hw.usb.timings.resume_recovery", (int *)&usb_resume_recovery); 114 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_recovery, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 115 &usb_resume_recovery, sizeof(usb_resume_recovery), 116 usb_timings_sysctl_handler, "IU", "Resume Recovery"); 117 TUNABLE_INT("hw.usb.timings.extra_power_up_time", (int *)&usb_extra_power_up_time); 118 SYSCTL_PROC(_hw_usb_timings, OID_AUTO, extra_power_up_time, CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_TUN, 119 &usb_extra_power_up_time, sizeof(usb_extra_power_up_time), 120 usb_timings_sysctl_handler, "IU", "Extra PowerUp Time"); 121 #endif 122 123 /*------------------------------------------------------------------------* 124 * usb_dump_iface 125 * 126 * This function dumps information about an USB interface. 127 *------------------------------------------------------------------------*/ 128 void 129 usb_dump_iface(struct usb_interface *iface) 130 { 131 printf("usb_dump_iface: iface=%p\n", iface); 132 if (iface == NULL) { 133 return; 134 } 135 printf(" iface=%p idesc=%p altindex=%d\n", 136 iface, iface->idesc, iface->alt_index); 137 } 138 139 /*------------------------------------------------------------------------* 140 * usb_dump_device 141 * 142 * This function dumps information about an USB device. 143 *------------------------------------------------------------------------*/ 144 void 145 usb_dump_device(struct usb_device *udev) 146 { 147 printf("usb_dump_device: dev=%p\n", udev); 148 if (udev == NULL) { 149 return; 150 } 151 printf(" bus=%p \n" 152 " address=%d config=%d depth=%d speed=%d self_powered=%d\n" 153 " power=%d langid=%d\n", 154 udev->bus, 155 udev->address, udev->curr_config_no, udev->depth, udev->speed, 156 udev->flags.self_powered, udev->power, udev->langid); 157 } 158 159 /*------------------------------------------------------------------------* 160 * usb_dump_queue 161 * 162 * This function dumps the USB transfer that are queued up on an USB endpoint. 163 *------------------------------------------------------------------------*/ 164 void 165 usb_dump_queue(struct usb_endpoint *ep) 166 { 167 struct usb_xfer *xfer; 168 usb_stream_t x; 169 170 printf("usb_dump_queue: endpoint=%p xfer: ", ep); 171 for (x = 0; x != USB_MAX_EP_STREAMS; x++) { 172 TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry) 173 printf(" %p", xfer); 174 } 175 printf("\n"); 176 } 177 178 /*------------------------------------------------------------------------* 179 * usb_dump_endpoint 180 * 181 * This function dumps information about an USB endpoint. 182 *------------------------------------------------------------------------*/ 183 void 184 usb_dump_endpoint(struct usb_endpoint *ep) 185 { 186 if (ep) { 187 printf("usb_dump_endpoint: endpoint=%p", ep); 188 189 printf(" edesc=%p isoc_next=%d toggle_next=%d", 190 ep->edesc, ep->isoc_next, ep->toggle_next); 191 192 if (ep->edesc) { 193 printf(" bEndpointAddress=0x%02x", 194 ep->edesc->bEndpointAddress); 195 } 196 printf("\n"); 197 usb_dump_queue(ep); 198 } else { 199 printf("usb_dump_endpoint: endpoint=NULL\n"); 200 } 201 } 202 203 /*------------------------------------------------------------------------* 204 * usb_dump_xfer 205 * 206 * This function dumps information about an USB transfer. 207 *------------------------------------------------------------------------*/ 208 void 209 usb_dump_xfer(struct usb_xfer *xfer) 210 { 211 struct usb_device *udev; 212 printf("usb_dump_xfer: xfer=%p\n", xfer); 213 if (xfer == NULL) { 214 return; 215 } 216 if (xfer->endpoint == NULL) { 217 printf("xfer %p: endpoint=NULL\n", 218 xfer); 219 return; 220 } 221 udev = xfer->xroot->udev; 222 printf("xfer %p: udev=%p vid=0x%04x pid=0x%04x addr=%d " 223 "endpoint=%p ep=0x%02x attr=0x%02x\n", 224 xfer, udev, 225 UGETW(udev->ddesc.idVendor), 226 UGETW(udev->ddesc.idProduct), 227 udev->address, xfer->endpoint, 228 xfer->endpoint->edesc->bEndpointAddress, 229 xfer->endpoint->edesc->bmAttributes); 230 } 231 232 #ifdef USB_DEBUG 233 unsigned int usb_port_reset_delay = USB_PORT_RESET_DELAY; 234 unsigned int usb_port_root_reset_delay = USB_PORT_ROOT_RESET_DELAY; 235 unsigned int usb_port_reset_recovery = USB_PORT_RESET_RECOVERY; 236 unsigned int usb_port_powerup_delay = USB_PORT_POWERUP_DELAY; 237 unsigned int usb_port_resume_delay = USB_PORT_RESUME_DELAY; 238 unsigned int usb_set_address_settle = USB_SET_ADDRESS_SETTLE; 239 unsigned int usb_resume_delay = USB_RESUME_DELAY; 240 unsigned int usb_resume_wait = USB_RESUME_WAIT; 241 unsigned int usb_resume_recovery = USB_RESUME_RECOVERY; 242 unsigned int usb_extra_power_up_time = USB_EXTRA_POWER_UP_TIME; 243 244 /*------------------------------------------------------------------------* 245 * usb_timings_sysctl_handler 246 * 247 * This function updates timings variables, adjusting them where necessary. 248 *------------------------------------------------------------------------*/ 249 static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS) 250 { 251 int error = 0; 252 unsigned int val; 253 254 /* 255 * Attempt to get a coherent snapshot by making a copy of the data. 256 */ 257 if (arg1) 258 val = *(unsigned int *)arg1; 259 else 260 val = arg2; 261 error = SYSCTL_OUT(req, &val, sizeof(int)); 262 if (error || !req->newptr) 263 return (error); 264 265 if (!arg1) 266 return EPERM; 267 268 error = SYSCTL_IN(req, &val, sizeof(unsigned int)); 269 if (error) 270 return (error); 271 272 /* 273 * Now make sure the values are decent, and certainly no lower than 274 * what the USB spec prescribes. 275 */ 276 unsigned int *p = (unsigned int *)arg1; 277 if (p == &usb_port_reset_delay) { 278 if (val < USB_PORT_RESET_DELAY_SPEC) 279 return (EINVAL); 280 } else if (p == &usb_port_root_reset_delay) { 281 if (val < USB_PORT_ROOT_RESET_DELAY_SPEC) 282 return (EINVAL); 283 } else if (p == &usb_port_reset_recovery) { 284 if (val < USB_PORT_RESET_RECOVERY_SPEC) 285 return (EINVAL); 286 } else if (p == &usb_port_powerup_delay) { 287 if (val < USB_PORT_POWERUP_DELAY_SPEC) 288 return (EINVAL); 289 } else if (p == &usb_port_resume_delay) { 290 if (val < USB_PORT_RESUME_DELAY_SPEC) 291 return (EINVAL); 292 } else if (p == &usb_set_address_settle) { 293 if (val < USB_SET_ADDRESS_SETTLE_SPEC) 294 return (EINVAL); 295 } else if (p == &usb_resume_delay) { 296 if (val < USB_RESUME_DELAY_SPEC) 297 return (EINVAL); 298 } else if (p == &usb_resume_wait) { 299 if (val < USB_RESUME_WAIT_SPEC) 300 return (EINVAL); 301 } else if (p == &usb_resume_recovery) { 302 if (val < USB_RESUME_RECOVERY_SPEC) 303 return (EINVAL); 304 } else if (p == &usb_extra_power_up_time) { 305 if (val < USB_EXTRA_POWER_UP_TIME_SPEC) 306 return (EINVAL); 307 } else { 308 /* noop */ 309 } 310 311 *p = val; 312 return 0; 313 } 314 #endif 315