Change in simtrace2[master]: card_emu: Use USART timeout for waiting time

laforge gerrit-no-reply at lists.osmocom.org
Thu Apr 8 21:28:42 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/simtrace2/+/23620 )

Change subject: card_emu: Use USART timeout for waiting time
......................................................................

card_emu: Use USART timeout for waiting time

Instead of using the timer/counter peripheral to handle the waiting time
and corresponding timeout, the USART peripheral internal timeout
mechanism is used.

This is particularly important for the SIMtrace board since there
(contrary to other boards) the I/O signal is not wired to a TIO pin
of the timer/counter block, and hence Rx/Tx data cannot reset that
timer/counter.

As a result of this migration, cardem is now supported not only on
owhw + qmod, but also on the simtrace board.

The guts of this change have been lifted out of Change-Id
Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5 by Kevin Redon, which was
unfortunately touching various different topics at the same time and
hence was split up. Some improvements are the introduction of the
ENABLE_TX_TIMER_ONLY mode, which avoids the USART interrupt handler
getting hammered with TXRDY between release of RST and start of the ATR.

Change-Id: Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5
Related: OS#1704
---
M firmware/apps/cardem/Makefile
M firmware/apps/trace/Makefile
M firmware/apps/triple_play/Makefile
M firmware/libcommon/include/card_emu.h
M firmware/libcommon/source/card_emu.c
M firmware/libcommon/source/mode_cardemu.c
M firmware/test/card_emu_tests.c
7 files changed, 141 insertions(+), 53 deletions(-)

Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/firmware/apps/cardem/Makefile b/firmware/apps/cardem/Makefile
index 75c43e8..c0d903f 100644
--- a/firmware/apps/cardem/Makefile
+++ b/firmware/apps/cardem/Makefile
@@ -1,3 +1,3 @@
 C_FILES += $(C_LIBUSB_RT)
 
-C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
+C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c
diff --git a/firmware/apps/trace/Makefile b/firmware/apps/trace/Makefile
index 75c43e8..c0d903f 100644
--- a/firmware/apps/trace/Makefile
+++ b/firmware/apps/trace/Makefile
@@ -1,3 +1,3 @@
 C_FILES += $(C_LIBUSB_RT)
 
-C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
+C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c
diff --git a/firmware/apps/triple_play/Makefile b/firmware/apps/triple_play/Makefile
index df89448..be06c11 100644
--- a/firmware/apps/triple_play/Makefile
+++ b/firmware/apps/triple_play/Makefile
@@ -1,3 +1,3 @@
 C_FILES += $(C_LIBUSB_RT)
 
-C_FILES += card_emu.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
+C_FILES += card_emu.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c
diff --git a/firmware/libcommon/include/card_emu.h b/firmware/libcommon/include/card_emu.h
index 8a73d5c..58e24cd 100644
--- a/firmware/libcommon/include/card_emu.h
+++ b/firmware/libcommon/include/card_emu.h
@@ -31,7 +31,6 @@
 
 /** initialise card slot
  *  @param[in] slot_num slot number (arbitrary number)
- *  @param[in] tc_chan timer counter channel (to measure the ETU)
  *  @param[in] uart_chan UART peripheral channel
  *  @param[in] in_ep USB IN end point number
  *  @param[in] irq_ep USB INTerrupt end point number
@@ -40,7 +39,7 @@
  *  @param[in] clocked initial CLK signat state (true = active)
  *  @return main card handle reference
  */
-struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked);
+struct card_handle *card_emu_init(uint8_t slot_num, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked);
 
 /* process a single byte received from the reader */
 void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte);
@@ -58,10 +57,17 @@
 void card_emu_have_new_uart_tx(struct card_handle *ch);
 void card_emu_report_status(struct card_handle *ch, bool report_on_irq);
 
-#define ENABLE_TX	0x01
-#define ENABLE_RX	0x02
+void card_emu_wtime_half_expired(void *ch);
+void card_emu_wtime_expired(void *ch);
+
+
+#define ENABLE_TX		0x01
+#define ENABLE_RX		0x02
+#define ENABLE_TX_TIMER_ONLY	0x03
 
 int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi);
+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt);
+void card_emu_uart_reset_wt(uint8_t uart_chan);
 int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte);
 void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx);
 void card_emu_uart_wait_tx_idle(uint8_t uart_chan);
