18030839bSHans Petter Selasky /*-
216346e14SHans Petter Selasky * Copyright (c) 2007-2022 Hans Petter Selasky
38030839bSHans Petter Selasky *
48030839bSHans Petter Selasky * Redistribution and use in source and binary forms, with or without
58030839bSHans Petter Selasky * modification, are permitted provided that the following conditions
68030839bSHans Petter Selasky * are met:
78030839bSHans Petter Selasky * 1. Redistributions of source code must retain the above copyright
88030839bSHans Petter Selasky * notice, this list of conditions and the following disclaimer.
98030839bSHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright
108030839bSHans Petter Selasky * notice, this list of conditions and the following disclaimer in the
118030839bSHans Petter Selasky * documentation and/or other materials provided with the distribution.
128030839bSHans Petter Selasky *
138030839bSHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
148030839bSHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158030839bSHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
168030839bSHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
178030839bSHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
188030839bSHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
198030839bSHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
208030839bSHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
218030839bSHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
228030839bSHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
238030839bSHans Petter Selasky * SUCH DAMAGE.
248030839bSHans Petter Selasky */
258030839bSHans Petter Selasky
268030839bSHans Petter Selasky #include <stdio.h>
278030839bSHans Petter Selasky #include <stdint.h>
288030839bSHans Petter Selasky #include <stdlib.h>
298030839bSHans Petter Selasky #include <err.h>
308030839bSHans Petter Selasky #include <string.h>
318030839bSHans Petter Selasky #include <errno.h>
328030839bSHans Petter Selasky #include <unistd.h>
338030839bSHans Petter Selasky
348030839bSHans Petter Selasky #include <sys/sysctl.h>
358030839bSHans Petter Selasky #include <sys/time.h>
368030839bSHans Petter Selasky
378030839bSHans Petter Selasky #include <libusb20.h>
388030839bSHans Petter Selasky #include <libusb20_desc.h>
398030839bSHans Petter Selasky
408030839bSHans Petter Selasky #include <dev/usb/usb_endian.h>
418030839bSHans Petter Selasky #include <dev/usb/usb.h>
428030839bSHans Petter Selasky #include <dev/usb/usb_cdc.h>
438030839bSHans Petter Selasky
448030839bSHans Petter Selasky #include "usbtest.h"
458030839bSHans Petter Selasky
468030839bSHans Petter Selasky static void
set_ctrl_ep_fail(int bus,int dev,int ds_fail,int ss_fail)478030839bSHans Petter Selasky set_ctrl_ep_fail(int bus, int dev, int ds_fail, int ss_fail)
488030839bSHans Petter Selasky {
498030839bSHans Petter Selasky int error;
508030839bSHans Petter Selasky
518030839bSHans Petter Selasky error = sysctlbyname("hw.usb.ctrl_bus_fail", NULL, NULL,
528030839bSHans Petter Selasky &bus, sizeof(bus));
538030839bSHans Petter Selasky if (error != 0)
548030839bSHans Petter Selasky goto emissing;
558030839bSHans Petter Selasky
568030839bSHans Petter Selasky error = sysctlbyname("hw.usb.ctrl_dev_fail", NULL, NULL,
578030839bSHans Petter Selasky &dev, sizeof(dev));
588030839bSHans Petter Selasky if (error != 0)
598030839bSHans Petter Selasky goto emissing;
608030839bSHans Petter Selasky
618030839bSHans Petter Selasky error = sysctlbyname("hw.usb.ctrl_ds_fail", NULL, NULL,
628030839bSHans Petter Selasky &ds_fail, sizeof(ds_fail));
638030839bSHans Petter Selasky if (error != 0)
648030839bSHans Petter Selasky goto emissing;
658030839bSHans Petter Selasky
668030839bSHans Petter Selasky error = sysctlbyname("hw.usb.ctrl_ss_fail", NULL, NULL,
678030839bSHans Petter Selasky &ss_fail, sizeof(ss_fail));
688030839bSHans Petter Selasky if (error != 0)
698030839bSHans Petter Selasky goto emissing;
708030839bSHans Petter Selasky return;
718030839bSHans Petter Selasky
728030839bSHans Petter Selasky emissing:
738030839bSHans Petter Selasky printf("Cannot set USB sysctl, missing USB_REQ_DEBUG option?\n");
748030839bSHans Petter Selasky }
758030839bSHans Petter Selasky
768030839bSHans Petter Selasky void
usb_control_ep_error_test(struct uaddr uaddr)7716346e14SHans Petter Selasky usb_control_ep_error_test(struct uaddr uaddr)
788030839bSHans Petter Selasky {
798030839bSHans Petter Selasky struct LIBUSB20_CONTROL_SETUP_DECODED req;
808030839bSHans Petter Selasky struct libusb20_device *pdev;
818030839bSHans Petter Selasky uint8_t buffer[256];
828030839bSHans Petter Selasky int error;
838030839bSHans Petter Selasky int fail = 0;
848030839bSHans Petter Selasky int bus;
858030839bSHans Petter Selasky int dev;
868030839bSHans Petter Selasky int cfg;
878030839bSHans Petter Selasky
8816346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
898030839bSHans Petter Selasky if (pdev == NULL) {
908030839bSHans Petter Selasky printf("USB device not found\n");
918030839bSHans Petter Selasky return;
928030839bSHans Petter Selasky }
938030839bSHans Petter Selasky error = libusb20_dev_open(pdev, 0);
948030839bSHans Petter Selasky if (error) {
958030839bSHans Petter Selasky printf("Could not open USB device\n");
968030839bSHans Petter Selasky libusb20_dev_free(pdev);
978030839bSHans Petter Selasky return;
988030839bSHans Petter Selasky }
998030839bSHans Petter Selasky
1008030839bSHans Petter Selasky bus = libusb20_dev_get_bus_number(pdev);
1018030839bSHans Petter Selasky dev = libusb20_dev_get_address(pdev);
1028030839bSHans Petter Selasky
1038030839bSHans Petter Selasky for (cfg = 0; cfg != 255; cfg++) {
1048030839bSHans Petter Selasky
1058030839bSHans Petter Selasky LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
1068030839bSHans Petter Selasky req.bmRequestType = 0x80; /* read */
1078030839bSHans Petter Selasky req.bRequest = 0x06; /* descriptor */
1088030839bSHans Petter Selasky req.wValue = 0x0200 | cfg; /* config descriptor */
1098030839bSHans Petter Selasky req.wIndex = 0;
1108030839bSHans Petter Selasky req.wLength = 255;
1118030839bSHans Petter Selasky
1128030839bSHans Petter Selasky printf("Test #%d.1/3 ...\n", cfg);
1138030839bSHans Petter Selasky
1148030839bSHans Petter Selasky set_ctrl_ep_fail(-1,-1,0,0);
1158030839bSHans Petter Selasky
1168030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev, &req, buffer,
1178030839bSHans Petter Selasky NULL, 1000, 0);
1188030839bSHans Petter Selasky if (error != 0) {
1198030839bSHans Petter Selasky printf("Last configuration index is: %d\n", cfg - 1);
1208030839bSHans Petter Selasky break;
1218030839bSHans Petter Selasky }
1228030839bSHans Petter Selasky
1238030839bSHans Petter Selasky printf("Test #%d.2/3 ...\n", cfg);
1248030839bSHans Petter Selasky
1258030839bSHans Petter Selasky set_ctrl_ep_fail(bus,dev,1,1);
1268030839bSHans Petter Selasky
1278030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev, &req, buffer,
1288030839bSHans Petter Selasky NULL, 1000, 0);
1298030839bSHans Petter Selasky
1308030839bSHans Petter Selasky set_ctrl_ep_fail(-1,-1,0,0);
1318030839bSHans Petter Selasky
1328030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev, &req, buffer,
1338030839bSHans Petter Selasky NULL, 1000, 0);
1348030839bSHans Petter Selasky if (error != 0) {
1358030839bSHans Petter Selasky printf("Cannot fetch descriptor (unexpected)\n");
1368030839bSHans Petter Selasky fail++;
1378030839bSHans Petter Selasky }
1388030839bSHans Petter Selasky
1398030839bSHans Petter Selasky printf("Test #%d.3/3 ...\n", cfg);
1408030839bSHans Petter Selasky
1418030839bSHans Petter Selasky set_ctrl_ep_fail(bus,dev,0,1);
1428030839bSHans Petter Selasky
1438030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev, &req, buffer,
1448030839bSHans Petter Selasky NULL, 1000, 0);
1458030839bSHans Petter Selasky
1468030839bSHans Petter Selasky set_ctrl_ep_fail(-1,-1,0,0);
1478030839bSHans Petter Selasky
1488030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev, &req, buffer,
1498030839bSHans Petter Selasky NULL, 1000, 0);
1508030839bSHans Petter Selasky if (error != 0) {
1518030839bSHans Petter Selasky printf("Cannot fetch descriptor (unexpected)\n");
1528030839bSHans Petter Selasky fail++;
1538030839bSHans Petter Selasky }
1548030839bSHans Petter Selasky }
1558030839bSHans Petter Selasky
1568030839bSHans Petter Selasky libusb20_dev_close(pdev);
1578030839bSHans Petter Selasky libusb20_dev_free(pdev);
1588030839bSHans Petter Selasky
1598030839bSHans Petter Selasky printf("Test completed detecting %d failures\nDone\n\n", fail);
1608030839bSHans Petter Selasky }
1618030839bSHans Petter Selasky
1628030839bSHans Petter Selasky void
usb_get_string_desc_test(struct uaddr uaddr)16316346e14SHans Petter Selasky usb_get_string_desc_test(struct uaddr uaddr)
1648030839bSHans Petter Selasky {
1658030839bSHans Petter Selasky struct libusb20_device *pdev;
1668030839bSHans Petter Selasky uint32_t x;
1678030839bSHans Petter Selasky uint32_t y;
1688030839bSHans Petter Selasky uint32_t valid;
1698030839bSHans Petter Selasky uint8_t *buf;
1708030839bSHans Petter Selasky int error;
1718030839bSHans Petter Selasky
17216346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
1738030839bSHans Petter Selasky if (pdev == NULL) {
1748030839bSHans Petter Selasky printf("USB device not found\n");
1758030839bSHans Petter Selasky return;
1768030839bSHans Petter Selasky }
1778030839bSHans Petter Selasky error = libusb20_dev_open(pdev, 0);
1788030839bSHans Petter Selasky if (error) {
1798030839bSHans Petter Selasky printf("Could not open USB device\n");
1808030839bSHans Petter Selasky libusb20_dev_free(pdev);
1818030839bSHans Petter Selasky return;
1828030839bSHans Petter Selasky }
1838030839bSHans Petter Selasky buf = malloc(256);
1848030839bSHans Petter Selasky if (buf == NULL) {
1858030839bSHans Petter Selasky printf("Cannot allocate memory\n");
1868030839bSHans Petter Selasky libusb20_dev_free(pdev);
1878030839bSHans Petter Selasky return;
1888030839bSHans Petter Selasky }
1898030839bSHans Petter Selasky valid = 0;
1908030839bSHans Petter Selasky
1918030839bSHans Petter Selasky printf("Starting string descriptor test for "
19216346e14SHans Petter Selasky "VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
1938030839bSHans Petter Selasky
1948030839bSHans Petter Selasky for (x = 0; x != 256; x++) {
1958030839bSHans Petter Selasky
1968030839bSHans Petter Selasky if (libusb20_dev_check_connected(pdev) != 0) {
1978030839bSHans Petter Selasky printf("Device disconnected\n");
1988030839bSHans Petter Selasky break;
1998030839bSHans Petter Selasky }
2008030839bSHans Petter Selasky printf("%d .. ", (int)x);
2018030839bSHans Petter Selasky
2028030839bSHans Petter Selasky fflush(stdout);
2038030839bSHans Petter Selasky
2048030839bSHans Petter Selasky error = libusb20_dev_req_string_simple_sync(pdev, x, buf, 255);
2058030839bSHans Petter Selasky
2068030839bSHans Petter Selasky if (error == 0) {
2078030839bSHans Petter Selasky printf("\nINDEX=%d, STRING='%s' (Default language)\n", (int)x, buf);
2088030839bSHans Petter Selasky fflush(stdout);
2098030839bSHans Petter Selasky } else {
2108030839bSHans Petter Selasky continue;
2118030839bSHans Petter Selasky }
2128030839bSHans Petter Selasky
2138030839bSHans Petter Selasky valid = 0;
2148030839bSHans Petter Selasky
2158030839bSHans Petter Selasky for (y = 0; y != 65536; y++) {
2168030839bSHans Petter Selasky
2178030839bSHans Petter Selasky if (libusb20_dev_check_connected(pdev) != 0) {
2188030839bSHans Petter Selasky printf("Device disconnected\n");
2198030839bSHans Petter Selasky break;
2208030839bSHans Petter Selasky }
2218030839bSHans Petter Selasky error = libusb20_dev_req_string_sync(pdev, x, y, buf, 256);
2228030839bSHans Petter Selasky if (error == 0)
2238030839bSHans Petter Selasky valid++;
2248030839bSHans Petter Selasky }
2258030839bSHans Petter Selasky
2268030839bSHans Petter Selasky printf("String at INDEX=%d responds to %d "
2278030839bSHans Petter Selasky "languages\n", (int)x, (int)valid);
2288030839bSHans Petter Selasky }
2298030839bSHans Petter Selasky
2308030839bSHans Petter Selasky printf("\nDone\n");
2318030839bSHans Petter Selasky
2328030839bSHans Petter Selasky free(buf);
2338030839bSHans Petter Selasky
2348030839bSHans Petter Selasky libusb20_dev_free(pdev);
2358030839bSHans Petter Selasky }
2368030839bSHans Petter Selasky
2378030839bSHans Petter Selasky void
usb_port_reset_test(struct uaddr uaddr,uint32_t duration)23816346e14SHans Petter Selasky usb_port_reset_test(struct uaddr uaddr, uint32_t duration)
2398030839bSHans Petter Selasky {
2408030839bSHans Petter Selasky struct timeval sub_tv;
2418030839bSHans Petter Selasky struct timeval ref_tv;
2428030839bSHans Petter Selasky struct timeval res_tv;
2438030839bSHans Petter Selasky
2448030839bSHans Petter Selasky struct libusb20_device *pdev;
2458030839bSHans Petter Selasky
2468030839bSHans Petter Selasky int error;
2478030839bSHans Petter Selasky int iter;
2488030839bSHans Petter Selasky int errcnt;
2498030839bSHans Petter Selasky
2508030839bSHans Petter Selasky time_t last_sec;
2518030839bSHans Petter Selasky
2528030839bSHans Petter Selasky /* sysctl() - no set config */
2538030839bSHans Petter Selasky
25416346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
2558030839bSHans Petter Selasky if (pdev == NULL) {
2568030839bSHans Petter Selasky printf("USB device not found\n");
2578030839bSHans Petter Selasky return;
2588030839bSHans Petter Selasky }
2598030839bSHans Petter Selasky error = libusb20_dev_open(pdev, 0);
2608030839bSHans Petter Selasky if (error) {
2618030839bSHans Petter Selasky libusb20_dev_free(pdev);
2628030839bSHans Petter Selasky printf("Could not open USB device\n");
2638030839bSHans Petter Selasky return;
2648030839bSHans Petter Selasky }
2658030839bSHans Petter Selasky iter = 0;
2668030839bSHans Petter Selasky
2678030839bSHans Petter Selasky errcnt = 0;
2688030839bSHans Petter Selasky
2698030839bSHans Petter Selasky gettimeofday(&ref_tv, 0);
2708030839bSHans Petter Selasky
2718030839bSHans Petter Selasky last_sec = ref_tv.tv_sec;
2728030839bSHans Petter Selasky
2738030839bSHans Petter Selasky while (1) {
2748030839bSHans Petter Selasky
2758030839bSHans Petter Selasky gettimeofday(&sub_tv, 0);
2768030839bSHans Petter Selasky
2778030839bSHans Petter Selasky if (last_sec != sub_tv.tv_sec) {
2788030839bSHans Petter Selasky
2798030839bSHans Petter Selasky printf("STATUS: ID=%u, ERR=%u\n",
2808030839bSHans Petter Selasky (int)iter, (int)errcnt);
2818030839bSHans Petter Selasky
2828030839bSHans Petter Selasky fflush(stdout);
2838030839bSHans Petter Selasky
2848030839bSHans Petter Selasky last_sec = sub_tv.tv_sec;
2858030839bSHans Petter Selasky }
2868030839bSHans Petter Selasky timersub(&sub_tv, &ref_tv, &res_tv);
2878030839bSHans Petter Selasky
288f7b25aedSHans Petter Selasky if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration))
2898030839bSHans Petter Selasky break;
2908030839bSHans Petter Selasky
2918030839bSHans Petter Selasky if (libusb20_dev_reset(pdev)) {
2928030839bSHans Petter Selasky errcnt++;
2938030839bSHans Petter Selasky usleep(50000);
2948030839bSHans Petter Selasky }
2958030839bSHans Petter Selasky if (libusb20_dev_check_connected(pdev) != 0) {
2968030839bSHans Petter Selasky printf("Device disconnected\n");
2978030839bSHans Petter Selasky break;
2988030839bSHans Petter Selasky }
2998030839bSHans Petter Selasky iter++;
3008030839bSHans Petter Selasky }
3018030839bSHans Petter Selasky
3028030839bSHans Petter Selasky libusb20_dev_reset(pdev);
3038030839bSHans Petter Selasky
3048030839bSHans Petter Selasky libusb20_dev_free(pdev);
3058030839bSHans Petter Selasky }
3068030839bSHans Petter Selasky
3078030839bSHans Petter Selasky void
usb_set_config_test(struct uaddr uaddr,uint32_t duration)30816346e14SHans Petter Selasky usb_set_config_test(struct uaddr uaddr, uint32_t duration)
3098030839bSHans Petter Selasky {
3108030839bSHans Petter Selasky struct libusb20_device *pdev;
3118030839bSHans Petter Selasky struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
3128030839bSHans Petter Selasky int x;
3138030839bSHans Petter Selasky int error;
3148030839bSHans Petter Selasky int failed;
3158030839bSHans Petter Selasky int exp;
3168030839bSHans Petter Selasky
31716346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
3188030839bSHans Petter Selasky if (pdev == NULL) {
3198030839bSHans Petter Selasky printf("USB device not found\n");
3208030839bSHans Petter Selasky return;
3218030839bSHans Petter Selasky }
3228030839bSHans Petter Selasky error = libusb20_dev_open(pdev, 0);
3238030839bSHans Petter Selasky if (error) {
3248030839bSHans Petter Selasky printf("Could not open USB device\n");
3258030839bSHans Petter Selasky libusb20_dev_free(pdev);
3268030839bSHans Petter Selasky return;
3278030839bSHans Petter Selasky }
3288030839bSHans Petter Selasky failed = 0;
3298030839bSHans Petter Selasky
3308030839bSHans Petter Selasky printf("Starting set config test for "
33116346e14SHans Petter Selasky "VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
3328030839bSHans Petter Selasky
3338030839bSHans Petter Selasky for (x = 255; x > -1; x--) {
3348030839bSHans Petter Selasky
3358030839bSHans Petter Selasky error = libusb20_dev_set_config_index(pdev, x);
3368030839bSHans Petter Selasky if (error == 0) {
3378030839bSHans Petter Selasky if (x == 255) {
3388030839bSHans Petter Selasky printf("Unconfiguring USB device "
3398030839bSHans Petter Selasky "was successful\n");
3408030839bSHans Petter Selasky } else {
3418030839bSHans Petter Selasky printf("Setting configuration %d "
3428030839bSHans Petter Selasky "was successful\n", x);
3438030839bSHans Petter Selasky }
3448030839bSHans Petter Selasky } else {
3458030839bSHans Petter Selasky failed++;
3468030839bSHans Petter Selasky }
3478030839bSHans Petter Selasky }
3488030839bSHans Petter Selasky
3498030839bSHans Petter Selasky ddesc = libusb20_dev_get_device_desc(pdev);
3508030839bSHans Petter Selasky if (ddesc != NULL)
3518030839bSHans Petter Selasky exp = ddesc->bNumConfigurations + 1;
3528030839bSHans Petter Selasky else
3538030839bSHans Petter Selasky exp = 1;
3548030839bSHans Petter Selasky
3558030839bSHans Petter Selasky printf("\n\n"
3568030839bSHans Petter Selasky "Set configuration summary\n"
3578030839bSHans Petter Selasky "Valid count: %d/%d %s\n"
3588030839bSHans Petter Selasky "Failed count: %d\n",
3598030839bSHans Petter Selasky 256 - failed, exp,
3608030839bSHans Petter Selasky (exp == (256 - failed)) ? "(expected)" : "(unexpected)",
3618030839bSHans Petter Selasky failed);
3628030839bSHans Petter Selasky
3638030839bSHans Petter Selasky libusb20_dev_free(pdev);
3648030839bSHans Petter Selasky }
3658030839bSHans Petter Selasky
3668030839bSHans Petter Selasky void
usb_get_descriptor_test(struct uaddr uaddr,uint32_t duration)36716346e14SHans Petter Selasky usb_get_descriptor_test(struct uaddr uaddr, uint32_t duration)
3688030839bSHans Petter Selasky {
3698030839bSHans Petter Selasky struct libusb20_device *pdev;
3708030839bSHans Petter Selasky
37116346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
3728030839bSHans Petter Selasky if (pdev == NULL) {
3738030839bSHans Petter Selasky printf("USB device not found\n");
3748030839bSHans Petter Selasky return;
3758030839bSHans Petter Selasky }
3768030839bSHans Petter Selasky libusb20_dev_free(pdev);
3778030839bSHans Petter Selasky }
3788030839bSHans Petter Selasky
3798030839bSHans Petter Selasky void
usb_suspend_resume_test(struct uaddr uaddr,uint32_t duration)38016346e14SHans Petter Selasky usb_suspend_resume_test(struct uaddr uaddr, uint32_t duration)
3818030839bSHans Petter Selasky {
3828030839bSHans Petter Selasky struct timeval sub_tv;
3838030839bSHans Petter Selasky struct timeval ref_tv;
3848030839bSHans Petter Selasky struct timeval res_tv;
3858030839bSHans Petter Selasky
3868030839bSHans Petter Selasky struct libusb20_device *pdev;
3878030839bSHans Petter Selasky
3888030839bSHans Petter Selasky time_t last_sec;
3898030839bSHans Petter Selasky
3908030839bSHans Petter Selasky int iter;
3918030839bSHans Petter Selasky int error;
3928030839bSHans Petter Selasky int ptimo;
3938030839bSHans Petter Selasky int errcnt;
3948030839bSHans Petter Selasky int power_old;
3958030839bSHans Petter Selasky
3968030839bSHans Petter Selasky ptimo = 1; /* second(s) */
3978030839bSHans Petter Selasky
3988030839bSHans Petter Selasky error = sysctlbyname("hw.usb.power_timeout", NULL, NULL,
3998030839bSHans Petter Selasky &ptimo, sizeof(ptimo));
4008030839bSHans Petter Selasky
4018030839bSHans Petter Selasky if (error != 0) {
4028030839bSHans Petter Selasky printf("WARNING: Could not set power "
4038030839bSHans Petter Selasky "timeout to 1 (error=%d) \n", errno);
4048030839bSHans Petter Selasky }
40516346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
4068030839bSHans Petter Selasky if (pdev == NULL) {
4078030839bSHans Petter Selasky printf("USB device not found\n");
4088030839bSHans Petter Selasky return;
4098030839bSHans Petter Selasky }
4108030839bSHans Petter Selasky error = libusb20_dev_open(pdev, 0);
4118030839bSHans Petter Selasky if (error) {
4128030839bSHans Petter Selasky printf("Could not open USB device\n");
4138030839bSHans Petter Selasky libusb20_dev_free(pdev);
4148030839bSHans Petter Selasky return;
4158030839bSHans Petter Selasky }
4168030839bSHans Petter Selasky power_old = libusb20_dev_get_power_mode(pdev);
4178030839bSHans Petter Selasky
4188030839bSHans Petter Selasky printf("Starting suspend and resume "
41916346e14SHans Petter Selasky "test for VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
4208030839bSHans Petter Selasky
4218030839bSHans Petter Selasky iter = 0;
4228030839bSHans Petter Selasky errcnt = 0;
4238030839bSHans Petter Selasky
4248030839bSHans Petter Selasky gettimeofday(&ref_tv, 0);
4258030839bSHans Petter Selasky
4268030839bSHans Petter Selasky last_sec = ref_tv.tv_sec;
4278030839bSHans Petter Selasky
4288030839bSHans Petter Selasky while (1) {
4298030839bSHans Petter Selasky
4308030839bSHans Petter Selasky if (libusb20_dev_check_connected(pdev) != 0) {
4318030839bSHans Petter Selasky printf("Device disconnected\n");
4328030839bSHans Petter Selasky break;
4338030839bSHans Petter Selasky }
4348030839bSHans Petter Selasky gettimeofday(&sub_tv, 0);
4358030839bSHans Petter Selasky
4368030839bSHans Petter Selasky if (last_sec != sub_tv.tv_sec) {
4378030839bSHans Petter Selasky
4388030839bSHans Petter Selasky printf("STATUS: ID=%u, ERR=%u\n",
4398030839bSHans Petter Selasky (int)iter, (int)errcnt);
4408030839bSHans Petter Selasky
4418030839bSHans Petter Selasky fflush(stdout);
4428030839bSHans Petter Selasky
4438030839bSHans Petter Selasky last_sec = sub_tv.tv_sec;
4448030839bSHans Petter Selasky }
4458030839bSHans Petter Selasky timersub(&sub_tv, &ref_tv, &res_tv);
4468030839bSHans Petter Selasky
447f7b25aedSHans Petter Selasky if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration))
4488030839bSHans Petter Selasky break;
4498030839bSHans Petter Selasky
4508030839bSHans Petter Selasky error = libusb20_dev_set_power_mode(pdev, (iter & 1) ?
4518030839bSHans Petter Selasky LIBUSB20_POWER_ON : LIBUSB20_POWER_SAVE);
4528030839bSHans Petter Selasky
4538030839bSHans Petter Selasky if (error)
4548030839bSHans Petter Selasky errcnt++;
4558030839bSHans Petter Selasky
4568030839bSHans Petter Selasky /* wait before switching power mode */
4578030839bSHans Petter Selasky usleep(4100000 +
4588030839bSHans Petter Selasky (((uint32_t)usb_ts_rand_noise()) % 2000000U));
4598030839bSHans Petter Selasky
4608030839bSHans Petter Selasky iter++;
4618030839bSHans Petter Selasky }
4628030839bSHans Petter Selasky
4638030839bSHans Petter Selasky /* restore default power mode */
4648030839bSHans Petter Selasky libusb20_dev_set_power_mode(pdev, power_old);
4658030839bSHans Petter Selasky
4668030839bSHans Petter Selasky libusb20_dev_free(pdev);
4678030839bSHans Petter Selasky }
4688030839bSHans Petter Selasky
4698030839bSHans Petter Selasky void
usb_set_and_clear_stall_test(struct uaddr uaddr)47016346e14SHans Petter Selasky usb_set_and_clear_stall_test(struct uaddr uaddr)
4718030839bSHans Petter Selasky {
4728030839bSHans Petter Selasky struct libusb20_device *pdev;
4738030839bSHans Petter Selasky struct libusb20_transfer *pxfer;
4748030839bSHans Petter Selasky
4758030839bSHans Petter Selasky int iter;
4768030839bSHans Petter Selasky int error;
4778030839bSHans Petter Selasky int errcnt;
4788030839bSHans Petter Selasky int ep;
4798030839bSHans Petter Selasky
48016346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
4818030839bSHans Petter Selasky if (pdev == NULL) {
4828030839bSHans Petter Selasky printf("USB device not found\n");
4838030839bSHans Petter Selasky return;
4848030839bSHans Petter Selasky }
4858030839bSHans Petter Selasky error = libusb20_dev_open(pdev, 1);
4868030839bSHans Petter Selasky if (error) {
4878030839bSHans Petter Selasky printf("Could not open USB device\n");
4888030839bSHans Petter Selasky libusb20_dev_free(pdev);
4898030839bSHans Petter Selasky return;
4908030839bSHans Petter Selasky }
4918030839bSHans Petter Selasky printf("Starting set and clear stall test "
49216346e14SHans Petter Selasky "for VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
4938030839bSHans Petter Selasky
4948030839bSHans Petter Selasky iter = 0;
4958030839bSHans Petter Selasky errcnt = 0;
4968030839bSHans Petter Selasky
4978030839bSHans Petter Selasky for (ep = 2; ep != 32; ep++) {
4988030839bSHans Petter Selasky
4998030839bSHans Petter Selasky struct LIBUSB20_CONTROL_SETUP_DECODED setup_set_stall;
5008030839bSHans Petter Selasky struct LIBUSB20_CONTROL_SETUP_DECODED setup_get_status;
5018030839bSHans Petter Selasky
5028030839bSHans Petter Selasky uint8_t epno = ((ep / 2) | ((ep & 1) << 7));
5038030839bSHans Petter Selasky uint8_t buf[1];
5048030839bSHans Petter Selasky
5058030839bSHans Petter Selasky LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_set_stall);
5068030839bSHans Petter Selasky setup_set_stall.bmRequestType = 0x02; /* write endpoint */
5078030839bSHans Petter Selasky setup_set_stall.bRequest = 0x03; /* set feature */
5088030839bSHans Petter Selasky setup_set_stall.wValue = 0x00; /* UF_ENDPOINT_HALT */
5098030839bSHans Petter Selasky setup_set_stall.wIndex = epno;
5108030839bSHans Petter Selasky setup_set_stall.wLength = 0;
5118030839bSHans Petter Selasky
5128030839bSHans Petter Selasky LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_get_status);
5138030839bSHans Petter Selasky setup_get_status.bmRequestType = 0x82; /* read endpoint */
5148030839bSHans Petter Selasky setup_get_status.bRequest = 0x00; /* get status */
5158030839bSHans Petter Selasky setup_get_status.wValue = 0x00;
5168030839bSHans Petter Selasky setup_get_status.wIndex = epno;
5178030839bSHans Petter Selasky setup_get_status.wLength = 1;
5188030839bSHans Petter Selasky
5198030839bSHans Petter Selasky if (libusb20_dev_check_connected(pdev) != 0) {
5208030839bSHans Petter Selasky printf("Device disconnected\n");
5218030839bSHans Petter Selasky break;
5228030839bSHans Petter Selasky }
5238030839bSHans Petter Selasky pxfer = libusb20_tr_get_pointer(pdev, 0);
5248030839bSHans Petter Selasky
5258030839bSHans Petter Selasky error = libusb20_tr_open(pxfer, 1, 1, epno);
5268030839bSHans Petter Selasky
5278030839bSHans Petter Selasky if (error != 0) {
5288030839bSHans Petter Selasky printf("Endpoint 0x%02x does not exist "
5298030839bSHans Petter Selasky "in current setting. (%s, ignored)\n",
5308030839bSHans Petter Selasky epno, libusb20_strerror(error));
5318030839bSHans Petter Selasky continue;
5328030839bSHans Petter Selasky }
5338030839bSHans Petter Selasky printf("Stalling endpoint 0x%02x\n", epno);
5348030839bSHans Petter Selasky
5358030839bSHans Petter Selasky /* set stall */
5368030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev,
5378030839bSHans Petter Selasky &setup_set_stall, NULL, NULL, 250, 0);
5388030839bSHans Petter Selasky
5398030839bSHans Petter Selasky if (error != 0) {
5408030839bSHans Petter Selasky printf("Endpoint 0x%02x does not allow "
5418030839bSHans Petter Selasky "setting of stall. (%s)\n",
5428030839bSHans Petter Selasky epno, libusb20_strerror(error));
5438030839bSHans Petter Selasky errcnt++;
5448030839bSHans Petter Selasky }
5458030839bSHans Petter Selasky /* get EP status */
5468030839bSHans Petter Selasky buf[0] = 0;
5478030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev,
5488030839bSHans Petter Selasky &setup_get_status, buf, NULL, 250, 0);
5498030839bSHans Petter Selasky
5508030839bSHans Petter Selasky if (error != 0) {
5518030839bSHans Petter Selasky printf("Endpoint 0x%02x does not allow "
5528030839bSHans Petter Selasky "reading status. (%s)\n",
5538030839bSHans Petter Selasky epno, libusb20_strerror(error));
5548030839bSHans Petter Selasky errcnt++;
5558030839bSHans Petter Selasky } else {
5568030839bSHans Petter Selasky if (!(buf[0] & 1)) {
5578030839bSHans Petter Selasky printf("Endpoint 0x%02x status is "
5588030839bSHans Petter Selasky "not set to stalled\n", epno);
5598030839bSHans Petter Selasky errcnt++;
5608030839bSHans Petter Selasky }
5618030839bSHans Petter Selasky }
5628030839bSHans Petter Selasky
5638030839bSHans Petter Selasky buf[0] = 0;
5648030839bSHans Petter Selasky error = libusb20_tr_bulk_intr_sync(pxfer, buf, 1, NULL, 250);
5658030839bSHans Petter Selasky if (error != LIBUSB20_TRANSFER_STALL) {
5668030839bSHans Petter Selasky printf("Endpoint 0x%02x does not appear to "
5678030839bSHans Petter Selasky "have stalled. Missing stall PID!\n", epno);
5688030839bSHans Petter Selasky errcnt++;
5698030839bSHans Petter Selasky }
5708030839bSHans Petter Selasky printf("Unstalling endpoint 0x%02x\n", epno);
5718030839bSHans Petter Selasky
5728030839bSHans Petter Selasky libusb20_tr_clear_stall_sync(pxfer);
5738030839bSHans Petter Selasky
5748030839bSHans Petter Selasky /* get EP status */
5758030839bSHans Petter Selasky buf[0] = 0;
5768030839bSHans Petter Selasky error = libusb20_dev_request_sync(pdev,
5778030839bSHans Petter Selasky &setup_get_status, buf, NULL, 250, 0);
5788030839bSHans Petter Selasky
5798030839bSHans Petter Selasky if (error != 0) {
5808030839bSHans Petter Selasky printf("Endpoint 0x%02x does not allow "
5818030839bSHans Petter Selasky "reading status. (%s)\n",
5828030839bSHans Petter Selasky epno, libusb20_strerror(error));
5838030839bSHans Petter Selasky errcnt++;
5848030839bSHans Petter Selasky } else {
5858030839bSHans Petter Selasky if (buf[0] & 1) {
5868030839bSHans Petter Selasky printf("Endpoint 0x%02x status is "
5878030839bSHans Petter Selasky "still stalled\n", epno);
5888030839bSHans Petter Selasky errcnt++;
5898030839bSHans Petter Selasky }
5908030839bSHans Petter Selasky }
5918030839bSHans Petter Selasky
5928030839bSHans Petter Selasky libusb20_tr_close(pxfer);
5938030839bSHans Petter Selasky iter++;
5948030839bSHans Petter Selasky }
5958030839bSHans Petter Selasky
5968030839bSHans Petter Selasky libusb20_dev_free(pdev);
5978030839bSHans Petter Selasky
5988030839bSHans Petter Selasky printf("\n"
5998030839bSHans Petter Selasky "Test summary\n"
6008030839bSHans Petter Selasky "============\n"
6018030839bSHans Petter Selasky "Endpoints tested: %d\n"
6028030839bSHans Petter Selasky "Errors: %d\n", iter, errcnt);
6038030839bSHans Petter Selasky }
6048030839bSHans Petter Selasky
6058030839bSHans Petter Selasky void
usb_set_alt_interface_test(struct uaddr uaddr)60616346e14SHans Petter Selasky usb_set_alt_interface_test(struct uaddr uaddr)
6078030839bSHans Petter Selasky {
6088030839bSHans Petter Selasky struct libusb20_device *pdev;
6098030839bSHans Petter Selasky struct libusb20_config *config;
6108030839bSHans Petter Selasky
6118030839bSHans Petter Selasky int iter;
6128030839bSHans Petter Selasky int error;
6138030839bSHans Petter Selasky int errcnt;
6148030839bSHans Petter Selasky int n;
6158030839bSHans Petter Selasky int m;
6168030839bSHans Petter Selasky
61716346e14SHans Petter Selasky pdev = find_usb_device(uaddr);
6188030839bSHans Petter Selasky if (pdev == NULL) {
6198030839bSHans Petter Selasky printf("USB device not found\n");
6208030839bSHans Petter Selasky return;
6218030839bSHans Petter Selasky }
6228030839bSHans Petter Selasky printf("Starting set alternate setting test "
62316346e14SHans Petter Selasky "for VID=0x%04x PID=0x%04x\n", uaddr.vid, uaddr.pid);
6248030839bSHans Petter Selasky
6258030839bSHans Petter Selasky config = libusb20_dev_alloc_config(pdev,
6268030839bSHans Petter Selasky libusb20_dev_get_config_index(pdev));
6278030839bSHans Petter Selasky if (config == NULL) {
6288030839bSHans Petter Selasky printf("Could not get configuration descriptor\n");
6298030839bSHans Petter Selasky libusb20_dev_free(pdev);
6308030839bSHans Petter Selasky return;
6318030839bSHans Petter Selasky }
6328030839bSHans Petter Selasky iter = 0;
6338030839bSHans Petter Selasky errcnt = 0;
6348030839bSHans Petter Selasky
6358030839bSHans Petter Selasky for (n = 0; n != config->num_interface; n++) {
6368030839bSHans Petter Selasky /* detach kernel driver */
6378030839bSHans Petter Selasky libusb20_dev_detach_kernel_driver(pdev, n);
6388030839bSHans Petter Selasky
6398030839bSHans Petter Selasky error = libusb20_dev_open(pdev, 0);
6408030839bSHans Petter Selasky if (error)
6418030839bSHans Petter Selasky printf("ERROR could not open device\n");
6428030839bSHans Petter Selasky
6438030839bSHans Petter Selasky /* Try the alternate settings */
6448030839bSHans Petter Selasky for (m = 0; m != config->interface[n].num_altsetting; m++) {
6458030839bSHans Petter Selasky
6468030839bSHans Petter Selasky iter++;
6478030839bSHans Petter Selasky
6488030839bSHans Petter Selasky if (libusb20_dev_set_alt_index(pdev, n, m + 1)) {
6498030839bSHans Petter Selasky printf("ERROR on interface %d alt %d\n", n, m + 1);
6508030839bSHans Petter Selasky errcnt++;
6518030839bSHans Petter Selasky }
6528030839bSHans Petter Selasky }
6538030839bSHans Petter Selasky
6548030839bSHans Petter Selasky /* Restore to default */
6558030839bSHans Petter Selasky
6568030839bSHans Petter Selasky iter++;
6578030839bSHans Petter Selasky
6588030839bSHans Petter Selasky if (libusb20_dev_set_alt_index(pdev, n, 0)) {
6598030839bSHans Petter Selasky printf("ERROR on interface %d alt %d\n", n, 0);
6608030839bSHans Petter Selasky errcnt++;
6618030839bSHans Petter Selasky }
6628030839bSHans Petter Selasky libusb20_dev_close(pdev);
6638030839bSHans Petter Selasky }
6648030839bSHans Petter Selasky
6658030839bSHans Petter Selasky libusb20_dev_free(pdev);
6668030839bSHans Petter Selasky
6678030839bSHans Petter Selasky printf("\n"
6688030839bSHans Petter Selasky "Test summary\n"
6698030839bSHans Petter Selasky "============\n"
6708030839bSHans Petter Selasky "Interfaces tested: %d\n"
6718030839bSHans Petter Selasky "Errors: %d\n", iter, errcnt);
6728030839bSHans Petter Selasky }
673