static size_t usbFormatLogSetupPacket (char *buffer, size_t size, const void *data) { const UsbSetupPacket *setup = data; size_t length; STR_BEGIN(buffer, size); STR_PRINTF("setup packet: Typ:%02X Req:%02X Val:%04X Idx:%04X Len:%04X", setup->bRequestType, setup->bRequest, getLittleEndian16(setup->wValue), getLittleEndian16(setup->wIndex), getLittleEndian16(setup->wLength)); length = STR_LENGTH; STR_END; return length; }
int usbGetLanguage ( UsbDevice *device, uint16_t *language, int timeout ) { UsbDescriptor descriptor; ssize_t size = usbGetDescriptor(device, UsbDescriptorType_String, 0, 0, &descriptor, timeout); if (size != -1) { if (size >= 4) { *language = getLittleEndian16(descriptor.string.wData[0]); logMessage(LOG_CATEGORY(USB_IO), "USB language: %02X", *language); return 1; } else { logMessage(LOG_ERR, "USB language code string too short: %"PRIssize, size); errno = EIO; } } else { logMessage(LOG_ERR, "USB language code string read error"); } return 0; }
static int usbReadHostDeviceDescriptor (UsbHostDevice *host) { int ok = 0; int file = -1; int sysfs = 0; if (file == -1) { if (host->sysfsPath) { char *path; if ((path = makePath(host->sysfsPath, "descriptors"))) { if ((file = open(path, O_RDONLY)) != -1) { sysfs = 1; } free(path); } } } if (file == -1) { file = open(host->usbfsPath, O_RDONLY); } if (file != -1) { int count = read(file, &host->usbDescriptor, UsbDescriptorSize_Device); if (count == -1) { logSystemError("USB device descriptor read"); } else if (count != UsbDescriptorSize_Device) { logMessage(LOG_ERR, "USB short device descriptor: %d", count); } else { ok = 1; if (!sysfs) { host->usbDescriptor.bcdUSB = getLittleEndian16(host->usbDescriptor.bcdUSB); host->usbDescriptor.idVendor = getLittleEndian16(host->usbDescriptor.idVendor); host->usbDescriptor.idProduct = getLittleEndian16(host->usbDescriptor.idProduct); host->usbDescriptor.bcdDevice = getLittleEndian16(host->usbDescriptor.bcdDevice); } } close(file); } return ok; }
const UsbConfigurationDescriptor * usbConfigurationDescriptor ( UsbDevice *device ) { if (!device->configuration) { unsigned char current; if (device->descriptor.bNumConfigurations < 2) { current = 1; } else if (!usbGetConfiguration(device, ¤t)) { current = 0; } if (current) { UsbDescriptor descriptor; unsigned char number; for (number=0; number<device->descriptor.bNumConfigurations; number++) { int size = usbGetDescriptor(device, UsbDescriptorType_Configuration, number, 0, &descriptor, 1000); if (size == -1) { logMessage(LOG_WARNING, "USB configuration descriptor not readable: %d", number); } else if (descriptor.configuration.bConfigurationValue == current) { break; } } if (number < device->descriptor.bNumConfigurations) { int length = getLittleEndian16(descriptor.configuration.wTotalLength); UsbDescriptor *descriptors; if ((descriptors = malloc(length))) { ssize_t size; if (length > sizeof(descriptor)) { size = usbControlRead(device, UsbControlRecipient_Device, UsbControlType_Standard, UsbStandardRequest_GetDescriptor, (UsbDescriptorType_Configuration << 8) | number, 0, descriptors, length, 1000); } else { memcpy(descriptors, &descriptor, (size = length)); } if (size != -1) { device->configuration = &descriptors->configuration; } else { free(descriptors); } } else { logSystemError("USB configuration descriptor allocate"); } } else { logMessage(LOG_ERR, "USB configuration descriptor not found: %d", current); } } } return device->configuration; }
UsbEndpoint * usbGetEndpoint (UsbDevice *device, unsigned char endpointAddress) { UsbEndpoint *endpoint; const UsbEndpointDescriptor *descriptor; if ((endpoint = findItem(device->endpoints, usbTestEndpoint, &endpointAddress))) return endpoint; if ((descriptor = usbEndpointDescriptor(device, endpointAddress))) { { const char *direction; const char *transfer; switch (USB_ENDPOINT_DIRECTION(descriptor)) { default: direction = "?"; break; case UsbEndpointDirection_Input: direction = "in"; break; case UsbEndpointDirection_Output: direction = "out"; break; } switch (USB_ENDPOINT_TRANSFER(descriptor)) { default: transfer = "?"; break; case UsbEndpointTransfer_Control: transfer = "ctl"; break; case UsbEndpointTransfer_Isochronous: transfer = "iso"; break; case UsbEndpointTransfer_Bulk: transfer = "blk"; break; case UsbEndpointTransfer_Interrupt: transfer = "int"; break; } logMessage(LOG_DEBUG, "USB: ept=%02X dir=%s xfr=%s pkt=%d ivl=%dms", descriptor->bEndpointAddress, direction, transfer, getLittleEndian16(descriptor->wMaxPacketSize), descriptor->bInterval); } if ((endpoint = malloc(sizeof(*endpoint)))) { memset(endpoint, 0, sizeof(*endpoint)); endpoint->device = device; endpoint->descriptor = descriptor; switch (USB_ENDPOINT_DIRECTION(endpoint->descriptor)) { case UsbEndpointDirection_Input: endpoint->direction.input.pending = NULL; endpoint->direction.input.completed = NULL; endpoint->direction.input.buffer = NULL; endpoint->direction.input.length = 0; endpoint->direction.input.asynchronous = 0; break; } endpoint->extension = NULL; if (usbAllocateEndpointExtension(endpoint)) { if (enqueueItem(device->endpoints, endpoint)) return endpoint; usbDeallocateEndpointExtension(endpoint->extension); } free(endpoint); } } return NULL; }
ssize_t usbControlTransfer ( UsbDevice *device, uint8_t direction, uint8_t recipient, uint8_t type, uint8_t request, uint16_t value, uint16_t index, void *buffer, uint16_t length, int timeout ) { UsbDeviceExtension *devx = device->extension; UsbSetupPacket setup; int result; usbMakeSetupPacket(&setup, direction, recipient, type, request, value, index, length); if (direction == UsbControlDirection_Output) { if (length) logBytes(LOG_CATEGORY(USB_IO), "control output", buffer, length); } result = usb_control_msg(devx->handle, setup.bRequestType, setup.bRequest, getLittleEndian16(setup.wValue), getLittleEndian16(setup.wIndex), buffer, getLittleEndian16(setup.wLength), timeout); if (result >= 0) { if (direction == UsbControlDirection_Input) { logBytes(LOG_CATEGORY(USB_IO), "control input", buffer, result); } return result; } errno = -result; logSystemError("USB control transfer"); return -1; }
char * usbDecodeString (const UsbStringDescriptor *descriptor) { int count = (descriptor->bLength - 2) / sizeof(descriptor->wData[0]); char *string = malloc(count+1); if (string) { string[count] = 0; while (count--) { uint16_t character = getLittleEndian16(descriptor->wData[count]); if (character & 0XFF00) character = '?'; string[count] = character; } } else { logSystemError("USB string allocate"); } return string; }
int usbGetLanguage ( UsbDevice *device, uint16_t *language, int timeout ) { UsbDescriptor descriptor; int size = usbGetDescriptor(device, UsbDescriptorType_String, 0, 0, &descriptor, timeout); if (size != -1) { if (size >= 4) { *language = getLittleEndian16(descriptor.string.wData[0]); logMessage(LOG_DEBUG, "USB Language: %02X", *language); return 1; } errno = EIO; } return 0; }
int usbNextDescriptor ( UsbDevice *device, const UsbDescriptor **descriptor ) { if (*descriptor) { const UsbDescriptor *next = (UsbDescriptor *)&(*descriptor)->bytes[(*descriptor)->header.bLength]; const UsbDescriptor *first = (UsbDescriptor *)device->configuration; unsigned int length = getLittleEndian16(first->configuration.wTotalLength); if ((&next->bytes[0] - &first->bytes[0]) >= length) return 0; if ((&next->bytes[next->header.bLength] - &first->bytes[0]) > length) return 0; *descriptor = next; } else if (usbConfigurationDescriptor(device)) { *descriptor = (UsbDescriptor *)device->configuration; } else { return 0; } return 1; }
ssize_t usbHidGetItems ( UsbDevice *device, unsigned char interface, unsigned char number, unsigned char **items, int timeout ) { const UsbHidDescriptor *hid = usbHidDescriptor(device); if (hid) { if (number < hid->bNumDescriptors) { const UsbClassDescriptor *descriptor = &hid->descriptors[number]; uint16_t length = getLittleEndian16(descriptor->wDescriptorLength); void *buffer = malloc(length); if (buffer) { ssize_t result = usbControlRead(device, UsbControlRecipient_Interface, UsbControlType_Standard, UsbStandardRequest_GetDescriptor, (descriptor->bDescriptorType << 8) | interface, number, buffer, length, timeout); if (result != -1) { *items = buffer; return result; } free(buffer); } else { logMallocError(); } } else { logMessage(LOG_WARNING, "USB report descriptor not found: %u[%u]", interface, number); } } return -1; }
char * usbDecodeString (const UsbStringDescriptor *descriptor) { size_t count = (descriptor->bLength - 2) / sizeof(descriptor->wData[0]); char buffer[(count * UTF8_LEN_MAX) + 1]; const uint16_t *source = descriptor->wData; const uint16_t *end = source + count; char *target = buffer; while (source < end) { size_t length = convertWcharToUtf8(getLittleEndian16(*source++), target); target += length; } *target = 0; { char *string = strdup(buffer); if (!string) logMallocError(); return string; } }
static wchar_t * getUsbString (BrailleDisplay *brl, uint8_t request) { UsbDescriptor descriptor; if (askResource(brl, request, 0, 0, descriptor.bytes, sizeof(descriptor.bytes))) { size_t count = (descriptor.string.bLength - 2) / sizeof(descriptor.string.wData[0]); wchar_t *string = malloc((count + 1) * sizeof(*string)); if (string) { string[count] = 0; while (count) { count -= 1; string[count] = getLittleEndian16(descriptor.string.wData[count]); } return string; } else { logMallocError(); } } return NULL; }
UsbDevice * usbFindDevice (UsbDeviceChooser *chooser, UsbChooseChannelData *data) { UsbDevice *device = NULL; int result; { static int initialized = 0; if (!initialized) { usb_init(); initialized = 1; } } if ((result = usb_find_busses()) >= 0) { if ((result = usb_find_devices()) >= 0) { struct usb_bus *bus = usb_get_busses(); if (bus) { struct usb_bus *bus0 = bus; do { struct usb_device *dev = bus->devices; if (dev) { struct usb_device *dev0 = dev; do { UsbDeviceExtension *devx; if ((devx = malloc(sizeof(*devx)))) { if ((devx->handle = usb_open(dev))) { if ((device = usbTestDevice(devx, chooser, data))) return device; usb_close(devx->handle); } else { logMessage(LOG_ERR, "USB open error: vendor=%X product=%X", getLittleEndian16(dev->descriptor.idVendor), getLittleEndian16(dev->descriptor.idProduct)); } free(devx); } else { logSystemError("USB device extension allocate"); } if ((dev = dev->next) == dev0) dev = NULL; } while (dev); } if ((bus = bus->next) == bus0) bus = NULL; } while (bus); } } else { errno = -result; logSystemError("USB devices find"); } } else { errno = -result; logSystemError("USB busses find"); } return device; }
UsbEndpoint * usbGetEndpoint (UsbDevice *device, unsigned char endpointAddress) { UsbEndpoint *endpoint; const UsbEndpointDescriptor *descriptor; if ((endpoint = findItem(device->endpoints, usbTestEndpoint, &endpointAddress))) return endpoint; if ((descriptor = usbEndpointDescriptor(device, endpointAddress))) { { const char *direction; const char *transfer; switch (USB_ENDPOINT_DIRECTION(descriptor)) { default: direction = "?"; break; case UsbEndpointDirection_Input: direction = "in"; break; case UsbEndpointDirection_Output: direction = "out"; break; } switch (USB_ENDPOINT_TRANSFER(descriptor)) { default: transfer = "?"; break; case UsbEndpointTransfer_Control: transfer = "ctl"; break; case UsbEndpointTransfer_Isochronous: transfer = "iso"; break; case UsbEndpointTransfer_Bulk: transfer = "blk"; break; case UsbEndpointTransfer_Interrupt: transfer = "int"; break; } logMessage(LOG_CATEGORY(USB_IO), "ept=%02X dir=%s xfr=%s pkt=%d ivl=%dms", descriptor->bEndpointAddress, direction, transfer, getLittleEndian16(descriptor->wMaxPacketSize), descriptor->bInterval); } if ((endpoint = malloc(sizeof(*endpoint)))) { memset(endpoint, 0, sizeof(*endpoint)); endpoint->device = device; endpoint->descriptor = descriptor; endpoint->extension = NULL; endpoint->prepare = NULL; switch (USB_ENDPOINT_DIRECTION(endpoint->descriptor)) { case UsbEndpointDirection_Input: endpoint->direction.input.pending.requests = NULL; endpoint->direction.input.pending.alarm = NULL; endpoint->direction.input.pending.delay = 0; endpoint->direction.input.completed.request = NULL; endpoint->direction.input.completed.buffer = NULL; endpoint->direction.input.completed.length = 0; endpoint->direction.input.pipe.input = INVALID_FILE_DESCRIPTOR; endpoint->direction.input.pipe.output = INVALID_FILE_DESCRIPTOR; endpoint->direction.input.pipe.monitor = NULL; endpoint->direction.input.pipe.error = 0; break; } if (usbAllocateEndpointExtension(endpoint)) { if (enqueueItem(device->endpoints, endpoint)) { if (device->disableEndpointReset) { logMessage(LOG_CATEGORY(USB_IO), "endpoint reset disabled"); } else { usbClearHalt(device, endpoint->descriptor->bEndpointAddress); } if (!endpoint->prepare || endpoint->prepare(endpoint)) return endpoint; deleteItem(device->endpoints, endpoint); } usbDeallocateEndpointExtension(endpoint->extension); usbDestroyInputPipe(endpoint); } free(endpoint); } } return NULL; }
int usbVerifyProductIdentifier (const UsbDeviceDescriptor *descriptor, uint16_t identifier) { if (!identifier) return 1; return identifier == getLittleEndian16(descriptor->idProduct); }