diff --git a/firmware/libcommon/source/card_emu.c b/firmware/libcommon/source/card_emu.c
index 0ba6eb0..cefc957 100644
--- a/firmware/libcommon/source/card_emu.c
+++ b/firmware/libcommon/source/card_emu.c
@@ -27,7 +27,6 @@
 #include "utils.h"
 #include "trace.h"
 #include "iso7816_fidi.h"
-#include "tc_etu.h"
 #include "card_emu.h"
 #include "simtrace_prot.h"
 #include "usb_buf.h"
@@ -177,7 +176,6 @@
 	 *  \note this depends on Fi, Di, and WI if T=0 is used */
 	uint32_t waiting_time;	/* in etu */
 
-	uint8_t tc_chan;	/* TC channel number */
 	uint8_t uart_chan;	/* UART channel */
 
 	uint8_t in_ep;		/* USB IN EP */
@@ -222,7 +220,7 @@
 {
 	struct msgb *msg;
 
-	tc_etu_disable(ch->tc_chan);
+	card_emu_uart_update_wt(ch->uart_chan, 0);
 
 	/* release any buffers we may still own */
 	if (ch->uart_tx_msg) {
@@ -383,8 +381,6 @@
 			   ch->F_index, ch->D_index, rc);
 		/* make sure UART uses new F/D ratio */
 		card_emu_uart_update_fidi(ch->uart_chan, rc);
-		/* notify ETU timer about this */
-		tc_etu_set_etu(ch->tc_chan, rc);
 	} else
 		TRACE_INFO("%u: computed F/D ratio %d unsupported\r\n",
 			   ch->num, rc);
@@ -408,6 +404,8 @@
 	case ISO_S_WAIT_RST:
 		/* disable Rx and Tx of UART */
 		card_emu_uart_enable(ch->uart_chan, 0);
+		/* disable timeout */
+		card_emu_uart_update_wt(ch->uart_chan, 0);
 		break;
 	case ISO_S_WAIT_ATR:
 		/* Reset to initial Fi / Di ratio */
@@ -416,13 +414,13 @@
 		ch->wi = ISO7816_3_DEFAULT_WI;
 		ch->waiting_time = ISO7816_3_INIT_WTIME;
 		emu_update_fidi(ch);
+		/* enable TX to be able to use the timeout */
+		card_emu_uart_enable(ch->uart_chan, ENABLE_TX_TIMER_ONLY);
 		/* the ATR should only be sent 400 to 40k clock cycles after the RESET.
-		 * we use the tc_etu mechanism to wait this time.
+		 * we use the UART timeout mechanism to wait this time.
 		 * since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.
 		 */
-		tc_etu_set_wtime(ch->tc_chan, 2);
-		/* enable the TC/ETU counter once reset has been released */
-		tc_etu_enable(ch->tc_chan);
+		card_emu_uart_update_wt(ch->uart_chan, 2);
 		break;
 	case ISO_S_IN_ATR:
 		/* initialize to default WI, this will be overwritten if we
@@ -432,7 +430,7 @@
 		/* update waiting time to initial waiting time */
 		ch->waiting_time = ISO7816_3_INIT_WTIME;
 		/* set initial waiting time */
-		tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
+		card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
 		/* Set ATR sub-state to initial state */
 		ch->atr.idx = 0;
 		/* enable USART transmission to reader */
@@ -509,7 +507,6 @@
 		}
 		/* update waiting time (see ISO 7816-3 10.2) */
 		ch->waiting_time = ch->wi * 960 * iso7816_3_fi_table[ch->F_index];
-		tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
 		/* go to next state */
 		card_set_state(ch, ISO_S_WAIT_TPDU);
 		return 0;
@@ -677,6 +674,7 @@
 		emu_update_fidi(ch);
 		/* Wait for the next TPDU */
 		card_set_state(ch, ISO_S_WAIT_TPDU);
+		set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
 		break;
 	default:
 		/* calculate the next state and set it */
