6 Commits

Author SHA1 Message Date
Harald Welte
575acd9b03 simtrace2_api: Fix transmission of SIMTRACE_CMD_BD_BOARD_INFO
Prior to this commit we didn't pass the pointer to the slot when
requesting board_info.

Change-Id: Ib99e7c0a96f7738480ca68ed2c144c1756a5f11b
2023-10-20 10:09:34 +02:00
Harald Welte
f22a615158 WIP: hack simtrace2-tool for USB testing of rp2040 firmware
Command used for continuous cycles of board_info messages:

./simtrace2-tool -V 1d50 -P aaaa -C 1 -I 0 -S 0 generic board-info

Change-Id: I577a0266b68c8161b9eaec653c3c7d17d320faaf
2023-10-20 10:07:24 +02:00
Harald Welte
4a8ec296fa WIP: generic board-info
Change-Id: I0642269c924a0abe464a64c004681f507f14bc92
2023-09-14 18:36:32 +02:00
Harald Welte
73a8ef31f1 firmware/sniffer: Handle USART BREAK condition
Let's count + report BREAK conditions (all-zero bits + parity + stop
bit)

Change-Id: Idefb552fc9878ca6c88a9bf8bf1c0ced668c5c04
2023-09-14 18:36:32 +02:00
Harald Welte
95c85b6f0c firmware/sniffer: Add performance/error counters
Let's add some counters for number of bytes/tpdu/pps/atr/reset
as well as for all the various error conditions from USART through
ring buffer and TPDU buffer overflows, timeouts, ...

Change-Id: Ic679664191259d321ad1f1829d5568fe0b297f39
2023-09-14 18:36:32 +02:00
Harald Welte
a8d13dea9b HACK: Solve weird problem wih lost OUT transfer on ping-pong endpoint
This adds an unconditional endpoint reset procedure to every SET_FEATURE(UnHalt).

It doesn't really make sense that this is required, *particularly* as
we *MUST NOT* set bEndpoint->bank to 0 here.

Without this patch, I'm observing the following problem:

Every first OUT transfer after a SET_INTERFACE + UNHALT on a bulk endpoint
is lost. "lost" means that it completes successfully on the host, can
be seen completing successfully with an ACK on a USB bus analyzer,
but still doesn't show up in the firmware.  No Endpoint Interrupt
is generated.

This can be reproduced by calling libusb_set_interface_alt_setting()
from the host and then submitting a single OUT transfer.

Related: OS#5770
Related: https://gerrit.osmocom.org/c/simtrace2/+/26864
Change-Id: I18ed530e617baddf76e8f9829512443ce2a76e0d
2023-09-14 18:36:32 +02:00
22 changed files with 250 additions and 238 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1 +0,0 @@
open_collective: osmocom

View File

