From d256545b2fd62d78910efcc6273c3b70abd3aa13 Mon Sep 17 00:00:00 2001 From: laforge Date: Tue, 12 Sep 2006 17:35:30 +0000 Subject: move to new directory git-svn-id: https://svn.openpcd.org:2342/trunk@191 6dc7ffe9-61d6-0310-9af1-9938baff3ed1 --- firmware/src/os/usb_handler.c | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 firmware/src/os/usb_handler.c (limited to 'firmware/src/os/usb_handler.c') diff --git a/firmware/src/os/usb_handler.c b/firmware/src/os/usb_handler.c new file mode 100644 index 0000000..274353c --- /dev/null +++ b/firmware/src/os/usb_handler.c @@ -0,0 +1,88 @@ +/* OpenPCD USB handler - handle incoming USB requests on OUT pipe + * (C) 2006 by Harald Welte + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "../openpcd.h" + +static usb_cmd_fn *cmd_hdlrs[16]; + +int usb_hdlr_register(usb_cmd_fn *hdlr, u_int8_t class) +{ + cmd_hdlrs[class] = hdlr; + return 0; +} + +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]; + usb_cmd_fn *hdlr; + + DEBUGP("usb_in(cls=%d) ", OPENPCD_CMD_CLS(poh->cmd)); + + if (rctx->rx.tot_len < sizeof(*poh)) + return -EINVAL; + + memcpy(pih, poh, sizeof(*poh)); + rctx->tx.tot_len = sizeof(*poh); + + hdlr = cmd_hdlrs[OPENPCD_CMD_CLS(poh->cmd)]; + if (hdlr) + return (hdlr)(rctx); + else + DEBUGPCR("no handler for this class\n"); +} + +/* Process all pending request contexts that want to Tx on either + * IN or INTERRUPT endpoint */ +void usb_out_process(void) +{ + struct req_ctx *rctx; + + while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP3_PENDING, + RCTX_STATE_UDP_EP3_BUSY)) { + DEBUGPCRF("EP3_BUSY for ctx %u", req_ctx_num(rctx)); + if (udp_refill_ep(3, rctx) < 0) + req_ctx_set_state(rctx, RCTX_STATE_UDP_EP3_PENDING); + } + + while (rctx = req_ctx_find_get(RCTX_STATE_UDP_EP2_PENDING, + RCTX_STATE_UDP_EP2_BUSY)) { + DEBUGPCRF("EP2_BUSY for ctx %u", req_ctx_num(rctx)); + if (udp_refill_ep(2, rctx) < 0) + req_ctx_set_state(rctx, RCTX_STATE_UDP_EP2_PENDING); + } +} + +/* process incoming USB packets (OUT pipe) that have already been + * put into request contexts by the UDP IRQ handler */ +void usb_in_process(void) +{ + struct req_ctx *rctx; + + while (rctx = req_ctx_find_get(RCTX_STATE_UDP_RCV_DONE, + RCTX_STATE_MAIN_PROCESSING)) { + DEBUGPCRF("found used ctx %u: len=%u", + req_ctx_num(rctx), rctx->rx.tot_len); + usb_in(rctx); + } + udp_unthrottle(); +} + -- cgit v1.2.3