@@ -752,14 +750,28 @@
 
 	switch (new_ts) {
 	case TPDU_S_WAIT_CLA:
-	case TPDU_S_WAIT_RX:
+		/* switch back to receiving mode */
 		card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
+		/* disable waiting time since we don't expect any data */
+		card_emu_uart_update_wt(ch->uart_chan, 0);
+		break;
+	case TPDU_S_WAIT_INS:
+		/* start waiting for the rest of the header/body */
+		card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
+		break;
+	case TPDU_S_WAIT_RX:
+		/* switch to receive mode to receive the body */
+		card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
+		/* start waiting for the body */
+		card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
 		break;
 	case TPDU_S_WAIT_PB:
 		/* we just completed the TPDU header from reader to card
 		 * and now need to disable the receiver, enable the
 		 * transmitter and transmit the procedure byte */
 		card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
+		/* prepare to extend the waiting time once half of it is reached */
+		card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
 		break;
 	default:
 		break;
@@ -1103,8 +1115,6 @@
 		if (active == 0 && ch->in_reset) {
 			TRACE_INFO("%u: RST released\r\n", ch->num);
 			if (ch->vcc_active && ch->clocked && ch->state == ISO_S_WAIT_RST) {
-				/* enable the TC/ETU counter once reset has been released */
-				tc_etu_enable(ch->tc_chan);
 				/* prepare to send the ATR */
 				card_set_state(ch, ISO_S_WAIT_ATR);
 			}
@@ -1163,7 +1173,7 @@
 }
 
 /* hardware driver informs us that one (more) ETU has expired */
-void tc_etu_wtime_half_expired(void *handle)
+void card_emu_wtime_half_expired(void *handle)
 {
 	struct card_handle *ch = handle;
 	/* transmit NULL procedure byte well before waiting time expires */
@@ -1173,7 +1183,10 @@
 		case TPDU_S_WAIT_PB:
 		case TPDU_S_WAIT_TX:
 			putchar('N');
+			/* we are waiting for data from the user. Send a procedure byte to ask the
+			 * reader to wait more time */
 			card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL);
+			card_emu_uart_reset_wt(ch->uart_chan);
 			break;
 		default:
 			break;
@@ -1185,7 +1198,7 @@
 }
 
 /* hardware driver informs us that one (more) ETU has expired */
-void tc_etu_wtime_expired(void *handle)
+void card_emu_wtime_expired(void *handle)
 {
 	struct card_handle *ch = handle;
 	switch (ch->state) {
@@ -1231,7 +1244,7 @@
 	return 0;
 }
 
-struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked)
+struct card_handle *card_emu_init(uint8_t slot_num, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked)
 {
 	struct card_handle *ch;
 
@@ -1256,7 +1269,6 @@
 	ch->Di_index = ch->D_index = 1;
 	ch->wi = ISO7816_3_DEFAULT_WI;
 
-	ch->tc_chan = tc_chan;
 	ch->uart_chan = uart_chan;
 	ch->waiting_time = ISO7816_3_INIT_WTIME;
 
@@ -1269,7 +1281,5 @@
 
 	card_handle_reset(ch);
 
-	tc_etu_init(ch->tc_chan, ch);
-
 	return ch;
 }
diff --git a/firmware/libcommon/source/mode_cardemu.c b/firmware/libcommon/source/mode_cardemu.c
index 4886983..8531eb5 100644
--- a/firmware/libcommon/source/mode_cardemu.c
+++ b/firmware/libcommon/source/mode_cardemu.c
@@ -55,6 +55,14 @@
 	struct llist_head usb_out_queue;
 	struct ringbuf rb;
 	struct Usart_info usart_info;
+	struct {
+		/*! receiver waiting time to trigger timeout (0 to deactivate it) */
+		uint32_t total;
+		/*! remaining waiting time (we may need multiple timer runs to reach total */
+		uint32_t remaining;
+		/*! did we already notify about half the time having expired? */
+		bool half_time_notified;
+	} wt;
 	int usb_pending_old;
 	uint8_t ep_out;
 	uint8_t ep_in;
