From 3b7f816a23a56167c7ebd5253394d21884ceb5eb Mon Sep 17 00:00:00 2001 From: Rutherther Date: Thu, 24 Oct 2024 14:10:07 +0200 Subject: [PATCH] feat: implement simple control usb read, writes --- include/usb.h | 9 ++++ src/usb.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/usb.c diff --git a/include/usb.h b/include/usb.h index cbbf155..848c3e2 100644 --- a/include/usb.h +++ b/include/usb.h @@ -191,4 +191,13 @@ typedef struct { uint8_t *bString; } usb_unicode_string_descriptor_t; +void usb_send_descriptor(usb_descriptor_t* descriptor, uint32_t *fifo_tx_target); +/* void usb_send_ack(uint32_t* fifo_tx_target); */ +void usb_send_configuration_descriptor(usb_configuration_descriptor_t* descriptor, uint32_t *fifo_tx_target); +void usb_send_interface_descriptor(usb_interface_descriptor_t* descriptor, uint32_t *fifo_tx_target); +void usb_send_endpoint_descriptor(usb_endpoint_descriptor_t* descriptor, uint32_t *fifo_tx_target); +void usb_send_string_descriptor_zero(usb_string_descriptor_zero_t* string_descriptor, uint32_t *fifo_tx_target); +void usb_send_unicode_string_descriptor(usb_unicode_string_descriptor_t* string_descriptor, uint32_t *fifo_tx_target); + + #endif // USB_H diff --git a/src/usb.c b/src/usb.c new file mode 100644 index 0000000..a4be090 --- /dev/null +++ b/src/usb.c @@ -0,0 +1,115 @@ +#include "usb.h" + +typedef union { + uint32_t word; + uint16_t halfwords[2]; + uint8_t bytes[4]; +} usb_data_t; + +void usb_generic_send(uint8_t* data, uint16_t size, uint32_t *fifo_tx_target) { + usb_data_t tx_data; + uint8_t subWordBytes = size % 4; + uint8_t wordCount = size / 4; + + for (uint8_t i = 0; i < wordCount; i++) { + tx_data.word = *((uint32_t*)data); + *fifo_tx_target = tx_data.word; + data += 4; + } + + // TODO: check where to put it... beginning, end... + if (subWordBytes != 0) { + tx_data.word = 0; + for (uint8_t i = 0; i < subWordBytes; i++) { + tx_data.bytes[i] = *(data + i); + } + *fifo_tx_target = tx_data.word; + } +} + +void usb_generic_read(uint8_t *data, uint16_t size, uint32_t *fifo_rx_source) { + usb_data_t rx_data; + uint8_t subWordBytes = size % 4; + uint8_t wordCount = size / 4; + + for (uint8_t i = 0; i < wordCount; i++) { + rx_data.word = *fifo_rx_source; + *((uint32_t*)data) = rx_data.word; + data += 4; + } + + // TODO: check where to put it... beginning, end... + if (subWordBytes > 0) { + rx_data.word = 0; + for (uint8_t i = 0; i < subWordBytes; i++) { + *(data + i) = rx_data.bytes[i]; + } + } +} + +void usb_send_descriptor(usb_descriptor_t *descriptor, + uint32_t *fifo_tx_target) { + usb_generic_send((uint8_t*)descriptor, descriptor->bLength, fifo_tx_target); +} + +void usb_send_configuration_descriptor( + usb_configuration_descriptor_t *descriptor, 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_interface_descriptor(usb_interface_descriptor_t *descriptor, + 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); +} +void usb_send_endpoint_descriptor(usb_endpoint_descriptor_t *descriptor, + 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); +} + +void usb_send_string_descriptor_zero(usb_string_descriptor_zero_t *string_descriptor, + uint32_t *fifo_tx_target) { + usb_data_t data; + data.word = 0; + + data.bytes[0] = string_descriptor->header.bLength; + data.bytes[1] = string_descriptor->header.bDescriptorType; + + if (string_descriptor->header.bLength == 2) { + *fifo_tx_target = data.word; + return; + } + + data.halfwords[1] = string_descriptor->wLANGID[0]; + + *fifo_tx_target = data.word; + + // TODO: Now the rest only from wLANGID[1..] + if (string_descriptor->header.bLength > 4) { + usb_generic_send((uint8_t *)&string_descriptor->wLANGID[1], + string_descriptor->header.bLength - 4, + fifo_tx_target); + } +} +void usb_send_unicode_string_descriptor( + usb_unicode_string_descriptor_t *string_descriptor, + uint32_t *fifo_tx_target) { + + usb_data_t data = { .word = 0 }; + data.halfwords[0] = *((uint16_t*)string_descriptor); + if (string_descriptor->bString != 0 && string_descriptor->header.bLength > 2) { + // NOTE: if the string had length of just one, there would be two bytes + // read here. That shouldn't usually matter much, so we don't care about + // that here. + data.halfwords[1] = *((uint16_t*)string_descriptor->bString); + } + *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); + } +} -- 2.48.1