aboutsummaryrefslogtreecommitdiff
path: root/src/usb/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usb/utils.c')
-rw-r--r--src/usb/utils.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/usb/utils.c b/src/usb/utils.c
new file mode 100644
index 0000000..5c6a83e
--- /dev/null
+++ b/src/usb/utils.c
@@ -0,0 +1,130 @@
+#include "CH58x_common.h"
+
+#include "utils.h"
+#include "debug.h"
+
+// A response a has been set, if not, that transaction is not handled
+int res_sent;
+
+static uint8_t *current_IN_buf;
+
+static volatile uint8_t *len_regs[] = {
+ &R8_UEP0_T_LEN,
+ &R8_UEP1_T_LEN,
+ &R8_UEP2_T_LEN,
+ &R8_UEP3_T_LEN,
+ &R8_UEP4_T_LEN,
+ &R8_UEP5_T_LEN,
+ &R8_UEP6_T_LEN,
+ &R8_UEP7_T_LEN
+};
+static volatile uint8_t *ctrl_regs[] = {
+ &R8_UEP0_CTRL,
+ &R8_UEP1_CTRL,
+ &R8_UEP2_CTRL,
+ &R8_UEP3_CTRL,
+ &R8_UEP4_CTRL,
+ &R8_UEP5_CTRL,
+ &R8_UEP6_CTRL,
+ &R8_UEP7_CTRL
+};
+
+static void __handshake(uint8_t ep_num, int dir, int type, int tog, uint8_t len)
+{
+ _TRACE();
+ if (ep_num > 7)
+ return;
+
+ char *type_mean[] = { "ACK", "NO_RESP", "NAK", "STALL"};
+ PRINT("Loaded %d byte, DATA%d with an %s to EP%dIN.\n",
+ len, tog != 0, type_mean[type], ep_num);
+
+ uint8_t ctrl = type << (dir ? 0 : 2);
+ ctrl |= (tog) ? RB_UEP_T_TOG : RB_UEP_R_TOG;
+
+ res_sent = 1;
+ *len_regs[ep_num] = len;
+ *ctrl_regs[ep_num] = ctrl;
+}
+
+void set_handshake(uint8_t ep_num, int type, int tog, uint8_t len)
+{
+ _TRACE();
+ __handshake(ep_num, 1, type, tog, len);
+}
+
+void ctrl_ack()
+{
+ _TRACE();
+ set_handshake(0, USB_ACK, 1, 0);
+}
+
+void clear_handshake_sent_flag()
+{
+ res_sent = 0;
+}
+
+int handshake_sent()
+{
+ return res_sent;
+}
+
+static uint8_t *p_buf;
+static uint16_t remain_len, req_len, _tog;
+
+static uint16_t
+load_chunk(void *ep_buf, void *block, uint16_t block_len, uint16_t req_len,
+ int tog)
+{
+ _TRACE();
+ uint16_t remain_len = 0;
+
+ if (req_len > MAX_PACKET_SIZE)
+ req_len = MAX_PACKET_SIZE;
+
+ if (block_len >= req_len) {
+ remain_len = block_len - req_len;
+ block_len = req_len;
+ }
+ p_buf = block;
+
+ memcpy(ep_buf, p_buf, block_len);
+ p_buf += block_len;
+
+ set_handshake(0, USB_ACK, tog, block_len);
+
+ PRINT("remain_len: %d\n", remain_len);
+ return remain_len;
+}
+
+void usb_flush()
+{
+ _TRACE();
+ remain_len = 0;
+ _tog = 0;
+}
+
+int usb_load_next_chunk()
+{
+ _TRACE();
+ if (remain_len) {
+ remain_len = load_chunk(current_IN_buf, p_buf, remain_len, req_len,
+ _tog);
+ _tog = !_tog;
+ } else {
+ _tog = 0;
+ return -1;
+ }
+ return remain_len;
+}
+
+uint16_t
+usb_start_load_block(void *ep_IN_buf, void *buf, uint16_t len, int tog)
+{
+ _TRACE();
+ req_len = len;
+ current_IN_buf = ep_IN_buf;
+ remain_len = load_chunk(ep_IN_buf, buf, len, len, tog);
+ _tog = !tog;
+ return remain_len;
+}