@@ -140,12 +148,23 @@
 	Usart *usart = get_usart_by_chan(uart_chan);
 	switch (rxtx) {
 	case ENABLE_TX:
-		USART_DisableIt(usart, ~US_IER_TXRDY);
+		USART_DisableIt(usart, ~(US_IER_TXRDY | US_IER_TIMEOUT));
 		/* as irritating as it is, we actually want to keep the
 		 * receiver enabled during transmit */
 		USART_SetReceiverEnabled(usart, 1);
 		usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
-		USART_EnableIt(usart, US_IER_TXRDY);
+		USART_EnableIt(usart, US_IER_TXRDY | US_IER_TIMEOUT);
+		USART_SetTransmitterEnabled(usart, 1);
+		break;
+	case ENABLE_TX_TIMER_ONLY:
+		/* enable the transmitter without generating TXRDY interrupts
+		 * just so that the timer can run */
+		USART_DisableIt(usart, ~US_IER_TIMEOUT);
+		/* as irritating as it is, we actually want to keep the
+		 * receiver enabled during transmit */
+		USART_SetReceiverEnabled(usart, 1);
+		usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
+		USART_EnableIt(usart, US_IER_TIMEOUT);
 		USART_SetTransmitterEnabled(usart, 1);
 		break;
 	case ENABLE_RX:
@@ -225,11 +244,40 @@
 	}
 
 	/* check if any error flags are set */
-	if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) {
+	if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|US_CSR_NACK|(1<<10))) {
 		/* clear any error flags */
 		usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
 		TRACE_ERROR("%u USART error on 0x%x status: 0x%lx\n", ci->num, byte, csr);
 	}
+
+	/* check if the timeout has expired. We "abuse" the receive timer for tracking
+	 * how many etu have expired since we last sent a byte.  See section
+	 * 33.7.3.11 "Receiver Time-out" of the SAM3S8 Data Sheet */
+	if (csr & US_CSR_TIMEOUT) {
+		/* RX has been inactive for some time */
+		if (ci->wt.remaining <= (usart->US_RTOR & 0xffff)) {
+			/* waiting time is over; will stop the timer */
+			ci->wt.remaining = 0;
+		} else {
+			/* subtract the actual timeout since the new might not have been set and
+			 * reloaded yet */
+			ci->wt.remaining -= (usart->US_RTOR & 0xffff);
+		}
+		if (ci->wt.remaining == 0) {
+			/* let the FSM know that WT has expired */
+			card_emu_wtime_expired(ci->ch);
+		} else if (ci->wt.remaining <= ci->wt.total / 2 && !ci->wt.half_time_notified) {
+			/* let the FS know that half of the WT has expired */
+			card_emu_wtime_half_expired(ci->ch);
+			ci->wt.half_time_notified = true;
+		}
+		/* if value exceeds the USART TO range, use the maximum for now */
+		usart->US_RTOR = OSMO_MIN(ci->wt.remaining, 0xffff);
+		/* clear timeout flag (and stop timeout until next character is received) */
+		usart->US_CR |= US_CR_STTTO;
+		/* restart the counter (it wt is 0, the timeout is not started) */
+		usart->US_CR |= US_CR_RETTO;
+	}
 }
 
 /*! ISR called for USART0 */
@@ -258,6 +306,42 @@
 	return 0;
 }
 
