From 8fd37eafa2cd7ba0dc587922c113260ce53aabca Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sun, 27 Oct 2024 09:53:48 +0100 Subject: [PATCH] feat: move all sending instructions to generic send functions --- include/usb.h | 57 +++++++++++++++++++++++------- include/usb_device.h | 8 ----- src/usb.c | 84 +++++++++++++++++++++++++++++++++----------- src/usb_device.c | 77 +++++++++++++++------------------------- 4 files changed, 136 insertions(+), 90 deletions(-) diff --git a/include/usb.h b/include/usb.h index 4583fb52549616247b7eec301f0a3b9c4e842e05..308173b84eb034192b6a89c9574b6241eab25901 100644 --- a/include/usb.h +++ b/include/usb.h @@ -1,8 +1,16 @@ #include +#include #ifndef USB_H #define USB_H +// NOTE: fields here have to be kept in same order, +// and care must be taken the structs are not padded. +// They are from the usb standard. + +#define USB_SUBLANG_ENGLISH_US 0x01 +#define USB_LANG_ENGLISH 0x09 + #pragma GCC diagnostic error "-Wpadded" typedef struct { uint8_t self_powered : 1; @@ -127,7 +135,7 @@ typedef struct { uint8_t reserved1 : 1; uint8_t self_powered : 1; uint8_t remote_wakeup : 1; - uint8_t reserved2: 5; + uint8_t reserved_zeros: 5; } usb_configuration_descriptor_attributes; typedef struct __attribute__((packed)) { @@ -160,10 +168,10 @@ typedef enum { USB_ENDPOINT_IN = 1, } usb_endpoint_direction_t; -typedef struct { +typedef struct __attribute__((packed)) { uint8_t endpoint_number : 4; uint8_t reserved : 3; - uint8_t direction : 1; + usb_endpoint_direction_t direction : 1; } usb_endpoint_address_t; typedef enum { @@ -215,28 +223,51 @@ typedef struct { uint8_t *bString; } usb_unicode_string_descriptor_t; -void usb_generic_send(uint8_t *data, uint16_t size, +// NOTE: End of structs from usb specification here + +typedef struct __attribute__((packed)) { + usb_device_descriptor_t device_descriptor; + usb_device_qualifier_t device_qualifier; + // NOTE: keep these three fields in this order! + usb_configuration_descriptor_t configuration_descriptor; + usb_interface_descriptor_t interface_descriptor; + usb_endpoint_descriptor_t endpoint_descriptors[8]; + // + usb_string_descriptor_zero_t string_descriptor_zero; + usb_unicode_string_descriptor_t *string_descriptors; +} usb_class_t; + +void usb_generic_send(USB_OTG_INEndpointTypeDef *endpoint, + uint8_t *data, + uint16_t size, volatile uint32_t *fifo_tx_target); -void usb_generic_read(uint8_t *data, uint16_t size, +void usb_generic_read(uint8_t *data, + uint16_t size, volatile uint32_t *fifo_rx_source); -void usb_send_descriptor(usb_descriptor_t *descriptor, +void usb_send_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target); -void usb_send_device_descriptor(usb_device_descriptor_t *descriptor, +void usb_send_device_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_device_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target); -void usb_send_device_qualifier_descriptor(usb_device_qualifier_t *descriptor, +void usb_send_device_qualifier_descriptor(USB_OTG_INEndpointTypeDef* endpoint,usb_device_qualifier_t *descriptor, volatile uint32_t *fifo_tx_target); /* void usb_send_ack(uint32_t* fifo_tx_target); */ -void usb_send_configuration_descriptor( - usb_configuration_descriptor_t *descriptor, - volatile uint32_t *fifo_tx_target); -void usb_send_interface_descriptor(usb_interface_descriptor_t *descriptor, +void usb_send_configuration_descriptor(USB_OTG_INEndpointTypeDef* endpoint, + usb_class_t *class, + volatile uint32_t *fifo_tx_target); +void usb_send_interface_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_interface_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target); -void usb_send_endpoint_descriptor(usb_endpoint_descriptor_t *descriptor, +void usb_send_endpoint_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_endpoint_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target); void usb_send_string_descriptor_zero( + USB_OTG_INEndpointTypeDef *endpoint, usb_string_descriptor_zero_t *string_descriptor, volatile uint32_t *fifo_tx_target); void usb_send_unicode_string_descriptor( + USB_OTG_INEndpointTypeDef *endpoint, usb_unicode_string_descriptor_t *string_descriptor, volatile uint32_t *fifo_tx_target); diff --git a/include/usb_device.h b/include/usb_device.h index 87cc9f52579eb5a1e5b00197fb46eca628736537..ba8faaec32819b6936d8db2bf2448076b1bb31e3 100644 --- a/include/usb_device.h +++ b/include/usb_device.h @@ -23,14 +23,6 @@ typedef struct { volatile uint32_t data[128]; } usb_fifo_t; -typedef struct { - usb_device_descriptor_t device_descriptor; - usb_configuration_descriptor_t configuration_descriptor; - usb_interface_descriptor_t interface_descriptor; - usb_device_qualifier_t device_qualifier; - usb_endpoint_descriptor_t endpoint_descriptors[8]; -} usb_class_t; - typedef struct { USB_OTG_GlobalTypeDef *core; USB_OTG_DeviceTypeDef *device; diff --git a/src/usb.c b/src/usb.c index 1fd5afe8be8945ece840be753b02ad7bfc9674ae..6b566d92ee376c9374412e79b3bd1ba3c75592c3 100644 --- a/src/usb.c +++ b/src/usb.c @@ -1,4 +1,6 @@ #include "usb.h" +#include "usb_device.h" +#include typedef union { uint32_t word; @@ -6,7 +8,20 @@ typedef union { uint8_t bytes[4]; } usb_data_t; -void usb_generic_send(uint8_t* data, uint16_t size, volatile uint32_t *fifo_tx_target) { +void usb_generic_send(USB_OTG_INEndpointTypeDef *endpoint, + uint8_t *data, + uint16_t size, + volatile uint32_t *fifo_tx_target) { + if (endpoint->DIEPCTL & USB_OTG_DIEPCTL_EPENA) { + // this is bad! Can't send the packet, this shouldn't get here, ever. + while (endpoint->DIEPCTL & USB_OTG_DIEPCTL_EPENA); + } + + // TODO: generic max packet size + uint16_t packet_count = size + 63 / 64; + + endpoint->DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | (size << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); + usb_data_t tx_data; uint8_t subWordBytes = size % 4; uint8_t wordCount = size / 4; @@ -25,6 +40,8 @@ void usb_generic_send(uint8_t* data, uint16_t size, volatile uint32_t *fifo_tx_t } *fifo_tx_target = tx_data.word; } + + endpoint->DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; } void usb_generic_read(uint8_t *data, uint16_t size, volatile uint32_t *fifo_rx_source) { @@ -47,43 +64,66 @@ void usb_generic_read(uint8_t *data, uint16_t size, volatile uint32_t *fifo_rx_s } } -void usb_send_descriptor(usb_descriptor_t *descriptor, +void usb_send_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target) { - usb_generic_send((uint8_t*)descriptor, descriptor->bLength, fifo_tx_target); + usb_generic_send(endpoint, (uint8_t*)descriptor, descriptor->bLength, fifo_tx_target); } -void usb_send_configuration_descriptor( - usb_configuration_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target) { - descriptor->header.bDescriptorType = DESCRIPTOR_CONFIGURATION; - descriptor->header.bLength = sizeof(usb_configuration_descriptor_t); - usb_send_descriptor(&descriptor->header, fifo_tx_target); +void usb_send_configuration_descriptor(USB_OTG_INEndpointTypeDef* endpoint, + usb_class_t *class, + volatile uint32_t *fifo_tx_target) { + class->configuration_descriptor.header.bDescriptorType = DESCRIPTOR_CONFIGURATION; + class->configuration_descriptor.header.bLength = sizeof(usb_configuration_descriptor_t); + class->interface_descriptor.header.bDescriptorType = DESCRIPTOR_INTERFACE; + class->interface_descriptor.header.bLength = sizeof(usb_interface_descriptor_t); + uint16_t total_length = + sizeof(usb_configuration_descriptor_t) + + sizeof(usb_interface_descriptor_t) + + class->interface_descriptor.bNumEndpoints * sizeof(usb_endpoint_descriptor_t); + + for (int i = 0; i < class->interface_descriptor.bNumEndpoints; i++) { + class->endpoint_descriptors[i].header.bDescriptorType = DESCRIPTOR_ENDPOINT; + class->endpoint_descriptors[i].header.bLength = sizeof(usb_endpoint_descriptor_t); + } + + // NOTE: since the memory layout is: configuration, interface, endpoints, + // we can send directly like this. + usb_generic_send(endpoint, + (uint8_t*)&class->configuration_descriptor, + total_length, fifo_tx_target); } -void usb_send_device_descriptor(usb_device_descriptor_t *descriptor, - volatile uint32_t *fifo_tx_target) { +void usb_send_device_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_device_descriptor_t *descriptor, + volatile uint32_t *fifo_tx_target) { descriptor->header.bDescriptorType = DESCRIPTOR_DEVICE; descriptor->header.bLength = sizeof(usb_device_descriptor_t); - usb_send_descriptor(&descriptor->header, fifo_tx_target); + usb_send_descriptor(endpoint, &descriptor->header, fifo_tx_target); } -void usb_send_device_qualifier_descriptor(usb_device_qualifier_t *descriptor, +void usb_send_device_qualifier_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_device_qualifier_t *descriptor, volatile uint32_t *fifo_tx_target) { descriptor->header.bDescriptorType = DESCRIPTOR_DEVICE_QUALIFIER; descriptor->header.bLength = sizeof(usb_device_qualifier_t); - usb_send_descriptor(&descriptor->header, fifo_tx_target); + usb_send_descriptor(endpoint, &descriptor->header, fifo_tx_target); } -void usb_send_interface_descriptor(usb_interface_descriptor_t *descriptor, +void usb_send_interface_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_interface_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target) { descriptor->header.bDescriptorType = DESCRIPTOR_INTERFACE; descriptor->header.bLength = sizeof(usb_interface_descriptor_t); - usb_send_descriptor(&descriptor->header, fifo_tx_target); + usb_send_descriptor(endpoint, &descriptor->header, fifo_tx_target); } -void usb_send_endpoint_descriptor(usb_endpoint_descriptor_t *descriptor, +void usb_send_endpoint_descriptor(USB_OTG_INEndpointTypeDef *endpoint, + usb_endpoint_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target) { descriptor->header.bDescriptorType = DESCRIPTOR_ENDPOINT; descriptor->header.bLength = sizeof(usb_endpoint_descriptor_t); - usb_send_descriptor(&descriptor->header, fifo_tx_target); + usb_send_descriptor(endpoint, &descriptor->header, fifo_tx_target); } -void usb_send_string_descriptor_zero(usb_string_descriptor_zero_t *string_descriptor, +void usb_send_string_descriptor_zero(USB_OTG_INEndpointTypeDef *endpoint, + usb_string_descriptor_zero_t *string_descriptor, volatile uint32_t *fifo_tx_target) { usb_data_t data; data.word = 0; @@ -102,12 +142,14 @@ void usb_send_string_descriptor_zero(usb_string_descriptor_zero_t *string_descri // TODO: Now the rest only from wLANGID[1..] if (string_descriptor->header.bLength > 4) { - usb_generic_send((uint8_t *)&string_descriptor->wLANGID[1], + usb_generic_send(endpoint, + (uint8_t *)&string_descriptor->wLANGID[1], string_descriptor->header.bLength - 4, fifo_tx_target); } } void usb_send_unicode_string_descriptor( + USB_OTG_INEndpointTypeDef *endpoint, usb_unicode_string_descriptor_t *string_descriptor, volatile uint32_t *fifo_tx_target) { usb_data_t data = { .word = 0 }; @@ -121,6 +163,8 @@ void usb_send_unicode_string_descriptor( *fifo_tx_target = data.word; if (string_descriptor->header.bLength > 4) { - usb_generic_send(&string_descriptor->bString[2], string_descriptor->header.bLength - 4, fifo_tx_target); + usb_generic_send(endpoint, &string_descriptor->bString[2], + string_descriptor->header.bLength - 4, + fifo_tx_target); } } diff --git a/src/usb_device.c b/src/usb_device.c index de886037b8946260eb69fcf148d046cb7c1a2a3f..09b18c5b1617ab2195760ac77566370d49bf0e04 100644 --- a/src/usb_device.c +++ b/src/usb_device.c @@ -142,28 +142,6 @@ typedef struct { uint8_t endpoint_num; } packet_info_t; -void usb_prepare_send_packet(USB_OTG_INEndpointTypeDef* in, uint8_t packet_count, uint8_t packet_size) { - if (ep enabled) { - // this is bad! Can't send the packet - } - - in->DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | (packet_size << USB_OTG_DIEPTSIZ_XFRSIZ_Pos); -} - -void usb_control_send(usb_device_t *device, uint8_t value) { - usb_prepare_send_packet(&device->in[0], - 1, sizeof(uint8_t)); - usb_generic_send(&value, - sizeof(uint8_t), &device->fifos[0].data[0]); - device->in[0].DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; -} - -void usb_control_send_ack(usb_device_t* device) { - usb_prepare_send_packet(&device->in[0], - 1, sizeof(uint8_t)); - device->in[0].DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; -} - void usb_handle_setup(usb_device_t *device, usb_setup_command_t* cmd) { switch (cmd->bRequest) { case USB_SETUP_GET_STATUS: { @@ -197,10 +175,8 @@ void usb_handle_setup(usb_device_t *device, usb_setup_command_t* cmd) { break; } - usb_prepare_send_packet(device, 1, size); - usb_generic_send(packet, size, + usb_generic_send(device->in, packet, size, &device->fifos[0].data[0]); - device->in[0].DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; } break; case USB_SETUP_GET_DESCRIPTOR: { @@ -209,30 +185,30 @@ void usb_handle_setup(usb_device_t *device, usb_setup_command_t* cmd) { switch (descriptor_type) { case DESCRIPTOR_DEVICE: - usb_prepare_send_packet(&device->in[0], - 1, sizeof(usb_device_descriptor_t)); - usb_send_device_descriptor(&device->class.device_descriptor, &device->fifos[0].data[0]); - device->in[0].DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; + usb_send_device_descriptor(device->in, &device->class.device_descriptor, &device->fifos[0].data[0]); break; case DESCRIPTOR_CONFIGURATION: - usb_prepare_send_packet(&device->in[0], - 1, sizeof(usb_configuration_descriptor_t)); - usb_send_configuration_descriptor(&device->class.configuration_descriptor, &device->fifos[0].data[0]); - device->in[0].DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; + usb_send_configuration_descriptor(device->in, &device->class.configuration_descriptor, &device->fifos[0].data[0]); break; - case DESCRIPTOR_STRING: + case DESCRIPTOR_STRING: { + if (descriptor_index == 0) { + usb_send_string_descriptor_zero(device->in, &device->class.string_descriptor_zero, &device->fifos[0].data[0]); + } else { + uint8_t index = descriptor_index - 1; + // NOTE: the user could potentially read different memory part!! + // This has to be fixed, the length has to be stored somewhere. + usb_send_unicode_string_descriptor(device->in, &device->class.string_descriptors[index], &device->fifos[0].data[0]); + } + } + break; + case DESCRIPTOR_INTERFACE: + usb_send_interface_descriptor(device->in, &device->class.interface_descriptor, &device->fifos[0].data[0]); break; case DESCRIPTOR_ENDPOINT: - usb_prepare_send_packet(&device->in[0], - 1, sizeof(usb_endpoint_descriptor_t)); - usb_send_endpoint_descriptor(&device->class.endpoint_descriptors[descriptor_index], &device->fifos[0].data[0]); - device->in[0].DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; + usb_send_endpoint_descriptor(device->in, &device->class.endpoint_descriptors[descriptor_index], &device->fifos[0].data[0]); break; case DESCRIPTOR_DEVICE_QUALIFIER: - usb_prepare_send_packet(&device->in[0], - 1, sizeof(usb_device_qualifier_t)); - usb_send_device_qualifier_descriptor(&device->class.device_qualifier, &device->fifos[0].data[0]); - device->in[0].DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA; + usb_send_device_qualifier_descriptor(device->in, &device->class.device_qualifier, &device->fifos[0].data[0]); break; case DESCRIPTOR_OTHER_SPEED_CONFIGURATION: case DESCRIPTOR_INTERFACE_POWER: @@ -247,11 +223,14 @@ void usb_handle_setup(usb_device_t *device, usb_setup_command_t* cmd) { if (device->state != ENUMERATED) { value = 0; } - usb_control_send(device, value); + usb_generic_send(device->in, &value, sizeof(value), &device->fifos[0].data[0]); } break; case USB_SETUP_GET_INTERFACE: { - usb_control_send(device, device->class.interface_descriptor.bAlternateSetting); + usb_generic_send(device->in, + &device->class.interface_descriptor.bAlternateSetting, + sizeof(uint8_t), + &device->fifos[0].data[0]); } break; case USB_SETUP_SET_ADDRESS: @@ -259,18 +238,18 @@ void usb_handle_setup(usb_device_t *device, usb_setup_command_t* cmd) { cmd->wValue, USB_OTG_DCFG_DAD_Pos, 0x7F); - usb_control_send_ack(device); + usb_generic_send(device->in, NULL, 0, &device->fifos[0].data[0]); device->state = SET_ADDRESS_RCVD; break; case USB_SETUP_SET_CONFIGURATION: { if (cmd->wValue == 0) { device->state = SET_ADDRESS_RCVD; - usb_control_send_ack(device); + usb_generic_send(device->in, NULL, 0, &device->fifos[0].data[0]); // TODO disable endpoints } else if (cmd->wValue == device->class.configuration_descriptor.bConfigurationValue) { device->state = ENUMERATED; - usb_control_send_ack(device); + usb_generic_send(device->in, NULL, 0, &device->fifos[0].data[0]); // TODO setup endpoints } else { @@ -292,7 +271,7 @@ void usb_handle_setup(usb_device_t *device, usb_setup_command_t* cmd) { break; } - usb_control_send_ack(device); + usb_generic_send(device->in, NULL, 0, &device->fifos[0].data[0]); break; case USB_SETUP_SET_FEATURE: switch (cmd->wValue) { @@ -308,7 +287,7 @@ void usb_handle_setup(usb_device_t *device, usb_setup_command_t* cmd) { break; } - usb_control_send_ack(device); + usb_generic_send(device->in, NULL, 0, &device->fifos[0].data[0]); break; case USB_SETUP_SET_DESCRIPTOR: case USB_SETUP_SET_INTERFACE: