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 libusb20_dev_req_string_sync(struct libusb20_device *pdev, uint8_t str_index, uint16_t langid, void *ptr, uint16_t len) { struct LIBUSB20_CONTROL_SETUP_DECODED req; int error; /* make sure memory is initialised */ memset(ptr, 0, len); if (len < 4) { /* invalid length */ return (LIBUSB20_ERROR_INVALID_PARAM); } LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); /* * We need to read the USB string in two steps else some USB * devices will complain. */ req.bmRequestType = LIBUSB20_REQUEST_TYPE_STANDARD | LIBUSB20_RECIPIENT_DEVICE | LIBUSB20_ENDPOINT_IN; req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR; req.wValue = (LIBUSB20_DT_STRING << 8) | str_index; req.wIndex = langid; req.wLength = 4; /* bytes */ error = libusb20_dev_request_sync(pdev, &req, ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); if (error) { return (error); } req.wLength = *(uint8_t *)ptr; /* bytes */ if (req.wLength > len) { /* partial string read */ req.wLength = len; } error = libusb20_dev_request_sync(pdev, &req, ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK); if (error) { return (error); } if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING) { return (LIBUSB20_ERROR_OTHER); } return (0); /* success */ }
int usb_control_msg(usb_dev_handle * dev, int requesttype, int request, int value, int wIndex, char *bytes, int size, int timeout) { struct LIBUSB20_CONTROL_SETUP_DECODED req; int err; uint16_t actlen; LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); req.bmRequestType = requesttype; req.bRequest = request; req.wValue = value; req.wIndex = wIndex; req.wLength = size; err = libusb20_dev_request_sync((void *)dev, &req, bytes, &actlen, timeout, 0); if (err) return (-1); return (actlen); }
static void usb_modem_control_ep_test(struct modem *p, uint32_t duration, uint8_t flag) { struct timeval sub_tv; struct timeval ref_tv; struct timeval res_tv; struct LIBUSB20_CONTROL_SETUP_DECODED setup; struct usb_cdc_abstract_state ast; struct usb_cdc_line_state ls; uint16_t feature = UCDC_ABSTRACT_STATE; uint16_t state = UCDC_DATA_MULTIPLEXED; uint8_t iface_no; uint8_t buf[4]; int id = 0; int iter = 0; time_t last_sec; iface_no = p->usb_iface - 1; gettimeofday(&ref_tv, 0); last_sec = ref_tv.tv_sec; printf("\nTest=%d\n", (int)flag); while (1) { gettimeofday(&sub_tv, 0); if (last_sec != sub_tv.tv_sec) { printf("STATUS: ID=%u, COUNT=%u tests/sec ERR=%u\n", (int)id, (int)iter, (int)p->errors); fflush(stdout); last_sec = sub_tv.tv_sec; id++; iter = 0; } timersub(&sub_tv, &ref_tv, &res_tv); if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) break; LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup); if (flag & 1) { setup.bmRequestType = UT_READ_CLASS_INTERFACE; setup.bRequest = 0x03; setup.wValue = 0x0001; setup.wIndex = iface_no; setup.wLength = 0x0002; if (libusb20_dev_request_sync(p->usb_dev, &setup, buf, NULL, 250, 0)) { p->errors++; } } if (flag & 2) { setup.bmRequestType = UT_WRITE_CLASS_INTERFACE; setup.bRequest = UCDC_SET_COMM_FEATURE; setup.wValue = feature; setup.wIndex = iface_no; setup.wLength = UCDC_ABSTRACT_STATE_LENGTH; USETW(ast.wState, state); if (libusb20_dev_request_sync(p->usb_dev, &setup, &ast, NULL, 250, 0)) { p->errors++; } } if (flag & 4) { USETDW(ls.dwDTERate, 115200); ls.bCharFormat = UCDC_STOP_BIT_1; ls.bParityType = UCDC_PARITY_NONE; ls.bDataBits = 8; setup.bmRequestType = UT_WRITE_CLASS_INTERFACE; setup.bRequest = UCDC_SET_LINE_CODING; setup.wValue = 0; setup.wIndex = iface_no; setup.wLength = sizeof(ls); if (libusb20_dev_request_sync(p->usb_dev, &setup, &ls, NULL, 250, 0)) { p->errors++; } } iter++; } printf("\nModem control endpoint test done!\n"); }
int main(int argc, char **argv) { unsigned int vid = UINT_MAX, pid = UINT_MAX; /* impossible VID:PID */ int c; /* * Initialize setup struct. This step is required, and initializes * internal fields in the struct. * * All the "public" fields are named exactly the way as the USB * standard describes them, namely: * * setup.bmRequestType: bitmask, bit 7 is direction * bits 6/5 is request type * (standard, class, vendor) * bits 4..0 is recipient * (device, interface, endpoint, * other) * setup.bRequest: the request itself (see get_req() for standard * requests, or specific value) * setup.wValue: a 16-bit value * setup.wIndex: another 16-bit value * setup.wLength: length of associated data transfer, direction * depends on bit 7 of bmRequestType */ LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup); while ((c = getopt(argc, argv, "i:p:v:")) != -1) switch (c) { case 'i': intr_ep = strtol(optarg, NULL, 0); break; case 'p': pid = strtol(optarg, NULL, 0); break; case 'v': vid = strtol(optarg, NULL, 0); break; default: usage(); break; } argc -= optind; argv += optind; if (vid != UINT_MAX || pid != UINT_MAX) { if (intr_ep != 0 && (intr_ep & 0x80) == 0) { fprintf(stderr, "Interrupt endpoint must be of type IN\n"); usage(); } if (argc > 0) { do_request = true; int rv = parse_req(argc, argv); if (rv < 0) return EX_USAGE; argc = rv; if (argc > 0) { for (out_len = 0; argc > 0 && out_len < BUFLEN; out_len++, argc--) { unsigned n = strtoul(argv[out_len], 0, 0); if (n > 255) fprintf(stderr, "Warning: data #%d 0x%0x > 0xff, truncating\n", out_len, n); out_buf[out_len] = (uint8_t)n; } out_len++; if (argc > 0) fprintf(stderr, "Data count exceeds maximum of %d, ignoring %d elements\n", BUFLEN, optind); } } } struct libusb20_backend *be; struct libusb20_device *dev; if ((be = libusb20_be_alloc_default()) == NULL) { perror("libusb20_be_alloc()"); return 1; } dev = NULL; while ((dev = libusb20_be_device_foreach(be, dev)) != NULL) { struct LIBUSB20_DEVICE_DESC_DECODED *ddp = libusb20_dev_get_device_desc(dev); printf("Found device %s (VID:PID = 0x%04x:0x%04x)\n", libusb20_dev_get_desc(dev), ddp->idVendor, ddp->idProduct); if (ddp->idVendor == vid && ddp->idProduct == pid) doit(dev); } libusb20_be_free(be); return 0; }
void usb_control_ep_error_test(uint16_t vid, uint16_t pid) { struct LIBUSB20_CONTROL_SETUP_DECODED req; struct libusb20_device *pdev; uint8_t buffer[256]; int error; int fail = 0; int bus; int dev; int cfg; 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; } bus = libusb20_dev_get_bus_number(pdev); dev = libusb20_dev_get_address(pdev); for (cfg = 0; cfg != 255; cfg++) { LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); req.bmRequestType = 0x80; /* read */ req.bRequest = 0x06; /* descriptor */ req.wValue = 0x0200 | cfg; /* config descriptor */ req.wIndex = 0; req.wLength = 255; printf("Test #%d.1/3 ...\n", cfg); set_ctrl_ep_fail(-1,-1,0,0); error = libusb20_dev_request_sync(pdev, &req, buffer, NULL, 1000, 0); if (error != 0) { printf("Last configuration index is: %d\n", cfg - 1); break; } printf("Test #%d.2/3 ...\n", cfg); set_ctrl_ep_fail(bus,dev,1,1); error = libusb20_dev_request_sync(pdev, &req, buffer, NULL, 1000, 0); set_ctrl_ep_fail(-1,-1,0,0); error = libusb20_dev_request_sync(pdev, &req, buffer, NULL, 1000, 0); if (error != 0) { printf("Cannot fetch descriptor (unexpected)\n"); fail++; } printf("Test #%d.3/3 ...\n", cfg); set_ctrl_ep_fail(bus,dev,0,1); error = libusb20_dev_request_sync(pdev, &req, buffer, NULL, 1000, 0); set_ctrl_ep_fail(-1,-1,0,0); error = libusb20_dev_request_sync(pdev, &req, buffer, NULL, 1000, 0); if (error != 0) { printf("Cannot fetch descriptor (unexpected)\n"); fail++; } } libusb20_dev_close(pdev); libusb20_dev_free(pdev); printf("Test completed detecting %d failures\nDone\n\n", fail); }
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 int ugen20_enumerate(struct libusb20_device *pdev, const char *id) { const char *tmp = id; struct usb_device_descriptor ddesc; struct usb_device_info devinfo; uint32_t plugtime; char buf[64]; int f; int error; pdev->bus_number = ugen20_path_convert_one(&tmp); pdev->device_address = ugen20_path_convert_one(&tmp); snprintf(buf, sizeof(buf), "/dev/" USB_GENERIC_NAME "%u.%u", pdev->bus_number, pdev->device_address); f = open(buf, O_RDWR); if (f < 0) { return (LIBUSB20_ERROR_OTHER); } if (ioctl(f, IOUSB(USB_GET_PLUGTIME), &plugtime)) { error = LIBUSB20_ERROR_OTHER; goto done; } /* store when the device was plugged */ pdev->session_data.plugtime = plugtime; if (ioctl(f, IOUSB(USB_GET_DEVICE_DESC), &ddesc)) { error = LIBUSB20_ERROR_OTHER; goto done; } LIBUSB20_INIT(LIBUSB20_DEVICE_DESC, &(pdev->ddesc)); libusb20_me_decode(&ddesc, sizeof(ddesc), &(pdev->ddesc)); if (pdev->ddesc.bNumConfigurations == 0) { error = LIBUSB20_ERROR_OTHER; goto done; } else if (pdev->ddesc.bNumConfigurations >= 8) { error = LIBUSB20_ERROR_OTHER; goto done; } if (ioctl(f, IOUSB(USB_GET_DEVICEINFO), &devinfo)) { error = LIBUSB20_ERROR_OTHER; goto done; } switch (devinfo.udi_mode) { case USB_MODE_DEVICE: pdev->usb_mode = LIBUSB20_MODE_DEVICE; break; default: pdev->usb_mode = LIBUSB20_MODE_HOST; break; } switch (devinfo.udi_speed) { case USB_SPEED_LOW: pdev->usb_speed = LIBUSB20_SPEED_LOW; break; case USB_SPEED_FULL: pdev->usb_speed = LIBUSB20_SPEED_FULL; break; case USB_SPEED_HIGH: pdev->usb_speed = LIBUSB20_SPEED_HIGH; break; case USB_SPEED_VARIABLE: pdev->usb_speed = LIBUSB20_SPEED_VARIABLE; break; case USB_SPEED_SUPER: pdev->usb_speed = LIBUSB20_SPEED_SUPER; break; default: pdev->usb_speed = LIBUSB20_SPEED_UNKNOWN; break; } /* get parent HUB index and port */ pdev->parent_address = devinfo.udi_hubindex; pdev->parent_port = devinfo.udi_hubport; /* generate a nice description for printout */ snprintf(pdev->usb_desc, sizeof(pdev->usb_desc), USB_GENERIC_NAME "%u.%u: <%s %s> at usbus%u", pdev->bus_number, pdev->device_address, devinfo.udi_product, devinfo.udi_vendor, pdev->bus_number); error = 0; done: close(f); return (error); }