void usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid) { struct libusb20_device *pdev; struct libusb20_transfer *pxfer; int iter; int error; int errcnt; int ep; pdev = find_usb_device(vid, pid); if (pdev == NULL) { printf("USB device not found\n"); return; } error = libusb20_dev_open(pdev, 1); if (error) { printf("Could not open USB device\n"); libusb20_dev_free(pdev); return; } printf("Starting set and clear stall test " "for VID=0x%04x PID=0x%04x\n", vid, pid); iter = 0; errcnt = 0; for (ep = 2; ep != 32; ep++) { struct LIBUSB20_CONTROL_SETUP_DECODED setup_set_stall; struct LIBUSB20_CONTROL_SETUP_DECODED setup_get_status; uint8_t epno = ((ep / 2) | ((ep & 1) << 7)); uint8_t buf[1]; LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_set_stall); setup_set_stall.bmRequestType = 0x02; /* write endpoint */ setup_set_stall.bRequest = 0x03; /* set feature */ setup_set_stall.wValue = 0x00; /* UF_ENDPOINT_HALT */ setup_set_stall.wIndex = epno; setup_set_stall.wLength = 0; LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_get_status); setup_get_status.bmRequestType = 0x82; /* read endpoint */ setup_get_status.bRequest = 0x00; /* get status */ setup_get_status.wValue = 0x00; setup_get_status.wIndex = epno; setup_get_status.wLength = 1; if (libusb20_dev_check_connected(pdev) != 0) { printf("Device disconnected\n"); break; } pxfer = libusb20_tr_get_pointer(pdev, 0); error = libusb20_tr_open(pxfer, 1, 1, epno); if (error != 0) { printf("Endpoint 0x%02x does not exist " "in current setting. (%s, ignored)\n", epno, libusb20_strerror(error)); continue; } printf("Stalling endpoint 0x%02x\n", epno); /* set stall */ error = libusb20_dev_request_sync(pdev, &setup_set_stall, NULL, NULL, 250, 0); if (error != 0) { printf("Endpoint 0x%02x does not allow " "setting of stall. (%s)\n", epno, libusb20_strerror(error)); errcnt++; } /* get EP status */ buf[0] = 0; error = libusb20_dev_request_sync(pdev, &setup_get_status, buf, NULL, 250, 0); if (error != 0) { printf("Endpoint 0x%02x does not allow " "reading status. (%s)\n", epno, libusb20_strerror(error)); errcnt++; } else { if (!(buf[0] & 1)) { printf("Endpoint 0x%02x status is " "not set to stalled\n", epno); errcnt++; } } buf[0] = 0; error = libusb20_tr_bulk_intr_sync(pxfer, buf, 1, NULL, 250); if (error != LIBUSB20_TRANSFER_STALL) { printf("Endpoint 0x%02x does not appear to " "have stalled. Missing stall PID!\n", epno); errcnt++; } printf("Unstalling endpoint 0x%02x\n", epno); libusb20_tr_clear_stall_sync(pxfer); /* get EP status */ buf[0] = 0; error = libusb20_dev_request_sync(pdev, &setup_get_status, buf, NULL, 250, 0); if (error != 0) { printf("Endpoint 0x%02x does not allow " "reading status. (%s)\n", epno, libusb20_strerror(error)); errcnt++; } else { if (buf[0] & 1) { printf("Endpoint 0x%02x status is " "still stalled\n", epno); errcnt++; } } libusb20_tr_close(pxfer); iter++; } libusb20_dev_free(pdev); printf("\n" "Test summary\n" "============\n" "Endpoints tested: %d\n" "Errors: %d\n", iter, errcnt); }
void usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration) { struct timeval sub_tv; struct timeval ref_tv; struct timeval res_tv; struct libusb20_device *pdev; time_t last_sec; int iter; int error; int ptimo; int errcnt; int power_old; ptimo = 1; /* second(s) */ error = sysctlbyname("hw.usb.power_timeout", NULL, NULL, &ptimo, sizeof(ptimo)); if (error != 0) { printf("WARNING: Could not set power " "timeout to 1 (error=%d) \n", errno); } pdev = find_usb_device(vid, pid); if (pdev == NULL) { printf("USB device not found\n"); return; } error = libusb20_dev_open(pdev, 0); if (error) { printf("Could not open USB device\n"); libusb20_dev_free(pdev); return; } power_old = libusb20_dev_get_power_mode(pdev); printf("Starting suspend and resume " "test for VID=0x%04x PID=0x%04x\n", vid, pid); iter = 0; errcnt = 0; gettimeofday(&ref_tv, 0); last_sec = ref_tv.tv_sec; while (1) { if (libusb20_dev_check_connected(pdev) != 0) { printf("Device disconnected\n"); break; } gettimeofday(&sub_tv, 0); if (last_sec != sub_tv.tv_sec) { printf("STATUS: ID=%u, ERR=%u\n", (int)iter, (int)errcnt); fflush(stdout); last_sec = sub_tv.tv_sec; } timersub(&sub_tv, &ref_tv, &res_tv); if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) break; error = libusb20_dev_set_power_mode(pdev, (iter & 1) ? LIBUSB20_POWER_ON : LIBUSB20_POWER_SAVE); if (error) errcnt++; /* wait before switching power mode */ usleep(4100000 + (((uint32_t)usb_ts_rand_noise()) % 2000000U)); iter++; } /* restore default power mode */ libusb20_dev_set_power_mode(pdev, power_old); libusb20_dev_free(pdev); }
void usb_port_reset_test(uint16_t vid, uint16_t pid, uint32_t duration) { struct timeval sub_tv; struct timeval ref_tv; struct timeval res_tv; struct libusb20_device *pdev; int error; int iter; int errcnt; time_t last_sec; /* sysctl() - no set config */ pdev = find_usb_device(vid, pid); if (pdev == NULL) { printf("USB device not found\n"); return; } error = libusb20_dev_open(pdev, 0); if (error) { libusb20_dev_free(pdev); printf("Could not open USB device\n"); return; } iter = 0; errcnt = 0; gettimeofday(&ref_tv, 0); last_sec = ref_tv.tv_sec; while (1) { gettimeofday(&sub_tv, 0); if (last_sec != sub_tv.tv_sec) { printf("STATUS: ID=%u, ERR=%u\n", (int)iter, (int)errcnt); fflush(stdout); last_sec = sub_tv.tv_sec; } timersub(&sub_tv, &ref_tv, &res_tv); if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) break; if (libusb20_dev_reset(pdev)) { errcnt++; usleep(50000); } if (libusb20_dev_check_connected(pdev) != 0) { printf("Device disconnected\n"); break; } iter++; } libusb20_dev_reset(pdev); libusb20_dev_free(pdev); }
void usb_get_string_desc_test(uint16_t vid, uint16_t pid) { struct libusb20_device *pdev; uint32_t x; uint32_t y; uint32_t valid; uint8_t *buf; int error; pdev = find_usb_device(vid, pid); if (pdev == NULL) { printf("USB device not found\n"); return; } error = libusb20_dev_open(pdev, 0); if (error) { printf("Could not open USB device\n"); libusb20_dev_free(pdev); return; } buf = malloc(256); if (buf == NULL) { printf("Cannot allocate memory\n"); libusb20_dev_free(pdev); return; } valid = 0; printf("Starting string descriptor test for " "VID=0x%04x PID=0x%04x\n", vid, pid); for (x = 0; x != 256; x++) { if (libusb20_dev_check_connected(pdev) != 0) { printf("Device disconnected\n"); break; } printf("%d .. ", (int)x); fflush(stdout); error = libusb20_dev_req_string_simple_sync(pdev, x, buf, 255); if (error == 0) { printf("\nINDEX=%d, STRING='%s' (Default language)\n", (int)x, buf); fflush(stdout); } else { continue; } valid = 0; for (y = 0; y != 65536; y++) { if (libusb20_dev_check_connected(pdev) != 0) { printf("Device disconnected\n"); break; } error = libusb20_dev_req_string_sync(pdev, x, y, buf, 256); if (error == 0) valid++; } printf("String at INDEX=%d responds to %d " "languages\n", (int)x, (int)valid); } printf("\nDone\n"); free(buf); libusb20_dev_free(pdev); }
static void usb_modem_data_stress_test(struct modem *p, uint32_t duration) { struct timeval sub_tv; struct timeval ref_tv; struct timeval res_tv; time_t last_sec; uint8_t in_pending = 0; uint8_t in_ready = 0; uint8_t out_pending = 0; uint32_t id = 0; uint32_t in_max; uint32_t out_max; uint32_t io_max; uint8_t *in_buffer = 0; uint8_t *out_buffer = 0; gettimeofday(&ref_tv, 0); last_sec = ref_tv.tv_sec; printf("\n"); in_max = libusb20_tr_get_max_total_length(p->xfer_in); out_max = libusb20_tr_get_max_total_length(p->xfer_out); /* get the smallest buffer size and use that */ io_max = (in_max < out_max) ? in_max : out_max; if (in_max != out_max) printf("WARNING: Buffer sizes are un-equal: %u vs %u\n", in_max, out_max); in_buffer = malloc(io_max); if (in_buffer == NULL) goto fail; out_buffer = malloc(io_max); if (out_buffer == NULL) goto fail; while (1) { gettimeofday(&sub_tv, 0); if (last_sec != sub_tv.tv_sec) { printf("STATUS: ID=%u, RX=%u bytes/sec, TX=%u bytes/sec, ERR=%d\n", (int)id, (int)p->rx_bytes.bytes, (int)p->tx_bytes.bytes, (int)p->errors); p->rx_bytes.bytes = 0; p->tx_bytes.bytes = 0; fflush(stdout); last_sec = sub_tv.tv_sec; id++; } timersub(&sub_tv, &ref_tv, &res_tv); if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) break; libusb20_dev_process(p->usb_dev); if (!libusb20_tr_pending(p->xfer_in)) { if (in_pending) { if (libusb20_tr_get_status(p->xfer_in) == 0) { modem_read(in_buffer, libusb20_tr_get_length(p->xfer_in, 0)); } else { p->errors++; usleep(10000); } in_pending = 0; in_ready = 1; } if (p->loop_data == 0) { libusb20_tr_setup_bulk(p->xfer_in, in_buffer, io_max, 0); libusb20_tr_start(p->xfer_in); in_pending = 1; in_ready = 0; } } if (!libusb20_tr_pending(p->xfer_out)) { uint32_t len; uint32_t dly; if (out_pending) { if (libusb20_tr_get_status(p->xfer_out) != 0) { p->errors++; usleep(10000); } } if (p->random_tx_length) { len = ((uint32_t)usb_ts_rand_noise()) % ((uint32_t)io_max); } else { len = io_max; } if (p->random_tx_delay) { dly = ((uint32_t)usb_ts_rand_noise()) % 16000U; } else { dly = 0; } if (p->loop_data != 0) { if (in_ready != 0) { len = libusb20_tr_get_length(p->xfer_in, 0); memcpy(out_buffer, in_buffer, len); in_ready = 0; } else { len = io_max + 1; } if (!libusb20_tr_pending(p->xfer_in)) { libusb20_tr_setup_bulk(p->xfer_in, in_buffer, io_max, 0); libusb20_tr_start(p->xfer_in); in_pending = 1; } } else { modem_write(out_buffer, len); } if (len <= io_max) { libusb20_tr_setup_bulk(p->xfer_out, out_buffer, len, 0); if (dly != 0) usleep(dly); libusb20_tr_start(p->xfer_out); out_pending = 1; } } libusb20_dev_wait_process(p->usb_dev, 500); if (libusb20_dev_check_connected(p->usb_dev) != 0) { printf("Device disconnected\n"); break; } } libusb20_tr_stop(p->xfer_in); libusb20_tr_stop(p->xfer_out); printf("\nData stress test done!\n"); fail: if (in_buffer) free(in_buffer); if (out_buffer) free(out_buffer); }
static void usb_msc_test(struct usb_msc_params *p) { struct stats last_stat; struct timeval sub_tv; struct timeval ref_tv; struct timeval res_tv; uint8_t *buffer = NULL; uint8_t *reference = NULL; uint32_t dummy_buf[65536 / 4]; uint32_t lba_max; uint32_t x; uint32_t y; uint32_t capacity_lba; uint32_t capacity_bs; time_t last_sec; uint8_t lun; int tries; memset(&last_stat, 0, sizeof(last_stat)); switch (p->io_lun) { case USB_MSC_IO_LUN_0: lun = 0; break; case USB_MSC_IO_LUN_1: lun = 1; break; case USB_MSC_IO_LUN_2: lun = 2; break; case USB_MSC_IO_LUN_3: lun = 3; break; default: lun = 0; break; } p->done = 0; sense_recurse = p->try_sense_on_error ? 0 : 1; printf("Resetting device ...\n"); do_msc_reset(lun); printf("Testing SCSI commands ...\n"); if (p->try_all_lun) { printf("Requesting sense from LUN 0..255 ... "); for (x = y = 0; x != 256; x++) { if (do_msc_cmd(mode_sense_6, sizeof(mode_sense_6), dummy_buf, 255, 1, 1, x, 0)) y++; if (libusb20_dev_check_connected(usb_pdev) != 0) { printf(" disconnect "); break; } } printf("Passed=%d, Failed=%d\n", 256 - y, y); } do_msc_cmd(mode_sense_6, sizeof(mode_sense_6), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); for (tries = 0; tries != 4; tries++) { memset(dummy_buf, 0, sizeof(dummy_buf)); if (do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0) != 0) { printf("Cannot read disk capacity (%u / 4)\n", tries); if (tries == 3) return; usleep(50000); continue; } else { break; } } capacity_lba = be32toh(dummy_buf[0]); capacity_bs = be32toh(dummy_buf[1]); printf("Disk reports a capacity of LBA=%u and BS=%u\n", capacity_lba, capacity_bs); block_size = capacity_bs; if (capacity_bs > 65535) { printf("Blocksize is too big\n"); return; } if (capacity_bs < 1) { printf("Blocksize is too small\n"); return; } if (capacity_bs != 512) printf("INFO: Blocksize is not 512 bytes\n"); if (p->try_shorter_wrapper_block) { printf("Trying too short command wrapper:\n"); do_msc_shorter_cmd(lun); } if (p->try_invalid_scsi_command) { int status; for (tries = 0; tries != 4; tries++) { printf("Trying invalid SCSI command: "); status = do_msc_cmd(request_invalid, sizeof(request_invalid), dummy_buf, 255, 1, 1, lun, 0); printf("Result%s as expected\n", status ? "" : " NOT"); usleep(50000); } } if (p->try_invalid_wrapper_block) { int status; for (tries = 0; tries != 4; tries++) { printf("Trying invalid USB wrapper block signature: "); xfer_wrapper_sig = 0x55663322; status = do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0); printf("Result%s as expected\n", status ? "" : " NOT"); xfer_wrapper_sig = CBWSIGNATURE; usleep(50000); } } do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(mode_page_inquiry, sizeof(mode_page_inquiry), dummy_buf, 255, 1, 1, lun, 0); do_msc_cmd(mode_page_inquiry, sizeof(mode_page_inquiry), dummy_buf, 255, 1, 1, lun, 0); if (do_msc_cmd(prevent_removal, sizeof(prevent_removal), 0, 0, 1, 1, lun, 0)) { printf("INFO: Prevent medium removal failed\n"); } if (do_msc_cmd(read_toc, sizeof(read_toc), dummy_buf, 255, 1, 1, lun, 0)) { printf("INFO: Read Table Of Content failed\n"); } if (p->try_last_lba) { for (y = 0, x = (1UL << 31); x; x >>= 1) { if (do_read_10(x | y, block_size, dummy_buf, lun) == 0) y |= x; } printf("Highest readable LBA: %u (%s), " "Capacity is %u MBytes\n", y, (capacity_lba != y) ? "WRONG" : "OK", (int)((((uint64_t)(y) * (uint64_t)block_size) + (uint64_t)block_size) / 1000000ULL)); } else {