# HG changeset patch # User Paul Boddie # Date 1363303591 0 # Node ID 97ba84d5e0145bea0dc9c92194592b9bf3c1fcac # Parent f33f9c21ca2f6aa5f4fdb44810d2e95e2014e7fd Added support for transferring multi-packet payloads. Introduced transfers of limited amounts of data in order to discover the full size of descriptors and then to transfer the full descriptor payloads. Separated the display of device descriptors from their initialisation. diff -r f33f9c21ca2f -r 97ba84d5e014 test.c --- a/test.c Wed Mar 13 17:11:10 2013 +0000 +++ b/test.c Thu Mar 14 23:26:31 2013 +0000 @@ -341,7 +341,7 @@ * the given length, indicating the preserved toggle state of the endpoint * (which will be updated). */ -uint8_t max_send(uint8_t endpoint, uint8_t *data, uint8_t len, bool *toggle) +uint8_t max_send_packet(uint8_t endpoint, uint8_t *data, uint8_t len, bool *toggle) { uint8_t status, hrsl = 0; @@ -375,13 +375,12 @@ /** * Make a request for data from the given endpoint, collecting it in the - * supplied buffer with the given length, indicating the preserved toggle state - * of the endpoint (which will be updated). The length will be updated to - * indicate the total length of the received data. + * supplied buffer, updating the given length of data received, and recording + * the data within the given limit, also indicating the preserved toggle state + * of the endpoint (which will be updated). */ -bool max_recv(uint8_t endpoint, uint8_t *data, uint8_t *len, bool *toggle) +bool max_recv_packet(uint8_t endpoint, uint8_t **data, uint8_t *received, uint8_t *datalimit, bool *toggle) { - uint8_t *datalimit = data + *len; uint8_t status, hrsl = 0; uint16_t attempt = 1024; @@ -410,7 +409,7 @@ while (status & MAX_HIRQ_RCVDAVIRQ) { - max_read_fifo(&data, len, datalimit); + max_read_fifo(data, received, datalimit); /* Indicate that all data has been read. */ @@ -424,6 +423,26 @@ } /** + * Make a request for data from the given endpoint, collecting it in the + * supplied buffer, updating the given length of data received, and also + * indicating the preserved toggle state of the endpoint (which will be updated). + */ +bool max_recv(uint8_t endpoint, uint8_t *data, uint8_t *len, bool *toggle) +{ + uint8_t *datalimit = data + *len; + + *len = 0; + + while (max_recv_packet(endpoint, &data, len, datalimit, toggle)) + { + if (data == datalimit) + return true; + } + + return false; +} + +/** * Send a control request consisting of the given setup data. */ uint8_t max_control(uint8_t *setup) @@ -603,20 +622,15 @@ } /** - * Get a descriptor from the device having the given type, value and index. + * 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. */ -uint8_t *max_get_descriptor(max_device *device, uint8_t type, uint8_t value, uint8_t index, bool initial) +uint8_t *max_get_descriptor_with_length(max_device *device, uint8_t type, uint8_t value, uint8_t index, uint8_t length) { - static uint8_t data[64]; - uint8_t len = 64, setup[8]; + static uint8_t data[1024]; + uint8_t len = length, setup[8]; - printf("Sending descriptor request to address %d, endpoint 0...\n", device->address); - - max_write(MAX_REG_PERADDR, device->address); - - setup_packet(setup, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, usb_descriptor_type(type) | value, index, - initial ? 8 : 64); + setup_packet(setup, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, usb_descriptor_type(type) | value, index, length); max_control(setup); if (!max_control_input(data, &len, device)) @@ -626,23 +640,71 @@ } max_control_status(true); - if (len >= usb_descriptor_size(type)) + if (len >= length) return data; else { - printf("Expected %d but received %d.\n", usb_descriptor_size(type), len); + printf("Expected %d but received %d.\n", length, len); return NULL; } } /** + * Get a descriptor from the device having the given type, value, index and + * length. If the length is given as zero, the descriptor header will first be + * received and then the full descriptor will be retrieved. + * The descriptor buffer is static and must be copied if it is to be preserved. + */ +uint8_t *max_get_descriptor(max_device *device, uint8_t type, uint8_t value, uint8_t index, uint8_t length) +{ + uint8_t *data; + + printf("Sending descriptor request to address %d, endpoint 0...\n", device->address); + + max_write(MAX_REG_PERADDR, device->address); + + if (!length) + { + data = max_get_descriptor_with_length(device, type, value, index, usb_descriptor_size(type)); + if (data == NULL) + return NULL; + + if (type == USB_DT_CONFIG) + length = le16toh(((struct usb_config_descriptor *) data)->wTotalLength); + else + length = ((struct usb_descriptor_header *) data)->bLength; + + if (length == usb_descriptor_size(type)) + return data; + } + + return max_get_descriptor_with_length(device, type, value, index, length); +} + +bool usb_init_device(max_device *device, uint8_t *data) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *) data; + + if (data == NULL) + return false; + + 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; +} + +/** * Perform initialisation on a device, obtaining the device details and storing * this information in the device structure, returning true if successful and * false otherwise. */ bool max_init_device(max_device *device) { - struct usb_device_descriptor *desc; + uint8_t *data; printf("Sending control request to address 0, endpoint 0...\n"); @@ -650,10 +712,11 @@ /* Send a "get descriptor" request for the device descriptor. */ - desc = (struct usb_device_descriptor *) max_get_descriptor(device, USB_DT_DEVICE, 0, 0, true); + data = max_get_descriptor(device, USB_DT_DEVICE, 0, 0, 8); - if (desc != NULL) + if (data != NULL) { + usb_init_device(device, data); device->max_packet_size = device->desc.bMaxPacketSize0; /* Reset the device. */ @@ -665,47 +728,6 @@ return false; } -bool max_complete_device(max_device *device) -{ - struct usb_device_descriptor *desc; - - printf("Sending control request to address 0, endpoint 0...\n"); - - device->address = 0; - - /* Send a "get descriptor" request for the device descriptor. */ - - desc = (struct usb_device_descriptor *) max_get_descriptor(device, USB_DT_DEVICE, 0, 0, false); - - if (desc != NULL) - { - 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); - - printf("bLength: %d\n", device->desc.bLength); - printf("bDescriptorType: %d\n", device->desc.bDescriptorType); - printf("bcdUSB: %04x\n", device->desc.bcdUSB); - printf("bDeviceClass: %d\n", device->desc.bDeviceClass); - printf("bDeviceSubClass: %d\n", device->desc.bDeviceSubClass); - printf("bDeviceProtocol: %d\n", device->desc.bDeviceProtocol); - printf("bMaxPacketSize0: %d\n", device->desc.bMaxPacketSize0); - printf("idVendor: %04x\n", device->desc.idVendor); - printf("idProduct: %04x\n", device->desc.idProduct); - printf("bcdDevice: %04x\n", device->desc.bcdDevice); - printf("iManufacturer: %d\n", device->desc.iManufacturer); - printf("iProduct: %d\n", device->desc.iProduct); - printf("iSerialNumber: %d\n", device->desc.iSerialNumber); - printf("bNumConfigurations: %d\n", device->desc.bNumConfigurations); - - return true; - } - - return false; -} - /** * Assign a new address to the given device. */ @@ -724,6 +746,24 @@ max_control_status(false); } +void usb_show_device(max_device *device) +{ + printf("bLength: %d\n", device->desc.bLength); + printf("bDescriptorType: %d\n", device->desc.bDescriptorType); + printf("bcdUSB: %04x\n", device->desc.bcdUSB); + printf("bDeviceClass: %d\n", device->desc.bDeviceClass); + printf("bDeviceSubClass: %d\n", device->desc.bDeviceSubClass); + printf("bDeviceProtocol: %d\n", device->desc.bDeviceProtocol); + printf("bMaxPacketSize0: %d\n", device->desc.bMaxPacketSize0); + printf("idVendor: %04x\n", device->desc.idVendor); + printf("idProduct: %04x\n", device->desc.idProduct); + printf("bcdDevice: %04x\n", device->desc.bcdDevice); + printf("iManufacturer: %d\n", device->desc.iManufacturer); + printf("iProduct: %d\n", device->desc.iProduct); + printf("iSerialNumber: %d\n", device->desc.iSerialNumber); + printf("bNumConfigurations: %d\n", device->desc.bNumConfigurations); +} + void usb_show_languages(uint8_t *data) { struct usb_string_descriptor *desc = (struct usb_string_descriptor *) data; @@ -989,23 +1029,23 @@ else if ((devstate == MAX_DEVSTATE_RESET_AGAIN) && frame_event && !(--framecount)) { - if (!max_complete_device(&device)) - printf("FAILED: RESET_AGAIN -> ADDRESSING\n"); - else - { - max_set_address(&device); - devstate = MAX_DEVSTATE_ADDRESSING; - framecount = 30; - printf("ADDRESSING\n"); - } + max_set_address(&device); + devstate = MAX_DEVSTATE_ADDRESSING; + framecount = 30; + printf("ADDRESSING\n"); } /* Post-addressing. */ else if ((devstate == MAX_DEVSTATE_ADDRESSING) && frame_event && !(--framecount)) { - usb_show_languages(max_get_descriptor(&device, USB_DT_STRING, 0, 0, false)); - usb_show_configuration(max_get_descriptor(&device, USB_DT_CONFIG, 0, 0, false)); + if (usb_init_device(&device, max_get_descriptor(&device, USB_DT_DEVICE, 0, 0, usb_descriptor_size(USB_DT_DEVICE)))) + usb_show_device(&device); + else + printf("DEVICE?\n"); + + usb_show_languages(max_get_descriptor(&device, USB_DT_STRING, 0, 0, 0)); + usb_show_configuration(max_get_descriptor(&device, USB_DT_CONFIG, 0, 0, 0)); devstate = MAX_DEVSTATE_READY; printf("READY\n"); }