@@ -13,17 +13,12 @@ stack and host software.
Supported Hardware
------------------
* Osmocom [SIMtrace2](https://osmocom.org/projects/simtrace2/wiki) with SAM3 controller
* this is open hardware and schematics / PCB design is published
* pre-built hardware available from [sysmocom webshop](https://shop.sysmocom.de/SIMtrace2-Hardware-Kit/simtrace2-kit)
* Osmocom [ngff-cardem](https://osmocom.org/projects/ngff-cardem/wiki) M.2/NGFF modem carrier with SAM3 controller
* this is open hardware and schematics / PCB design is published
* pre-built hardware available from [sysmocom webshoo](https://shop.sysmocom.de/M.2-modem-carrier-with-remote-SIM-tracing/ngff-cardem-kit-external)
* sysmocom [sysmoQMOD](https://sysmocom.de/products/lab/sysmoqmod/index.html) (with 4 Modems, 4 SIM slots and 2 SAM3)
* this is a proprietary device, publicly available from sysmocom
* hardware evaluation kit available from [sysmocom webshop](https://shop.sysmocom.de/sysmoQMOD-evaluation-kit/sysmoQMOD-evk)
* Osmocom SIMtrace 1.x with SAM3 controller
** this is open hardware and schematics / PCB design is published
* sysmocom sysmoQMOD (with 4 Modems, 4 SIM slots and 2 SAM3)
** this is a proprietary device, publicly available from sysmocom
* sysmocom OWHW (with 2 Modems and 1 SAM3 onboard)
* this is not publicly available hardware, but still supported
** this is not publicly available hardware, but still supported
This Repository
---------------
@@ -41,14 +36,3 @@ The host software includes
* simtrace2-list - list any USB-attached devices running simtrace2 firmware
* simtrace2-sniff - interface the 'trace' firmware to obtain card protocol traces
* simtrace2-cardem-pcsc - interface the 'cardem' fimrware to use a SIM in a PC/SC reader
Do not expect SIMtrace2 to work in VMs
--------------------------------------
We only support running SIMtrace2 together with a Linux system running
"bare iron" on actual hardware (x86, x86_64, arm, ...). **using VMs
with USB pass-through for things with critical timing like SIMtrace2 is
calling for trouble** and we will not accept related bug reports or
support you if you do. If you still want to use VMs: Feel free to do
so, but understand that it's unsupported and you are on your own.

View File

@@ -3,7 +3,8 @@
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
# LIBVERSION=c:r:a
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
simtrace2 API/ABI change osmo_st2_transport new member

View File

@@ -58,7 +58,6 @@ local hf_pts_resp = ProtoField.bytes("usb_simtrace.pts_resp", "PTS response")
local hf_cemu_cfg_features = ProtoField.uint32("usb_simtrace.cemu_cfg.features.status_irq", "CardEm Features", base.HEX)
local hf_cemu_cfg_slot_mux_nr = ProtoField.uint32("usb_simtrace.cemu_cfg.features.slot_mux_nr", "CardEm Slot Mux Nr", base.DEC)
local hf_cemu_cfg_presence_polarity = ProtoField.uint8("usb_simtrace.cemu_cfg.features.presence_polarity", "Sim presence polarity", base.DEC)
local card_insert_types = {
[0x00] = "not inserted",
@@ -72,9 +71,6 @@ local CEMU_STATUS_F_RCEMU_ACTIVE = ProtoField.uint32("usb_simtrace.CEMU_STATUS.
local CEMU_STATUS_F_CARD_INSERT = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_CARD_INSERT", "CARD_INSERT", base.HEX_DEC, NULL, 0x00000008)
local CEMU_STATUS_F_RESET_ACTIVE = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_RESET_ACTIVE", "RESET_ACTIVE", base.HEX_DEC, NULL, 0x00000010)
local CEMU_CONFIG_PRES_POL_PRES_H = ProtoField.uint32("usb_simtrace.CEMU_CONFIG.PRES_POL_PRES_H", "PRESENCE_HIGH", base.HEX_DEC, NULL, 0x00000001)
local CEMU_CONFIG_PRES_POL_VALID = ProtoField.uint32("usb_simtrace.CEMU_CONFIG.PRES_POL_VALID", "PRESENCE_VALID", base.HEX_DEC, NULL, 0x00000002)
local modem_reset_types = {
[0x00] = "de-assert",
[0x01] = "assert",
@@ -93,10 +89,9 @@ usb_simtrace_protocol.fields = {
msgtype, seqnr, slotnr, reserved, payloadlen, payload,
pb_and_rx, pb_and_tx, final, tpdu_hdr, rxtxdatalen, rxtxdata,
CEMU_STATUS_F_VCC_PRESENT, CEMU_STATUS_F_CLK_ACTIVE, CEMU_STATUS_F_RCEMU_ACTIVE, CEMU_STATUS_F_CARD_INSERT, CEMU_STATUS_F_RESET_ACTIVE,
CEMU_CONFIG_PRES_POL_PRES_H, CEMU_CONFIG_PRES_POL_VALID,
modem_reset_status, modem_reset_len,
hf_pts_len, hf_pts_req, hf_pts_resp,
hf_cemu_cfg_features, hf_cemu_cfg_slot_mux_nr, hf_cemu_cfg_presence_polarity,
hf_cemu_cfg_features, hf_cemu_cfg_slot_mux_nr,
hf_cemu_cardinsert, hf_modem_sim_select,
}
@@ -219,15 +214,7 @@ function dissect_cemu_config(payload_data, pinfo, tree)
local subtree = tree:add(usb_simtrace_protocol, payload_data, "Card Emu Config")
subtree:add(hf_cemu_cfg_features, payload_data(0,4));
if payload_data:len() >= 4 then
subtree:add(hf_cemu_cfg_slot_mux_nr, payload_data(4,1));
end
if payload_data:len() >= 5 then
local pres = payload_data(5,1):le_uint();
subtree:add(hf_cemu_cfg_presence_polarity, payload_data(5,1));
headerSubtree:add(CEMU_CONFIG_PRES_POL_PRES_H, pres)
headerSubtree:add(CEMU_CONFIG_PRES_POL_VALID, pres)
end
subtree:add(hf_cemu_cfg_slot_mux_nr, payload_data(4,1));
end
function dissect_modem_sim_sel(payload_data, pinfo, tree)

96
debian/changelog vendored
View File

@@ -1,99 +1,3 @@
simtrace2 (0.9.0) unstable; urgency=medium
[ Oliver Smith ]
* host/contrib/simtrace2.spec.in: update
* treewide: remove FSF address
* contrib/jenkins.sh: set USE_CLANG=1
* Cosmetic: fix CI errors
* debian/rules: remove override_dh_autoreconf
* debian: set compat level to 10
* contrib/jenkins: tweak shell logic
* firmware/Makefile: don't use distribution's CFLAGS
* contrib: remove rpm spec file
[ Eric Wild ]
* firmware: add crc stub to all dfu apps to ensure reliable loading
* wireshark lua dissector: dissect more
* lua dissector: adjust usage instructions
* conrtrib/upload : upload elf files
* contrib/jenkins.sh : build and publish combined targets
* fw: only build the bl with clang
[ James Tavares ]
* simtrace2-tool: add "modem sim-card (insert|remove)" command
* firmware: add definition for main osc bypass when using external osc
* gitignore: add missing entries binaries
* firmware: bugfix: disable cardemu comms in local SIM mode
* main: rotor: erase immediately after send
* Fix missing generation of waiting-time-extension in some situations
[ Harald Welte ]
* host: Print strerror(errno) in case of problems opening the USB device
* cosmetic: Fix indent of printf() statement
* host: properly zero-initialize interface match structures
* contrib/simtrace.lua: Add VID/PID of all currentl simtrace2 devices
* cosmetic: contrib/simtrace.lua: more consistent formatting
* contrib/simtrace.lua: Add header with author/description/usage
* contrib/simtrace.lua: print length + slot-number in decimal only
* contrib/simtrace.lua: Don't print SIMTRACE_MSGT_ in every COL_INFO
* contrib/simtrace.lua: Dissect some more cardem related message types
* contrib/simtrace.lua: Register for "decode as..."
* cardem: Report the VCC voltage (if supported)
* card_emu_uart_interrupt: ASSERT if we get called with wrong uart_chan
* cardem: set more reasonable interrupt priorities
* host: Always initialize libosmocore logging before using it
* simtrace2-cardem-pcsc: rename 'flags' to 'status_flags'
* simtrace2-cardem-pcsc: Move all logging into libosmocore
* simtrace2-cardem-pcsc: Detect card power-up without RESET
* host: Don't pass -1 (converted to 255) as address
* simtrace2-cardem-pcsc: Fix copy+paste error in log message
* simtrace2-cardem-pcsc: continue in case of LIBUSB_TRANSFER_ERROR
* contrib/simtrace.lua: Add Flag bits + Data to COL_INFO
* Reduce bInterval of interrupt endpoints to avoid interrupt misses
* simtrace2-cardem-pcsc.c: Send APDUs via GSMTAP
* update git URLs (git -> https; gitea)
* cardem: reset the uC in case of USB disconnect
* cosmetic: Fix compile-time #error message string typo
* firmware/sniffer: Fix copy+paste when logging invalid INS bytes
* firmware/sniffer: Log parity errors, just like overruns and framing errors
* firmware/sniffer: refactor setting TPDU state
* firmware/sniffer: Log old and new state in ISO7816-3 state changes
* firmware/sniffer: Avoid extra call for rbuf_is_full
* firmware/sniffer: Fix programming error in PPS
* firmware/sniffer: Make all global variables 'static'
* firmware/sniffer: Group global variables in structs
* firmware/sniffer: Log cause of WT change
* firmware/sniffer: Rename global variable 'wt' to 'g_wt'
* firmware/sniffer: Disable TIMEOUT interrupts in USART IER on exit
* firmware/sniffer: Add + use 16bit ringbuffer
* firmware/sniffer: Pass PARITY/OVERRUN/FRAMING error via ringbuffer
* firmware/sniffer: Handle WT timeouts via ring-buffer
* firmware/sniffer: introduce #define for interrupt enable flags
* firmware/sniffer: Enable interrupts for overrun/parity/frame errors
* Fix unchecked return value of osmo_libusb_init()
* Add funding link to github mirror
* README.md: Fix mark-down nested bullet syntax
* README.md: Fix mark-down nested bullet syntax
* README.md: add links to SIMtrace2 and QMOD
* README.md: Add links to where hardware can be bought
* README.md: Add section on ngff_carem
* README.md: Add note to avoid using a VM
[ Alexander Couzens ]
* firmware: usb: call USBD_HAL_DISCONNECT while usb init to recover from resets
* ngff_cardem: cosmetic: fix superflous space
* dissector: add support for sim polarity
* firmware: allow to change the sim presence pin polarity
* simtrace2-cardem-pcsc: allow to set sim presence polarity
[ Vadim Yanitskiy ]
* host/cardem: fix integer overflow in process_do_rx_da()
[ Philipp Maier ]
* simtrace2-cardem-pcsc: mark reset events in GSMTAP trace
-- Oliver Smith <osmith@sysmocom.de> Wed, 12 Feb 2025 16:07:53 +0100
simtrace2 (0.8.1) unstable; urgency=medium
* host/contrib/simtrace2.spec.in: fix soname

2
debian/control vendored
View File

@@ -10,7 +10,7 @@ Build-Depends: debhelper (>= 10),
pkg-config,
git,
dh-autoreconf,
libosmocore-dev (>= 1.11.0),
libosmocore-dev (>= 1.4.0),
libpcsclite-dev,
libnewlib-arm-none-eabi,
libusb-1.0-0-dev,

View File

@@ -1672,6 +1672,10 @@ uint8_t USBD_HAL_Halt(uint8_t bEndpoint, uint8_t ctl)
UDP->UDP_RST_EP |= 1 << bEndpoint;
UDP->UDP_RST_EP &= ~(1 << bEndpoint);
}
/* This fixes a weird bug with regard to ping-pong OUT endpoints */
UDP->UDP_RST_EP |= 1 << bEndpoint;
UDP->UDP_RST_EP &= ~(1 << bEndpoint);
}
/* Return Halt status */

View File

@@ -146,8 +146,8 @@ int board_override_enter_dfu(void)
return 0;
}
static const Pin deton = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static const Pin detoff = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT};
static const Pin deton = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
static const Pin detoff = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT};
void board_set_card_insert(struct cardem_inst *ci, bool card_insert)
{

View File

@@ -124,8 +124,4 @@ extern void mode_cardemu_usart1_irq(void);
void Timer_Init( void );
void TC0_Counter_Reset( void );
/* Sim presence pins */
bool mode_cardemu_get_presence_pol(uint8_t instance);
void mode_cardemu_set_presence_pol(uint8_t instance, bool high);
#endif /* SIMTRACE_H */

View File

@@ -1,6 +1,6 @@
/* SIMtrace2 USB protocol
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2015-2022 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -84,6 +84,8 @@ enum simtrace_msg_type_sniff {
SIMTRACE_MSGT_SNIFF_PPS,
/* TPDU data */
SIMTRACE_MSGT_SNIFF_TPDU,
/* Statistics */
SIMTRACE_MSGT_DO_SNIFF_STATS,
};
/* common message header */
@@ -261,21 +263,12 @@ struct cardemu_usb_msg_error {
/* enable/disable the generation of DO_STATUS on IRQ endpoint */
#define CEMU_FEAT_F_STATUS_IRQ 0x00000001
#define CEMU_CONFIG_PRES_POL_PRES_L 0x00
#define CEMU_CONFIG_PRES_POL_PRES_H 0x01
#define CEMU_CONFIG_PRES_POL_VALID 0x02
/* SIMTRACE_MSGT_BD_CEMU_CONFIG */
struct cardemu_usb_msg_config {
/* bit-mask of CEMU_FEAT_F flags */
uint32_t features;
/* the selected slot number (if an external mux is present) */
uint8_t slot_mux_nr;
/* Sim presence pin polarity. Bit 1 is a validity bit. Bit 0 gpio value when sim present.
* When sim is present, set sim_present gpio to high -> 0x03
* When sim is present, set sim_present gpio to low -> 0x02
*/
uint8_t pres_pol;
} __attribute__ ((packed));
/***********************************************************************
@@ -347,3 +340,24 @@ struct sniff_data {
/* data */
uint8_t data[0];
} __attribute__ ((packed));
/* SIMTRACE_MSGT_DO_SNIFF_STATS */
struct st_sniff_stats {
uint32_t flags; /* RFU */
uint32_t num_bytes; /* total lnumber of bytes received */
uint32_t num_tpdu; /* total number of TPDUs received */
uint32_t num_atr; /* total number of ATRs received */
uint32_t num_pps; /* total number of PPS (req, resp) received */
uint32_t num_reset; /* total number of resets */
struct {
uint32_t overruns;
uint32_t framing_errs;
uint32_t parity_errs;
uint32_t breaks;
} num_usart;
uint32_t num_waiting_time_exp;
uint32_t num_tpdu_overflows; /* TPDU buffer overflows */
uint32_t num_csum_errors; /* ATR + PPS checksum */
uint32_t num_ringbuf_overflows; /* ISR->main ringbuffer overflows */
uint32_t num_tpdu_malformed;
} __attribute__ ((packed));

View File

@@ -24,7 +24,6 @@
#include "trace.h"
#include "iso7816_fidi.h"
#include "card_emu.h"
#include "simtrace.h"
#include "simtrace_prot.h"
#include "usb_buf.h"
#include <osmocom/core/linuxlist.h>
@@ -1097,7 +1096,7 @@ static void card_emu_report_config(struct card_handle *ch)
#else
cfg->slot_mux_nr = 0;
#endif
cfg->pres_pol = mode_cardemu_get_presence_pol(ch->num) | CEMU_CONFIG_PRES_POL_VALID;
usb_buf_upd_len_and_submit(msg);
}
@@ -1271,11 +1270,6 @@ int card_emu_set_config(struct card_handle *ch, const struct cardemu_usb_msg_con
}
#endif
if (scfg_len >= sizeof(uint32_t)+sizeof(uint8_t)+sizeof(uint8_t)) {
if (scfg->pres_pol & CEMU_CONFIG_PRES_POL_VALID)
mode_cardemu_set_presence_pol(ch->num, scfg->pres_pol & CEMU_CONFIG_PRES_POL_PRES_H);
}
/* send back a report of our current configuration */
card_emu_report_config(ch);

View File

@@ -79,10 +79,7 @@ struct cardem_inst {
uint8_t ep_out;
uint8_t ep_in;
uint8_t ep_int;
/*! Pin to set when SIM is present/inserted (SIM presence pin). */
const Pin pin_insert;
/*! Invert the Pin polarity. When not inverted, the SIM pin_insert will be High, when a SIM is present. */
bool pin_insert_inverted;
#ifdef DETECT_VCC_BY_ADC
uint32_t vcc_uv;
#endif
@@ -116,10 +113,7 @@ struct cardem_inst cardem_inst[] = {
.ep_int = SIMTRACE_CARDEM_USB_EP_USIM1_INT,
#ifdef PIN_SET_USIM1_PRES
.pin_insert = PIN_SET_USIM1_PRES,
#endif /* PIN_SET_USIM1_PRES */
#ifdef PIN_SET_USIM1_PRES_INVERTED
.pin_insert_inverted = true,
#endif /* PIN_SET_USIM1_PRES_INVERTED */
#endif
},
#ifdef CARDEMU_SECOND_UART
{
@@ -134,10 +128,7 @@ struct cardem_inst cardem_inst[] = {
.ep_int = SIMTRACE_CARDEM_USB_EP_USIM2_INT,
#ifdef PIN_SET_USIM2_PRES
.pin_insert = PIN_SET_USIM2_PRES,
#endif /* PIN_SET_USIM2_PRES */
#ifdef PIN_SET_USIM2_PRES_INVERTED
.pin_insert_inverted = true,
#endif /* PIN_SET_USIM2_PRES_INVERTED */
#endif
},
#endif
};
@@ -709,7 +700,7 @@ static void process_card_insert(struct cardem_inst *ci, bool card_insert)
TRACE_INFO("%u: set card_insert to %s\r\n", ci->num, card_insert ? "INSERTED" : "REMOVED");
#ifdef HAVE_BOARD_CARDINSERT
board_set_card_insert(ci, card_insert ^ ci->pin_insert_inverted);
board_set_card_insert(ci, card_insert);
#else
if (!ci->pin_insert.pio) {
TRACE_INFO("%u: skipping unsupported card_insert to %s\r\n",
@@ -717,7 +708,7 @@ static void process_card_insert(struct cardem_inst *ci, bool card_insert)
return;
}
if (card_insert ^ ci->pin_insert_inverted)
if (card_insert)
PIO_Set(&ci->pin_insert);
else
PIO_Clear(&ci->pin_insert);
@@ -971,25 +962,3 @@ void mode_cardemu_run(void)
process_any_usb_commands(queue, ci);
}
}
void mode_cardemu_set_presence_pol(uint8_t instance, bool high)
{
struct cardem_inst *ci;
if (instance >= ARRAY_SIZE(cardem_inst))
return;
ci = &cardem_inst[instance];
ci->pin_insert_inverted = !high;
}
bool mode_cardemu_get_presence_pol(uint8_t instance)
{
struct cardem_inst *ci;
if (instance >= ARRAY_SIZE(cardem_inst))
return false;
ci = &cardem_inst[instance];
return !ci->pin_insert_inverted;
}

View File

@@ -116,6 +116,7 @@ enum tpdu_sniff_state {
#define RBUF16_F_FRAMING 0x0200
#define RBUF16_F_PARITY 0x0400
#define RBUF16_F_TIMEOUT_WT 0x0800
#define RBUF16_F_BREAK 0x1000
#define RBUF16_F_DATA_BYTE 0x8000
/*------------------------------------------------------------------------------
@@ -150,6 +151,9 @@ static struct ringbuf16 sniff_buffer;
/* Flags to know is the card status changed (see SIMTRACE_MSGT_DT_SNIFF_CHANGE flags) */
static volatile uint32_t change_flags = 0;
/* statistics for SIMTRACE_MSGT_DO_SNIFF_STATS */
static struct st_sniff_stats g_stats;
/* ISO 7816 variables */
/*! ISO 7816-3 state */
static enum iso7816_3_sniff_state iso_state = ISO7816_S_RESET;
@@ -453,6 +457,7 @@ static void process_byte_atr(uint8_t byte)
default:
TRACE_WARNING("Invalid TS received\n\r");
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
g_stats.num_tpdu_malformed++;
usb_send_atr(SNIFF_DATA_FLAG_ERROR_MALFORMED); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_ATR); /* reset state */
break;
@@ -523,9 +528,11 @@ static void process_byte_atr(uint8_t byte)
/* We still consider the data as valid (e.g. for WT) even is the checksum is wrong.
* It is up to the reader to handle this error (e.g. by resetting)
*/
g_stats.num_csum_errors++;
}
}
usb_send_atr(flags); /* send ATR to host software using USB */
g_stats.num_atr++;
change_state(ISO7816_S_WAIT_TPDU); /* go to next state */
break;
default:
@@ -617,6 +624,7 @@ static void process_byte_pps(uint8_t byte)
} else {
TRACE_INFO("Invalid PPSS received\n\r");
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
g_stats.num_tpdu_malformed++;
usb_send_pps(SNIFF_DATA_FLAG_ERROR_MALFORMED); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
}
@@ -668,6 +676,7 @@ static void process_byte_pps(uint8_t byte)
if (0 == check) { /* checksum is valid */
change_state(ISO7816_S_WAIT_PPS_RSP); /* go to next state */
} else { /* checksum is invalid */
g_stats.num_csum_errors++;
change_state(ISO7816_S_WAIT_TPDU); /* go to next state */
}
} else if (ISO7816_S_IN_PPS_RSP == iso_state) {
@@ -687,7 +696,9 @@ static void process_byte_pps(uint8_t byte)
usb_send_fidi(pps_cur[2]); /* send Fi/Di change notification to host software over USB */
} else { /* checksum is invalid */
TRACE_INFO("PPS negotiation failed\n\r");
g_stats.num_csum_errors++;
}
g_stats.num_pps++;
change_state(ISO7816_S_WAIT_TPDU); /* go to next state */
}
break;
@@ -724,6 +735,7 @@ static void process_byte_tpdu(uint8_t byte)
return;
}
if (g_tpdu.packet_i >= ARRAY_SIZE(g_tpdu.packet)) {
g_stats.num_tpdu_overflows++;
TRACE_ERROR("TPDU data overflow\n\r");
return;
}
@@ -734,6 +746,7 @@ static void process_byte_tpdu(uint8_t byte)
if (0xff == byte) {
TRACE_WARNING("0xff is not a valid class byte\n\r");
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
g_stats.num_tpdu_malformed++;
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_MALFORMED); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return;
@@ -746,6 +759,7 @@ static void process_byte_tpdu(uint8_t byte)
if ((0x60 == (byte & 0xf0)) || (0x90 == (byte & 0xf0))) {
TRACE_WARNING("invalid INS 0x%02x\n\r", byte);
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
g_stats.num_tpdu_malformed++;
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_MALFORMED); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return;
@@ -786,6 +800,7 @@ static void process_byte_tpdu(uint8_t byte)
} else {
TRACE_WARNING("invalid SW1 0x%02x\n\r", byte);
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
g_stats.num_tpdu_malformed++;
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_MALFORMED); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return;
@@ -794,6 +809,7 @@ static void process_byte_tpdu(uint8_t byte)
case TPDU_S_SW2:
g_tpdu.packet[g_tpdu.packet_i++] = byte;
usb_send_tpdu(0); /* send TPDU to host software using USB */
g_stats.num_tpdu++;
change_state(ISO7816_S_WAIT_TPDU); /* this is the end of the TPDU */
break;
case TPDU_S_DATA_SINGLE:
@@ -832,17 +848,28 @@ void Sniffer_usart_isr(void)
if (csr & US_CSR_RXRDY) {
/* Read communication data byte between phone and SIM */
byte = RBUF16_F_DATA_BYTE | (sniff_usart.base->US_RHR & 0xff);
g_stats.num_bytes++;
/* Reset WT timer */
wt_remaining = g_wt;
}
/* Verify if there was an error */
if (csr & US_CSR_OVRE)
if (csr & US_CSR_OVRE) {
g_stats.num_usart.overruns++;
byte |= RBUF16_F_OVERRUN;
if (csr & US_CSR_FRAME)
}
if (csr & US_CSR_FRAME) {
g_stats.num_usart.framing_errs++;
byte |= RBUF16_F_FRAMING;
if (csr & US_CSR_PARE)
}
if (csr & US_CSR_PARE) {
g_stats.num_usart.parity_errs++;
byte |= RBUF16_F_PARITY;
}
if (csr & US_CSR_RXBRK) {
g_stats.num_usart.breaks++;
byte |= RBUF16_F_BREAK;
};
if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE))
sniff_usart.base->US_CR |= US_CR_RSTSTA;
@@ -856,6 +883,7 @@ void Sniffer_usart_isr(void)
change_flags |= SNIFF_CHANGE_FLAG_TIMEOUT_WT;
/* Reset timeout value */
wt_remaining = g_wt;
g_stats.num_waiting_time_exp++;
} else {
wt_remaining -= (sniff_usart.base->US_RTOR & 0xffff); /* be sure to subtract the actual timeout since the new might not have been set and reloaded yet */
}
@@ -874,8 +902,10 @@ void Sniffer_usart_isr(void)
/* Store sniffed data (or error flags, or both) into buffer */
if (byte) {
if (rbuf16_write(&sniff_buffer, byte) != 0)
if (rbuf16_write(&sniff_buffer, byte) != 0) {
g_stats.num_ringbuf_overflows++;
TRACE_ERROR("USART buffer full\n\r");
}
}
}
@@ -891,6 +921,7 @@ static void Sniffer_reset_isr(const Pin* pPin)
/* Update the ISO state according to the reset change (reset is active low) */
if (PIO_Get(&pin_rst)) {
change_flags |= SNIFF_CHANGE_FLAG_RESET_DEASSERT; /* set flag and let main loop send it */
g_stats.num_reset++;
} else {
change_flags |= SNIFF_CHANGE_FLAG_RESET_ASSERT; /* set flag and let main loop send it */
}
@@ -918,7 +949,8 @@ void Sniffer_usart0_irq(void)
* Initialization routine
*-----------------------------------------------------------------------------*/
#define SNIFFER_IER (US_IER_RXRDY | US_IER_TIMEOUT | US_IER_OVRE | US_IER_FRAME | US_IER_PARE)
#define SNIFFER_IER (US_IER_RXRDY | US_IER_TIMEOUT | US_IER_OVRE | US_IER_FRAME | US_IER_PARE | \
US_CSR_RXBRK)
/* Called during USB enumeration after device is enumerated by host */
void Sniffer_configure(void)
@@ -945,6 +977,8 @@ void Sniffer_init(void)
{
TRACE_INFO("Sniffer Init\n\r");
memset(&g_stats, 0, sizeof(g_stats));
/* Configure pins to sniff communication between phone and card */
PIO_Configure(pins_sniff, PIO_LISTSIZE(pins_sniff));
/* Configure pins to connect phone to card */
@@ -1101,6 +1135,8 @@ void Sniffer_run(void)
TRACE_ERROR("USART FRAMING Error\r\n");
if (entry & RBUF16_F_OVERRUN)
TRACE_ERROR("USART OVERRUN Error\r\n");
if (entry & RBUF16_F_BREAK)
TRACE_ERROR("USART BREAK Error\r\n");
}
/* Handle flags */

