From fd50dee1a73f27372392f528cda343b258e16f99 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Fri, 25 Oct 2024 18:38:43 +0200 Subject: [PATCH] feat: receive setup packets --- include/usb_device.h | 29 +++++++++---- src/usb_device.c | 98 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 99 insertions(+), 28 deletions(-) diff --git a/include/usb_device.h b/include/usb_device.h index 99ffef9..45b1f42 100644 --- a/include/usb_device.h +++ b/include/usb_device.h @@ -1,12 +1,13 @@ +#include +#include "usb.h" + #ifndef USB_DEVICE_H #define USB_DEVICE_H -// -#include - typedef enum { // error states first so they are lowest CONTROL_ERROR = -4, + UNKNOWN_CONTROL_COMMAND = -4, ERROR = -3, UNKNOWN_INTERRUPT = -2, OTG_ERROR = -1, // shouldn't happen, since otg is not used @@ -19,6 +20,17 @@ typedef enum { ENUMERATED = 5, } usb_device_state_t; +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_endpoint_descriptor_t endpoint_descriptors[8]; +} usb_class_t; + typedef struct { USB_OTG_GlobalTypeDef *core; USB_OTG_DeviceTypeDef *device; @@ -26,17 +38,16 @@ typedef struct { USB_OTG_OUTEndpointTypeDef *out; USB_OTG_INEndpointTypeDef *in; + usb_fifo_t *fifos; + uint8_t endpoint_count; + usb_class_t class; + usb_device_state_t state; + usb_setup_command_t received_setup_command; } usb_device_t; -struct usb_configuration_t; - -typedef struct { - -} usb_class_t; - // has configuration etc #define USB_DEVICE_SIZE sizeof(usb_device_t) diff --git a/src/usb_device.c b/src/usb_device.c index f4e1f51..ed76a0f 100644 --- a/src/usb_device.c +++ b/src/usb_device.c @@ -1,4 +1,5 @@ #include "usb_device.h" +#include "usb.h" #include #include #include @@ -20,6 +21,7 @@ void* usb_device_init(void* peripheral_address, usb_class_t* class, void* buffer device->device = peripheral_address + USB_OTG_DEVICE_BASE; device->out = peripheral_address + USB_OTG_OUT_ENDPOINT_BASE; 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; // TODO: clarify how this should work... @@ -112,26 +114,83 @@ void usb_device_setup(void* device_ptr) { /* while (((device->core->GINTSTS) & USB_OTG_GINTSTS_ENUMDNE) == 0) {} */ } -void usb_handle_control_interrupt(usb_device_t *device) { - uint32_t daint = device->device->DAINT; +void usb_handle_endpoint_int(usb_device_t* device) { + device->core->GRXSTSP; + device->core->GRXFSIZ; +} - if (daint & (1 << USB_OTG_DAINT_IEPINT_Pos)) { - // in (that means sending data) - } else if (daint & (1 << USB_OTG_DAINT_OEPINT_Pos)) { - // out (that means receiving data) - } else { - device->state = CONTROL_ERROR; +typedef enum { + PACKET_GLOBAL_OUT_NAK = 1, + PACKET_OUT_DATA_PACKET_RCVD = 2, + PACKET_OUT_TRANSFER_COMPLETED = 3, + PACKET_SETUP_TRANSACTION_COMPLETED = 4, + PACKET_SETUP_DATA_PACKET_RECEIVED = 6, +} packet_status_t; + +typedef enum { + DATA0 = 0, + DATA1 = 1, + DATA2 = 2, + MDATA = 3 +} packet_dpid_t; + +typedef struct { + packet_status_t packet_status; + packet_dpid_t dpid; + uint8_t byte_count; + uint8_t endpoint_num; +} packet_info_t; + +void usb_handle_rxflvl_control_int(usb_device_t *device, + packet_info_t *packet_info) { + uint32_t dummy; + uint8_t data[64]; + uint32_t *fifo = device->fifos[0].data; + + if (packet_info->packet_status == PACKET_SETUP_TRANSACTION_COMPLETED) { + + } 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 + + dummy = *fifo; // the last that will trigger another interrupt + } else if (packet_info->byte_count != 0) { + usb_generic_read(data, packet_info->byte_count, fifo); } } -void usb_handle_endpoint_interrupt(usb_device_t* device) { - // TODO - - if ((device->state < ENUMERATED) || (device->device->DAINT & ((1 << USB_OTG_DAINT_IEPINT_Pos) | (1 << USB_OTG_DAINT_OEPINT_Pos)))) { - usb_handle_control_interrupt(device); - } else { - // new data received, put it to application level?. +void usb_handle_rxflvl_int(usb_device_t *device) { + // Disable the interrupt + reg_clear_bits(&device->core->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); + + /* uint32_t rx_data; */ + /* while ((rx_data = device->core->GRXSTSP) != 0) { */ + while (device->core->GINTSTS & USB_OTG_GINTSTS_RXFLVL) { + uint32_t status_data = device->core->GRXSTSP; + + /* uint8_t status_phase_start = reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_STSPHST); */ + packet_info_t packet_info = { + .packet_status = (packet_status_t)reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_PKTSTS_Pos, 0xF), + .dpid = (packet_dpid_t)reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_DPID_Pos, 0x3), + .byte_count = reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_BCNT_Pos, 0x7FF), + .endpoint_num = reg_read_bits_pos(&status_data, USB_OTG_GRXSTSP_EPNUM_Pos, 0xF), + }; + + if (packet_info.endpoint_num == 0) { + usb_handle_rxflvl_control_int(device, &packet_info); + } else { + // TODO: ... + } } + + // Read info about the endoint etc. + + // Re-enable the interrupt + reg_set_bits(&device->core->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); } // NOTE: this is irq handler @@ -145,11 +204,10 @@ void otg_hs_handler(void) { reg_set_bits(&device->device->DOEPMSK, USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_OEPINT); // TODO: should this be done for ep 0 as well? - for (int ep = 1; ep < device->endpoint_count; ep++) { + for (int ep = 0; ep < device->endpoint_count; ep++) { USB_OTG_OUTEndpointTypeDef *out = device->out + ep; out->DOEPCTL |= USB_OTG_DOEPCTL_SNAK; } - device->device->DAINTMSK |= 1 << USB_OTG_DAINTMSK_IEPM_Pos; device->device->DAINTMSK |= 1 << USB_OTG_DAINTMSK_OEPM_Pos; @@ -180,6 +238,8 @@ void otg_hs_handler(void) { // speed would differ, but these are not supported! reg_write_bits_pos(&device->in->DIEPCTL, 64, USB_OTG_DIEPCTL_MPSIZ_Pos, 0x7FFUL); + device->out->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + device->state = RESET_DONE; // clear it reg_set_bits(&device->core->GINTSTS, USB_OTG_GINTSTS_ENUMDNE); @@ -211,13 +271,13 @@ void otg_hs_handler(void) { // Setup, data... if (device->core->GINTSTS & (USB_OTG_GINTSTS_OEPINT | USB_OTG_GINTSTS_IEPINT)) { // TODO - usb_handle_endpoint_interrupt(device); + usb_handle_endpoint_int(device); return; } if (device->core->GINTSTS & (USB_OTG_GINTSTS_RXFLVL)) { // TODO - usb_handle_endpoint_interrupt(device); + usb_handle_rxflvl_int(device); return; } -- 2.48.1