@@ 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
@@ 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);
+ }
+}