3 * Copyright (c) 2007-2010 Hans Petter Selasky. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
35 #include <sys/sysctl.h>
39 #include <libusb20_desc.h>
41 #include <dev/usb/usb_endian.h>
42 #include <dev/usb/usb.h>
43 #include <dev/usb/usb_cdc.h>
48 set_ctrl_ep_fail(int bus, int dev, int ds_fail, int ss_fail)
52 error = sysctlbyname("hw.usb.ctrl_bus_fail", NULL, NULL,
57 error = sysctlbyname("hw.usb.ctrl_dev_fail", NULL, NULL,
62 error = sysctlbyname("hw.usb.ctrl_ds_fail", NULL, NULL,
63 &ds_fail, sizeof(ds_fail));
67 error = sysctlbyname("hw.usb.ctrl_ss_fail", NULL, NULL,
68 &ss_fail, sizeof(ss_fail));
74 printf("Cannot set USB sysctl, missing USB_REQ_DEBUG option?\n");
78 usb_control_ep_error_test(uint16_t vid, uint16_t pid)
80 struct LIBUSB20_CONTROL_SETUP_DECODED req;
81 struct libusb20_device *pdev;
89 pdev = find_usb_device(vid, pid);
91 printf("USB device not found\n");
94 error = libusb20_dev_open(pdev, 0);
96 printf("Could not open USB device\n");
97 libusb20_dev_free(pdev);
101 bus = libusb20_dev_get_bus_number(pdev);
102 dev = libusb20_dev_get_address(pdev);
104 for (cfg = 0; cfg != 255; cfg++) {
106 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
107 req.bmRequestType = 0x80; /* read */
108 req.bRequest = 0x06; /* descriptor */
109 req.wValue = 0x0200 | cfg; /* config descriptor */
113 printf("Test #%d.1/3 ...\n", cfg);
115 set_ctrl_ep_fail(-1,-1,0,0);
117 error = libusb20_dev_request_sync(pdev, &req, buffer,
120 printf("Last configuration index is: %d\n", cfg - 1);
124 printf("Test #%d.2/3 ...\n", cfg);
126 set_ctrl_ep_fail(bus,dev,1,1);
128 error = libusb20_dev_request_sync(pdev, &req, buffer,
131 set_ctrl_ep_fail(-1,-1,0,0);
133 error = libusb20_dev_request_sync(pdev, &req, buffer,
136 printf("Cannot fetch descriptor (unexpected)\n");
140 printf("Test #%d.3/3 ...\n", cfg);
142 set_ctrl_ep_fail(bus,dev,0,1);
144 error = libusb20_dev_request_sync(pdev, &req, buffer,
147 set_ctrl_ep_fail(-1,-1,0,0);
149 error = libusb20_dev_request_sync(pdev, &req, buffer,
152 printf("Cannot fetch descriptor (unexpected)\n");
157 libusb20_dev_close(pdev);
158 libusb20_dev_free(pdev);
160 printf("Test completed detecting %d failures\nDone\n\n", fail);
164 usb_get_string_desc_test(uint16_t vid, uint16_t pid)
166 struct libusb20_device *pdev;
173 pdev = find_usb_device(vid, pid);
175 printf("USB device not found\n");
178 error = libusb20_dev_open(pdev, 0);
180 printf("Could not open USB device\n");
181 libusb20_dev_free(pdev);
186 printf("Cannot allocate memory\n");
187 libusb20_dev_free(pdev);
192 printf("Starting string descriptor test for "
193 "VID=0x%04x PID=0x%04x\n", vid, pid);
195 for (x = 0; x != 256; x++) {
197 if (libusb20_dev_check_connected(pdev) != 0) {
198 printf("Device disconnected\n");
201 printf("%d .. ", (int)x);
205 error = libusb20_dev_req_string_simple_sync(pdev, x, buf, 255);
208 printf("\nINDEX=%d, STRING='%s' (Default language)\n", (int)x, buf);
216 for (y = 0; y != 65536; y++) {
218 if (libusb20_dev_check_connected(pdev) != 0) {
219 printf("Device disconnected\n");
222 error = libusb20_dev_req_string_sync(pdev, x, y, buf, 256);
227 printf("String at INDEX=%d responds to %d "
228 "languages\n", (int)x, (int)valid);
235 libusb20_dev_free(pdev);
239 usb_port_reset_test(uint16_t vid, uint16_t pid, uint32_t duration)
241 struct timeval sub_tv;
242 struct timeval ref_tv;
243 struct timeval res_tv;
245 struct libusb20_device *pdev;
253 /* sysctl() - no set config */
255 pdev = find_usb_device(vid, pid);
257 printf("USB device not found\n");
260 error = libusb20_dev_open(pdev, 0);
262 libusb20_dev_free(pdev);
263 printf("Could not open USB device\n");
270 gettimeofday(&ref_tv, 0);
272 last_sec = ref_tv.tv_sec;
276 gettimeofday(&sub_tv, 0);
278 if (last_sec != sub_tv.tv_sec) {
280 printf("STATUS: ID=%u, ERR=%u\n",
281 (int)iter, (int)errcnt);
285 last_sec = sub_tv.tv_sec;
287 timersub(&sub_tv, &ref_tv, &res_tv);
289 if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration))
292 if (libusb20_dev_reset(pdev)) {
296 if (libusb20_dev_check_connected(pdev) != 0) {
297 printf("Device disconnected\n");
303 libusb20_dev_reset(pdev);
305 libusb20_dev_free(pdev);
309 usb_set_config_test(uint16_t vid, uint16_t pid, uint32_t duration)
311 struct libusb20_device *pdev;
312 struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
318 pdev = find_usb_device(vid, pid);
320 printf("USB device not found\n");
323 error = libusb20_dev_open(pdev, 0);
325 printf("Could not open USB device\n");
326 libusb20_dev_free(pdev);
331 printf("Starting set config test for "
332 "VID=0x%04x PID=0x%04x\n", vid, pid);
334 for (x = 255; x > -1; x--) {
336 error = libusb20_dev_set_config_index(pdev, x);
339 printf("Unconfiguring USB device "
342 printf("Setting configuration %d "
343 "was successful\n", x);
350 ddesc = libusb20_dev_get_device_desc(pdev);
352 exp = ddesc->bNumConfigurations + 1;
357 "Set configuration summary\n"
358 "Valid count: %d/%d %s\n"
359 "Failed count: %d\n",
361 (exp == (256 - failed)) ? "(expected)" : "(unexpected)",
364 libusb20_dev_free(pdev);
368 usb_get_descriptor_test(uint16_t vid, uint16_t pid, uint32_t duration)
370 struct libusb20_device *pdev;
372 pdev = find_usb_device(vid, pid);
374 printf("USB device not found\n");
377 libusb20_dev_free(pdev);
381 usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration)
383 struct timeval sub_tv;
384 struct timeval ref_tv;
385 struct timeval res_tv;
387 struct libusb20_device *pdev;
397 ptimo = 1; /* second(s) */
399 error = sysctlbyname("hw.usb.power_timeout", NULL, NULL,
400 &ptimo, sizeof(ptimo));
403 printf("WARNING: Could not set power "
404 "timeout to 1 (error=%d) \n", errno);
406 pdev = find_usb_device(vid, pid);
408 printf("USB device not found\n");
411 error = libusb20_dev_open(pdev, 0);
413 printf("Could not open USB device\n");
414 libusb20_dev_free(pdev);
417 power_old = libusb20_dev_get_power_mode(pdev);
419 printf("Starting suspend and resume "
420 "test for VID=0x%04x PID=0x%04x\n", vid, pid);
425 gettimeofday(&ref_tv, 0);
427 last_sec = ref_tv.tv_sec;
431 if (libusb20_dev_check_connected(pdev) != 0) {
432 printf("Device disconnected\n");
435 gettimeofday(&sub_tv, 0);
437 if (last_sec != sub_tv.tv_sec) {
439 printf("STATUS: ID=%u, ERR=%u\n",
440 (int)iter, (int)errcnt);
444 last_sec = sub_tv.tv_sec;
446 timersub(&sub_tv, &ref_tv, &res_tv);
448 if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration))
451 error = libusb20_dev_set_power_mode(pdev, (iter & 1) ?
452 LIBUSB20_POWER_ON : LIBUSB20_POWER_SAVE);
457 /* wait before switching power mode */
459 (((uint32_t)usb_ts_rand_noise()) % 2000000U));
464 /* restore default power mode */
465 libusb20_dev_set_power_mode(pdev, power_old);
467 libusb20_dev_free(pdev);
471 usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid)
473 struct libusb20_device *pdev;
474 struct libusb20_transfer *pxfer;
481 pdev = find_usb_device(vid, pid);
483 printf("USB device not found\n");
486 error = libusb20_dev_open(pdev, 1);
488 printf("Could not open USB device\n");
489 libusb20_dev_free(pdev);
492 printf("Starting set and clear stall test "
493 "for VID=0x%04x PID=0x%04x\n", vid, pid);
498 for (ep = 2; ep != 32; ep++) {
500 struct LIBUSB20_CONTROL_SETUP_DECODED setup_set_stall;
501 struct LIBUSB20_CONTROL_SETUP_DECODED setup_get_status;
503 uint8_t epno = ((ep / 2) | ((ep & 1) << 7));
506 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_set_stall);
507 setup_set_stall.bmRequestType = 0x02; /* write endpoint */
508 setup_set_stall.bRequest = 0x03; /* set feature */
509 setup_set_stall.wValue = 0x00; /* UF_ENDPOINT_HALT */
510 setup_set_stall.wIndex = epno;
511 setup_set_stall.wLength = 0;
513 LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_get_status);
514 setup_get_status.bmRequestType = 0x82; /* read endpoint */
515 setup_get_status.bRequest = 0x00; /* get status */
516 setup_get_status.wValue = 0x00;
517 setup_get_status.wIndex = epno;
518 setup_get_status.wLength = 1;
520 if (libusb20_dev_check_connected(pdev) != 0) {
521 printf("Device disconnected\n");
524 pxfer = libusb20_tr_get_pointer(pdev, 0);
526 error = libusb20_tr_open(pxfer, 1, 1, epno);
529 printf("Endpoint 0x%02x does not exist "
530 "in current setting. (%s, ignored)\n",
531 epno, libusb20_strerror(error));
534 printf("Stalling endpoint 0x%02x\n", epno);
537 error = libusb20_dev_request_sync(pdev,
538 &setup_set_stall, NULL, NULL, 250, 0);
541 printf("Endpoint 0x%02x does not allow "
542 "setting of stall. (%s)\n",
543 epno, libusb20_strerror(error));
548 error = libusb20_dev_request_sync(pdev,
549 &setup_get_status, buf, NULL, 250, 0);
552 printf("Endpoint 0x%02x does not allow "
553 "reading status. (%s)\n",
554 epno, libusb20_strerror(error));
558 printf("Endpoint 0x%02x status is "
559 "not set to stalled\n", epno);
565 error = libusb20_tr_bulk_intr_sync(pxfer, buf, 1, NULL, 250);
566 if (error != LIBUSB20_TRANSFER_STALL) {
567 printf("Endpoint 0x%02x does not appear to "
568 "have stalled. Missing stall PID!\n", epno);
571 printf("Unstalling endpoint 0x%02x\n", epno);
573 libusb20_tr_clear_stall_sync(pxfer);
577 error = libusb20_dev_request_sync(pdev,
578 &setup_get_status, buf, NULL, 250, 0);
581 printf("Endpoint 0x%02x does not allow "
582 "reading status. (%s)\n",
583 epno, libusb20_strerror(error));
587 printf("Endpoint 0x%02x status is "
588 "still stalled\n", epno);
593 libusb20_tr_close(pxfer);
597 libusb20_dev_free(pdev);
602 "Endpoints tested: %d\n"
603 "Errors: %d\n", iter, errcnt);
607 usb_set_alt_interface_test(uint16_t vid, uint16_t pid)
609 struct libusb20_device *pdev;
610 struct libusb20_config *config;
618 pdev = find_usb_device(vid, pid);
620 printf("USB device not found\n");
623 printf("Starting set alternate setting test "
624 "for VID=0x%04x PID=0x%04x\n", vid, pid);
626 config = libusb20_dev_alloc_config(pdev,
627 libusb20_dev_get_config_index(pdev));
628 if (config == NULL) {
629 printf("Could not get configuration descriptor\n");
630 libusb20_dev_free(pdev);
636 for (n = 0; n != config->num_interface; n++) {
637 /* detach kernel driver */
638 libusb20_dev_detach_kernel_driver(pdev, n);
640 error = libusb20_dev_open(pdev, 0);
642 printf("ERROR could not open device\n");
644 /* Try the alternate settings */
645 for (m = 0; m != config->interface[n].num_altsetting; m++) {
649 if (libusb20_dev_set_alt_index(pdev, n, m + 1)) {
650 printf("ERROR on interface %d alt %d\n", n, m + 1);
655 /* Restore to default */
659 if (libusb20_dev_set_alt_index(pdev, n, 0)) {
660 printf("ERROR on interface %d alt %d\n", n, 0);
663 libusb20_dev_close(pdev);
666 libusb20_dev_free(pdev);
671 "Interfaces tested: %d\n"
672 "Errors: %d\n", iter, errcnt);