1*129a2703SSascha Wildner /* $FreeBSD: head/tools/tools/usbtest/usb_control_ep_test.c 254241 2013-08-12 09:15:33Z hselasky $ */
257bed822SMarkus Pfeiffer /*-
357bed822SMarkus Pfeiffer * Copyright (c) 2007-2010 Hans Petter Selasky. All rights reserved.
457bed822SMarkus Pfeiffer *
557bed822SMarkus Pfeiffer * Redistribution and use in source and binary forms, with or without
657bed822SMarkus Pfeiffer * modification, are permitted provided that the following conditions
757bed822SMarkus Pfeiffer * are met:
857bed822SMarkus Pfeiffer * 1. Redistributions of source code must retain the above copyright
957bed822SMarkus Pfeiffer * notice, this list of conditions and the following disclaimer.
1057bed822SMarkus Pfeiffer * 2. Redistributions in binary form must reproduce the above copyright
1157bed822SMarkus Pfeiffer * notice, this list of conditions and the following disclaimer in the
1257bed822SMarkus Pfeiffer * documentation and/or other materials provided with the distribution.
1357bed822SMarkus Pfeiffer *
1457bed822SMarkus Pfeiffer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1557bed822SMarkus Pfeiffer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1657bed822SMarkus Pfeiffer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1757bed822SMarkus Pfeiffer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1857bed822SMarkus Pfeiffer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1957bed822SMarkus Pfeiffer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2057bed822SMarkus Pfeiffer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2157bed822SMarkus Pfeiffer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2257bed822SMarkus Pfeiffer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2357bed822SMarkus Pfeiffer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2457bed822SMarkus Pfeiffer * SUCH DAMAGE.
2557bed822SMarkus Pfeiffer */
2657bed822SMarkus Pfeiffer
2757bed822SMarkus Pfeiffer #include <stdio.h>
2857bed822SMarkus Pfeiffer #include <stdint.h>
2957bed822SMarkus Pfeiffer #include <stdlib.h>
3057bed822SMarkus Pfeiffer #include <err.h>
3157bed822SMarkus Pfeiffer #include <string.h>
3257bed822SMarkus Pfeiffer #include <errno.h>
3357bed822SMarkus Pfeiffer #include <unistd.h>
3457bed822SMarkus Pfeiffer
3557bed822SMarkus Pfeiffer #include <sys/sysctl.h>
3657bed822SMarkus Pfeiffer #include <sys/time.h>
3757bed822SMarkus Pfeiffer
3857bed822SMarkus Pfeiffer #include <libusb20.h>
3957bed822SMarkus Pfeiffer #include <libusb20_desc.h>
4057bed822SMarkus Pfeiffer
41*129a2703SSascha Wildner #include <bus/u4b/usb_endian.h>
42*129a2703SSascha Wildner #include <bus/u4b/usb.h>
43*129a2703SSascha Wildner #include <bus/u4b/usb_cdc.h>
4457bed822SMarkus Pfeiffer
4557bed822SMarkus Pfeiffer #include "usbtest.h"
4657bed822SMarkus Pfeiffer
4757bed822SMarkus Pfeiffer static void
set_ctrl_ep_fail(int bus,int dev,int ds_fail,int ss_fail)4857bed822SMarkus Pfeiffer set_ctrl_ep_fail(int bus, int dev, int ds_fail, int ss_fail)
4957bed822SMarkus Pfeiffer {
5057bed822SMarkus Pfeiffer int error;
5157bed822SMarkus Pfeiffer
5257bed822SMarkus Pfeiffer error = sysctlbyname("hw.usb.ctrl_bus_fail", NULL, NULL,
5357bed822SMarkus Pfeiffer &bus, sizeof(bus));
5457bed822SMarkus Pfeiffer if (error != 0)
5557bed822SMarkus Pfeiffer goto emissing;
5657bed822SMarkus Pfeiffer
5757bed822SMarkus Pfeiffer error = sysctlbyname("hw.usb.ctrl_dev_fail", NULL, NULL,
5857bed822SMarkus Pfeiffer &dev, sizeof(dev));
5957bed822SMarkus Pfeiffer if (error != 0)
6057bed822SMarkus Pfeiffer goto emissing;
6157bed822SMarkus Pfeiffer
6257bed822SMarkus Pfeiffer error = sysctlbyname("hw.usb.ctrl_ds_fail", NULL, NULL,
6357bed822SMarkus Pfeiffer &ds_fail, sizeof(ds_fail));
6457bed822SMarkus Pfeiffer if (error != 0)
6557bed822SMarkus Pfeiffer goto emissing;
6657bed822SMarkus Pfeiffer
6757bed822SMarkus Pfeiffer error = sysctlbyname("hw.usb.ctrl_ss_fail", NULL, NULL,
6857bed822SMarkus Pfeiffer &ss_fail, sizeof(ss_fail));
6957bed822SMarkus Pfeiffer if (error != 0)
7057bed822SMarkus Pfeiffer goto emissing;
7157bed822SMarkus Pfeiffer return;
7257bed822SMarkus Pfeiffer
7357bed822SMarkus Pfeiffer emissing:
7457bed822SMarkus Pfeiffer printf("Cannot set USB sysctl, missing USB_REQ_DEBUG option?\n");
7557bed822SMarkus Pfeiffer }
7657bed822SMarkus Pfeiffer
7757bed822SMarkus Pfeiffer void
usb_control_ep_error_test(uint16_t vid,uint16_t pid)7857bed822SMarkus Pfeiffer usb_control_ep_error_test(uint16_t vid, uint16_t pid)
7957bed822SMarkus Pfeiffer {
8057bed822SMarkus Pfeiffer struct LIBUSB20_CONTROL_SETUP_DECODED req;
8157bed822SMarkus Pfeiffer struct libusb20_device *pdev;
8257bed822SMarkus Pfeiffer uint8_t buffer[256];
8357bed822SMarkus Pfeiffer int error;
8457bed822SMarkus Pfeiffer int fail = 0;
8557bed822SMarkus Pfeiffer int bus;
8657bed822SMarkus Pfeiffer int dev;
8757bed822SMarkus Pfeiffer int cfg;
8857bed822SMarkus Pfeiffer
8957bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
9057bed822SMarkus Pfeiffer if (pdev == NULL) {
9157bed822SMarkus Pfeiffer printf("USB device not found\n");
9257bed822SMarkus Pfeiffer return;
9357bed822SMarkus Pfeiffer }
9457bed822SMarkus Pfeiffer error = libusb20_dev_open(pdev, 0);
9557bed822SMarkus Pfeiffer if (error) {
9657bed822SMarkus Pfeiffer printf("Could not open USB device\n");
9757bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
9857bed822SMarkus Pfeiffer return;
9957bed822SMarkus Pfeiffer }
10057bed822SMarkus Pfeiffer
10157bed822SMarkus Pfeiffer bus = libusb20_dev_get_bus_number(pdev);
10257bed822SMarkus Pfeiffer dev = libusb20_dev_get_address(pdev);
10357bed822SMarkus Pfeiffer
10457bed822SMarkus Pfeiffer for (cfg = 0; cfg != 255; cfg++) {
10557bed822SMarkus Pfeiffer
10657bed822SMarkus Pfeiffer LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
10757bed822SMarkus Pfeiffer req.bmRequestType = 0x80; /* read */
10857bed822SMarkus Pfeiffer req.bRequest = 0x06; /* descriptor */
10957bed822SMarkus Pfeiffer req.wValue = 0x0200 | cfg; /* config descriptor */
11057bed822SMarkus Pfeiffer req.wIndex = 0;
11157bed822SMarkus Pfeiffer req.wLength = 255;
11257bed822SMarkus Pfeiffer
11357bed822SMarkus Pfeiffer printf("Test #%d.1/3 ...\n", cfg);
11457bed822SMarkus Pfeiffer
11557bed822SMarkus Pfeiffer set_ctrl_ep_fail(-1,-1,0,0);
11657bed822SMarkus Pfeiffer
11757bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev, &req, buffer,
11857bed822SMarkus Pfeiffer NULL, 1000, 0);
11957bed822SMarkus Pfeiffer if (error != 0) {
12057bed822SMarkus Pfeiffer printf("Last configuration index is: %d\n", cfg - 1);
12157bed822SMarkus Pfeiffer break;
12257bed822SMarkus Pfeiffer }
12357bed822SMarkus Pfeiffer
12457bed822SMarkus Pfeiffer printf("Test #%d.2/3 ...\n", cfg);
12557bed822SMarkus Pfeiffer
12657bed822SMarkus Pfeiffer set_ctrl_ep_fail(bus,dev,1,1);
12757bed822SMarkus Pfeiffer
12857bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev, &req, buffer,
12957bed822SMarkus Pfeiffer NULL, 1000, 0);
13057bed822SMarkus Pfeiffer
13157bed822SMarkus Pfeiffer set_ctrl_ep_fail(-1,-1,0,0);
13257bed822SMarkus Pfeiffer
13357bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev, &req, buffer,
13457bed822SMarkus Pfeiffer NULL, 1000, 0);
13557bed822SMarkus Pfeiffer if (error != 0) {
13657bed822SMarkus Pfeiffer printf("Cannot fetch descriptor (unexpected)\n");
13757bed822SMarkus Pfeiffer fail++;
13857bed822SMarkus Pfeiffer }
13957bed822SMarkus Pfeiffer
14057bed822SMarkus Pfeiffer printf("Test #%d.3/3 ...\n", cfg);
14157bed822SMarkus Pfeiffer
14257bed822SMarkus Pfeiffer set_ctrl_ep_fail(bus,dev,0,1);
14357bed822SMarkus Pfeiffer
14457bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev, &req, buffer,
14557bed822SMarkus Pfeiffer NULL, 1000, 0);
14657bed822SMarkus Pfeiffer
14757bed822SMarkus Pfeiffer set_ctrl_ep_fail(-1,-1,0,0);
14857bed822SMarkus Pfeiffer
14957bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev, &req, buffer,
15057bed822SMarkus Pfeiffer NULL, 1000, 0);
15157bed822SMarkus Pfeiffer if (error != 0) {
15257bed822SMarkus Pfeiffer printf("Cannot fetch descriptor (unexpected)\n");
15357bed822SMarkus Pfeiffer fail++;
15457bed822SMarkus Pfeiffer }
15557bed822SMarkus Pfeiffer }
15657bed822SMarkus Pfeiffer
15757bed822SMarkus Pfeiffer libusb20_dev_close(pdev);
15857bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
15957bed822SMarkus Pfeiffer
16057bed822SMarkus Pfeiffer printf("Test completed detecting %d failures\nDone\n\n", fail);
16157bed822SMarkus Pfeiffer }
16257bed822SMarkus Pfeiffer
16357bed822SMarkus Pfeiffer void
usb_get_string_desc_test(uint16_t vid,uint16_t pid)16457bed822SMarkus Pfeiffer usb_get_string_desc_test(uint16_t vid, uint16_t pid)
16557bed822SMarkus Pfeiffer {
16657bed822SMarkus Pfeiffer struct libusb20_device *pdev;
16757bed822SMarkus Pfeiffer uint32_t x;
16857bed822SMarkus Pfeiffer uint32_t y;
16957bed822SMarkus Pfeiffer uint32_t valid;
17057bed822SMarkus Pfeiffer uint8_t *buf;
17157bed822SMarkus Pfeiffer int error;
17257bed822SMarkus Pfeiffer
17357bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
17457bed822SMarkus Pfeiffer if (pdev == NULL) {
17557bed822SMarkus Pfeiffer printf("USB device not found\n");
17657bed822SMarkus Pfeiffer return;
17757bed822SMarkus Pfeiffer }
17857bed822SMarkus Pfeiffer error = libusb20_dev_open(pdev, 0);
17957bed822SMarkus Pfeiffer if (error) {
18057bed822SMarkus Pfeiffer printf("Could not open USB device\n");
18157bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
18257bed822SMarkus Pfeiffer return;
18357bed822SMarkus Pfeiffer }
18457bed822SMarkus Pfeiffer buf = malloc(256);
18557bed822SMarkus Pfeiffer if (buf == NULL) {
18657bed822SMarkus Pfeiffer printf("Cannot allocate memory\n");
18757bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
18857bed822SMarkus Pfeiffer return;
18957bed822SMarkus Pfeiffer }
19057bed822SMarkus Pfeiffer valid = 0;
19157bed822SMarkus Pfeiffer
19257bed822SMarkus Pfeiffer printf("Starting string descriptor test for "
19357bed822SMarkus Pfeiffer "VID=0x%04x PID=0x%04x\n", vid, pid);
19457bed822SMarkus Pfeiffer
19557bed822SMarkus Pfeiffer for (x = 0; x != 256; x++) {
19657bed822SMarkus Pfeiffer
19757bed822SMarkus Pfeiffer if (libusb20_dev_check_connected(pdev) != 0) {
19857bed822SMarkus Pfeiffer printf("Device disconnected\n");
19957bed822SMarkus Pfeiffer break;
20057bed822SMarkus Pfeiffer }
20157bed822SMarkus Pfeiffer printf("%d .. ", (int)x);
20257bed822SMarkus Pfeiffer
20357bed822SMarkus Pfeiffer fflush(stdout);
20457bed822SMarkus Pfeiffer
20557bed822SMarkus Pfeiffer error = libusb20_dev_req_string_simple_sync(pdev, x, buf, 255);
20657bed822SMarkus Pfeiffer
20757bed822SMarkus Pfeiffer if (error == 0) {
20857bed822SMarkus Pfeiffer printf("\nINDEX=%d, STRING='%s' (Default language)\n", (int)x, buf);
20957bed822SMarkus Pfeiffer fflush(stdout);
21057bed822SMarkus Pfeiffer } else {
21157bed822SMarkus Pfeiffer continue;
21257bed822SMarkus Pfeiffer }
21357bed822SMarkus Pfeiffer
21457bed822SMarkus Pfeiffer valid = 0;
21557bed822SMarkus Pfeiffer
21657bed822SMarkus Pfeiffer for (y = 0; y != 65536; y++) {
21757bed822SMarkus Pfeiffer
21857bed822SMarkus Pfeiffer if (libusb20_dev_check_connected(pdev) != 0) {
21957bed822SMarkus Pfeiffer printf("Device disconnected\n");
22057bed822SMarkus Pfeiffer break;
22157bed822SMarkus Pfeiffer }
22257bed822SMarkus Pfeiffer error = libusb20_dev_req_string_sync(pdev, x, y, buf, 256);
22357bed822SMarkus Pfeiffer if (error == 0)
22457bed822SMarkus Pfeiffer valid++;
22557bed822SMarkus Pfeiffer }
22657bed822SMarkus Pfeiffer
22757bed822SMarkus Pfeiffer printf("String at INDEX=%d responds to %d "
22857bed822SMarkus Pfeiffer "languages\n", (int)x, (int)valid);
22957bed822SMarkus Pfeiffer }
23057bed822SMarkus Pfeiffer
23157bed822SMarkus Pfeiffer printf("\nDone\n");
23257bed822SMarkus Pfeiffer
23357bed822SMarkus Pfeiffer free(buf);
23457bed822SMarkus Pfeiffer
23557bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
23657bed822SMarkus Pfeiffer }
23757bed822SMarkus Pfeiffer
23857bed822SMarkus Pfeiffer void
usb_port_reset_test(uint16_t vid,uint16_t pid,uint32_t duration)23957bed822SMarkus Pfeiffer usb_port_reset_test(uint16_t vid, uint16_t pid, uint32_t duration)
24057bed822SMarkus Pfeiffer {
24157bed822SMarkus Pfeiffer struct timeval sub_tv;
24257bed822SMarkus Pfeiffer struct timeval ref_tv;
24357bed822SMarkus Pfeiffer struct timeval res_tv;
24457bed822SMarkus Pfeiffer
24557bed822SMarkus Pfeiffer struct libusb20_device *pdev;
24657bed822SMarkus Pfeiffer
24757bed822SMarkus Pfeiffer int error;
24857bed822SMarkus Pfeiffer int iter;
24957bed822SMarkus Pfeiffer int errcnt;
25057bed822SMarkus Pfeiffer
25157bed822SMarkus Pfeiffer time_t last_sec;
25257bed822SMarkus Pfeiffer
25357bed822SMarkus Pfeiffer /* sysctl() - no set config */
25457bed822SMarkus Pfeiffer
25557bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
25657bed822SMarkus Pfeiffer if (pdev == NULL) {
25757bed822SMarkus Pfeiffer printf("USB device not found\n");
25857bed822SMarkus Pfeiffer return;
25957bed822SMarkus Pfeiffer }
26057bed822SMarkus Pfeiffer error = libusb20_dev_open(pdev, 0);
26157bed822SMarkus Pfeiffer if (error) {
26257bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
26357bed822SMarkus Pfeiffer printf("Could not open USB device\n");
26457bed822SMarkus Pfeiffer return;
26557bed822SMarkus Pfeiffer }
26657bed822SMarkus Pfeiffer iter = 0;
26757bed822SMarkus Pfeiffer
26857bed822SMarkus Pfeiffer errcnt = 0;
26957bed822SMarkus Pfeiffer
27057bed822SMarkus Pfeiffer gettimeofday(&ref_tv, 0);
27157bed822SMarkus Pfeiffer
27257bed822SMarkus Pfeiffer last_sec = ref_tv.tv_sec;
27357bed822SMarkus Pfeiffer
27457bed822SMarkus Pfeiffer while (1) {
27557bed822SMarkus Pfeiffer
27657bed822SMarkus Pfeiffer gettimeofday(&sub_tv, 0);
27757bed822SMarkus Pfeiffer
27857bed822SMarkus Pfeiffer if (last_sec != sub_tv.tv_sec) {
27957bed822SMarkus Pfeiffer
28057bed822SMarkus Pfeiffer printf("STATUS: ID=%u, ERR=%u\n",
28157bed822SMarkus Pfeiffer (int)iter, (int)errcnt);
28257bed822SMarkus Pfeiffer
28357bed822SMarkus Pfeiffer fflush(stdout);
28457bed822SMarkus Pfeiffer
28557bed822SMarkus Pfeiffer last_sec = sub_tv.tv_sec;
28657bed822SMarkus Pfeiffer }
28757bed822SMarkus Pfeiffer timersub(&sub_tv, &ref_tv, &res_tv);
28857bed822SMarkus Pfeiffer
289*129a2703SSascha Wildner if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration))
29057bed822SMarkus Pfeiffer break;
29157bed822SMarkus Pfeiffer
29257bed822SMarkus Pfeiffer if (libusb20_dev_reset(pdev)) {
29357bed822SMarkus Pfeiffer errcnt++;
29457bed822SMarkus Pfeiffer usleep(50000);
29557bed822SMarkus Pfeiffer }
29657bed822SMarkus Pfeiffer if (libusb20_dev_check_connected(pdev) != 0) {
29757bed822SMarkus Pfeiffer printf("Device disconnected\n");
29857bed822SMarkus Pfeiffer break;
29957bed822SMarkus Pfeiffer }
30057bed822SMarkus Pfeiffer iter++;
30157bed822SMarkus Pfeiffer }
30257bed822SMarkus Pfeiffer
30357bed822SMarkus Pfeiffer libusb20_dev_reset(pdev);
30457bed822SMarkus Pfeiffer
30557bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
30657bed822SMarkus Pfeiffer }
30757bed822SMarkus Pfeiffer
30857bed822SMarkus Pfeiffer void
usb_set_config_test(uint16_t vid,uint16_t pid,uint32_t duration)30957bed822SMarkus Pfeiffer usb_set_config_test(uint16_t vid, uint16_t pid, uint32_t duration)
31057bed822SMarkus Pfeiffer {
31157bed822SMarkus Pfeiffer struct libusb20_device *pdev;
31257bed822SMarkus Pfeiffer struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
31357bed822SMarkus Pfeiffer int x;
31457bed822SMarkus Pfeiffer int error;
31557bed822SMarkus Pfeiffer int failed;
31657bed822SMarkus Pfeiffer int exp;
31757bed822SMarkus Pfeiffer
31857bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
31957bed822SMarkus Pfeiffer if (pdev == NULL) {
32057bed822SMarkus Pfeiffer printf("USB device not found\n");
32157bed822SMarkus Pfeiffer return;
32257bed822SMarkus Pfeiffer }
32357bed822SMarkus Pfeiffer error = libusb20_dev_open(pdev, 0);
32457bed822SMarkus Pfeiffer if (error) {
32557bed822SMarkus Pfeiffer printf("Could not open USB device\n");
32657bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
32757bed822SMarkus Pfeiffer return;
32857bed822SMarkus Pfeiffer }
32957bed822SMarkus Pfeiffer failed = 0;
33057bed822SMarkus Pfeiffer
33157bed822SMarkus Pfeiffer printf("Starting set config test for "
33257bed822SMarkus Pfeiffer "VID=0x%04x PID=0x%04x\n", vid, pid);
33357bed822SMarkus Pfeiffer
33457bed822SMarkus Pfeiffer for (x = 255; x > -1; x--) {
33557bed822SMarkus Pfeiffer
33657bed822SMarkus Pfeiffer error = libusb20_dev_set_config_index(pdev, x);
33757bed822SMarkus Pfeiffer if (error == 0) {
33857bed822SMarkus Pfeiffer if (x == 255) {
33957bed822SMarkus Pfeiffer printf("Unconfiguring USB device "
34057bed822SMarkus Pfeiffer "was successful\n");
34157bed822SMarkus Pfeiffer } else {
34257bed822SMarkus Pfeiffer printf("Setting configuration %d "
34357bed822SMarkus Pfeiffer "was successful\n", x);
34457bed822SMarkus Pfeiffer }
34557bed822SMarkus Pfeiffer } else {
34657bed822SMarkus Pfeiffer failed++;
34757bed822SMarkus Pfeiffer }
34857bed822SMarkus Pfeiffer }
34957bed822SMarkus Pfeiffer
35057bed822SMarkus Pfeiffer ddesc = libusb20_dev_get_device_desc(pdev);
35157bed822SMarkus Pfeiffer if (ddesc != NULL)
35257bed822SMarkus Pfeiffer exp = ddesc->bNumConfigurations + 1;
35357bed822SMarkus Pfeiffer else
35457bed822SMarkus Pfeiffer exp = 1;
35557bed822SMarkus Pfeiffer
35657bed822SMarkus Pfeiffer printf("\n\n"
35757bed822SMarkus Pfeiffer "Set configuration summary\n"
35857bed822SMarkus Pfeiffer "Valid count: %d/%d %s\n"
35957bed822SMarkus Pfeiffer "Failed count: %d\n",
36057bed822SMarkus Pfeiffer 256 - failed, exp,
36157bed822SMarkus Pfeiffer (exp == (256 - failed)) ? "(expected)" : "(unexpected)",
36257bed822SMarkus Pfeiffer failed);
36357bed822SMarkus Pfeiffer
36457bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
36557bed822SMarkus Pfeiffer }
36657bed822SMarkus Pfeiffer
36757bed822SMarkus Pfeiffer void
usb_get_descriptor_test(uint16_t vid,uint16_t pid,uint32_t duration)36857bed822SMarkus Pfeiffer usb_get_descriptor_test(uint16_t vid, uint16_t pid, uint32_t duration)
36957bed822SMarkus Pfeiffer {
37057bed822SMarkus Pfeiffer struct libusb20_device *pdev;
37157bed822SMarkus Pfeiffer
37257bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
37357bed822SMarkus Pfeiffer if (pdev == NULL) {
37457bed822SMarkus Pfeiffer printf("USB device not found\n");
37557bed822SMarkus Pfeiffer return;
37657bed822SMarkus Pfeiffer }
37757bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
37857bed822SMarkus Pfeiffer }
37957bed822SMarkus Pfeiffer
38057bed822SMarkus Pfeiffer void
usb_suspend_resume_test(uint16_t vid,uint16_t pid,uint32_t duration)38157bed822SMarkus Pfeiffer usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration)
38257bed822SMarkus Pfeiffer {
38357bed822SMarkus Pfeiffer struct timeval sub_tv;
38457bed822SMarkus Pfeiffer struct timeval ref_tv;
38557bed822SMarkus Pfeiffer struct timeval res_tv;
38657bed822SMarkus Pfeiffer
38757bed822SMarkus Pfeiffer struct libusb20_device *pdev;
38857bed822SMarkus Pfeiffer
38957bed822SMarkus Pfeiffer time_t last_sec;
39057bed822SMarkus Pfeiffer
39157bed822SMarkus Pfeiffer int iter;
39257bed822SMarkus Pfeiffer int error;
39357bed822SMarkus Pfeiffer int ptimo;
39457bed822SMarkus Pfeiffer int errcnt;
39557bed822SMarkus Pfeiffer int power_old;
39657bed822SMarkus Pfeiffer
39757bed822SMarkus Pfeiffer ptimo = 1; /* second(s) */
39857bed822SMarkus Pfeiffer
39957bed822SMarkus Pfeiffer error = sysctlbyname("hw.usb.power_timeout", NULL, NULL,
40057bed822SMarkus Pfeiffer &ptimo, sizeof(ptimo));
40157bed822SMarkus Pfeiffer
40257bed822SMarkus Pfeiffer if (error != 0) {
40357bed822SMarkus Pfeiffer printf("WARNING: Could not set power "
40457bed822SMarkus Pfeiffer "timeout to 1 (error=%d) \n", errno);
40557bed822SMarkus Pfeiffer }
40657bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
40757bed822SMarkus Pfeiffer if (pdev == NULL) {
40857bed822SMarkus Pfeiffer printf("USB device not found\n");
40957bed822SMarkus Pfeiffer return;
41057bed822SMarkus Pfeiffer }
41157bed822SMarkus Pfeiffer error = libusb20_dev_open(pdev, 0);
41257bed822SMarkus Pfeiffer if (error) {
41357bed822SMarkus Pfeiffer printf("Could not open USB device\n");
41457bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
41557bed822SMarkus Pfeiffer return;
41657bed822SMarkus Pfeiffer }
41757bed822SMarkus Pfeiffer power_old = libusb20_dev_get_power_mode(pdev);
41857bed822SMarkus Pfeiffer
41957bed822SMarkus Pfeiffer printf("Starting suspend and resume "
42057bed822SMarkus Pfeiffer "test for VID=0x%04x PID=0x%04x\n", vid, pid);
42157bed822SMarkus Pfeiffer
42257bed822SMarkus Pfeiffer iter = 0;
42357bed822SMarkus Pfeiffer errcnt = 0;
42457bed822SMarkus Pfeiffer
42557bed822SMarkus Pfeiffer gettimeofday(&ref_tv, 0);
42657bed822SMarkus Pfeiffer
42757bed822SMarkus Pfeiffer last_sec = ref_tv.tv_sec;
42857bed822SMarkus Pfeiffer
42957bed822SMarkus Pfeiffer while (1) {
43057bed822SMarkus Pfeiffer
43157bed822SMarkus Pfeiffer if (libusb20_dev_check_connected(pdev) != 0) {
43257bed822SMarkus Pfeiffer printf("Device disconnected\n");
43357bed822SMarkus Pfeiffer break;
43457bed822SMarkus Pfeiffer }
43557bed822SMarkus Pfeiffer gettimeofday(&sub_tv, 0);
43657bed822SMarkus Pfeiffer
43757bed822SMarkus Pfeiffer if (last_sec != sub_tv.tv_sec) {
43857bed822SMarkus Pfeiffer
43957bed822SMarkus Pfeiffer printf("STATUS: ID=%u, ERR=%u\n",
44057bed822SMarkus Pfeiffer (int)iter, (int)errcnt);
44157bed822SMarkus Pfeiffer
44257bed822SMarkus Pfeiffer fflush(stdout);
44357bed822SMarkus Pfeiffer
44457bed822SMarkus Pfeiffer last_sec = sub_tv.tv_sec;
44557bed822SMarkus Pfeiffer }
44657bed822SMarkus Pfeiffer timersub(&sub_tv, &ref_tv, &res_tv);
44757bed822SMarkus Pfeiffer
448*129a2703SSascha Wildner if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration))
44957bed822SMarkus Pfeiffer break;
45057bed822SMarkus Pfeiffer
45157bed822SMarkus Pfeiffer error = libusb20_dev_set_power_mode(pdev, (iter & 1) ?
45257bed822SMarkus Pfeiffer LIBUSB20_POWER_ON : LIBUSB20_POWER_SAVE);
45357bed822SMarkus Pfeiffer
45457bed822SMarkus Pfeiffer if (error)
45557bed822SMarkus Pfeiffer errcnt++;
45657bed822SMarkus Pfeiffer
45757bed822SMarkus Pfeiffer /* wait before switching power mode */
45857bed822SMarkus Pfeiffer usleep(4100000 +
45957bed822SMarkus Pfeiffer (((uint32_t)usb_ts_rand_noise()) % 2000000U));
46057bed822SMarkus Pfeiffer
46157bed822SMarkus Pfeiffer iter++;
46257bed822SMarkus Pfeiffer }
46357bed822SMarkus Pfeiffer
46457bed822SMarkus Pfeiffer /* restore default power mode */
46557bed822SMarkus Pfeiffer libusb20_dev_set_power_mode(pdev, power_old);
46657bed822SMarkus Pfeiffer
46757bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
46857bed822SMarkus Pfeiffer }
46957bed822SMarkus Pfeiffer
47057bed822SMarkus Pfeiffer void
usb_set_and_clear_stall_test(uint16_t vid,uint16_t pid)47157bed822SMarkus Pfeiffer usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid)
47257bed822SMarkus Pfeiffer {
47357bed822SMarkus Pfeiffer struct libusb20_device *pdev;
47457bed822SMarkus Pfeiffer struct libusb20_transfer *pxfer;
47557bed822SMarkus Pfeiffer
47657bed822SMarkus Pfeiffer int iter;
47757bed822SMarkus Pfeiffer int error;
47857bed822SMarkus Pfeiffer int errcnt;
47957bed822SMarkus Pfeiffer int ep;
48057bed822SMarkus Pfeiffer
48157bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
48257bed822SMarkus Pfeiffer if (pdev == NULL) {
48357bed822SMarkus Pfeiffer printf("USB device not found\n");
48457bed822SMarkus Pfeiffer return;
48557bed822SMarkus Pfeiffer }
48657bed822SMarkus Pfeiffer error = libusb20_dev_open(pdev, 1);
48757bed822SMarkus Pfeiffer if (error) {
48857bed822SMarkus Pfeiffer printf("Could not open USB device\n");
48957bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
49057bed822SMarkus Pfeiffer return;
49157bed822SMarkus Pfeiffer }
49257bed822SMarkus Pfeiffer printf("Starting set and clear stall test "
49357bed822SMarkus Pfeiffer "for VID=0x%04x PID=0x%04x\n", vid, pid);
49457bed822SMarkus Pfeiffer
49557bed822SMarkus Pfeiffer iter = 0;
49657bed822SMarkus Pfeiffer errcnt = 0;
49757bed822SMarkus Pfeiffer
49857bed822SMarkus Pfeiffer for (ep = 2; ep != 32; ep++) {
49957bed822SMarkus Pfeiffer
50057bed822SMarkus Pfeiffer struct LIBUSB20_CONTROL_SETUP_DECODED setup_set_stall;
50157bed822SMarkus Pfeiffer struct LIBUSB20_CONTROL_SETUP_DECODED setup_get_status;
50257bed822SMarkus Pfeiffer
50357bed822SMarkus Pfeiffer uint8_t epno = ((ep / 2) | ((ep & 1) << 7));
50457bed822SMarkus Pfeiffer uint8_t buf[1];
50557bed822SMarkus Pfeiffer
50657bed822SMarkus Pfeiffer LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_set_stall);
50757bed822SMarkus Pfeiffer setup_set_stall.bmRequestType = 0x02; /* write endpoint */
50857bed822SMarkus Pfeiffer setup_set_stall.bRequest = 0x03; /* set feature */
50957bed822SMarkus Pfeiffer setup_set_stall.wValue = 0x00; /* UF_ENDPOINT_HALT */
51057bed822SMarkus Pfeiffer setup_set_stall.wIndex = epno;
51157bed822SMarkus Pfeiffer setup_set_stall.wLength = 0;
51257bed822SMarkus Pfeiffer
51357bed822SMarkus Pfeiffer LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_get_status);
51457bed822SMarkus Pfeiffer setup_get_status.bmRequestType = 0x82; /* read endpoint */
51557bed822SMarkus Pfeiffer setup_get_status.bRequest = 0x00; /* get status */
51657bed822SMarkus Pfeiffer setup_get_status.wValue = 0x00;
51757bed822SMarkus Pfeiffer setup_get_status.wIndex = epno;
51857bed822SMarkus Pfeiffer setup_get_status.wLength = 1;
51957bed822SMarkus Pfeiffer
52057bed822SMarkus Pfeiffer if (libusb20_dev_check_connected(pdev) != 0) {
52157bed822SMarkus Pfeiffer printf("Device disconnected\n");
52257bed822SMarkus Pfeiffer break;
52357bed822SMarkus Pfeiffer }
52457bed822SMarkus Pfeiffer pxfer = libusb20_tr_get_pointer(pdev, 0);
52557bed822SMarkus Pfeiffer
52657bed822SMarkus Pfeiffer error = libusb20_tr_open(pxfer, 1, 1, epno);
52757bed822SMarkus Pfeiffer
52857bed822SMarkus Pfeiffer if (error != 0) {
52957bed822SMarkus Pfeiffer printf("Endpoint 0x%02x does not exist "
53057bed822SMarkus Pfeiffer "in current setting. (%s, ignored)\n",
53157bed822SMarkus Pfeiffer epno, libusb20_strerror(error));
53257bed822SMarkus Pfeiffer continue;
53357bed822SMarkus Pfeiffer }
53457bed822SMarkus Pfeiffer printf("Stalling endpoint 0x%02x\n", epno);
53557bed822SMarkus Pfeiffer
53657bed822SMarkus Pfeiffer /* set stall */
53757bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev,
53857bed822SMarkus Pfeiffer &setup_set_stall, NULL, NULL, 250, 0);
53957bed822SMarkus Pfeiffer
54057bed822SMarkus Pfeiffer if (error != 0) {
54157bed822SMarkus Pfeiffer printf("Endpoint 0x%02x does not allow "
54257bed822SMarkus Pfeiffer "setting of stall. (%s)\n",
54357bed822SMarkus Pfeiffer epno, libusb20_strerror(error));
54457bed822SMarkus Pfeiffer errcnt++;
54557bed822SMarkus Pfeiffer }
54657bed822SMarkus Pfeiffer /* get EP status */
54757bed822SMarkus Pfeiffer buf[0] = 0;
54857bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev,
54957bed822SMarkus Pfeiffer &setup_get_status, buf, NULL, 250, 0);
55057bed822SMarkus Pfeiffer
55157bed822SMarkus Pfeiffer if (error != 0) {
55257bed822SMarkus Pfeiffer printf("Endpoint 0x%02x does not allow "
55357bed822SMarkus Pfeiffer "reading status. (%s)\n",
55457bed822SMarkus Pfeiffer epno, libusb20_strerror(error));
55557bed822SMarkus Pfeiffer errcnt++;
55657bed822SMarkus Pfeiffer } else {
55757bed822SMarkus Pfeiffer if (!(buf[0] & 1)) {
55857bed822SMarkus Pfeiffer printf("Endpoint 0x%02x status is "
55957bed822SMarkus Pfeiffer "not set to stalled\n", epno);
56057bed822SMarkus Pfeiffer errcnt++;
56157bed822SMarkus Pfeiffer }
56257bed822SMarkus Pfeiffer }
56357bed822SMarkus Pfeiffer
56457bed822SMarkus Pfeiffer buf[0] = 0;
56557bed822SMarkus Pfeiffer error = libusb20_tr_bulk_intr_sync(pxfer, buf, 1, NULL, 250);
56657bed822SMarkus Pfeiffer if (error != LIBUSB20_TRANSFER_STALL) {
56757bed822SMarkus Pfeiffer printf("Endpoint 0x%02x does not appear to "
56857bed822SMarkus Pfeiffer "have stalled. Missing stall PID!\n", epno);
56957bed822SMarkus Pfeiffer errcnt++;
57057bed822SMarkus Pfeiffer }
57157bed822SMarkus Pfeiffer printf("Unstalling endpoint 0x%02x\n", epno);
57257bed822SMarkus Pfeiffer
57357bed822SMarkus Pfeiffer libusb20_tr_clear_stall_sync(pxfer);
57457bed822SMarkus Pfeiffer
57557bed822SMarkus Pfeiffer /* get EP status */
57657bed822SMarkus Pfeiffer buf[0] = 0;
57757bed822SMarkus Pfeiffer error = libusb20_dev_request_sync(pdev,
57857bed822SMarkus Pfeiffer &setup_get_status, buf, NULL, 250, 0);
57957bed822SMarkus Pfeiffer
58057bed822SMarkus Pfeiffer if (error != 0) {
58157bed822SMarkus Pfeiffer printf("Endpoint 0x%02x does not allow "
58257bed822SMarkus Pfeiffer "reading status. (%s)\n",
58357bed822SMarkus Pfeiffer epno, libusb20_strerror(error));
58457bed822SMarkus Pfeiffer errcnt++;
58557bed822SMarkus Pfeiffer } else {
58657bed822SMarkus Pfeiffer if (buf[0] & 1) {
58757bed822SMarkus Pfeiffer printf("Endpoint 0x%02x status is "
58857bed822SMarkus Pfeiffer "still stalled\n", epno);
58957bed822SMarkus Pfeiffer errcnt++;
59057bed822SMarkus Pfeiffer }
59157bed822SMarkus Pfeiffer }
59257bed822SMarkus Pfeiffer
59357bed822SMarkus Pfeiffer libusb20_tr_close(pxfer);
59457bed822SMarkus Pfeiffer iter++;
59557bed822SMarkus Pfeiffer }
59657bed822SMarkus Pfeiffer
59757bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
59857bed822SMarkus Pfeiffer
59957bed822SMarkus Pfeiffer printf("\n"
60057bed822SMarkus Pfeiffer "Test summary\n"
60157bed822SMarkus Pfeiffer "============\n"
60257bed822SMarkus Pfeiffer "Endpoints tested: %d\n"
60357bed822SMarkus Pfeiffer "Errors: %d\n", iter, errcnt);
60457bed822SMarkus Pfeiffer }
60557bed822SMarkus Pfeiffer
60657bed822SMarkus Pfeiffer void
usb_set_alt_interface_test(uint16_t vid,uint16_t pid)60757bed822SMarkus Pfeiffer usb_set_alt_interface_test(uint16_t vid, uint16_t pid)
60857bed822SMarkus Pfeiffer {
60957bed822SMarkus Pfeiffer struct libusb20_device *pdev;
61057bed822SMarkus Pfeiffer struct libusb20_config *config;
61157bed822SMarkus Pfeiffer
61257bed822SMarkus Pfeiffer int iter;
61357bed822SMarkus Pfeiffer int error;
61457bed822SMarkus Pfeiffer int errcnt;
61557bed822SMarkus Pfeiffer int n;
61657bed822SMarkus Pfeiffer int m;
61757bed822SMarkus Pfeiffer
61857bed822SMarkus Pfeiffer pdev = find_usb_device(vid, pid);
61957bed822SMarkus Pfeiffer if (pdev == NULL) {
62057bed822SMarkus Pfeiffer printf("USB device not found\n");
62157bed822SMarkus Pfeiffer return;
62257bed822SMarkus Pfeiffer }
62357bed822SMarkus Pfeiffer printf("Starting set alternate setting test "
62457bed822SMarkus Pfeiffer "for VID=0x%04x PID=0x%04x\n", vid, pid);
62557bed822SMarkus Pfeiffer
62657bed822SMarkus Pfeiffer config = libusb20_dev_alloc_config(pdev,
62757bed822SMarkus Pfeiffer libusb20_dev_get_config_index(pdev));
62857bed822SMarkus Pfeiffer if (config == NULL) {
62957bed822SMarkus Pfeiffer printf("Could not get configuration descriptor\n");
63057bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
63157bed822SMarkus Pfeiffer return;
63257bed822SMarkus Pfeiffer }
63357bed822SMarkus Pfeiffer iter = 0;
63457bed822SMarkus Pfeiffer errcnt = 0;
63557bed822SMarkus Pfeiffer
63657bed822SMarkus Pfeiffer for (n = 0; n != config->num_interface; n++) {
63757bed822SMarkus Pfeiffer /* detach kernel driver */
63857bed822SMarkus Pfeiffer libusb20_dev_detach_kernel_driver(pdev, n);
63957bed822SMarkus Pfeiffer
64057bed822SMarkus Pfeiffer error = libusb20_dev_open(pdev, 0);
64157bed822SMarkus Pfeiffer if (error)
64257bed822SMarkus Pfeiffer printf("ERROR could not open device\n");
64357bed822SMarkus Pfeiffer
64457bed822SMarkus Pfeiffer /* Try the alternate settings */
64557bed822SMarkus Pfeiffer for (m = 0; m != config->interface[n].num_altsetting; m++) {
64657bed822SMarkus Pfeiffer
64757bed822SMarkus Pfeiffer iter++;
64857bed822SMarkus Pfeiffer
64957bed822SMarkus Pfeiffer if (libusb20_dev_set_alt_index(pdev, n, m + 1)) {
65057bed822SMarkus Pfeiffer printf("ERROR on interface %d alt %d\n", n, m + 1);
65157bed822SMarkus Pfeiffer errcnt++;
65257bed822SMarkus Pfeiffer }
65357bed822SMarkus Pfeiffer }
65457bed822SMarkus Pfeiffer
65557bed822SMarkus Pfeiffer /* Restore to default */
65657bed822SMarkus Pfeiffer
65757bed822SMarkus Pfeiffer iter++;
65857bed822SMarkus Pfeiffer
65957bed822SMarkus Pfeiffer if (libusb20_dev_set_alt_index(pdev, n, 0)) {
66057bed822SMarkus Pfeiffer printf("ERROR on interface %d alt %d\n", n, 0);
66157bed822SMarkus Pfeiffer errcnt++;
66257bed822SMarkus Pfeiffer }
66357bed822SMarkus Pfeiffer libusb20_dev_close(pdev);
66457bed822SMarkus Pfeiffer }
66557bed822SMarkus Pfeiffer
66657bed822SMarkus Pfeiffer libusb20_dev_free(pdev);
66757bed822SMarkus Pfeiffer
66857bed822SMarkus Pfeiffer printf("\n"
66957bed822SMarkus Pfeiffer "Test summary\n"
67057bed822SMarkus Pfeiffer "============\n"
67157bed822SMarkus Pfeiffer "Interfaces tested: %d\n"
67257bed822SMarkus Pfeiffer "Errors: %d\n", iter, errcnt);
67357bed822SMarkus Pfeiffer }
674