summaryrefslogtreecommitdiff
path: root/openpcd/firmware/src/usb_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'openpcd/firmware/src/usb_handler.c')
-rw-r--r--openpcd/firmware/src/usb_handler.c129
1 files changed, 20 insertions, 109 deletions
diff --git a/openpcd/firmware/src/usb_handler.c b/openpcd/firmware/src/usb_handler.c
index bb5f5d4..4252369 100644
--- a/openpcd/firmware/src/usb_handler.c
+++ b/openpcd/firmware/src/usb_handler.c
@@ -9,132 +9,43 @@
#include <openpcd.h>
#include "pcd_enumerate.h"
+#include "usb_handler.h"
#include "openpcd.h"
#include "rc632.h"
#include "led.h"
#include "dbgu.h"
-#define MAX_PAYLOAD_LEN (64 - sizeof(struct openpcd_hdr))
+static usb_cmd_fn *cmd_hdlrs[16];
+
+int usb_hdlr_register(usb_cmd_fn *hdlr, u_int8_t class)
+{
+ cmd_hdlrs[class] = hdlr;
+}
+
+void usb_hdlr_unregister(u_int8_t class)
+{
+ cmd_hdlrs[class] = NULL;
+}
static int usb_in(struct req_ctx *rctx)
{
struct openpcd_hdr *poh = (struct openpcd_hdr *) &rctx->rx.data[0];
struct openpcd_hdr *pih = (struct openpcd_hdr *) &rctx->tx.data[0];
- u_int16_t len = rctx->rx.tot_len;
+ usb_cmd_fn *hdlr;
- DEBUGP("usb_in ");
+ DEBUGP("usb_in(cls=%d) ", OPENPCD_CMD_CLS(poh->cmd));
- if (len < sizeof(*poh))
+ if (rctx->rx.tot_len < sizeof(*poh))
return -EINVAL;
- len -= sizeof(*poh);
-
memcpy(pih, poh, sizeof(*poh));
rctx->tx.tot_len = sizeof(*poh);
- switch (poh->cmd) {
- case OPENPCD_CMD_READ_REG:
- rc632_reg_read(RAH, poh->reg, &pih->val);
- DEBUGP("READ REG(0x%02x)=0x%02x ", poh->reg, pih->val);
- goto respond;
- break;
- case OPENPCD_CMD_READ_FIFO:
- {
- u_int16_t req_len = poh->val, remain_len, pih_len;
- if (req_len > MAX_PAYLOAD_LEN) {
- pih_len = MAX_PAYLOAD_LEN;
- remain_len -= pih_len;
- rc632_fifo_read(RAH, pih_len, pih->data);
- rctx->tx.tot_len += pih_len;
- DEBUGP("READ FIFO(len=%u)=%s ", req_len,
- hexdump(pih->data, pih_len));
- req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
- udp_refill_ep(2, rctx);
-
- /* get and initialize second rctx */
- rctx = req_ctx_find_get(RCTX_STATE_FREE,
- RCTX_STATE_MAIN_PROCESSING);
- if (!rctx) {
- DEBUGPCRF("FATAL_NO_RCTX!!!\n");
- break;
- }
- poh = (struct openpcd_hdr *) &rctx->rx.data[0];
- pih = (struct openpcd_hdr *) &rctx->tx.data[0];
- memcpy(pih, poh, sizeof(*poh));
- rctx->tx.tot_len = sizeof(*poh);
-
- pih_len = remain_len;
- rc632_fifo_read(RAH, pih_len, pih->data);
- rctx->tx.tot_len += pih_len;
- DEBUGP("READ FIFO(len=%u)=%s ", pih_len,
- hexdump(pih->data, pih_lenl));
- /* don't set state of second rctx, main function
- * body will do this after switch statement */
- } else {
- pih_len = poh->val;
- rc632_fifo_read(RAH, poh->val, pih->data);
- rctx->tx.tot_len += pih_len;
- DEBUGP("READ FIFO(len=%u)=%s ", poh->val,
- hexdump(pih->data, poh->val));
- }
- goto respond;
- break;
- }
- case OPENPCD_CMD_WRITE_REG:
- DEBUGP("WRITE_REG(0x%02x, 0x%02x) ", poh->reg, poh->val);
- rc632_reg_write(RAH, poh->reg, poh->val);
- break;
- case OPENPCD_CMD_WRITE_FIFO:
- DEBUGP("WRITE FIFO(len=%d) ", len);
- if (len <= 0)
- return -EINVAL;
- rc632_fifo_write(RAH, len, poh->data, 0);
- break;
- case OPENPCD_CMD_READ_VFIFO:
- DEBUGP("READ VFIFO ");
- DEBUGP("NOT IMPLEMENTED YET ");
- goto respond;
- break;
- case OPENPCD_CMD_WRITE_VFIFO:
- DEBUGP("WRITE VFIFO(len=%d) ", len);
- if (len <= 0)
- return -EINVAL;
- DEBUGP("NOT IMPLEMENTED YET ");
- break;
- case OPENPCD_CMD_REG_BITS_CLEAR:
- DEBUGP("CLEAR BITS ");
- pih->val = rc632_clear_bits(RAH, poh->reg, poh->val);
- break;
- case OPENPCD_CMD_REG_BITS_SET:
- DEBUGP("SET BITS ");
- pih->val = rc632_set_bits(RAH, poh->reg, poh->val);
- break;
- case OPENPCD_CMD_SET_LED:
- DEBUGP("SET LED(%u,%u) ", poh->reg, poh->val);
- led_switch(poh->reg, poh->val);
- break;
- case OPENPCD_CMD_DUMP_REGS:
- DEBUGP("DUMP REGS ");
- DEBUGP("NOT IMPLEMENTED YET ");
- goto respond;
- break;
- default:
- /* FIXME: add a method how other firmware modules can
- * register callback functions for additional commands */
- DEBUGP("UNKNOWN ");
- return -EINVAL;
- break;
- }
- req_ctx_put(rctx);
- return 0;
-
-respond:
- req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING);
- /* FIXME: we could try to send this immediately */
- udp_refill_ep(2, rctx);
- DEBUGPCR("");
-
- return 1;
+ hdlr = cmd_hdlrs[OPENPCD_CMD_CLS(poh->cmd)];
+ if (hdlr)
+ return (hdlr)(rctx);
+ else
+ DEBUGPCR("no handler for this class\n");
}
void usb_out_process(void)
personal git repositories of Harald Welte. Your mileage may vary