M include/usb.h => include/usb.h +58 -20
@@ 3,6 3,25 @@
#ifndef USB_H
#define USB_H
+#pragma GCC diagnostic error "-Wpadded"
+typedef struct {
+ uint8_t self_powered : 1;
+ uint8_t remote_wakeup : 1;
+ uint16_t reserved_zeros : 14;
+} usb_device_status_t;
+_Static_assert(sizeof(usb_device_status_t) == 2, "Size check");
+
+typedef struct {
+ uint8_t halt : 1;
+ uint16_t reserved_zeros : 15;
+} usb_endpoint_status_t;
+_Static_assert(sizeof(usb_endpoint_status_t) == 2, "Size check");
+
+typedef struct {
+ uint16_t reserved;
+} usb_interface_status_t;
+_Static_assert(sizeof(usb_interface_status_t) == 2, "Size check");
+
typedef enum {
USB_SETUP_HOST_TO_DEVICE,
USB_SETUP_DEVICE_TO_HOST,
@@ 22,13 41,13 @@ typedef enum {
USB_SETUP_OTHER,
} usb_setup_command_recipient_t;
-typedef struct {
+typedef struct __attribute__((packed)) {
uint8_t recipient : 5;
usb_setup_command_type_t type : 2;
usb_setup_command_direction_t direction : 1;
} usb_setup_command_request_type_t;
-typedef enum {
+typedef enum __attribute__((packed)) {
USB_SETUP_GET_STATUS = 0,
USB_SETUP_CLEAR_FEATURE = 1,
RESERVED1 = 2,
@@ 45,17 64,22 @@ typedef enum {
} usb_setup_request_t;
typedef enum {
+ USB_FEATURE_ENDPOINT_HALT = 0,
+ USB_FEATURE_DEVICE_REMOTE_WAKEUP = 1,
+ USB_FEATURE_TEST_MODE = 2,
+} usb_setup_feature_selector_t;
+
+typedef enum {
DESCRIPTOR_DEVICE = 1,
- DESCRIPTOR_CONFIGURATION = 1,
- DESCRIPTOR_STRING = 2,
- DESCRIPTOR_INTERFACE = 3,
- DESCRIPTOR_ENDPOINT = 4,
- DESCRIPTOR_DEVICE_QUALIFIER = 5,
- DESCRIPTOR_OTHER_SPEED_CONFIGURATION = 6,
- DESCRIPTOR_INTERFACE_POWER = 7,
+ DESCRIPTOR_CONFIGURATION = 2,
+ DESCRIPTOR_STRING = 3,
+ DESCRIPTOR_INTERFACE = 4,
+ DESCRIPTOR_ENDPOINT = 5,
+ DESCRIPTOR_DEVICE_QUALIFIER = 6,
+ DESCRIPTOR_OTHER_SPEED_CONFIGURATION = 7,
+ DESCRIPTOR_INTERFACE_POWER = 8,
} usb_descriptor_type_t;
-#pragma GCC diagnostic error "-Wpadded"
typedef struct __attribute__((packed)) {
usb_setup_command_request_type_t bmRequestType;
usb_setup_request_t bRequest;
@@ 191,17 215,31 @@ typedef struct {
uint8_t *bString;
} usb_unicode_string_descriptor_t;
-
-void usb_generic_send(uint8_t* data, uint16_t size, uint32_t *fifo_tx_target);
-void usb_generic_read(uint8_t *data, uint16_t size, uint32_t *fifo_rx_source);
-
-void usb_send_descriptor(usb_descriptor_t* descriptor, uint32_t *fifo_tx_target);
+void usb_generic_send(uint8_t *data, uint16_t size,
+ volatile uint32_t *fifo_tx_target);
+void usb_generic_read(uint8_t *data, uint16_t size,
+ volatile uint32_t *fifo_rx_source);
+void usb_send_descriptor(usb_descriptor_t *descriptor,
+ volatile uint32_t *fifo_tx_target);
+void usb_send_device_descriptor(usb_device_descriptor_t *descriptor,
+ volatile uint32_t *fifo_tx_target);
+void usb_send_device_qualifier_descriptor(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, 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);
+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,
+ volatile uint32_t *fifo_tx_target);
+void usb_send_endpoint_descriptor(usb_endpoint_descriptor_t *descriptor,
+ volatile uint32_t *fifo_tx_target);
+void usb_send_string_descriptor_zero(
+ usb_string_descriptor_zero_t *string_descriptor,
+ volatile uint32_t *fifo_tx_target);
+void usb_send_unicode_string_descriptor(
+ usb_unicode_string_descriptor_t *string_descriptor,
+ volatile uint32_t *fifo_tx_target);
+
#endif // USB_H
M include/usb_device.h => include/usb_device.h +7 -3
@@ 16,8 16,7 @@ typedef enum {
RESET = 1,
RESET_DONE = 2,
SET_ADDRESS_RCVD = 3,
- SET_CONFIG_RCVD = 4,
- ENUMERATED = 5,
+ ENUMERATED = 4,
} usb_device_state_t;
typedef struct {
@@ 28,6 27,7 @@ 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;
@@ 45,7 45,11 @@ typedef struct {
usb_class_t class;
usb_device_state_t state;
- usb_setup_command_t received_setup_command;
+
+ // TODO: is this count field required?
+ uint8_t received_setup_commands_count;
+ uint8_t received_setup_commands_index;
+ usb_setup_command_t received_setup_commands[3];
} usb_device_t;
// has configuration etc
M src/usb.c => src/usb.c +20 -9
@@ 6,7 6,7 @@ typedef union {
uint8_t bytes[4];
} usb_data_t;
-void usb_generic_send(uint8_t* data, uint16_t size, uint32_t *fifo_tx_target) {
+void usb_generic_send(uint8_t* data, uint16_t size, volatile uint32_t *fifo_tx_target) {
usb_data_t tx_data;
uint8_t subWordBytes = size % 4;
uint8_t wordCount = size / 4;
@@ 27,7 27,7 @@ void usb_generic_send(uint8_t* data, uint16_t size, uint32_t *fifo_tx_target) {
}
}
-void usb_generic_read(uint8_t *data, uint16_t size, uint32_t *fifo_rx_source) {
+void usb_generic_read(uint8_t *data, uint16_t size, volatile uint32_t *fifo_rx_source) {
usb_data_t rx_data;
uint8_t subWordBytes = size % 4;
uint8_t wordCount = size / 4;
@@ 48,31 48,43 @@ void usb_generic_read(uint8_t *data, uint16_t size, uint32_t *fifo_rx_source) {
}
void usb_send_descriptor(usb_descriptor_t *descriptor,
- uint32_t *fifo_tx_target) {
+ volatile 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) {
+ 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_device_descriptor(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);
+}
+void usb_send_device_qualifier_descriptor(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);
+}
void usb_send_interface_descriptor(usb_interface_descriptor_t *descriptor,
- uint32_t *fifo_tx_target) {
+ 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);
}
void usb_send_endpoint_descriptor(usb_endpoint_descriptor_t *descriptor,
- uint32_t *fifo_tx_target) {
+ 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);
}
void usb_send_string_descriptor_zero(usb_string_descriptor_zero_t *string_descriptor,
- uint32_t *fifo_tx_target) {
+ volatile uint32_t *fifo_tx_target) {
usb_data_t data;
data.word = 0;
@@ 97,8 109,7 @@ void usb_send_string_descriptor_zero(usb_string_descriptor_zero_t *string_descri
}
void usb_send_unicode_string_descriptor(
usb_unicode_string_descriptor_t *string_descriptor,
- uint32_t *fifo_tx_target) {
-
+ volatile 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) {
M src/usb_device.c => src/usb_device.c +333 -16
@@ 4,6 4,7 @@
#include <stddef.h>
#include <stm32h747xx.h>
#include "registers.h"
+#include "delay.h"
/* USB_OTG_GlobalTypeDef */
@@ 23,6 24,9 @@ void* usb_device_init(void* peripheral_address, usb_class_t* class, void* buffer
device->in = peripheral_address + USB_OTG_IN_ENDPOINT_BASE;
device->fifos = (usb_fifo_t*)(((uint8_t*)device->core) + USB_OTG_FIFO_BASE);
device->endpoint_count = 8;
+ device->received_setup_commands_count = 0;
+ device->received_setup_commands_index = 0;
+ device->class = *class;
// TODO: clarify how this should work...
usb1_device = device;
@@ 41,6 45,7 @@ void usb_device_reset(void* device_ptr) {
while (device->core->GRSTCTL & USB_OTG_GRSTCTL_CSRST);
// Wait for idle
while ((device->core->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
+ DELAY_US(3);
}
void usb_device_clear_interrupts(void* device_ptr) {
@@ 78,6 83,7 @@ void usb_device_setup(void* device_ptr) {
device->core->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
+ DELAY_US(3);
usb_device_reset(device_ptr);
// global interrupt mask
@@ 114,11 120,6 @@ void usb_device_setup(void* device_ptr) {
/* while (((device->core->GINTSTS) & USB_OTG_GINTSTS_ENUMDNE) == 0) {} */
}
-void usb_handle_endpoint_int(usb_device_t* device) {
- device->core->GRXSTSP;
- device->core->GRXFSIZ;
-}
-
typedef enum {
PACKET_GLOBAL_OUT_NAK = 1,
PACKET_OUT_DATA_PACKET_RCVD = 2,
@@ 141,6 142,187 @@ 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: {
+ uint8_t size;
+ uint8_t* packet;
+ usb_device_status_t device_status;
+ usb_interface_status_t interface_status;
+ usb_endpoint_status_t endpoint_status;
+
+ switch (cmd->bmRequestType.recipient) {
+ case USB_SETUP_DEVICE: {
+ size = sizeof(usb_device_status_t);
+ device_status.self_powered = 0;
+ device_status.remote_wakeup = 0;
+ device_status.reserved_zeros = 0;
+ packet = (uint8_t*)&device_status;
+ }
+ break;
+ case USB_SETUP_INTERFACE: {
+ size = sizeof(usb_interface_status_t);
+ interface_status.reserved = 0;
+ packet = (uint8_t*)&interface_status;
+ }
+ break;
+ case USB_SETUP_ENDPOINT: {
+ size = sizeof(usb_endpoint_status_t);
+ endpoint_status.halt = 0;
+ endpoint_status.reserved_zeros = 0;
+ packet = (uint8_t*)&interface_status;
+ }
+ break;
+ }
+
+ usb_prepare_send_packet(device, 1, size);
+ usb_generic_send(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: {
+ usb_descriptor_type_t descriptor_type = (cmd->wValue >> 8) & 0xFF;
+ uint8_t descriptor_index = cmd->wValue & 0xFF;
+
+ 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;
+ 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;
+ break;
+ case DESCRIPTOR_STRING:
+ 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;
+ 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;
+ break;
+ case DESCRIPTOR_OTHER_SPEED_CONFIGURATION:
+ case DESCRIPTOR_INTERFACE_POWER:
+ reg_set_bits(&device->out[0].DOEPCTL, USB_OTG_DOEPCTL_STALL);
+ break;
+ }
+ // TODO
+ }
+ break;
+ case USB_SETUP_GET_CONFIGURATION: {
+ uint8_t value = device->class.configuration_descriptor.bConfigurationValue;
+ if (device->state != ENUMERATED) {
+ value = 0;
+ }
+ usb_control_send(device, value);
+ }
+ break;
+ case USB_SETUP_GET_INTERFACE: {
+ usb_control_send(device, device->class.interface_descriptor.bAlternateSetting);
+ }
+ break;
+ case USB_SETUP_SET_ADDRESS:
+ reg_write_bits_pos(&device->device->DCFG,
+ cmd->wValue,
+ USB_OTG_DCFG_DAD_Pos,
+ 0x7F);
+ usb_control_send_ack(device);
+ 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);
+
+ // TODO disable endpoints
+ } else if (cmd->wValue == device->class.configuration_descriptor.bConfigurationValue) {
+ device->state = ENUMERATED;
+ usb_control_send_ack(device);
+
+ // TODO setup endpoints
+ } else {
+ reg_set_bits(&device->in[0].DIEPCTL, USB_OTG_DIEPCTL_STALL);
+ }
+ }
+ break;
+ case USB_SETUP_CLEAR_FEATURE:
+ switch (cmd->wValue) {
+ case USB_FEATURE_ENDPOINT_HALT: {
+ uint8_t ep_id = cmd->wIndex;
+ reg_clear_bits(&device->in[ep_id].DIEPCTL, USB_OTG_DIEPCTL_STALL);
+ reg_clear_bits(&device->out[ep_id].DOEPCTL, USB_OTG_DOEPCTL_STALL);
+ }
+ break;
+ case USB_FEATURE_TEST_MODE:
+ case USB_FEATURE_DEVICE_REMOTE_WAKEUP:
+ // Do not do anything...
+ break;
+ }
+
+ usb_control_send_ack(device);
+ break;
+ case USB_SETUP_SET_FEATURE:
+ switch (cmd->wValue) {
+ case USB_FEATURE_ENDPOINT_HALT: {
+ uint8_t ep_id = cmd->wIndex;
+ reg_set_bits(&device->in[ep_id].DIEPCTL, USB_OTG_DIEPCTL_STALL);
+ reg_set_bits(&device->out[ep_id].DOEPCTL, USB_OTG_DOEPCTL_STALL);
+ }
+ break;
+ case USB_FEATURE_TEST_MODE:
+ case USB_FEATURE_DEVICE_REMOTE_WAKEUP:
+ // Do not do anything...
+ break;
+ }
+
+ usb_control_send_ack(device);
+ break;
+ case USB_SETUP_SET_DESCRIPTOR:
+ case USB_SETUP_SET_INTERFACE:
+ case USB_SETUP_SYNCH_FRAME:
+ device->in->DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_STALL;
+ device->state = UNKNOWN_CONTROL_COMMAND;
+ break;
+ case RESERVED1:
+ case RESERVED2:
+ device->state = UNKNOWN_CONTROL_COMMAND;
+ break;
+ }
+}
+
void usb_handle_rxflvl_control_int(usb_device_t *device,
packet_info_t *packet_info) {
uint32_t dummy;
@@ 148,14 330,20 @@ void usb_handle_rxflvl_control_int(usb_device_t *device,
uint32_t *fifo = device->fifos[0].data;
if (packet_info->packet_status == PACKET_SETUP_TRANSACTION_COMPLETED) {
-
+ // Nothing do to.
} else if (packet_info->packet_status == PACKET_SETUP_DATA_PACKET_RECEIVED) {
- /* dummy = *fifo; // internal info */
// SAVE data
- usb_generic_read((uint8_t*)&device->received_setup_command, 8, fifo);
-
- // 00000000010000000000000000000000
- // 00000000101010000000000000000000
+ uint8_t setup_packets_count = 3 - reg_read_bits_pos(&device->out[0].DOEPTSIZ, USB_OTG_DOEPTSIZ_STUPCNT_Pos, 3);
+ usb_generic_read(
+ (uint8_t *)&device
+ ->received_setup_commands[device->received_setup_commands_index++],
+ 8,
+ fifo);
+ device->received_setup_commands_index %= 3;
+
+ if (setup_packets_count == 0) {
+ reg_write_bits_pos(&device->out[0].DOEPTSIZ, 3, USB_OTG_DOEPTSIZ_STUPCNT_Pos, 3);
+ }
dummy = *fifo; // the last that will trigger another interrupt
} else if (packet_info->byte_count != 0) {
@@ 187,12 375,137 @@ void usb_handle_rxflvl_int(usb_device_t *device) {
}
}
- // Read info about the endoint etc.
+ // Read info about the endpoint etc.
// Re-enable the interrupt
reg_set_bits(&device->core->GINTMSK, USB_OTG_GINTMSK_RXFLVLM);
}
+uint8_t usb_daint_get_endpoint_number(uint32_t endpoints) {
+ for (int i = 0; i < 15; i++) {
+ if (endpoints & (1 << i)) {
+ return i;
+ }
+ }
+ return 0xFF;
+}
+
+void usb_handle_endpoint_in_int(usb_device_t* device) {
+ uint8_t ep_id = usb_daint_get_endpoint_number(reg_read_bits_pos(&device->device->DAINT, USB_OTG_DAINT_IEPINT_Pos, 0xFFFF));
+ uint32_t interrupt_reg = device->in[ep_id].DIEPINT;
+
+ if (interrupt_reg & USB_OTG_DIEPINT_PKTDRPSTS) {
+ // Not generated by interrupt! So if we get this one
+ // here, it's not from the interrupt. Just clear it,
+ // isochronous pipes can drop data from time to time
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_PKTDRPSTS);
+ }
+
+ if (interrupt_reg & USB_OTG_DIEPINT_NAK) {
+ // NOTE no need to do much. Hardware will resend
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_NAK);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_BNA) {
+ // NOTE this should not be reached as DMA is not used
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_BNA);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_TXFIFOUDRN) {
+ // NOTE this should not be reached as thresholding is not used
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_TXFIFOUDRN);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_TXFE) {
+ // Now we can send more data. TODO notify application about this
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_TXFE);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_INEPNE) {
+ // NAK effective. Okay, ack, go on.
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_INEPNE);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_INEPNM) {
+ device->state = ERROR; // data on top of TxFIFO belong to endpoint other
+ // than the one for which in token was received.
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_INEPNM);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_ITTXFE) {
+ // In token when no data. How to proceed? TODO
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_ITTXFE);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_TOC) {
+ // Timeout condition. Skip? TODO how to proceed?
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_TOC);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_AHBERR) {
+ // NOTE this should not be reached as thresholding is not used
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_AHBERR);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_EPDISD) {
+ // Endpoint is disabled, per application's request. Okay.
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_EPDISD);
+ } else if (interrupt_reg & USB_OTG_DIEPINT_XFRC) {
+ // Transfer is completed. TODO notify application?
+ reg_clear_bits(&device->in[ep_id].DIEPINT, USB_OTG_DIEPINT_XFRC);
+ }
+}
+
+#define USB_OTG_DOEPINT_BNA_Pos (9U)
+#define USB_OTG_DOEPINT_BNA_Msk (0x1UL << USB_OTG_DOEPINT_B2BSTUP_Pos) /*!< 0x00000040 */
+#define USB_OTG_DOEPINT_BNA USB_OTG_DOEPINT_B2BSTUP_Msk /*!< Back-to-back SETUP packets received */
+
+void usb_handle_endpoint_out_int(usb_device_t* device) {
+ /* device->core->GRXSTSP; */
+ /* device->core->GRXFSIZ; */
+
+ uint8_t ep_id = usb_daint_get_endpoint_number(reg_read_bits_pos(&device->device->DAINT, USB_OTG_DAINT_OEPINT_Pos, 0xFFFF));
+ uint32_t interrupt_reg = device->out[ep_id].DOEPINT;
+
+ if (interrupt_reg & USB_OTG_DOEPINT_STPKTRX) {
+ // NOTE This shouldn't be reached since DMA is not used
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_STPKTRX);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_NYET) {
+ // We don't really care about this one for now
+ // TODO: for future - trigger a callback to application
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_NYET);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_NAK) {
+ // We don't really care about this one for now
+ // TODO: for future - trigger a callback to application
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_NAK);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_BERR) {
+ // Uh? Babble much?
+ device->state = CONTROL_ERROR;
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_BERR);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_BNA) {
+ // NOTE This shoudln't be reached since DMA is not used
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_BNA);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_OUTPKTERR) {
+ // NOTE thresholding not enabled, so this shouldn't be reached
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_OUTPKTERR);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_B2BSTUP) {
+ // TODO: this is a problem! we couldn't capture all the packets!
+ device->state = CONTROL_ERROR;
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_B2BSTUP);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_OTEPSPR) {
+ // TODO: ack or stall the status phase? How?
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_OTEPSPR);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_OTEPDIS) {
+ // NOTE: Can we handle this? a callback to application?
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_OTEPDIS);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_STUP) {
+ // handle all setup commands
+ uint8_t setup_packets_count = 3 - reg_read_bits_pos(&device->out[ep_id].DOEPTSIZ, USB_OTG_DOEPTSIZ_STUPCNT_Pos, 3);
+ usb_handle_setup(device, &device->received_setup_commands[0]);
+ for (int i = 0; i < device->received_setup_commands_count; i++) {
+ }
+
+ device->received_setup_commands_count = 0;
+ // TODO: null the data? shouldn't be needed...
+
+ // 3 packets to receive as setup
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_STUP);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_AHBERR) {
+ // NOTE This shoudln't be reached since DMA is not used
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_AHBERR);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_EPDISD) {
+ // NOTE endpoint has been disabled, as was instructed. So this shoudln't
+ // need handling?
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_EPDISD);
+ } else if (interrupt_reg & USB_OTG_DOEPINT_XFRC) {
+ // Transfer has been completed
+ // TODO: handle data? - callback to device data handle?
+ reg_clear_bits(&device->out[ep_id].DOEPINT, USB_OTG_DOEPINT_XFRC);
+ }
+}
+
// NOTE: this is irq handler
void otg_hs_handler(void) {
@@ 215,7 528,7 @@ void otg_hs_handler(void) {
device->device->DIEPMSK |= USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_TOM;
// 512 bytes
- device->core->GRXFSIZ = 512 / 4;
+ device->core->GRXFSIZ = 256 / 4;
// 64 bytes, beginning of ram
device->core->DIEPTXF[0] = (0) << USB_OTG_DIEPTXF_INEPTXSA_Pos | (64 / 4) << USB_OTG_DIEPTXF_INEPTXFD_Pos;
@@ 269,9 582,13 @@ void otg_hs_handler(void) {
}
// Setup, data...
- if (device->core->GINTSTS & (USB_OTG_GINTSTS_OEPINT | USB_OTG_GINTSTS_IEPINT)) {
- // TODO
- usb_handle_endpoint_int(device);
+ if (device->core->GINTSTS & USB_OTG_GINTSTS_OEPINT) {
+ usb_handle_endpoint_out_int(device);
+ return;
+ }
+
+ if (device->core->GINTSTS & USB_OTG_GINTSTS_IEPINT) {
+ usb_handle_endpoint_in_int(device);
return;
}