View File

@@ -7,7 +7,6 @@ CFLAGS=-g -Wall $(LIBOSMOCORE_CFLAGS) \
-I../atmel_softpack_libraries/libchip_sam3s/cmsis \
-I../atmel_softpack_libraries/libchip_sam3s/include \
-I../atmel_softpack_libraries/usb/include \
-I../atmel_softpack_libraries/ \
-I../libcommon/include \
-I../libboard/common/include \
-I../libboard/simtrace/include \

View File

@@ -93,14 +93,7 @@ void card_emu_uart_reset_wt(uint8_t uart_chan)
printf("%s(uart_chan=%u\n", __func__, uart_chan);
}
void mode_cardemu_set_presence_pol(uint8_t instance, bool high)
{
}
bool mode_cardemu_get_presence_pol(uint8_t instance)
{
return false;
}
/***********************************************************************
* test helper functions

View File

@@ -56,9 +56,9 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
CFLAGS="$saved_CFLAGS"
AC_SUBST(SYMBOL_VISIBILITY)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.11.0)
PKG_CHECK_MODULES(LIBOSMOSIM, libosmosim >= 1.11.0)
PKG_CHECK_MODULES(LIBOSMOUSB, libosmousb >= 1.11.0)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
PKG_CHECK_MODULES(LIBOSMOSIM, libosmosim >= 1.4.0)
PKG_CHECK_MODULES(LIBOSMOUSB, libosmousb >= 1.4.0)
PKG_CHECK_MODULES(LIBUSB, libusb-1.0)
AC_ARG_ENABLE(sanitize,
@@ -100,4 +100,5 @@ AC_OUTPUT(
src/Makefile
lib/Makefile
contrib/Makefile
contrib/simtrace2.spec
Makefile)

View File

@@ -0,0 +1,102 @@
#
# spec file for package simtrace2
#
# Copyright (c) 2021 SUSE LLC
# Copyright (c) 2018-2021, Martin Hauke <mardnh@gmx.de>
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
%define sover 1
Name: simtrace2
Version: @VERSION@
Release: 0
Summary: Osmocom SIMtrace host utility
License: GPL-2.0-or-later
Group: Productivity/Telephony/Utilities
URL: https://osmocom.org/projects/simtrace2/wiki
Source: %{name}-%{version}.tar.xz
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
BuildRequires: pkgconfig
BuildRequires: pkgconfig(libosmocore) >= 1.4.0
BuildRequires: pkgconfig(libosmosim) >= 1.4.0
BuildRequires: pkgconfig(libosmousb) >= 1.4.0
BuildRequires: pkgconfig(libpcsclite)
BuildRequires: pkgconfig(libusb-1.0)
%description
Osmocom SIMtrace 2 is a software and hardware system for passively
tracing SIM-ME communication between the SIM card and the mobile phone,
and remote SIM operation.
This package contains SIMtrace 2 host utility.
%package -n libosmo-simtrace2-%{sover}
Summary: Driver functions for Osmocom SIMtrace2 and compatible firmware
Group: System/Libraries
%description -n libosmo-simtrace2-%{sover}
This library contains core "driver" functionality to interface with the
Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
applications to implement SIM card / smart card tracing as well as
SIM / smart card emulation functions.
%package -n libosmo-simtrace2-devel
Summary: Development files for the Osmocom SIMtrace2 library
Group: Development/Libraries/C and C++
Requires: libosmo-simtrace2-%{sover} = %{version}
%description -n libosmo-simtrace2-devel
Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
applications to implement SIM card / smart card tracing as well as
SIM / smart card emulation functions.
This subpackage contains libraries and header files for developing
applications that want to make use of libosmo-simtrace2.
%prep
%setup -q
%build
cd host
echo "%{version}" >.tarball-version
autoreconf -fiv
%configure --disable-static
%make_build
%install
%make_install -C host
install -Dm0644 host/contrib/99-simtrace2.rules %{buildroot}/%{_udevrulesdir}/99-simtrace2.rules
find %{buildroot} -type f -name "*.la" -delete -print
%post -n libosmo-simtrace2-%{sover} -p /sbin/ldconfig
%postun -n libosmo-simtrace2-%{sover} -p /sbin/ldconfig
%files
%license host/COPYING
%doc README.md
%{_bindir}/simtrace2-cardem-pcsc
%{_bindir}/simtrace2-list
%{_bindir}/simtrace2-sniff
%{_bindir}/simtrace2-tool
%{_udevrulesdir}/99-simtrace2.rules
%files -n libosmo-simtrace2-%{sover}
%{_libdir}/libosmo-simtrace2.so.%{sover}*
%files -n libosmo-simtrace2-devel
%dir %{_includedir}/osmocom/
%dir %{_includedir}/osmocom/simtrace2/
%{_includedir}/osmocom/simtrace2/*.h
%{_libdir}/libosmo-simtrace2.so
%{_libdir}/pkgconfig/libosmo-simtrace2.pc
%changelog

View File

@@ -41,11 +41,10 @@ struct osmo_st2_cardem_inst {
void *priv;
};
struct cardemu_usb_msg_config;
int osmo_st2_slot_tx_msg(struct osmo_st2_slot *slot, struct msgb *msg,
uint8_t msg_class, uint8_t msg_type);
int osmo_st2_generic_request_board_info(struct osmo_st2_slot *slot);
int osmo_st2_cardem_request_card_insert(struct osmo_st2_cardem_inst *ci, bool inserted);
int osmo_st2_cardem_request_pb_and_rx(struct osmo_st2_cardem_inst *ci, uint8_t pb, uint8_t le);
@@ -55,7 +54,7 @@ int osmo_st2_cardem_request_sw_tx(struct osmo_st2_cardem_inst *ci, const uint8_t
int osmo_st2_cardem_request_set_atr(struct osmo_st2_cardem_inst *ci, const uint8_t *atr,
unsigned int atr_len);
int osmo_st2_cardem_request_config(struct osmo_st2_cardem_inst *ci, uint32_t features);
int osmo_st2_cardem_request_config2(struct osmo_st2_cardem_inst *ci, const struct cardemu_usb_msg_config *config);
int osmo_st2_modem_reset_pulse(struct osmo_st2_slot *slot, uint16_t duration_ms);
int osmo_st2_modem_reset_active(struct osmo_st2_slot *slot);

View File

@@ -1,7 +1,7 @@
# This is _NOT_ the library release version, it's an API version.
# Please read chapter "Library interface versions" of the libtool documentation
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
ST2_LIBVERSION=2:0:1
ST2_LIBVERSION=1:0:0
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS= -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSIM_CFLAGS) $(LIBUSB_CFLAGS) $(COVERAGE_CFLAGS)

View File

@@ -154,6 +154,19 @@ int osmo_st2_slot_tx_msg(struct osmo_st2_slot *slot, struct msgb *msg,
return rc;
}
/***********************************************************************
* Generic protocol
***********************************************************************/
/*! \brief Requeset the SIMtrace2 board information structure from the device */
int osmo_st2_generic_request_board_info(struct osmo_st2_slot *slot)
{
struct msgb *msg = st_msgb_alloc();
return osmo_st2_slot_tx_msg(slot, msg, SIMTRACE_MSGC_GENERIC, SIMTRACE_CMD_BD_BOARD_INFO);
}
/***********************************************************************
* Card Emulation protocol
***********************************************************************/
@@ -272,21 +285,6 @@ int osmo_st2_cardem_request_config(struct osmo_st2_cardem_inst *ci, uint32_t fea
return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_CONFIG);
}
/* user_cfg is in host byte order. */
int osmo_st2_cardem_request_config2(struct osmo_st2_cardem_inst *ci, const struct cardemu_usb_msg_config *user_cfg)
{
struct msgb *msg = st_msgb_alloc();
struct cardemu_usb_msg_config *tx_cfg;
tx_cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*tx_cfg));
LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(features=%08x)\n", __func__, tx_cfg->features);
memcpy(tx_cfg, user_cfg, sizeof(*tx_cfg));
osmo_store32le(user_cfg->features, &tx_cfg->features);
return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_CONFIG);
}
/***********************************************************************
* Modem Control protocol
***********************************************************************/

