# HG changeset patch # User Paul Boddie # Date 1364076780 0 # Node ID c2b1ef8023ffd3a4fdd4a702c55efe33896576cf # Parent da210002ee99cb7f991d6cf8fe57acf9b261e839 Added support for showing multiple configurations. Tidied up device descriptor initialisation. Added initial device configuration functionality. diff -r da210002ee99 -r c2b1ef8023ff test.c --- a/test.c Sat Mar 23 17:31:34 2013 +0000 +++ b/test.c Sat Mar 23 22:13:00 2013 +0000 @@ -622,6 +622,39 @@ } /** + * Obtain a device descriptor with usable structure members. + */ +struct usb_device_descriptor *usb_get_device_descriptor(uint8_t *data) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *) data; + desc->bcdUSB = le16toh(desc->bcdUSB); + desc->idVendor = le16toh(desc->idVendor); + desc->idProduct = le16toh(desc->idProduct); + desc->bcdDevice = le16toh(desc->bcdDevice); + return desc; +} + +/** + * Obtain a configuration descriptor with usable structure members. + */ +struct usb_config_descriptor *usb_get_config_descriptor(uint8_t *data) +{ + struct usb_config_descriptor *conf = (struct usb_config_descriptor *) data; + conf->wTotalLength = le16toh(conf->wTotalLength); + return conf; +} + +/** + * Obtain an endpoint descriptor with usable structure members. + */ +struct usb_endpoint_descriptor *usb_get_endpoint_descriptor(uint8_t *data) +{ + struct usb_endpoint_descriptor *endp = (struct usb_endpoint_descriptor *) data; + endp->wMaxPacketSize = le16toh(endp->wMaxPacketSize); + return endp; +} + +/** * Get a descriptor from the device having the given type, value, index and length. * The descriptor buffer is static and must be copied if it is to be preserved. */ @@ -670,7 +703,7 @@ return NULL; if (type == USB_DT_CONFIG) - length = le16toh(((struct usb_config_descriptor *) data)->wTotalLength); + length = usb_get_config_descriptor(data)->wTotalLength; else length = ((struct usb_descriptor_header *) data)->bLength; @@ -683,17 +716,13 @@ bool usb_init_device(max_device *device, uint8_t *data) { - struct usb_device_descriptor *desc = (struct usb_device_descriptor *) data; + struct usb_device_descriptor *desc; if (data == NULL) return false; + desc = usb_get_device_descriptor(data); memcpy(&device->desc, desc, sizeof(struct usb_device_descriptor)); - device->desc.bcdUSB = le16toh(device->desc.bcdUSB); - device->desc.idVendor = le16toh(device->desc.idVendor); - device->desc.idProduct = le16toh(device->desc.idProduct); - device->desc.bcdDevice = le16toh(device->desc.bcdDevice); - return true; } @@ -746,6 +775,23 @@ max_control_status(false); } +/** + * Set the configuration of the given device. + */ +void max_set_configuration(max_device *device, uint8_t config) +{ + uint8_t setup[8]; + + max_write(MAX_REG_PERADDR, device->address); + + setup_packet(setup, USB_ENDPOINT_OUT, USB_REQ_SET_CONFIGURATION, config, 0, 0); + max_control(setup); + max_control_status(false); +} + +/** + * Return a string representation of an endpoint address. + */ const char *usb_endpoint_address_str(uint8_t bEndpointAddress) { static char output[] = "255 (127 OUT)"; @@ -757,6 +803,9 @@ return output; } +/** + * Return a string representation of endpoint attributes. + */ const char *usb_endpoint_attributes_str(uint8_t bmAttributes) { switch (bmAttributes & USB_ENDPOINT_TYPE_MASK) @@ -813,26 +862,6 @@ } } -/** - * Obtain a configuration descriptor with usable structure members. - */ -struct usb_config_descriptor *usb_get_config_descriptor(uint8_t *data) -{ - struct usb_config_descriptor *conf = (struct usb_config_descriptor *) data; - conf->wTotalLength = le16toh(conf->wTotalLength); - return conf; -} - -/** - * Obtain an endpoint descriptor with usable structure members. - */ -struct usb_endpoint_descriptor *usb_get_endpoint_descriptor(uint8_t *data) -{ - struct usb_endpoint_descriptor *endp = (struct usb_endpoint_descriptor *) data; - endp->wMaxPacketSize = le16toh(endp->wMaxPacketSize); - return endp; -} - uint8_t *usb_descriptor_start(struct usb_config_descriptor *conf) { return ((uint8_t *) conf) + conf->bLength; @@ -930,6 +959,70 @@ } } +void usb_show_configurations(max_device *device) +{ + uint8_t n; + + for (n = 0; n < device->desc.bNumConfigurations; n++) + { + usb_show_configuration_full(max_get_descriptor(device, USB_DT_CONFIG, n, 0, 0)); + } +} + +bool usb_configuration_has_interface(uint8_t *data, uint8_t bInterfaceClass, uint8_t bInterfaceProtocol) +{ + struct usb_config_descriptor *conf; + struct usb_descriptor_header *desc; + struct usb_interface_descriptor *intf; + uint8_t *current, *last; + + if (data == NULL) + return false; + + conf = usb_get_config_descriptor(data); + current = usb_descriptor_start(conf); + last = usb_descriptor_end(conf); + + while ((current != NULL) && (current < last)) + { + desc = (struct usb_descriptor_header *) current; + switch (desc->bDescriptorType) + { + case USB_DT_INTERFACE: + intf = (struct usb_interface_descriptor *) current; + if ((intf->bInterfaceClass == bInterfaceClass) && (intf->bInterfaceProtocol == bInterfaceProtocol)) + return true; + break; + + default: + break; + } + + current = usb_descriptor_next(current); + } + + return false; +} + +bool usb_configure_device(max_device *device) +{ + uint8_t n, *data; + + for (n = 0; n < device->desc.bNumConfigurations; n++) + { + data = max_get_descriptor(device, USB_DT_CONFIG, n, 0, 0); + + /* USB HID mouse. */ + + if (usb_configuration_has_interface(data, 3, 2)) + { + return true; + } + } + + return false; +} + /** * Handle termination of the process. */ @@ -1130,9 +1223,13 @@ printf("DEVICE?\n"); usb_show_languages(max_get_descriptor(&device, USB_DT_STRING, 0, 0, 0)); - usb_show_configuration_full(max_get_descriptor(&device, USB_DT_CONFIG, 0, 0, 0)); + usb_show_configurations(&device); devstate = MAX_DEVSTATE_READY; printf("READY\n"); + + /* Detect supported interfaces and configure devices to use them. */ + + /* usb_configure_device(&device); */ } /* Handle device disconnection. */