static void do_msc_reset(uint8_t lun) { struct LIBUSB20_CONTROL_SETUP_DECODED setup; LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup); setup.bmRequestType = LIBUSB20_REQUEST_TYPE_CLASS | LIBUSB20_RECIPIENT_INTERFACE; setup.bRequest = 0xFF; /* BBB reset */ setup.wValue = 0; setup.wIndex = usb_iface; setup.wLength = 0; if (libusb20_dev_request_sync(usb_pdev, &setup, NULL, NULL, 5000, 0)) { printf("ERROR: %s\n", __FUNCTION__); stats.xfer_error++; } libusb20_tr_clear_stall_sync(xfer_in); libusb20_tr_clear_stall_sync(xfer_out); stats.xfer_reset++; usb_request_sense(lun); }
int usb_clear_halt(usb_dev_handle * dev, unsigned int ep) { struct libusb20_transfer *xfer; xfer = usb_get_transfer_by_ep_no(dev, ep); if (xfer == NULL) return (-1); libusb20_tr_clear_stall_sync(xfer); return (0); }
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); }
static uint8_t do_msc_cmd(uint8_t *pcmd, uint8_t cmdlen, void *pdata, uint32_t datalen, uint8_t isread, uint8_t isshort, uint8_t lun, uint8_t flags) { umass_bbb_cbw_t cbw; umass_bbb_csw_t csw; struct libusb20_transfer *xfer_io; uint32_t actlen; uint32_t timeout; int error; memset(&cbw, 0, sizeof(cbw)); USETDW(cbw.dCBWSignature, xfer_wrapper_sig); USETDW(cbw.dCBWTag, xfer_current_id); xfer_current_id++; USETDW(cbw.dCBWDataTransferLength, datalen); cbw.bCBWFlags = (isread ? CBWFLAGS_IN : CBWFLAGS_OUT); cbw.bCBWLUN = lun; cbw.bCDBLength = cmdlen; bcopy(pcmd, cbw.CBWCDB, cmdlen); actlen = 0; timeout = ((datalen + 299999) / 300000) * 1000; timeout += 5000; if ((error = libusb20_tr_bulk_intr_sync(xfer_out, &cbw, sizeof(cbw), &actlen, TIMEOUT_FILTER(1000)))) { printf("ERROR: CBW reception: %d\n", error); do_msc_reset(lun); return (1); } if (actlen != sizeof(cbw)) { printf("ERROR: CBW length: %d != %d\n", actlen, (int)sizeof(cbw)); do_msc_reset(lun); return (1); } if (flags & 1) datalen /= 2; if (datalen != 0) { xfer_io = isread ? xfer_in : xfer_out; if ((error = libusb20_tr_bulk_intr_sync(xfer_io, pdata, datalen, &actlen, TIMEOUT_FILTER(timeout)))) { printf("ERROR: Data transfer: %d\n", error); do_msc_reset(lun); return (1); } if ((actlen != datalen) && (!isshort)) { printf("ERROR: Short data: %d of %d bytes\n", actlen, datalen); do_msc_reset(lun); return (1); } } actlen = 0; timeout = 8; do { error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); if (error) { if (error == LIBUSB20_TRANSFER_TIMED_OUT) { printf("TIMEOUT: Trying to get CSW again. " "%d tries left.\n", timeout); } else { break; } } else { break; } } while (--timeout); if (error) { libusb20_tr_clear_stall_sync(xfer_in); error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); if (error) { libusb20_tr_clear_stall_sync(xfer_in); printf("ERROR: Could not read CSW: Stalled or " "timeout (%d).\n", error); do_msc_reset(lun); return (1); } } if (UGETDW(csw.dCSWSignature) != CSWSIGNATURE) { printf("ERROR: Wrong CSW signature\n"); do_msc_reset(lun); return (1); } if (actlen != sizeof(csw)) { printf("ERROR: Wrong CSW length: %d != %d\n", actlen, (int)sizeof(csw)); do_msc_reset(lun); return (1); } if (csw.bCSWStatus != 0) { printf("ERROR: CSW status: %d\n", (int)csw.bCSWStatus); return (1); } else { stats.xfer_success++; return (0); } }