View File

@@ -413,7 +413,6 @@ static void print_help(void)
"\t-S\t--usb-altsetting ALTSETTING_ID\n"
"\t-A\t--usb-address\tADDRESS\n"
"\t-H\t--usb-path\tPATH\n"
"\t-Z\t--set-sim-presence\t<0/1>\n"
"\n"
);
}
@@ -432,7 +431,6 @@ static const struct option opts[] = {
{ "usb-altsetting", 1, 0, 'S' },
{ "usb-address", 1, 0, 'A' },
{ "usb-path", 1, 0, 'H' },
{ "set-sim-presence", 1, 0, 'Z' },
{ NULL, 0, 0, 0 }
};
@@ -489,7 +487,6 @@ int main(int argc, char **argv)
char *path = NULL;
struct osim_reader_hdl *reader;
struct osim_card_hdl *card;
struct cardemu_usb_msg_config cardem_config = { .features = CEMU_FEAT_F_STATUS_IRQ };
print_welcome();
@@ -512,7 +509,7 @@ int main(int argc, char **argv)
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, "hi:V:P:C:I:S:A:H:akn:t:Z:", opts, &option_index);
c = getopt_long(argc, argv, "hi:V:P:C:I:S:A:H:akn:t:", opts, &option_index);
if (c == -1)
break;
switch (c) {
@@ -556,10 +553,6 @@ int main(int argc, char **argv)
case 'H':
path = optarg;
break;
case 'Z':
cardem_config.pres_pol = atoi(optarg) ? CEMU_CONFIG_PRES_POL_PRES_H : 0;
cardem_config.pres_pol |= CEMU_CONFIG_PRES_POL_VALID;
break;
}
}
@@ -643,7 +636,7 @@ int main(int argc, char **argv)
allocate_and_submit_in(ci);
/* request firmware to generate STATUS on IRQ endpoint */
osmo_st2_cardem_request_config2(ci, &cardem_config);
osmo_st2_cardem_request_config(ci, CEMU_FEAT_F_STATUS_IRQ);
/* simulate card-insert to modem (owhw, not qmod) */
osmo_st2_cardem_request_card_insert(ci, true);

View File

@@ -63,6 +63,7 @@ static void print_help(void)
"\n"
);
printf( "Commands:\n"
"\tgeneric board-info\n"
"\tmodem reset (enable|disable|cycle)\n"
"\tmodem sim-switch (local|remote)\n"
"\tmodem sim-card (insert|remove)\n"
@@ -98,9 +99,15 @@ static void run_mainloop(struct osmo_st2_cardem_inst *ci)
fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc);
return;
}
if (rc >= 0) {
printf("Rx(%u): %s\n", xfer_len, osmo_hexdump(buf, xfer_len));
osmo_st2_generic_request_board_info(ci->slot);
}
#if 0
/* break the loop if no new messages arrive within 100ms */
if (rc == LIBUSB_ERROR_TIMEOUT)
return;
#endif
}
}
@@ -216,6 +223,36 @@ static int do_subsys_modem(int argc, char **argv)
return rc;
}
static int do_generic_board_info(int argc, char **argv)
{
printf("ci: %p\n", ci);
printf("ci->slot: %p\n", ci->slot);
printf("ci->slot->transp: %p\n", ci->slot->transp);
return osmo_st2_generic_request_board_info(ci->slot);
}
static int do_subsys_generic(int argc, char **argv)
{
char *command;
int rc;
if (argc < 1)
return -EINVAL;
command = argv[0];
argc--;
argv++;
if (!strcmp(command, "board-info")) {
rc = do_generic_board_info(argc, argv);
} else {
fprintf(stderr, "Unsupported command for subsystem generic: '%s'\n", command);
return -EINVAL;
}
return rc;
}
static int do_command(int argc, char **argv)
{
char *subsys;
@@ -227,7 +264,9 @@ static int do_command(int argc, char **argv)
argc--;
argv++;
if (!strcmp(subsys, "modem"))
if (!strcmp(subsys, "generic")) {
rc= do_subsys_generic(argc, argv);
} else if (!strcmp(subsys, "modem"))
rc = do_subsys_modem(argc, argv);
else {
fprintf(stderr, "Unsupported subsystem '%s'\n", subsys);