mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-16 21:28:33 +03:00
firmware/sniffer: Add + use 16bit ringbuffer
So far, we use a uint8_t ring buffer as "FIFO" between USART Rx interrupt and main context. That's fine for expressing the bytes we receive. However, if we also want to report USART errors synchronously in that stream, we actually need more bits to express those. Reporting USART errors via the ring buffer is the only way how the sniffer code can know in which TPDU the error occurred. Reporting them any other way (global variable, ...) would loose the timing relationship where in the received stream the error occurred. This change just changes the ringbuffer from 1024-entry 8bit to 512-entry 16bit and doesn't add any error reporting. Change-Id: Ifde054fbfe7f753b61e7d3409c56eca6e0faeb4b
This commit is contained in:
@@ -32,4 +32,22 @@ int rbuf_write(volatile ringbuf * rb, uint8_t item);
|
|||||||
bool rbuf_is_empty(volatile ringbuf * rb);
|
bool rbuf_is_empty(volatile ringbuf * rb);
|
||||||
bool rbuf_is_full(volatile ringbuf * rb);
|
bool rbuf_is_full(volatile ringbuf * rb);
|
||||||
|
|
||||||
|
|
||||||
|
/* same as above but with 16bit values instead of 8bit */
|
||||||
|
|
||||||
|
#define RING16_BUFLEN 512
|
||||||
|
|
||||||
|
typedef struct ringbuf16 {
|
||||||
|
uint16_t buf[RING16_BUFLEN];
|
||||||
|
size_t ird;
|
||||||
|
size_t iwr;
|
||||||
|
} ringbuf16;
|
||||||
|
|
||||||
|
void rbuf16_reset(volatile ringbuf16 * rb);
|
||||||
|
uint16_t rbuf16_read(volatile ringbuf16 * rb);
|
||||||
|
uint16_t rbuf16_peek(volatile ringbuf16 * rb);
|
||||||
|
int rbuf16_write(volatile ringbuf16 * rb, uint16_t item);
|
||||||
|
bool rbuf16_is_empty(volatile ringbuf16 * rb);
|
||||||
|
bool rbuf16_is_full(volatile ringbuf16 * rb);
|
||||||
|
|
||||||
#endif /* end of include guard: SIMTRACE_RINGBUF_H */
|
#endif /* end of include guard: SIMTRACE_RINGBUF_H */
|
||||||
|
|||||||
@@ -28,6 +28,16 @@ void rbuf_reset(volatile ringbuf * rb)
|
|||||||
local_irq_restore(state);
|
local_irq_restore(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rbuf16_reset(volatile ringbuf16 * rb)
|
||||||
|
{
|
||||||
|
unsigned long state;
|
||||||
|
|
||||||
|
local_irq_save(state);
|
||||||
|
rb->ird = 0;
|
||||||
|
rb->iwr = 0;
|
||||||
|
local_irq_restore(state);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t rbuf_read(volatile ringbuf * rb)
|
uint8_t rbuf_read(volatile ringbuf * rb)
|
||||||
{
|
{
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
@@ -41,21 +51,49 @@ uint8_t rbuf_read(volatile ringbuf * rb)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t rbuf16_read(volatile ringbuf16 * rb)
|
||||||
|
{
|
||||||
|
unsigned long state;
|
||||||
|
uint16_t val;
|
||||||
|
|
||||||
|
local_irq_save(state);
|
||||||
|
val = rb->buf[rb->ird];
|
||||||
|
rb->ird = (rb->ird + 1) % RING16_BUFLEN;
|
||||||
|
local_irq_restore(state);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t rbuf_peek(volatile ringbuf * rb)
|
uint8_t rbuf_peek(volatile ringbuf * rb)
|
||||||
{
|
{
|
||||||
return rb->buf[rb->ird];
|
return rb->buf[rb->ird];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t rbuf16_peek(volatile ringbuf16 * rb)
|
||||||
|
{
|
||||||
|
return rb->buf[rb->ird];
|
||||||
|
}
|
||||||
|
|
||||||
bool rbuf_is_empty(volatile ringbuf * rb)
|
bool rbuf_is_empty(volatile ringbuf * rb)
|
||||||
{
|
{
|
||||||
return rb->ird == rb->iwr;
|
return rb->ird == rb->iwr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rbuf16_is_empty(volatile ringbuf16 * rb)
|
||||||
|
{
|
||||||
|
return rb->ird == rb->iwr;
|
||||||
|
}
|
||||||
|
|
||||||
static bool __rbuf_is_full(volatile ringbuf * rb)
|
static bool __rbuf_is_full(volatile ringbuf * rb)
|
||||||
{
|
{
|
||||||
return rb->ird == (rb->iwr + 1) % RING_BUFLEN;
|
return rb->ird == (rb->iwr + 1) % RING_BUFLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool __rbuf16_is_full(volatile ringbuf16 * rb)
|
||||||
|
{
|
||||||
|
return rb->ird == (rb->iwr + 1) % RING16_BUFLEN;
|
||||||
|
}
|
||||||
|
|
||||||
bool rbuf_is_full(volatile ringbuf * rb)
|
bool rbuf_is_full(volatile ringbuf * rb)
|
||||||
{
|
{
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
@@ -68,6 +106,18 @@ bool rbuf_is_full(volatile ringbuf * rb)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rbuf16_is_full(volatile ringbuf16 * rb)
|
||||||
|
{
|
||||||
|
unsigned long state;
|
||||||
|
bool rc;
|
||||||
|
|
||||||
|
local_irq_save(state);
|
||||||
|
rc = rb->ird == (rb->iwr + 1) % RING16_BUFLEN;
|
||||||
|
local_irq_restore(state);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int rbuf_write(volatile ringbuf * rb, uint8_t item)
|
int rbuf_write(volatile ringbuf * rb, uint8_t item)
|
||||||
{
|
{
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
@@ -84,4 +134,18 @@ int rbuf_write(volatile ringbuf * rb, uint8_t item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rbuf16_write(volatile ringbuf16 * rb, uint16_t item)
|
||||||
|
{
|
||||||
|
unsigned long state;
|
||||||
|
|
||||||
|
local_irq_save(state);
|
||||||
|
if (!__rbuf16_is_full(rb)) {
|
||||||
|
rb->buf[rb->iwr] = item;
|
||||||
|
rb->iwr = (rb->iwr + 1) % RING16_BUFLEN;
|
||||||
|
local_irq_restore(state);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
local_irq_restore(state);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ static struct Usart_info sniff_usart = {
|
|||||||
.state = USART_RCV,
|
.state = USART_RCV,
|
||||||
};
|
};
|
||||||
/*! Ring buffer to store sniffer communication data */
|
/*! Ring buffer to store sniffer communication data */
|
||||||
static struct ringbuf sniff_buffer;
|
static struct ringbuf16 sniff_buffer;
|
||||||
|
|
||||||
/* Flags to know is the card status changed (see SIMTRACE_MSGT_DT_SNIFF_CHANGE flags) */
|
/* Flags to know is the card status changed (see SIMTRACE_MSGT_DT_SNIFF_CHANGE flags) */
|
||||||
static volatile uint32_t change_flags = 0;
|
static volatile uint32_t change_flags = 0;
|
||||||
@@ -291,7 +291,7 @@ static void change_state(enum iso7816_3_sniff_state iso_state_new)
|
|||||||
update_wt(10, 1, "RESET"); /* reset WT time-out */
|
update_wt(10, 1, "RESET"); /* reset WT time-out */
|
||||||
break;
|
break;
|
||||||
case ISO7816_S_WAIT_ATR:
|
case ISO7816_S_WAIT_ATR:
|
||||||
rbuf_reset(&sniff_buffer); /* reset buffer for new communication */
|
rbuf16_reset(&sniff_buffer); /* reset buffer for new communication */
|
||||||
break;
|
break;
|
||||||
case ISO7816_S_IN_ATR:
|
case ISO7816_S_IN_ATR:
|
||||||
g_atr.atr_i = 0;
|
g_atr.atr_i = 0;
|
||||||
@@ -835,7 +835,7 @@ void Sniffer_usart_isr(void)
|
|||||||
/* Reset WT timer */
|
/* Reset WT timer */
|
||||||
wt_remaining = g_wt;
|
wt_remaining = g_wt;
|
||||||
/* Store sniffed data into buffer (also clear interrupt */
|
/* Store sniffed data into buffer (also clear interrupt */
|
||||||
if (rbuf_write(&sniff_buffer, byte) != 0)
|
if (rbuf16_write(&sniff_buffer, byte) != 0)
|
||||||
TRACE_ERROR("USART buffer full\n\r");
|
TRACE_ERROR("USART buffer full\n\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -941,7 +941,7 @@ void Sniffer_init(void)
|
|||||||
PIO_EnableIt(&pin_rst);
|
PIO_EnableIt(&pin_rst);
|
||||||
|
|
||||||
/* Clear ring buffer containing the sniffed data */
|
/* Clear ring buffer containing the sniffed data */
|
||||||
rbuf_reset(&sniff_buffer);
|
rbuf16_reset(&sniff_buffer);
|
||||||
/* Configure USART to as ISO-7816 slave communication to sniff communication */
|
/* Configure USART to as ISO-7816 slave communication to sniff communication */
|
||||||
ISO7816_Init(&sniff_usart, CLK_SLAVE);
|
ISO7816_Init(&sniff_usart, CLK_SLAVE);
|
||||||
/* Only receive data when sniffing */
|
/* Only receive data when sniffing */
|
||||||
@@ -1007,8 +1007,8 @@ void Sniffer_run(void)
|
|||||||
* is remaining
|
* is remaining
|
||||||
*/
|
*/
|
||||||
/* Handle sniffed data */
|
/* Handle sniffed data */
|
||||||
if (!rbuf_is_empty(&sniff_buffer)) { /* use if instead of while to let the main loop restart the watchdog */
|
if (!rbuf16_is_empty(&sniff_buffer)) { /* use if instead of while to let the main loop restart the watchdog */
|
||||||
uint8_t byte = rbuf_read(&sniff_buffer);
|
uint8_t byte = rbuf16_read(&sniff_buffer);
|
||||||
/* Convert convention if required */
|
/* Convert convention if required */
|
||||||
if (convention_convert) {
|
if (convention_convert) {
|
||||||
byte = convention_convert_lut[byte];
|
byte = convention_convert_lut[byte];
|
||||||
|
|||||||
Reference in New Issue
Block a user