This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
laforge gerrit-no-reply at lists.osmocom.orglaforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/simtrace2/+/16804 ) Change subject: firmware: More common infrastructure for USB handling ...................................................................... firmware: More common infrastructure for USB handling Let's move low-level handling of endpoint queue refill from the individual apps into common/shared code. Now the main simply has to call usb_process() for every interface, and inbound messages will be dispatched to call-back functions from there. Change-Id: Ic6f9c6c1ffdbb0c9c3b284371ecc83b17e3be746 --- M firmware/apps/cardem/main.c M firmware/libcommon/include/usb_buf.h M firmware/libcommon/source/host_communication.c M firmware/libcommon/source/mode_cardemu.c M firmware/libcommon/source/sniffer.c 5 files changed, 109 insertions(+), 63 deletions(-) git pull ssh://gerrit.osmocom.org:29418/simtrace2 refs/changes/04/16804/1 diff --git a/firmware/apps/cardem/main.c b/firmware/apps/cardem/main.c index 3476af2..3170a9e 100644 --- a/firmware/apps/cardem/main.c +++ b/firmware/apps/cardem/main.c @@ -220,6 +220,7 @@ } last_simtrace_config = simtrace_config; } else { + //FIXME: usb_proces() for every interface in this configuration? if (config_func_ptrs[simtrace_config].run) { config_func_ptrs[simtrace_config].run(); } diff --git a/firmware/libcommon/include/usb_buf.h b/firmware/libcommon/include/usb_buf.h index 3a4eda2..4c795a8 100644 --- a/firmware/libcommon/include/usb_buf.h +++ b/firmware/libcommon/include/usb_buf.h @@ -42,5 +42,15 @@ void usb_buf_init(void); struct usb_buffered_ep *usb_get_buf_ep(uint8_t ep); -int usb_refill_to_host(uint8_t ep); -int usb_refill_from_host(uint8_t ep); +struct usb_if { + uint8_t if_num; /* interface number */ + uint8_t ep_out; /* OUT endpoint (0 if none) */ + uint8_t ep_in; /* IN endpint (0 if none) */ + uint8_t ep_int; /* INT endpoint (0 if none) */ + void *data; /* opaque data, passed through */ + struct { + /* call-back to be called for inclming messages on OUT EP */ + void (*rx_out)(struct msgb *msg, const struct usb_if *usb_if); + } ops; +}; +void usb_process(const struct usb_if *usb_if); diff --git a/firmware/libcommon/source/host_communication.c b/firmware/libcommon/source/host_communication.c index 9a6e5b3..e367b37 100644 --- a/firmware/libcommon/source/host_communication.c +++ b/firmware/libcommon/source/host_communication.c @@ -57,7 +57,7 @@ } /* check if the spcified IN endpoint is idle and submit the next buffer from queue */ -int usb_refill_to_host(uint8_t ep) +static int usb_refill_to_host(uint8_t ep) { struct usb_buffered_ep *bep = usb_get_buf_ep(ep); struct msgb *msg; @@ -130,7 +130,7 @@ } /* refill the read queue for data received from host PC on OUT EP, if needed */ -int usb_refill_from_host(uint8_t ep) +static int usb_refill_from_host(uint8_t ep) { struct usb_buffered_ep *bep = usb_get_buf_ep(ep); struct msgb *msg; @@ -198,3 +198,45 @@ return ret; } + + + +/* iterate over the queue of incoming USB commands and dispatch/execute + * them */ +static void process_any_usb_commands(const struct usb_if *usb_if) +{ + struct llist_head *queue = usb_get_queue(usb_if->ep_out); + struct llist_head *lh; + struct msgb *msg; + int i; + + /* limit the number of iterations to 10, to ensure we don't get + * stuck here without returning to main loop processing */ + for (i = 0; i < 10; i++) { + /* de-queue the list head in an irq-safe way */ + lh = llist_head_dequeue_irqsafe(queue); + if (!lh) + break; + msg = llist_entry(lh, struct msgb, list); + usb_if->ops.rx_out(msg, usb_if); + } +} + +/* perform any action related to USB processing (IRQ/INT/OUT EP refill, handling OUT) */ +void usb_process(const struct usb_if *usb_if) +{ + /* first try to send any pending messages on IRQ */ + if (usb_if->ep_int) + usb_refill_to_host(usb_if->ep_int); + + /* then try to send any pending messages on IN */ + if (usb_if->ep_in) + usb_refill_to_host(usb_if->ep_in); + + /* ensure we can handle incoming USB messages from the + * host */ + if (usb_if->ep_out) { + usb_refill_from_host(usb_if->ep_out); + process_any_usb_commands(usb_if); + } +} diff --git a/firmware/libcommon/source/mode_cardemu.c b/firmware/libcommon/source/mode_cardemu.c index c5c173f..cab3cdf 100644 --- a/firmware/libcommon/source/mode_cardemu.c +++ b/firmware/libcommon/source/mode_cardemu.c @@ -34,6 +34,8 @@ #define TRACE_ENTRY() TRACE_DEBUG("%s entering\r\n", __func__) +static void dispatch_received_usb_msg(struct msgb *msg, const struct usb_if *usb_if); + #ifdef PINS_CARDSIM static const Pin pins_cardsim[] = PINS_CARDSIM; #endif @@ -56,9 +58,7 @@ struct ringbuf rb; struct Usart_info usart_info; int usb_pending_old; - uint8_t ep_out; - uint8_t ep_in; - uint8_t ep_int; + struct usb_if usb_if; const Pin pin_insert; #ifdef DETECT_VCC_BY_ADC uint32_t vcc_uv; @@ -77,9 +77,16 @@ .id = ID_USART1, .state = USART_RCV }, - .ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT, - .ep_in = SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN, - .ep_int = SIMTRACE_CARDEM_USB_EP_USIM1_INT, + .usb_if = { + .if_num = 0, + .ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT, + .ep_in = SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN, + .ep_int = SIMTRACE_CARDEM_USB_EP_USIM1_INT, + .data = &cardem_inst[0], + .ops = { + .rx_out = dispatch_received_usb_msg, + }, + }, #ifdef PIN_SET_USIM1_PRES .pin_insert = PIN_SET_USIM1_PRES, #endif @@ -92,9 +99,16 @@ .id = ID_USART0, .state = USART_RCV }, - .ep_out = SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT, - .ep_in = SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN, - .ep_int = SIMTRACE_CARDEM_USB_EP_USIM2_INT, + .usb_if = { + .if_num = 1, + .ep_out = SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT, + .ep_in = SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN, + .ep_int = SIMTRACE_CARDEM_USB_EP_USIM2_INT, + .data = &cardem_inst[1], + .ops = { + .rx_out = dispatch_received_usb_msg, + }, + } #ifdef PIN_SET_USIM2_PRES .pin_insert = PIN_SET_USIM2_PRES, #endif @@ -621,8 +635,9 @@ } /* handle a single USB command as received from the USB host */ -static void dispatch_usb_command(struct msgb *msg, struct cardem_inst *ci) +static void dispatch_usb_command(struct msgb *msg, const struct usb_if *usb_if) { + struct cardem_inst *ci = usb_if->data; struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *) msg->l1h; if (msgb_length(msg) < sizeof(*sh)) { @@ -651,7 +666,8 @@ } } -static void dispatch_received_msg(struct msgb *msg, struct cardem_inst *ci) +/* handle a single USB transfer as received from the USB host */ +static void dispatch_received_usb_msg(struct msgb *msg, const struct usb_if *usb_if) { struct msgb *segm; struct simtrace_msg_hdr *mh; @@ -662,7 +678,7 @@ mh = (struct simtrace_msg_hdr *) msg->data; if (mh->msg_len == msgb_length(msg)) { /* fast path: only one message in buffer */ - dispatch_usb_command(msg, ci); + dispatch_usb_command(msg, usb_if); return; } @@ -671,22 +687,22 @@ while (1) { mh = (struct simtrace_msg_hdr *) msg->data; - segm = usb_buf_alloc(ci->ep_out); + segm = usb_buf_alloc(usb_if->ep_out); if (!segm) { TRACE_ERROR("%u: ENOMEM during msg segmentation\r\n", - ci->num); + usb_if->if_num); break; } if (mh->msg_len > msgb_length(msg)) { TRACE_ERROR("%u: Unexpected large message (%u bytes)\n", - ci->num, mh->msg_len); + usb_if->if_num, mh->msg_len); usb_buf_free(segm); } else { uint8_t *cur = msgb_put(segm, mh->msg_len); segm->l1h = segm->head; memcpy(cur, mh, mh->msg_len); - dispatch_usb_command(segm, ci); + dispatch_usb_command(segm, usb_if); } /* pull this message */ msgb_pull(msg, mh->msg_len); @@ -698,35 +714,14 @@ usb_buf_free(msg); } -/* iterate over the queue of incoming USB commands and dispatch/execute - * them */ -static void process_any_usb_commands(struct llist_head *main_q, - struct cardem_inst *ci) -{ - struct llist_head *lh; - struct msgb *msg; - int i; - - /* limit the number of iterations to 10, to ensure we don't get - * stuck here without returning to main loop processing */ - for (i = 0; i < 10; i++) { - /* de-queue the list head in an irq-safe way */ - lh = llist_head_dequeue_irqsafe(main_q); - if (!lh) - break; - msg = llist_entry(lh, struct msgb, list); - dispatch_received_msg(msg, ci); - } -} - /* main loop function, called repeatedly */ void mode_cardemu_run(void) { - struct llist_head *queue; unsigned int i; for (i = 0; i < ARRAY_SIZE(cardem_inst); i++) { struct cardem_inst *ci = &cardem_inst[i]; + struct usb_if *usb_if = &ci->usb_if; /* drain the ring buffer from UART into card_emu */ while (1) { @@ -743,16 +738,6 @@ process_io_statechg(ci); - /* first try to send any pending messages on IRQ */ - usb_refill_to_host(ci->ep_int); - - /* then try to send any pending messages on IN */ - usb_refill_to_host(ci->ep_in); - - /* ensure we can handle incoming USB messages from the - * host */ - usb_refill_from_host(ci->ep_out); - queue = usb_get_queue(ci->ep_out); - process_any_usb_commands(queue, ci); + usb_process(&ci->usb_if); } } diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c index 08770e2..78413ec 100644 --- a/firmware/libcommon/source/sniffer.c +++ b/firmware/libcommon/source/sniffer.c @@ -974,20 +974,28 @@ usb_msg_upd_len_and_submit(usb_msg); } +/* handle incoming message from USB OUT EP */ +static void dispatch_usb_out(struct msgb *msg, const struct usb_if *usb_if) +{ + /* currently we don't need any incoming data */ + msgb_free(msg); +} + +static const struct usb_if sniffer_usb_if = { + .if_num = 0, + .ep_in = SIMTRACE_USB_EP_CARD_DATAIN, + .ep_int = SIMTRACE_USB_EP_CARD_INT, + .ep_out = SIMTRACE_USB_EP_CARD_DATAOUT, + .ops = { + .rx_out = dispatch_usb_out, + } +}; + /* Main (idle/busy) loop of this USB configuration */ void Sniffer_run(void) { /* Handle USB queue */ - /* first try to send any pending messages on INT */ - usb_refill_to_host(SIMTRACE_USB_EP_CARD_INT); - /* then try to send any pending messages on IN */ - usb_refill_to_host(SIMTRACE_USB_EP_CARD_DATAIN); - /* ensure we can handle incoming USB messages from the host */ - /* currently we don't need any incoming data - usb_refill_from_host(SIMTRACE_USB_EP_CARD_DATAOUT); - struct llist_head *queue = usb_get_queue(SIMTRACE_USB_EP_CARD_DATAOUT); - process_any_usb_commands(queue); - */ + usb_process(&sniffer_usb_if); /* WARNING: the signal data and flags are not synchronized. We have to hope * the processing is fast enough to not land in the wrong state while data -- To view, visit https://gerrit.osmocom.org/c/simtrace2/+/16804 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: simtrace2 Gerrit-Branch: master Gerrit-Change-Id: Ic6f9c6c1ffdbb0c9c3b284371ecc83b17e3be746 Gerrit-Change-Number: 16804 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge at osmocom.org> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200111/8a479858/attachment.htm>