M include/usb.h => include/usb.h +44 -13
@@ 1,8 1,16 @@
#include <stdint.h>
+#include <stm32h747xx.h>
#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);
M include/usb_device.h => include/usb_device.h +0 -8
@@ 24,14 24,6 @@ typedef struct {
} 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;
M src/usb.c => src/usb.c +64 -20
@@ 1,4 1,6 @@
#include "usb.h"
+#include "usb_device.h"
+#include <stm32h747xx.h>
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);
}
}
M src/usb_device.c => src/usb_device.c +28 -49
@@ 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: