1141a761fSMarkus Pfeiffer /* $FreeBSD: head/sys/dev/usb/usb_debug.c 267992 2014-06-28 03:56:17Z hselasky $ */
212bd3c8bSSascha Wildner /*-
312bd3c8bSSascha Wildner * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
412bd3c8bSSascha Wildner *
512bd3c8bSSascha Wildner * Redistribution and use in source and binary forms, with or without
612bd3c8bSSascha Wildner * modification, are permitted provided that the following conditions
712bd3c8bSSascha Wildner * are met:
812bd3c8bSSascha Wildner * 1. Redistributions of source code must retain the above copyright
912bd3c8bSSascha Wildner * notice, this list of conditions and the following disclaimer.
1012bd3c8bSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
1112bd3c8bSSascha Wildner * notice, this list of conditions and the following disclaimer in the
1212bd3c8bSSascha Wildner * documentation and/or other materials provided with the distribution.
1312bd3c8bSSascha Wildner *
1412bd3c8bSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1512bd3c8bSSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1612bd3c8bSSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1712bd3c8bSSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1812bd3c8bSSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1912bd3c8bSSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2012bd3c8bSSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2112bd3c8bSSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2212bd3c8bSSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2312bd3c8bSSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2412bd3c8bSSascha Wildner * SUCH DAMAGE.
2512bd3c8bSSascha Wildner */
2612bd3c8bSSascha Wildner
2712bd3c8bSSascha Wildner #include <sys/stdint.h>
2812bd3c8bSSascha Wildner #include <sys/queue.h>
2912bd3c8bSSascha Wildner #include <sys/types.h>
3012bd3c8bSSascha Wildner #include <sys/systm.h>
3112bd3c8bSSascha Wildner #include <sys/kernel.h>
3212bd3c8bSSascha Wildner #include <sys/bus.h>
3312bd3c8bSSascha Wildner #include <sys/module.h>
3412bd3c8bSSascha Wildner #include <sys/lock.h>
3512bd3c8bSSascha Wildner #include <sys/condvar.h>
3612bd3c8bSSascha Wildner #include <sys/sysctl.h>
3712bd3c8bSSascha Wildner #include <sys/unistd.h>
3812bd3c8bSSascha Wildner #include <sys/callout.h>
3912bd3c8bSSascha Wildner #include <sys/malloc.h>
40*2b3f93eaSMatthew Dillon #include <sys/caps.h>
4112bd3c8bSSascha Wildner
42722d05c3SSascha Wildner #include <bus/u4b/usb.h>
43722d05c3SSascha Wildner #include <bus/u4b/usbdi.h>
4412bd3c8bSSascha Wildner
45722d05c3SSascha Wildner #include <bus/u4b/usb_core.h>
46722d05c3SSascha Wildner #include <bus/u4b/usb_debug.h>
47722d05c3SSascha Wildner #include <bus/u4b/usb_process.h>
48722d05c3SSascha Wildner #include <bus/u4b/usb_device.h>
49722d05c3SSascha Wildner #include <bus/u4b/usb_busdma.h>
50722d05c3SSascha Wildner #include <bus/u4b/usb_transfer.h>
5112bd3c8bSSascha Wildner
5212bd3c8bSSascha Wildner #include <ddb/ddb.h>
5312bd3c8bSSascha Wildner #include <ddb/db_sym.h>
5412bd3c8bSSascha Wildner
5512bd3c8bSSascha Wildner /*
5612bd3c8bSSascha Wildner * Define this unconditionally in case a kernel module is loaded that
5712bd3c8bSSascha Wildner * has been compiled with debugging options.
5812bd3c8bSSascha Wildner */
5912bd3c8bSSascha Wildner int usb_debug = 0;
6012bd3c8bSSascha Wildner
6112bd3c8bSSascha Wildner SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging");
6212bd3c8bSSascha Wildner SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW,
6312bd3c8bSSascha Wildner &usb_debug, 0, "Debug level");
6412bd3c8bSSascha Wildner
6512bd3c8bSSascha Wildner TUNABLE_INT("hw.usb.debug", &usb_debug);
6612bd3c8bSSascha Wildner
675e41ab93SMarkus Pfeiffer #ifdef USB_DEBUG
685e41ab93SMarkus Pfeiffer /*
695e41ab93SMarkus Pfeiffer * Sysctls to modify timings/delays
705e41ab93SMarkus Pfeiffer */
715e41ab93SMarkus Pfeiffer static SYSCTL_NODE(_hw_usb, OID_AUTO, timings, CTLFLAG_RW, 0, "Timings");
725e41ab93SMarkus Pfeiffer static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS);
735e41ab93SMarkus Pfeiffer
745e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_reset_delay", (int *)&usb_port_reset_delay);
755e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_delay, CTLTYPE_UINT | CTLFLAG_RW,
765e41ab93SMarkus Pfeiffer &usb_port_reset_delay, sizeof(usb_port_reset_delay),
775e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Port Reset Delay");
785e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_root_reset_delay", (int *)&usb_port_root_reset_delay);
795e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_root_reset_delay, CTLTYPE_UINT | CTLFLAG_RW,
805e41ab93SMarkus Pfeiffer &usb_port_root_reset_delay, sizeof(usb_port_root_reset_delay),
815e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Root Port Reset Delay");
825e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_reset_recovery", (int *)&usb_port_reset_recovery);
835e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_recovery, CTLTYPE_UINT | CTLFLAG_RW,
845e41ab93SMarkus Pfeiffer &usb_port_reset_recovery, sizeof(usb_port_reset_recovery),
855e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Port Reset Recovery");
865e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_powerup_delay", (int *)&usb_port_powerup_delay);
875e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_powerup_delay, CTLTYPE_UINT | CTLFLAG_RW,
885e41ab93SMarkus Pfeiffer &usb_port_powerup_delay, sizeof(usb_port_powerup_delay),
895e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Port PowerUp Delay");
905e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_resume_delay", (int *)&usb_port_resume_delay);
915e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_resume_delay, CTLTYPE_UINT | CTLFLAG_RW,
925e41ab93SMarkus Pfeiffer &usb_port_resume_delay, sizeof(usb_port_resume_delay),
935e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Port Resume Delay");
945e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.set_address_settle", (int *)&usb_set_address_settle);
955e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, set_address_settle, CTLTYPE_UINT | CTLFLAG_RW,
965e41ab93SMarkus Pfeiffer &usb_set_address_settle, sizeof(usb_set_address_settle),
975e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Set Address Settle");
985e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.resume_delay", (int *)&usb_resume_delay);
995e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_delay, CTLTYPE_UINT | CTLFLAG_RW,
1005e41ab93SMarkus Pfeiffer &usb_resume_delay, sizeof(usb_resume_delay),
1015e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Resume Delay");
1025e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.resume_wait", (int *)&usb_resume_wait);
1035e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_wait, CTLTYPE_UINT | CTLFLAG_RW,
1045e41ab93SMarkus Pfeiffer &usb_resume_wait, sizeof(usb_resume_wait),
1055e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Resume Wait");
1065e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.resume_recovery", (int *)&usb_resume_recovery);
1075e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_recovery, CTLTYPE_UINT | CTLFLAG_RW,
1085e41ab93SMarkus Pfeiffer &usb_resume_recovery, sizeof(usb_resume_recovery),
1095e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Resume Recovery");
1105e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.extra_power_up_time", (int *)&usb_extra_power_up_time);
1115e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, extra_power_up_time, CTLTYPE_UINT | CTLFLAG_RW,
1125e41ab93SMarkus Pfeiffer &usb_extra_power_up_time, sizeof(usb_extra_power_up_time),
1135e41ab93SMarkus Pfeiffer usb_timings_sysctl_handler, "IU", "Extra PowerUp Time");
1145e41ab93SMarkus Pfeiffer #endif
1155e41ab93SMarkus Pfeiffer
11612bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
11712bd3c8bSSascha Wildner * usb_dump_iface
11812bd3c8bSSascha Wildner *
11912bd3c8bSSascha Wildner * This function dumps information about an USB interface.
12012bd3c8bSSascha Wildner *------------------------------------------------------------------------*/
12112bd3c8bSSascha Wildner void
usb_dump_iface(struct usb_interface * iface)12212bd3c8bSSascha Wildner usb_dump_iface(struct usb_interface *iface)
12312bd3c8bSSascha Wildner {
124722d05c3SSascha Wildner kprintf("usb_dump_iface: iface=%p\n", iface);
12512bd3c8bSSascha Wildner if (iface == NULL) {
12612bd3c8bSSascha Wildner return;
12712bd3c8bSSascha Wildner }
128722d05c3SSascha Wildner kprintf(" iface=%p idesc=%p altindex=%d\n",
12912bd3c8bSSascha Wildner iface, iface->idesc, iface->alt_index);
13012bd3c8bSSascha Wildner }
13112bd3c8bSSascha Wildner
13212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
13312bd3c8bSSascha Wildner * usb_dump_device
13412bd3c8bSSascha Wildner *
13512bd3c8bSSascha Wildner * This function dumps information about an USB device.
13612bd3c8bSSascha Wildner *------------------------------------------------------------------------*/
13712bd3c8bSSascha Wildner void
usb_dump_device(struct usb_device * udev)13812bd3c8bSSascha Wildner usb_dump_device(struct usb_device *udev)
13912bd3c8bSSascha Wildner {
140722d05c3SSascha Wildner kprintf("usb_dump_device: dev=%p\n", udev);
14112bd3c8bSSascha Wildner if (udev == NULL) {
14212bd3c8bSSascha Wildner return;
14312bd3c8bSSascha Wildner }
144722d05c3SSascha Wildner kprintf(" bus=%p \n"
14512bd3c8bSSascha Wildner " address=%d config=%d depth=%d speed=%d self_powered=%d\n"
14612bd3c8bSSascha Wildner " power=%d langid=%d\n",
14712bd3c8bSSascha Wildner udev->bus,
14812bd3c8bSSascha Wildner udev->address, udev->curr_config_no, udev->depth, udev->speed,
14912bd3c8bSSascha Wildner udev->flags.self_powered, udev->power, udev->langid);
15012bd3c8bSSascha Wildner }
15112bd3c8bSSascha Wildner
15212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
15312bd3c8bSSascha Wildner * usb_dump_queue
15412bd3c8bSSascha Wildner *
15512bd3c8bSSascha Wildner * This function dumps the USB transfer that are queued up on an USB endpoint.
15612bd3c8bSSascha Wildner *------------------------------------------------------------------------*/
15712bd3c8bSSascha Wildner void
usb_dump_queue(struct usb_endpoint * ep)15812bd3c8bSSascha Wildner usb_dump_queue(struct usb_endpoint *ep)
15912bd3c8bSSascha Wildner {
16012bd3c8bSSascha Wildner struct usb_xfer *xfer;
1615e41ab93SMarkus Pfeiffer usb_stream_t x;
16212bd3c8bSSascha Wildner
163722d05c3SSascha Wildner kprintf("usb_dump_queue: endpoint=%p xfer: ", ep);
1645e41ab93SMarkus Pfeiffer for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
1655e41ab93SMarkus Pfeiffer TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry) {
166722d05c3SSascha Wildner kprintf(" %p", xfer);
16712bd3c8bSSascha Wildner }
1685e41ab93SMarkus Pfeiffer }
169722d05c3SSascha Wildner kprintf("\n");
17012bd3c8bSSascha Wildner }
17112bd3c8bSSascha Wildner
17212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
17312bd3c8bSSascha Wildner * usb_dump_endpoint
17412bd3c8bSSascha Wildner *
17512bd3c8bSSascha Wildner * This function dumps information about an USB endpoint.
17612bd3c8bSSascha Wildner *------------------------------------------------------------------------*/
17712bd3c8bSSascha Wildner void
usb_dump_endpoint(struct usb_endpoint * ep)17812bd3c8bSSascha Wildner usb_dump_endpoint(struct usb_endpoint *ep)
17912bd3c8bSSascha Wildner {
18012bd3c8bSSascha Wildner if (ep) {
181722d05c3SSascha Wildner kprintf("usb_dump_endpoint: endpoint=%p", ep);
18212bd3c8bSSascha Wildner
183722d05c3SSascha Wildner kprintf(" edesc=%p isoc_next=%d toggle_next=%d",
18412bd3c8bSSascha Wildner ep->edesc, ep->isoc_next, ep->toggle_next);
18512bd3c8bSSascha Wildner
18612bd3c8bSSascha Wildner if (ep->edesc) {
187722d05c3SSascha Wildner kprintf(" bEndpointAddress=0x%02x",
18812bd3c8bSSascha Wildner ep->edesc->bEndpointAddress);
18912bd3c8bSSascha Wildner }
190722d05c3SSascha Wildner kprintf("\n");
19112bd3c8bSSascha Wildner usb_dump_queue(ep);
19212bd3c8bSSascha Wildner } else {
193722d05c3SSascha Wildner kprintf("usb_dump_endpoint: endpoint=NULL\n");
19412bd3c8bSSascha Wildner }
19512bd3c8bSSascha Wildner }
19612bd3c8bSSascha Wildner
19712bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
19812bd3c8bSSascha Wildner * usb_dump_xfer
19912bd3c8bSSascha Wildner *
20012bd3c8bSSascha Wildner * This function dumps information about an USB transfer.
20112bd3c8bSSascha Wildner *------------------------------------------------------------------------*/
20212bd3c8bSSascha Wildner void
usb_dump_xfer(struct usb_xfer * xfer)20312bd3c8bSSascha Wildner usb_dump_xfer(struct usb_xfer *xfer)
20412bd3c8bSSascha Wildner {
20512bd3c8bSSascha Wildner struct usb_device *udev;
206722d05c3SSascha Wildner kprintf("usb_dump_xfer: xfer=%p\n", xfer);
20712bd3c8bSSascha Wildner if (xfer == NULL) {
20812bd3c8bSSascha Wildner return;
20912bd3c8bSSascha Wildner }
21012bd3c8bSSascha Wildner if (xfer->endpoint == NULL) {
211722d05c3SSascha Wildner kprintf("xfer %p: endpoint=NULL\n",
21212bd3c8bSSascha Wildner xfer);
21312bd3c8bSSascha Wildner return;
21412bd3c8bSSascha Wildner }
21512bd3c8bSSascha Wildner udev = xfer->xroot->udev;
216722d05c3SSascha Wildner kprintf("xfer %p: udev=%p vid=0x%04x pid=0x%04x addr=%d "
21712bd3c8bSSascha Wildner "endpoint=%p ep=0x%02x attr=0x%02x\n",
21812bd3c8bSSascha Wildner xfer, udev,
21912bd3c8bSSascha Wildner UGETW(udev->ddesc.idVendor),
22012bd3c8bSSascha Wildner UGETW(udev->ddesc.idProduct),
22112bd3c8bSSascha Wildner udev->address, xfer->endpoint,
22212bd3c8bSSascha Wildner xfer->endpoint->edesc->bEndpointAddress,
22312bd3c8bSSascha Wildner xfer->endpoint->edesc->bmAttributes);
22412bd3c8bSSascha Wildner }
2255e41ab93SMarkus Pfeiffer
2265e41ab93SMarkus Pfeiffer #ifdef USB_DEBUG
2275e41ab93SMarkus Pfeiffer unsigned int usb_port_reset_delay = USB_PORT_RESET_DELAY;
2285e41ab93SMarkus Pfeiffer unsigned int usb_port_root_reset_delay = USB_PORT_ROOT_RESET_DELAY;
2295e41ab93SMarkus Pfeiffer unsigned int usb_port_reset_recovery = USB_PORT_RESET_RECOVERY;
2305e41ab93SMarkus Pfeiffer unsigned int usb_port_powerup_delay = USB_PORT_POWERUP_DELAY;
2315e41ab93SMarkus Pfeiffer unsigned int usb_port_resume_delay = USB_PORT_RESUME_DELAY;
2325e41ab93SMarkus Pfeiffer unsigned int usb_set_address_settle = USB_SET_ADDRESS_SETTLE;
2335e41ab93SMarkus Pfeiffer unsigned int usb_resume_delay = USB_RESUME_DELAY;
2345e41ab93SMarkus Pfeiffer unsigned int usb_resume_wait = USB_RESUME_WAIT;
2355e41ab93SMarkus Pfeiffer unsigned int usb_resume_recovery = USB_RESUME_RECOVERY;
2365e41ab93SMarkus Pfeiffer unsigned int usb_extra_power_up_time = USB_EXTRA_POWER_UP_TIME;
2375e41ab93SMarkus Pfeiffer
2385e41ab93SMarkus Pfeiffer /*------------------------------------------------------------------------*
2395e41ab93SMarkus Pfeiffer * usb_timings_sysctl_handler
2405e41ab93SMarkus Pfeiffer *
2415e41ab93SMarkus Pfeiffer * This function updates timings variables, adjusting them where necessary.
2425e41ab93SMarkus Pfeiffer *------------------------------------------------------------------------*/
usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS)2435e41ab93SMarkus Pfeiffer static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS)
2445e41ab93SMarkus Pfeiffer {
2455e41ab93SMarkus Pfeiffer int error = 0;
2465e41ab93SMarkus Pfeiffer unsigned int val;
2475e41ab93SMarkus Pfeiffer
2485e41ab93SMarkus Pfeiffer /*
2495e41ab93SMarkus Pfeiffer * Attempt to get a coherent snapshot by making a copy of the data.
2505e41ab93SMarkus Pfeiffer */
2515e41ab93SMarkus Pfeiffer if (arg1)
2525e41ab93SMarkus Pfeiffer val = *(unsigned int *)arg1;
2535e41ab93SMarkus Pfeiffer else
2545e41ab93SMarkus Pfeiffer val = arg2;
2555e41ab93SMarkus Pfeiffer error = SYSCTL_OUT(req, &val, sizeof(int));
2565e41ab93SMarkus Pfeiffer if (error || !req->newptr)
2575e41ab93SMarkus Pfeiffer return (error);
2585e41ab93SMarkus Pfeiffer
2595e41ab93SMarkus Pfeiffer if (!arg1)
2605e41ab93SMarkus Pfeiffer return EPERM;
2615e41ab93SMarkus Pfeiffer
2625e41ab93SMarkus Pfeiffer error = SYSCTL_IN(req, &val, sizeof(unsigned int));
2635e41ab93SMarkus Pfeiffer if (error)
2645e41ab93SMarkus Pfeiffer return (error);
2655e41ab93SMarkus Pfeiffer
2665e41ab93SMarkus Pfeiffer /*
2675e41ab93SMarkus Pfeiffer * Now make sure the values are decent, and certainly no lower than
2685e41ab93SMarkus Pfeiffer * what the USB spec prescribes.
2695e41ab93SMarkus Pfeiffer */
2705e41ab93SMarkus Pfeiffer unsigned int *p = (unsigned int *)arg1;
2715e41ab93SMarkus Pfeiffer if (p == &usb_port_reset_delay) {
2725e41ab93SMarkus Pfeiffer if (val < USB_PORT_RESET_DELAY_SPEC)
2735e41ab93SMarkus Pfeiffer return (EINVAL);
2745e41ab93SMarkus Pfeiffer } else if (p == &usb_port_root_reset_delay) {
2755e41ab93SMarkus Pfeiffer if (val < USB_PORT_ROOT_RESET_DELAY_SPEC)
2765e41ab93SMarkus Pfeiffer return (EINVAL);
2775e41ab93SMarkus Pfeiffer } else if (p == &usb_port_reset_recovery) {
2785e41ab93SMarkus Pfeiffer if (val < USB_PORT_RESET_RECOVERY_SPEC)
2795e41ab93SMarkus Pfeiffer return (EINVAL);
2805e41ab93SMarkus Pfeiffer } else if (p == &usb_port_powerup_delay) {
2815e41ab93SMarkus Pfeiffer if (val < USB_PORT_POWERUP_DELAY_SPEC)
2825e41ab93SMarkus Pfeiffer return (EINVAL);
2835e41ab93SMarkus Pfeiffer } else if (p == &usb_port_resume_delay) {
2845e41ab93SMarkus Pfeiffer if (val < USB_PORT_RESUME_DELAY_SPEC)
2855e41ab93SMarkus Pfeiffer return (EINVAL);
2865e41ab93SMarkus Pfeiffer } else if (p == &usb_set_address_settle) {
2875e41ab93SMarkus Pfeiffer if (val < USB_SET_ADDRESS_SETTLE_SPEC)
2885e41ab93SMarkus Pfeiffer return (EINVAL);
2895e41ab93SMarkus Pfeiffer } else if (p == &usb_resume_delay) {
2905e41ab93SMarkus Pfeiffer if (val < USB_RESUME_DELAY_SPEC)
2915e41ab93SMarkus Pfeiffer return (EINVAL);
2925e41ab93SMarkus Pfeiffer } else if (p == &usb_resume_wait) {
2935e41ab93SMarkus Pfeiffer if (val < USB_RESUME_WAIT_SPEC)
2945e41ab93SMarkus Pfeiffer return (EINVAL);
2955e41ab93SMarkus Pfeiffer } else if (p == &usb_resume_recovery) {
2965e41ab93SMarkus Pfeiffer if (val < USB_RESUME_RECOVERY_SPEC)
2975e41ab93SMarkus Pfeiffer return (EINVAL);
2985e41ab93SMarkus Pfeiffer } else if (p == &usb_extra_power_up_time) {
2995e41ab93SMarkus Pfeiffer if (val < USB_EXTRA_POWER_UP_TIME_SPEC)
3005e41ab93SMarkus Pfeiffer return (EINVAL);
3015e41ab93SMarkus Pfeiffer } else {
3025e41ab93SMarkus Pfeiffer /* noop */
3035e41ab93SMarkus Pfeiffer }
3045e41ab93SMarkus Pfeiffer
3055e41ab93SMarkus Pfeiffer *p = val;
3065e41ab93SMarkus Pfeiffer return 0;
3075e41ab93SMarkus Pfeiffer }
3085e41ab93SMarkus Pfeiffer #endif
309