summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2023-08-22 23:17:12 +0700
committerhathach <[email protected]>2023-08-22 23:17:12 +0700
commit274578ff46c31b231b3553dc9a20895646313130 (patch)
treeb28b366e8bafc79270be92af4e2031e0b6be207b /src
parentb4134394166c1f77463b5cb62f28cff465fde174 (diff)
able to send setup packet
Diffstat (limited to 'src')
-rw-r--r--src/host/hcd.h2
-rw-r--r--src/host/usbh.c32
-rw-r--r--src/portable/analog/max3421e/hcd_max3421e.c173
3 files changed, 147 insertions, 60 deletions
diff --git a/src/host/hcd.h b/src/host/hcd.h
index 1b5038ef4..079877b79 100644
--- a/src/host/hcd.h
+++ b/src/host/hcd.h
@@ -177,7 +177,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
-bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
+bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]);
// clear stall, data toggle is also reset to DATA0
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
diff --git a/src/host/usbh.c b/src/host/usbh.c
index 5423df669..7a09f5b6e 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -552,8 +552,7 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer)
}
// TODO timeout_ms is not supported yet
-bool tuh_control_xfer (tuh_xfer_t* xfer)
-{
+bool tuh_control_xfer (tuh_xfer_t* xfer) {
// EP0 with setup packet
TU_VERIFY(xfer->ep_addr == 0 && xfer->setup);
@@ -565,8 +564,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
(void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
- if (is_idle)
- {
+ if (is_idle) {
_ctrl_xfer.stage = CONTROL_STAGE_SETUP;
_ctrl_xfer.daddr = daddr;
_ctrl_xfer.actual_len = 0;
@@ -588,11 +586,9 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
TU_LOG_PTR(CFG_TUH_LOG_LEVEL, xfer->setup);
TU_LOG_USBH("\r\n");
- if (xfer->complete_cb)
- {
+ if (xfer->complete_cb) {
TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t const*) &_ctrl_xfer.request) );
- }else
- {
+ }else {
// blocking if complete callback is not provided
// change callback to internal blocking, and result as user argument
volatile xfer_result_t result = XFER_RESULT_INVALID;
@@ -656,15 +652,13 @@ static void _xfer_complete(uint8_t daddr, xfer_result_t result)
}
}
-static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
+static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) ep_addr;
const uint8_t rhport = usbh_get_rhport(dev_addr);
tusb_control_request_t const * request = &_ctrl_xfer.request;
- if (XFER_RESULT_SUCCESS != result)
- {
+ if (XFER_RESULT_SUCCESS != result) {
TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes);
#if CFG_TUSB_DEBUG == 1
TU_LOG1_PTR(request);
@@ -673,13 +667,10 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
// terminate transfer if any stage failed
_xfer_complete(dev_addr, result);
- }else
- {
- switch(_ctrl_xfer.stage)
- {
+ }else {
+ switch(_ctrl_xfer.stage) {
case CONTROL_STAGE_SETUP:
- if (request->wLength)
- {
+ if (request->wLength) {
// DATA stage: initial data toggle is always 1
_set_control_xfer_stage(CONTROL_STAGE_DATA);
TU_ASSERT( hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) );
@@ -688,8 +679,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
TU_ATTR_FALLTHROUGH;
case CONTROL_STAGE_DATA:
- if (request->wLength)
- {
+ if (request->wLength) {
TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr);
TU_LOG_MEM(CFG_TUH_LOG_LEVEL, _ctrl_xfer.buffer, xferred_bytes, 2);
}
@@ -1538,9 +1528,7 @@ static bool enum_new_device(hcd_event_t* event)
xfer.result = XFER_RESULT_SUCCESS;
xfer.user_data = ENUM_ADDR0_DEVICE_DESC;
-
process_enumeration(&xfer);
-
}
#if CFG_TUH_HUB
else
diff --git a/src/portable/analog/max3421e/hcd_max3421e.c b/src/portable/analog/max3421e/hcd_max3421e.c
index 870c616a9..c9596f695 100644
--- a/src/portable/analog/max3421e/hcd_max3421e.c
+++ b/src/portable/analog/max3421e/hcd_max3421e.c
@@ -136,30 +136,64 @@ enum {
HRSL_JSTATUS = 1u << 7,
};
+enum {
+ HRSL_SUCCESS = 0,
+ HRSL_BUSY,
+ HRSL_BAD_REQ,
+ HRSL_UNDEF,
+ HRSL_NAK,
+ HRSL_STALL,
+ HRSL_TOG_ERR,
+ HRSL_WRONG_PID,
+ HRSL_BAD_BYTECOUNT,
+ HRSL_PID_ERR,
+ HRSL_PKT_ERR,
+ HRSL_CRC_ERR,
+ HRSL_K_ERR,
+ HRSL_J_ERR,
+ HRSL_TIMEOUT,
+ HRSL_BABBLE,
+};
+
+
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
typedef struct {
+ // cached register
uint8_t mode;
+ uint8_t peraddr;
+ uint8_t hxfr;
volatile uint16_t frame_count;
+
+ struct {
+ uint16_t packet_size;
+ uint16_t total_len;
+ uint8_t xfer_type;
+ }ep[8][2];
} max2341e_data_t;
static max2341e_data_t _hcd_data;
//--------------------------------------------------------------------+
-//
+// API: SPI transfer with MAX3421E, must be implemented by application
//--------------------------------------------------------------------+
-// API: SPI transfer with MAX3421E, must be implemented by application
-bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len);
+bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len,
+ uint8_t * rx_buf, size_t rx_len, bool keep_cs);
+//void tuh_max3421e_int_enable(uint8_t rhport, bool enabled);
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
// return HIRQ register since we are in full-duplex mode
static uint8_t reg_write(uint8_t reg, uint8_t data) {
uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data};
uint8_t rx_buf[2] = {0, 0};
- tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2);
+ tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2, false);
TU_LOG2("HIRQ: %02X\r\n", rx_buf[0]);
return rx_buf[0];
}
@@ -167,7 +201,7 @@ static uint8_t reg_write(uint8_t reg, uint8_t data) {
static uint8_t reg_read(uint8_t reg) {
uint8_t tx_buf[2] = {reg, 0};
uint8_t rx_buf[2] = {0, 0};
- return tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2) ? rx_buf[1] : 0;
+ return tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2, false) ? rx_buf[1] : 0;
}
static inline uint8_t mode_write(uint8_t data) {
@@ -175,6 +209,24 @@ static inline uint8_t mode_write(uint8_t data) {
return reg_write(MODE_ADDR, data);
}
+static inline uint8_t peraddr_write(uint8_t data) {
+ if ( _hcd_data.peraddr == data ) return 0; // no need to change address
+
+ _hcd_data.peraddr = data;
+ return reg_write(PERADDR_ADDR, data);
+}
+
+static inline uint8_t hxfr_write(uint8_t data) {
+ _hcd_data.hxfr = data;
+ return reg_write(HXFR_ADDR, data);
+}
+
+static void fifo_write(uint8_t reg, uint8_t const * buffer, uint16_t len) {
+ uint8_t tx_buf[1] = {reg | CMDBYTE_WRITE};
+ tuh_max3421e_spi_xfer_api(0, tx_buf, 1, NULL, 0, true);
+ tuh_max3421e_spi_xfer_api(0, buffer, len, NULL, 0, false);
+}
+
//--------------------------------------------------------------------+
// Controller API
@@ -252,7 +304,7 @@ bool hcd_init(uint8_t rhport) {
mode_write(MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST);
// Enable Connection IRQ
- reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ);
+ reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ);
#if 0
// Note: if device is already connected, CONDET IRQ may not be triggered.
@@ -271,33 +323,6 @@ bool hcd_init(uint8_t rhport) {
return true;
}
-// Interrupt Handler
-void hcd_int_handler(uint8_t rhport) {
- (void) rhport;
-
- uint8_t hirq = reg_read(HIRQ_ADDR);
- TU_LOG3_HEX(hirq);
-
- if (hirq & HIRQ_CONDET_IRQ) {
- tusb_speed_t speed = handle_connect_irq(rhport);
-
- if (speed == TUSB_SPEED_INVALID) {
- hcd_event_device_remove(rhport, true);
- }else {
- hcd_event_device_attach(rhport, true);
- }
- }
-
- if (hirq & HIRQ_FRAME_IRQ) {
- _hcd_data.frame_count++;
- }
-
- // clear all interrupt
- if ( hirq ) {
- reg_write(HIRQ_ADDR, hirq);
- }
-}
-
// Enable USB interrupt
void hcd_int_enable (uint8_t rhport) {
(void) rhport;
@@ -359,7 +384,12 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
(void) dev_addr;
(void) ep_desc;
- return false;
+ uint8_t ep_num = tu_edpt_number(ep_desc->bEndpointAddress);
+ uint8_t ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress);
+
+ _hcd_data.ep[ep_num][ep_dir].packet_size = tu_edpt_packet_size(ep_desc);
+
+ return true;
}
// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
@@ -384,12 +414,18 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
}
// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
-bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) {
+bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]) {
(void) rhport;
- (void) dev_addr;
+ (void) daddr;
(void) setup_packet;
- return false;
+ _hcd_data.ep[0][0].total_len = 8;
+
+ peraddr_write(daddr);
+ fifo_write(SUDFIFO_ADDR, setup_packet, 8);
+ hxfr_write(HXFR_SETUP);
+
+ return true;
}
// clear stall, data toggle is also reset to DATA0
@@ -401,4 +437,67 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
return false;
}
+// Interrupt Handler
+void hcd_int_handler(uint8_t rhport) {
+ uint8_t hirq = reg_read(HIRQ_ADDR);
+ TU_LOG3_HEX(hirq);
+
+ if (hirq & HIRQ_CONDET_IRQ) {
+ tusb_speed_t speed = handle_connect_irq(rhport);
+
+ if (speed == TUSB_SPEED_INVALID) {
+ hcd_event_device_remove(rhport, true);
+ }else {
+ hcd_event_device_attach(rhport, true);
+ }
+ }
+
+ if (hirq & HIRQ_FRAME_IRQ) {
+ _hcd_data.frame_count++;
+ }
+
+ if (hirq & HIRQ_HXFRDN_IRQ) {
+ uint8_t const hrsl = reg_read(HRSL_ADDR);
+ uint8_t const result = hrsl & HRSL_RESULT_MASK;
+ uint8_t xfer_result;
+
+ TU_LOG3("HRSL: %02X\r\n", hrsl);
+ switch(result) {
+ case HRSL_SUCCESS:
+ xfer_result = XFER_RESULT_SUCCESS;
+ break;
+
+ case HRSL_STALL:
+ xfer_result = XFER_RESULT_STALLED;
+ break;
+
+ default:
+ xfer_result = XFER_RESULT_FAILED;
+ break;
+ }
+
+ uint8_t ep_dir = 0;
+ uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK;
+ uint8_t const xfer_type = _hcd_data.hxfr & 0xf0;
+
+ if ( xfer_type & HXFR_SETUP ) {
+ // SETUP transfer
+ ep_dir = 0;
+ }else if ( !(xfer_type & HXFR_OUT_NIN) ) {
+ // IN transfer
+ ep_dir = 1;
+ }
+
+ uint8_t const ep_addr = tu_edpt_addr(ep_num, ep_dir);
+ uint16_t xferred_len = _hcd_data.ep[ep_num][ep_dir].total_len;
+
+ hcd_event_xfer_complete(_hcd_data.peraddr, ep_addr, xferred_len, xfer_result, true);
+ }
+
+ // clear all interrupt
+ if ( hirq ) {
+ reg_write(HIRQ_ADDR, hirq);
+ }
+}
+
#endif