+/*! Update WT on USART peripheral.  Will automatically re-start timer with new value.
+ *  \param[in] usart USART peripheral to configure
+ *  \param[in] wt inactivity Waiting Time before card_emu_wtime_expired is called (0 to disable) */
+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)
+{
+	OSMO_ASSERT(uart_chan < ARRAY_SIZE(cardem_inst));
+	struct cardem_inst *ci = &cardem_inst[uart_chan];
+	Usart *usart = get_usart_by_chan(uart_chan);
+
+	if (ci->wt.total != wt) {
+		TRACE_DEBUG("%u: USART WT changed from %lu to %lu ETU\r\n", uart_chan,
+			    ci->wt.total, wt);
+	}
+
+	ci->wt.total = wt;
+	/* reset and start the timer */
+	card_emu_uart_reset_wt(uart_chan);
+}
+
+/*! Reset and re-start waiting timeout count down on USART peripheral.
+ *  \param[in] usart USART peripheral to configure */
+void card_emu_uart_reset_wt(uint8_t uart_chan)
+{
+	OSMO_ASSERT(uart_chan < ARRAY_SIZE(cardem_inst));
+	struct cardem_inst *ci = &cardem_inst[uart_chan];
+	Usart *usart = get_usart_by_chan(uart_chan);
+
+	/* FIXME: guard against race with interrupt handler */
+	ci->wt.remaining = ci->wt.total;
+	ci->wt.half_time_notified = false;
+	/* if value exceeds the USART TO range, use the maximum for now */
+	usart->US_RTOR = OSMO_MIN(ci->wt.remaining, 0xffff);
+	/* restart the counter (if wt is 0, the timeout is not started) */
+	usart->US_CR |= US_CR_RETTO;
+}
+
 /* call-back from card_emu.c to force a USART interrupt */
 void card_emu_uart_interrupt(uint8_t uart_chan)
 {
@@ -450,7 +534,7 @@
 	do {} while (!adc_triggered); /* wait for first ADC reading */
 #endif /* DETECT_VCC_BY_ADC */
 
-	cardem_inst[0].ch = card_emu_init(0, 2, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,
+	cardem_inst[0].ch = card_emu_init(0, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,
 					  SIMTRACE_CARDEM_USB_EP_USIM1_INT, cardem_inst[0].vcc_active,
 					  cardem_inst[0].rst_active, cardem_inst[0].vcc_active);
 	sim_switch_use_physical(0, 1);
@@ -473,7 +557,7 @@
 	do {} while (!adc_triggered); /* wait for first ADC reading */
 #endif /* DETECT_VCC_BY_ADC */
 
-	cardem_inst[1].ch = card_emu_init(1, 0, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,
+	cardem_inst[1].ch = card_emu_init(1, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,
 					  SIMTRACE_CARDEM_USB_EP_USIM2_INT, cardem_inst[1].vcc_active,
 					  cardem_inst[1].rst_active, cardem_inst[1].vcc_active);
 	sim_switch_use_physical(1, 1);
diff --git a/firmware/test/card_emu_tests.c b/firmware/test/card_emu_tests.c
index 2a1d682..69159a8 100644
--- a/firmware/test/card_emu_tests.c
+++ b/firmware/test/card_emu_tests.c
@@ -50,6 +50,9 @@
 	case ENABLE_TX:
 		rts = "TX";
 		break;
+	case ENABLE_TX_TIMER_ONLY:
+		rts = "TX-TIMER-ONLY";
+		break;
 	case ENABLE_RX:
 		rts = "RX";
 		break;
@@ -66,29 +69,14 @@
 	printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
 }
 
-void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)
 {
-	printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
+	printf("%s(uart_chan=%u, wtime=%u)\n", __func__, uart_chan, wt);
 }
 
-void tc_etu_set_etu(uint8_t tc_chan, uint16_t etu)
+void card_emu_uart_reset_wt(uint8_t uart_chan)
 {
-	printf("tc_etu_set_etu(tc_chan=%u, etu=%u)\n", tc_chan, etu);
-}
-
-void tc_etu_init(uint8_t chan_nr, void *handle)
-{
-	printf("tc_etu_init(tc_chan=%u)\n", chan_nr);
-}
-
-void tc_etu_enable(uint8_t chan_nr)
-{
-	printf("tc_etu_enable(tc_chan=%u)\n", chan_nr);
-}
-
-void tc_etu_disable(uint8_t chan_nr)
-{
-	printf("tc_etu_disable(tc_chan=%u)\n", chan_nr);
+	printf("%s(uart_chan=%u\n", __func__, uart_chan);
 }
 
 
@@ -136,7 +124,7 @@
 	/* release from reset and verify th ATR */
 	card_emu_io_statechg(ch, CARD_IO_RST, 0);
 	/* simulate waiting time before ATR expired */
-	tc_etu_wtime_expired(ch);
+	card_emu_wtime_expired(ch);
 	verify_atr(ch);
 }
 
@@ -408,7 +396,7 @@
 	struct card_handle *ch;
 	unsigned int i;
 
-	ch = card_emu_init(0, 23, 42, PHONE_DATAIN, PHONE_INT, false, true, false);
+	ch = card_emu_init(0, 42, PHONE_DATAIN, PHONE_INT, false, true, false);
 	assert(ch);
 
 	usb_buf_init();

-- 
To view, visit https://gerrit.osmocom.org/c/simtrace2/+/23620
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: simtrace2
Gerrit-Branch: master
Gerrit-Change-Id: Ibcb2c8cace9137695adf5fb3de43566f7cfb93b5
Gerrit-Change-Number: 23620
Gerrit-PatchSet: 5
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Reviewer: Hoernchen <ewild at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: tsaitgaist <kredon at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210408/c3db7f32/attachment.htm>


More information about the gerrit-log mailing list