Change in simtrace2[master]: firmware: More common infrastructure for USB handling

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.org
Sat Jan 11 16:56:22 UTC 2020


laforge 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>


More information about the gerrit-log mailing list