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; }
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; }
int usbGetDeviceDescriptor ( UsbDevice *device, UsbDeviceDescriptor *descriptor ) { UsbDescriptor desc; int size = usbGetDescriptor(device, UsbDescriptorType_Device, 0, 0, &desc, 1000); if (size != -1) { *descriptor = desc.device; } return size; }
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; }
char * usbGetString ( UsbDevice *device, unsigned char number, int timeout ) { UsbDescriptor descriptor; if (!device->language) if (!usbGetLanguage(device, &device->language, timeout)) return NULL; if (usbGetDescriptor(device, UsbDescriptorType_String, number, device->language, &descriptor, timeout) == -1) return NULL; return usbDecodeString(&descriptor.string); }
void usbStdInterfaceRequest(void) { uint8_t bRequest = usbRequest.bRequest; if (bRequest == USB_REQ_GET_STATUS) { if (usb_state == CONFIGURED) { // all values are reserved for interfaces in0buf[0] = 0x00; in0buf[1] = 0x00; in0bc = 0x02; } } else if (bRequest == USB_REQ_GET_DESCRIPTOR) { // this requests the HID report descriptor usbGetDescriptor(); } else { USB_EP0_STALL(); } }
char * usbGetString ( UsbDevice *device, unsigned char number, int timeout ) { UsbDescriptor descriptor; if (!device->language) { if (!usbGetLanguage(device, &device->language, timeout)) { return NULL; } } if (usbGetDescriptor(device, UsbDescriptorType_String, number, device->language, &descriptor, timeout) == -1) { logMessage(LOG_ERR, "USB string read error: %u", number); return NULL; } return usbDecodeString(&descriptor.string); }
void usbStdDeviceRequest(void) { switch (usbRequest.bRequest) { case USB_REQ_GET_STATUS: // We must be in ADDRESSED or CONFIGURED state, and wIndex must be 0 if ((usb_state == ADDRESSED || usb_state == CONFIGURED) && usbRequest.wIndexLSB == 0x00) { // We aren't self-powered and we don't support remote wakeup in0buf[0] = 0x00; in0buf[1] = 0x00; in0bc = 0x02; } else { // Stall for invalid requests USB_EP0_STALL(); } break; case USB_REQ_SET_ADDRESS: // USB controller takes care of setting our address usb_state = ADDRESSED; break; case USB_REQ_GET_DESCRIPTOR: usbGetDescriptor(); break; case USB_REQ_GET_CONFIGURATION: if (usb_state == ADDRESSED) { in0buf[0] = 0x00; in0bc = 0x01; } else if (usb_state == CONFIGURED) { in0buf[0] = usb_current_config; in0bc = 0x01; } else { // Behavior not specified in other states, so STALL USB_EP0_STALL(); } break; case USB_REQ_SET_CONFIGURATION: if (usbRequest.wValueLSB == 0x00) { usb_state = ADDRESSED; usb_current_config = 0x00; // Since there isn't a data stage for this request, // we have to explicitly clear the NAK bit USB_EP0_HSNAK(); } else if (usbRequest.wValueLSB == 0x01) { usb_state = CONFIGURED; usb_current_config = 0x01; // Since there isn't a data stage for this request, // we have to explicitly clear the NAK bit USB_EP0_HSNAK(); } else { // Stall for invalid config values USB_EP0_STALL(); } break; } }