13 Commits

Author SHA1 Message Date
Harald Welte
cb0772cb22 simtrace2-cardem-pcsc: Make it work again
* support Interrupt STATUS notifications
* use osmocom libusb abstraction
* use asynchronous URBs for interrupt + bulk

Change-Id: Ib04798572295f25477719124530b6584780c5b75
2021-04-05 20:30:21 +02:00
Harald Welte
0b41ef7055 cardem: 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
2021-04-05 19:19:26 +02:00
Harald Welte
43ddf10bbc card_emu: explicitly initialize PTS and TPDU states
Those are already initialized at various transitions of the master
7816 FSM, but let's properly initialize them at start-up, too.

Change-Id: I81b2a8ef3284559164700d94717e4ccf008f53df
2021-04-05 18:19:19 +02:00
Harald Welte
83832db7b7 card_emu: improve reset detection conditions
* enter ISO_S_WAIT_RST when RST is asserted
* enter ISO_S_WAIT_ATR only when we RST is released while in state ISO_S_WAIT_RST

Change-Id: I620333aa8d45561a8028b948955a27f667b58406
2021-04-05 18:16:14 +02:00
Harald Welte
7ee3a3812f iso7816_fidi: Add iso7816_3_ prefix to symbols; fix terminology
Fi/Di are not the index into the table, but the contents of the table
as resolved by Fi_index / Di_index.  Let's clarify the terminology.

Change-Id: If364e08e7c9a3a9707e6d54b9267c6a7c088e415
2021-04-05 18:08:49 +02:00
Harald Welte
eb1b0b3133 card_emu: Clarify and differentiate F/Fi/F_index/Fi_index
The ISO7816 spec terms are well-defined, let's not abuse them. We used
to consider "Fi" as the "index into the table of F values", while the
spec actually considers Fi as the initial value for F.

Let's make sure we use the terms quite clearly:
* Fi and Di are the initial values for F and D
* F*_index and D*_index are the indexes into the ISO7816-3 Tables

Furthermore, let's track Fi separately from F, as e.g. the waiting
time definition only considers Fi as indicated in the ATR, despite
an actually different F value might have been negotiated via PTS
meanwhile.

Change-Id: Ieb2425e8380a81b79df7b2bd072902994e9c3ee7
2021-04-05 17:59:42 +02:00
Harald Welte
d7af9be9b6 card_emu.c: Rename fi to Fi and di to Di
As we will soon introduce the distinction between Fi and F, we should
use uppercase letters, as lower-case 'f' is defined in ISO7816-3 as
the frequency, which is different from the upper-case 'F'.

Change-Id: Iaede621551520576e9b9af878fa46fbc88e59c2a
2021-04-05 17:04:38 +02:00
Kévin Redon
3f877b257b cardemu: different init for simtrace board which uses uart timers
Change-Id: I464f0ce1ec5e60be5f9377186b7d13a5e6dc637e
2021-04-05 17:00:45 +02:00
Kévin Redon
963ce603db make sim switch board specific
the simtrace board uses a bus switch not used on qmod and owhw to
switch the SIM between physical and virtual

Change-Id: Ieaf2ed4761fc3e04f33f9aac5c04a768c9a6f71e
2021-04-05 17:00:45 +02:00
Kévin Redon
95fcdb666e cardem: use edge-triggered VCC ADC logic
Before this patch, we used to st ci->vcc_active depending on the
instantaneous ADC reading of VCC.  Is it > .5v, we claim VCC is active,
and if it's below, VCC is inactive.

With this patch we move to an edge triggered approach: Only change
ci->vcc_active if the previous reading was different from the current
reading.

FIXME: why?

Change-Id: I71b703162219484e43638f1f2f692e9dd554ef55
2021-04-05 17:00:45 +02:00
Harald Welte
814c9aec0f card_emu: waiting_time is stored in etu, not clocks.
The comment didn't reflect the source.  I checked all users and
the code consistently stores the waiting time in units of 'etu'.

Change-Id: I2bc4a7c19cee5fb487ad639ee48ecaea706f6172
2021-04-05 17:00:45 +02:00
Harald Welte
0cf5586625 Revert "add library providing ISO 7816-3 utilities"
This reverts commit 4a29f64cbe.

The code replicates to a large extent what is already present in iso7816_fidi.c
and I have serious doubts about the correctness of the computation in
its iso7816_3_calculate_wt() function.
2021-04-05 17:00:45 +02:00
Harald Welte
0a1026c2de Revert "add ISO 7816-3 library to remsim project"
This reverts commit 4a58c08d67.

The code replicates to a large extent what is already present in iso7816_fidi.c
and I have serious doubts about the correctness of the computation in
its iso7816_3_calculate_wt() function.
2021-04-05 17:00:45 +02:00
30 changed files with 285 additions and 1005 deletions

View File

@@ -28,10 +28,9 @@ export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$inst/lib" export LD_LIBRARY_PATH="$inst/lib"
BUILDS="" BUILDS=""
BUILDS+="simtrace/dfu simtrace/trace simtrace/cardem " BUILDS+="simtrace/dfu simtrace/trace "
BUILDS+="qmod/dfu qmod/cardem " BUILDS+="qmod/dfu qmod/cardem "
BUILDS+="owhw/dfu owhw/cardem " BUILDS+="owhw/dfu owhw/cardem "
BUILDS+="octsimtest/cardem "
cd $TOPDIR/firmware cd $TOPDIR/firmware
for build in $BUILDS; do for build in $BUILDS; do
@@ -64,19 +63,21 @@ make dist
# make -C "$base/doc/manuals" publish # make -C "$base/doc/manuals" publish
#fi #fi
rm -rf $TOPDIR/firmware/bin/simtrace-cardem*
if [ "x$publish" = "x--publish" ]; then if [ "x$publish" = "x--publish" ]; then
echo echo
echo "=============== UPLOAD BUILD ==============" echo "=============== UPLOAD BUILD =============="
$TOPDIR/contrib/prepare_upload.sh $TOPDIR/contrib/prepare_upload.sh
cat > "/build/known_hosts" <<EOF cat > "/build/known_hosts" <<EOF
[ftp.osmocom.org]:48 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDgQ9HntlpWNmh953a2Gc8NysKE4orOatVT1wQkyzhARnfYUerRuwyNr1GqMyBKdSI9amYVBXJIOUFcpV81niA7zQRUs66bpIMkE9/rHxBd81SkorEPOIS84W4vm3SZtuNqa+fADcqe88Hcb0ZdTzjKILuwi19gzrQyME2knHY71EOETe9Yow5RD2hTIpB5ecNxI0LUKDq+Ii8HfBvndPBIr0BWYDugckQ3Bocf+yn/tn2/GZieFEyFpBGF/MnLbAAfUKIdeyFRX7ufaiWWz5yKAfEhtziqdAGZaXNaLG6gkpy3EixOAy6ZXuTAk3b3Y0FUmDjhOHllbPmTOcKMry9 [rita.osmocom.org]:48 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDgQ9HntlpWNmh953a2Gc8NysKE4orOatVT1wQkyzhARnfYUerRuwyNr1GqMyBKdSI9amYVBXJIOUFcpV81niA7zQRUs66bpIMkE9/rHxBd81SkorEPOIS84W4vm3SZtuNqa+fADcqe88Hcb0ZdTzjKILuwi19gzrQyME2knHY71EOETe9Yow5RD2hTIpB5ecNxI0LUKDq+Ii8HfBvndPBIr0BWYDugckQ3Bocf+yn/tn2/GZieFEyFpBGF/MnLbAAfUKIdeyFRX7ufaiWWz5yKAfEhtziqdAGZaXNaLG6gkpy3EixOAy6ZXuTAk3b3Y0FUmDjhOHllbPmTOcKMry9
[ftp.osmocom.org]:48 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPdWn1kEousXuKsZ+qJEZTt/NSeASxCrUfNDW3LWtH+d8Ust7ZuKp/vuyG+5pe5pwpPOgFu7TjN+0lVjYJVXH54= [rita.osmocom.org]:48 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPdWn1kEousXuKsZ+qJEZTt/NSeASxCrUfNDW3LWtH+d8Ust7ZuKp/vuyG+5pe5pwpPOgFu7TjN+0lVjYJVXH54=
[ftp.osmocom.org]:48 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8iivY70EiR5NiGChV39gRLjNpC8lvu1ZdHtdMw2zuX [rita.osmocom.org]:48 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8iivY70EiR5NiGChV39gRLjNpC8lvu1ZdHtdMw2zuX
EOF EOF
SSH_COMMAND="ssh -o 'UserKnownHostsFile=/build/known_hosts' -p 48" SSH_COMMAND="ssh -o 'UserKnownHostsFile=/build/known_hosts' -p 48"
rsync --archive --verbose --compress --delete --rsh "$SSH_COMMAND" $TOPDIR/firmware/bin/*-latest.{bin,elf} binaries@ftp.osmocom.org:web-files/simtrace2/firmware/latest/ rsync --archive --verbose --compress --delete --rsh "$SSH_COMMAND" $TOPDIR/firmware/bin/*-latest.{bin,elf} binaries@rita.osmocom.org:web-files/simtrace2/firmware/latest/
rsync --archive --verbose --compress --rsh "$SSH_COMMAND" --exclude $TOPDIR/firmware/bin/*-latest.{bin,elf} $TOPDIR/firmware/bin/*-*-*-*.{bin,elf} binaries@ftp.osmocom.org:web-files/simtrace2/firmware/all/ rsync --archive --verbose --compress --rsh "$SSH_COMMAND" --exclude $TOPDIR/firmware/bin/*-latest.{bin,elf} $TOPDIR/firmware/bin/*-*-*-*.{bin,elf} binaries@rita.osmocom.org:web-files/simtrace2/firmware/all/
fi fi
echo echo

View File

@@ -178,14 +178,6 @@ CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_L
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
CFLAGS += -DBOARD=\"$(BOARD)\" -DBOARD_$(BOARD) CFLAGS += -DBOARD=\"$(BOARD)\" -DBOARD_$(BOARD)
CFLAGS += -DAPPLICATION=\"$(APP)\" -DAPPLICATION_$(APP) CFLAGS += -DAPPLICATION=\"$(APP)\" -DAPPLICATION_$(APP)
# Disable stack protector by default (OS#5081)
ifeq ($(STACK_PROTECTOR), 1)
CFLAGS += -fstack-protector
else
CFLAGS += -fno-stack-protector
endif
ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__ ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__
LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--print-memory-usage -Wl,--no-undefined $(LIB) LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--print-memory-usage -Wl,--no-undefined $(LIB)
#LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats #LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats

View File

@@ -221,7 +221,6 @@ extern int main(void)
} }
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
} else { } else {
//FIXME: usb_proces() for every interface in this configuration?
if (config_func_ptrs[simtrace_config].run) { if (config_func_ptrs[simtrace_config].run) {
config_func_ptrs[simtrace_config].run(); config_func_ptrs[simtrace_config].run();
} }

View File

@@ -1672,10 +1672,6 @@ uint8_t USBD_HAL_Halt(uint8_t bEndpoint, uint8_t ctl)
UDP->UDP_RST_EP |= 1 << bEndpoint; UDP->UDP_RST_EP |= 1 << bEndpoint;
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 */ /* Return Halt status */

View File

@@ -50,28 +50,81 @@
/* Button to force bootloader start (shorted to ground when pressed */ /* Button to force bootloader start (shorted to ground when pressed */
#define PIN_BOOTLOADER_SW {PIO_PA5, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP} #define PIN_BOOTLOADER_SW {PIO_PA5, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
//FIXME SIM_PWEN_PIN collides with PA5/bootloader_sw on octsimtest
/* Enable powering the card using the second 3.3 V output of the LDO (active high) */
#define SIM_PWEN_PIN {PIO_PA12, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Enable powering the SIM card */
#define PWR_PINS SIM_PWEN_PIN
// FIXME PA8 is 32khz xtal on octsimtest // FIXME PA8 is 32khz xtal on octsimtest
/* Card presence pin */
#define SW_SIM PIO_PA11
/* Pull card presence pin high (shorted to ground in card slot when card is present) */ /* Pull card presence pin high (shorted to ground in card slot when card is present) */
#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
/** Smart card connection **/
//FIXME
/* Card RST reset signal input (active low; RST_SIM in schematic) */
#define PIN_SIM_RST {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* Card I/O data signal input/output (I/O_SIM in schematic) */
#define PIN_SIM_IO {PIO_PA6A_TXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Card CLK clock input (CLK_SIM in schematic) */
#define PIN_SIM_CLK {PIO_PA2B_SCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/* Pin to measure card I/O timing (to start measuring the ETU on I/O activity; connected I/O_SIM in schematic) */
#define PIN_SIM_IO_INPUT {PIO_PA1B_TIOB0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
//FIXME PIO_PA4B_TCLK0 PA4 is LED on octsimtest
/* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */
#define PIN_SIM_CLK_INPUT {PIO_PA14, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/* Pins used to measure ETU timing (using timer counter) */
#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT
/** Phone connection **/ /** Phone connection **/
/* Phone USIM slot 1 VCC pin (VCC_PHONE in schematic) */ /* Phone USIM slot 1 VCC pin (VCC_PHONE in schematic) */
#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT} #define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
/* Phone USIM slot 1 RST pin (active low; RST_PHONE in schematic) */ /* Phone USIM slot 1 RST pin (active low; RST_PHONE in schematic) */
#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_EDGE | PIO_DEGLITCH } #define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_RISE_EDGE | PIO_DEGLITCH }
/* Phone I/O data signal input/output (I/O_PHONE in schematic) */ /* Phone I/O data signal input/output (I/O_PHONE in schematic) */
#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Phone CLK clock input (CLK_PHONE in schematic) */ /* Phone CLK clock input (CLK_PHONE in schematic) */
#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Pin used to switch level shifter in I/O line between rx (0) and tx (1) */
#define PIN_USIM1_IO_DIR {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* Pin used for phone USIM slot 1 communication */ /* Pin used for phone USIM slot 1 communication */
#define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST, PIN_USIM1_IO_DIR #define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST
/* Phone I/O data signal input/output (unused USART RX input; connected to I/O_PHONE in schematic) */ /* Phone I/O data signal input/output (unused USART RX input; connected to I/O_PHONE in schematic) */
#define PIN_PHONE_IO_INPUT {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PIN_PHONE_IO_INPUT {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */ /* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */
#define PIN_PHONE_CLK_INPUT {PIO_PA29B_TCLK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} #define PIN_PHONE_CLK_INPUT {PIO_PA29B_TCLK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/** Default pin configuration **/ /** Default pin configuration **/
/* Disconnect VPP, CLK, and RST lines between card and phone using bus switch (high sets bus switch to high-impedance) */
#define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Disconnect I/O line between card and phone using bus switch (high sets bus switch to high-impedance) */
#define PIN_IO_SW_DEFAULT {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Disconnect all lines (VPP, CLK, RST, and I/O) between card and phone */
#define PINS_BUS_DEFAULT PIN_SC_SW_DEFAULT, PIN_IO_SW_DEFAULT
/** Sniffer configuration **/
/* Connect VPP, CLK, and RST lines between card and phone using bus switch (low connects signals on bus switch) */
#define PIN_SC_SW_SNIFF {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* Connect I/O line between card and phone using bus switch (low connects signals on bus switch) */
#define PIN_IO_SW_SNIFF {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* Connect all lines (VPP, CLK, RST, and I/O) between card and phone */
#define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF
/* Card RST reset signal input (use as input since the phone will drive it) */
#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
/* Pins used to sniff phone-card communication */
#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF
/* Disable power converter 4.5-6V to 3.3V (active high) */
#define PIN_SIM_PWEN_SNIFF {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* Enable power switch to forward VCC_PHONE to VCC_SIM (active high) */
#define PIN_VCC_FWD_SNIFF {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Use phone VCC to power card */
#define PINS_PWR_SNIFF PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF
/** CCID configuration */
/* Card RST reset signal input (active low; RST_SIM in schematic) */
#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* ISO7816-communication related pins */
#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2
/** External SPI flash interface **/ /** External SPI flash interface **/
/* SPI MISO pin definition */ /* SPI MISO pin definition */
@@ -96,32 +149,21 @@
/* OpenMoko SIMtrace 2 USB vendor ID */ /* OpenMoko SIMtrace 2 USB vendor ID */
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO #define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */ /* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_OCTSIMTEST #define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2
/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */ /* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_OCTSIMTEST #define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU
/* USB release number (bcdDevice, shown as 0.00) */ /* USB release number (bcdDevice, shown as 0.00) */
#define BOARD_USB_RELEASE 0x000 #define BOARD_USB_RELEASE 0x000
/* Indicate SIMtrace is bus power in USB attributes */ /* Indicate SIMtrace is bus power in USB attributes */
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP #define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
#define DETECT_VCC_BY_ADC
/* we have a resistive voltage divider of 47 + 30 kOhms to also detect 5V supply power */
#define VCC_UV_THRESH_1V8 (1500000*47)/(47+30)
#define VCC_UV_THRESH_3V (2500000*47)/(47+30)
#define HAVE_SLOT_MUX
#define HAVE_BOARD_CARDINSERT
struct cardem_inst;
void board_set_card_insert(struct cardem_inst *ci, bool card_insert);
/** Supported modes */ /** Supported modes */
/* SIMtrace board supports sniffer mode */ /* SIMtrace board supports sniffer mode */
//#define HAVE_SNIFFER //#define HAVE_SNIFFER
/* SIMtrace board supports CCID mode */ /* SIMtrace board supports CCID mode */
//#define HAVE_CCID //#define HAVE_CCID
/* SIMtrace board supports card emulation mode */ /* SIMtrace board supports card emulation mode */
#define HAVE_CARDEM //#define HAVE_CARDEM
/* SIMtrace board supports man-in-the-middle mode */ /* SIMtrace board supports man-in-the-middle mode */
//#define HAVE_MITM //#define HAVE_MITM
/* octsimtest board supports gpio_test mode */ /* octsimtest board supports gpio_test mode */

View File

@@ -18,10 +18,8 @@
#define MCP23017_ADDRESS 0x20 #define MCP23017_ADDRESS 0x20
int mcp23017_init(uint8_t slave, uint8_t iodira, uint8_t iodirb); int mcp23017_init(uint8_t slave);
int mcp23017_test(uint8_t slave); int mcp23017_test(uint8_t slave);
int mcp23017_toggle(uint8_t slave); int mcp23017_toggle(uint8_t slave);
int mcp23017_set_output_a(uint8_t slave, uint8_t val);
int mcp23017_set_output_b(uint8_t slave, uint8_t val);
//int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte); //int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
//int mcp23017_read_byte(uint8_t slave, uint8_t addr); //int mcp23017_read_byte(uint8_t slave, uint8_t addr);

View File

@@ -1,17 +0,0 @@
#pragma once
void mux_init(void);
int mux_set_slot(uint8_t s);
int mux_get_slot(void);
void mux_set_freq(uint8_t s);
/* this reflects the wiring between U5 and U4 */
#define MUX_FREQ_DIV_2 0
#define MUX_FREQ_DIV_4 1
#define MUX_FREQ_DIV_16 2
#define MUX_FREQ_DIV_32 3
#define MUX_FREQ_DIV_32 3
#define MUX_FREQ_DIV_128 4
#define MUX_FREQ_DIV_512 5
#define MUX_FREQ_DIV_2048 6
#define MUX_FREQ_DIV_4096 7

View File

@@ -17,7 +17,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/ */
#include <stdbool.h>
#include "board.h" #include "board.h"
#include "simtrace.h" #include "simtrace.h"
#include "utils.h" #include "utils.h"
@@ -26,29 +25,16 @@
#include "usb_buf.h" #include "usb_buf.h"
#include "i2c.h" #include "i2c.h"
#include "mcp23017.h" #include "mcp23017.h"
#include "mux.h"
static bool mcp2317_present = false;
void board_exec_dbg_cmd(int ch) void board_exec_dbg_cmd(int ch)
{ {
switch (ch) { switch (ch) {
case '?': case '?':
printf("\t?\thelp\n\r"); printf("\t?\thelp\n\r");
printf("\t0-8\tselect physical SIM slot\n\r");
printf("\tR\treset SAM3\n\r"); printf("\tR\treset SAM3\n\r");
printf("\tm\trun mcp23017 test\n\r"); printf("\tm\trun mcp23017 test\n\r");
printf("\ti\tset card insert via I2C\n\r"); printf("\tR\ttoggle MSB of gpio on mcp23017\n\r");
printf("\tI\tdisable card insert\n\r");
break; break;
case '0': mux_set_slot(0); break;
case '1': mux_set_slot(1); break;
case '2': mux_set_slot(2); break;
case '3': mux_set_slot(3); break;
case '4': mux_set_slot(4); break;
case '5': mux_set_slot(5); break;
case '6': mux_set_slot(6); break;
case '7': mux_set_slot(7); break;
case 'R': case 'R':
printf("Asking NVIC to reset us\n\r"); printf("Asking NVIC to reset us\n\r");
USBD_Disconnect(); USBD_Disconnect();
@@ -57,13 +43,8 @@ void board_exec_dbg_cmd(int ch)
case 'm': case 'm':
mcp23017_test(MCP23017_ADDRESS); mcp23017_test(MCP23017_ADDRESS);
break; break;
case 'i': case 't':
printf("Setting card insert (slot=%u)\r\n", mux_get_slot()); mcp23017_toggle(MCP23017_ADDRESS);
mcp23017_set_output_a(MCP23017_ADDRESS, (1 << mux_get_slot()));
break;
case 'I':
printf("Releasing card insert (slot=%u)\r\n", mux_get_slot());
mcp23017_set_output_a(MCP23017_ADDRESS, 0);
break; break;
default: default:
printf("Unknown command '%c'\n\r", ch); printf("Unknown command '%c'\n\r", ch);
@@ -76,13 +57,9 @@ void board_main_top(void)
#ifndef APPLICATION_dfu #ifndef APPLICATION_dfu
usb_buf_init(); usb_buf_init();
mux_init();
i2c_pin_init(); i2c_pin_init();
/* PORT A: all outputs, Port B0 output, B1..B7 unused */ if (!mcp23017_init(MCP23017_ADDRESS))
if (mcp23017_init(MCP23017_ADDRESS, 0x00, 0xfe) == 0) { printf("mcp23017 not found!\n\r");
mcp2317_present = true;
mcp23017_set_output_a(MCP23017_ADDRESS, 0);
}
/* Initialize checking for card insert/remove events */ /* Initialize checking for card insert/remove events */
//card_present_init(); //card_present_init();
#endif #endif
@@ -102,23 +79,3 @@ int board_override_enter_dfu(void)
} else } else
return 0; return 0;
} }
void board_set_card_insert(struct cardem_inst *ci, bool card_insert)
{
int s = mux_get_slot();
/* A0 .. A7 of the MCP are each connected to the gate of a FET which closes
* the sim-present signal of the respective slot */
if (mcp2317_present) {
if (card_insert) {
/* we must enable card-presence of the active slot and disable it on all others */
mcp23017_set_output_a(MCP23017_ADDRESS, (1 << s));
} else {
/* we disable all card insert signals */
mcp23017_set_output_a(MCP23017_ADDRESS, 0);
}
} else {
TRACE_WARNING("No MCP23017 present; cannot set CARD_INSERT\r\n");
}
}

View File

@@ -92,25 +92,19 @@ out_stop:
return 0; return 0;
} }
int mcp23017_init(uint8_t slave, uint8_t iodira, uint8_t iodirb) int mcp23017_init(uint8_t slave)
{ {
TRACE_DEBUG("mcp23017_init\n\r"); printf("mcp23017_init\n\r");
// all gpio input // all gpio input
if (mcp23017_write_byte(slave, MCP23017_IODIRA, iodira)) if (mcp23017_write_byte(slave, MCP23017_IODIRA, 0xff))
goto out_err; return false;
// msb of portb output, rest input // msb of portb output, rest input
if (mcp23017_write_byte(slave, MCP23017_IODIRB, iodirb)) if (mcp23017_write_byte(slave, MCP23017_IODIRB, 0x7f))
goto out_err; return false;
if (mcp23017_write_byte(slave, MCP23017_IOCONA, 0x20)) //disable SEQOP (autoinc addressing) if (mcp23017_write_byte(slave, MCP23017_IOCONA, 0x20)) //disable SEQOP (autoinc addressing)
goto out_err; return false;
printf("mcp23017 found\n\r");
TRACE_DEBUG("mcp23017 found\n\r"); return true;
return 0;
out_err:
TRACE_WARNING("mcp23017 NOT found!\n\r");
return -1;
} }
int mcp23017_test(uint8_t slave) int mcp23017_test(uint8_t slave)
@@ -126,16 +120,6 @@ int mcp23017_test(uint8_t slave)
return 0; return 0;
} }
int mcp23017_set_output_a(uint8_t slave, uint8_t val)
{
return mcp23017_write_byte(slave, MCP23017_OLATA, val);
}
int mcp23017_set_output_b(uint8_t slave, uint8_t val)
{
return mcp23017_write_byte(slave, MCP23017_OLATB, val);
}
int mcp23017_toggle(uint8_t slave) int mcp23017_toggle(uint8_t slave)
{ {
// example writing MSB of gpio // example writing MSB of gpio

View File

@@ -1,113 +0,0 @@
/* sysmoOCTSIMTEST support for multiplexers
*
* (C) 2021 by Harald Welte <laforge@gnumonks.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "mux.h"
#include <stdbool.h>
#include <errno.h>
/* 3-bit S0..S2 signal for slot selection */
static const Pin pin_in_sel[3] = {
{ PIO_PA1, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA2, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA3, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
};
/* 3-bit S0..S2 signal for frequency divider selection */
static const Pin pin_freq_sel[3] = {
{ PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA17, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
{ PIO_PA18, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
};
/* low-active output enable for all muxes */
static const Pin pin_oe = { PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT };
static uint8_t g_mux_slot = 0;
/* initialize the external 1:8 multiplexers */
void mux_init(void)
{
PIO_Configure(&pin_oe, PIO_LISTSIZE(pin_oe));
PIO_Configure(pin_in_sel, PIO_LISTSIZE(pin_in_sel));
PIO_Configure(pin_freq_sel, PIO_LISTSIZE(pin_freq_sel));
mux_set_slot(0);
}
/* set the slot selection mux */
int mux_set_slot(uint8_t s)
{
TRACE_INFO("%s(%u)\r\n", __func__, s);
if (s > 7)
return -EINVAL;
/* !OE = H: disconnect input and output of muxes */
PIO_Set(&pin_oe);
if (s & 1)
PIO_Set(&pin_in_sel[0]);
else
PIO_Clear(&pin_in_sel[0]);
if (s & 2)
PIO_Set(&pin_in_sel[1]);
else
PIO_Clear(&pin_in_sel[1]);
if (s & 4)
PIO_Set(&pin_in_sel[2]);
else
PIO_Clear(&pin_in_sel[2]);
/* !OE = L: (re-)enable the output of muxes */
PIO_Clear(&pin_oe);
g_mux_slot = s;
return s;
}
int mux_get_slot(void)
{
return g_mux_slot;
}
/* set the frequency divider mux */
void mux_set_freq(uint8_t s)
{
TRACE_INFO("%s(%u)\r\n", __func__, s);
/* no need for 'break before make' here, this would also affect
* the SIM card I/O signals which we don't want to disturb */
if (s & 1)
PIO_Set(&pin_freq_sel[0]);
else
PIO_Clear(&pin_freq_sel[0]);
if (s & 2)
PIO_Set(&pin_freq_sel[1]);
else
PIO_Clear(&pin_freq_sel[1]);
if (s & 4)
PIO_Set(&pin_freq_sel[2]);
else
PIO_Clear(&pin_freq_sel[2]);
/* !OE = L: ensure enable the output of muxes */
PIO_Clear(&pin_oe);
}

View File

@@ -1,37 +0,0 @@
/* Code to switch between local (physical) and remote (emulated) SIM
*
* (C) 2021 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "trace.h"
#include "sim_switch.h"
int sim_switch_use_physical(unsigned int nr, int physical)
{
if (physical) {
TRACE_ERROR("%u: Use local/physical SIM - UNSUPPORTED!\r\n", nr);
} else {
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
}
return 0;
}
int sim_switch_init(void)
{
return 1; // SIMtrace hardware has only one switchable interface
}

View File

@@ -91,8 +91,8 @@
#define PINS_WWAN_IN { PIN_WWAN1, PIN_WWAN2 } #define PINS_WWAN_IN { PIN_WWAN1, PIN_WWAN2 }
/* outputs controlling RESET input of modems */ /* outputs controlling RESET input of modems */
#define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_PULLUP} #define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_PULLUP}
#define PIN_PERST2 {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_PULLUP} #define PIN_PERST2 {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_PULLUP}
#define PINS_PERST { PIN_PERST1, PIN_PERST2 } #define PINS_PERST { PIN_PERST1, PIN_PERST2 }
#define PIN_VERSION_DET {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT} #define PIN_VERSION_DET {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}
@@ -109,9 +109,6 @@
#define BOARD_USB_RELEASE 0x010 #define BOARD_USB_RELEASE 0x010
#define CARDEMU_SECOND_UART #define CARDEMU_SECOND_UART
#define DETECT_VCC_BY_ADC #define DETECT_VCC_BY_ADC
#define VCC_UV_THRESH_1V8 1500000
#define VCC_UV_THRESH_3V 2500000
#define HAVE_CARDEM #define HAVE_CARDEM

View File

@@ -153,14 +153,10 @@
/** Supported modes */ /** Supported modes */
/* SIMtrace board supports sniffer mode */ /* SIMtrace board supports sniffer mode */
#ifdef APPLICATION_trace
#define HAVE_SNIFFER #define HAVE_SNIFFER
#endif
/* SIMtrace board supports CCID mode */ /* SIMtrace board supports CCID mode */
//#define HAVE_CCID //#define HAVE_CCID
/* SIMtrace board supports card emulation mode */ /* SIMtrace board supports card emulation mode */
#ifdef APPLICATION_cardem //#define HAVE_CARDEM
#define HAVE_CARDEM
#endif
/* SIMtrace board supports man-in-the-middle mode */ /* SIMtrace board supports man-in-the-middle mode */
//#define HAVE_MITM //#define HAVE_MITM

View File

@@ -89,7 +89,7 @@
/// \param condition Condition to verify. /// \param condition Condition to verify.
#define ASSERT(condition) { \ #define ASSERT(condition) { \
if (!(condition)) { \ if (!(condition)) { \
printf_sync("-F- ASSERT: %s %s:%d\n\r", #condition, __BASE_FILE__, __LINE__); \ printf("-F- ASSERT: %s %s:%d\n\r", #condition, __BASE_FILE__, __LINE__); \
while (1); \ while (1); \
} \ } \
} }

View File

@@ -31,6 +31,7 @@ enum card_io {
/** initialise card slot /** initialise card slot
* @param[in] slot_num slot number (arbitrary number) * @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] uart_chan UART peripheral channel
* @param[in] in_ep USB IN end point number * @param[in] in_ep USB IN end point number
* @param[in] irq_ep USB INTerrupt end point number * @param[in] irq_ep USB INTerrupt end point number
@@ -39,7 +40,7 @@ enum card_io {
* @param[in] clocked initial CLK signat state (true = active) * @param[in] clocked initial CLK signat state (true = active)
* @return main card handle reference * @return main card handle reference
*/ */
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 *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);
/* process a single byte received from the reader */ /* process a single byte received from the reader */
void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte); void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte);

View File

@@ -230,15 +230,9 @@ struct cardemu_usb_msg_status {
uint32_t flags; uint32_t flags;
/* phone-applied target voltage in mV */ /* phone-applied target voltage in mV */
uint16_t voltage_mv; uint16_t voltage_mv;
/* F/D related information. Not actual Fn/Dn values but indexes into tables! */ /* Fi/Di related information */
union { uint8_t F_index; /* <! Index to ISO7816-3 Table 7 (F and f_max values) */
uint8_t F_index; /* <! Index to ISO7816-3 Table 7 (F and f_max values) */ uint8_t D_index; /* <! Index into ISO7816-3 Table 8 (D value) */
uint8_t fi; /* <! old, wrong name for API compatibility */
};
union {
uint8_t D_index; /* <! Index to ISO7816-3 Table 8 (D value) */
uint8_t di; /* <! old, wrong name for API compatibility */
};
uint8_t wi; /* <! Waiting Integer as defined in ISO7816-3 Section 10.2 */ uint8_t wi; /* <! Waiting Integer as defined in ISO7816-3 Section 10.2 */
uint32_t waiting_time; /* <! Waiting Time in etu as defined in ISO7816-3 Section 8.1 */ uint32_t waiting_time; /* <! Waiting Time in etu as defined in ISO7816-3 Section 8.1 */
} __attribute__ ((packed)); } __attribute__ ((packed));
@@ -269,8 +263,6 @@ struct cardemu_usb_msg_error {
struct cardemu_usb_msg_config { struct cardemu_usb_msg_config {
/* bit-mask of CEMU_FEAT_F flags */ /* bit-mask of CEMU_FEAT_F flags */
uint32_t features; uint32_t features;
/* the selected slot number (if an external mux is present) */
uint8_t slot_mux_nr;
} __attribute__ ((packed)); } __attribute__ ((packed));
/*********************************************************************** /***********************************************************************

View File

@@ -25,7 +25,6 @@
#define USB_PRODUCT_QMOD_SAM3 0x4004 #define USB_PRODUCT_QMOD_SAM3 0x4004
#define USB_PRODUCT_SIMTRACE2_DFU 0x60e3 /* was 0x60e2 */ #define USB_PRODUCT_SIMTRACE2_DFU 0x60e3 /* was 0x60e2 */
#define USB_PRODUCT_SIMTRACE2 0x60e3 #define USB_PRODUCT_SIMTRACE2 0x60e3
#define USB_PRODUCT_OCTSIMTEST 0x616d
/* USB proprietary class */ /* USB proprietary class */
#define USB_CLASS_PROPRIETARY 0xff #define USB_CLASS_PROPRIETARY 0xff

View File

@@ -42,15 +42,5 @@ int usb_drain_queue(uint8_t ep);
void usb_buf_init(void); void usb_buf_init(void);
struct usb_buffered_ep *usb_get_buf_ep(uint8_t ep); struct usb_buffered_ep *usb_get_buf_ep(uint8_t ep);
struct usb_if { int usb_refill_to_host(uint8_t ep);
uint8_t if_num; /* interface number */ int usb_refill_from_host(uint8_t ep);
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);

View File

@@ -33,9 +33,6 @@
#include <osmocom/core/linuxlist.h> #include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h> #include <osmocom/core/msgb.h>
#ifdef HAVE_SLOT_MUX
#include "mux.h"
#endif
#define NUM_SLOTS 2 #define NUM_SLOTS 2
@@ -179,6 +176,7 @@ struct card_handle {
* \note this depends on Fi, Di, and WI if T=0 is used */ * \note this depends on Fi, Di, and WI if T=0 is used */
uint32_t waiting_time; /* in etu */ uint32_t waiting_time; /* in etu */
uint8_t tc_chan; /* TC channel number */
uint8_t uart_chan; /* UART channel */ uint8_t uart_chan; /* UART channel */
uint8_t in_ep; /* USB IN EP */ uint8_t in_ep; /* USB IN EP */
@@ -433,7 +431,7 @@ static void card_set_state(struct card_handle *ch,
/* update waiting time to initial waiting time */ /* update waiting time to initial waiting time */
ch->waiting_time = ISO7816_3_INIT_WTIME; ch->waiting_time = ISO7816_3_INIT_WTIME;
/* set initial waiting time */ /* set initial waiting time */
card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time); card_emu_uart_update_wt(ch->tc_chan, ch->waiting_time);
/* Set ATR sub-state to initial state */ /* Set ATR sub-state to initial state */
ch->atr.idx = 0; ch->atr.idx = 0;
/* enable USART transmission to reader */ /* enable USART transmission to reader */
@@ -508,11 +506,8 @@ static int tx_byte_atr(struct card_handle *ch)
} }
} }
} }
/* update waiting time (see ISO 7816-3 10.2). We can drop the Fi /* update waiting time (see ISO 7816-3 10.2) */
* multiplier as we store the waiting time in units of 'etu', and ch->waiting_time = ch->wi * 960 * iso7816_3_fi_table[ch->F_index];
* don't really care what the number of clock cycles or the absolute
* wall clock time is */
ch->waiting_time = ch->wi * 960;
/* go to next state */ /* go to next state */
card_set_state(ch, ISO_S_WAIT_TPDU); card_set_state(ch, ISO_S_WAIT_TPDU);
return 0; return 0;
@@ -1082,12 +1077,6 @@ static void card_emu_report_config(struct card_handle *ch)
cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg)); cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg));
cfg->features = ch->features; cfg->features = ch->features;
#ifdef HAVE_SLOT_MUX
cfg->slot_mux_nr = mux_get_slot();
#else
cfg->slot_mux_nr = 0;
#endif
usb_buf_upd_len_and_submit(msg); usb_buf_upd_len_and_submit(msg);
} }
@@ -1250,19 +1239,13 @@ int card_emu_set_config(struct card_handle *ch, const struct cardemu_usb_msg_con
if (scfg_len >= sizeof(uint32_t)) if (scfg_len >= sizeof(uint32_t))
ch->features = (scfg->features & SUPPORTED_FEATURES); ch->features = (scfg->features & SUPPORTED_FEATURES);
#ifdef HAVE_SLOT_MUX
if (scfg_len >= sizeof(uint32_t)+sizeof(uint8_t)) {
mux_set_slot(scfg->slot_mux_nr);
}
#endif
/* send back a report of our current configuration */ /* send back a report of our current configuration */
card_emu_report_config(ch); card_emu_report_config(ch);
return 0; return 0;
} }
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 *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 *ch; struct card_handle *ch;
@@ -1287,6 +1270,7 @@ struct card_handle *card_emu_init(uint8_t slot_num, uint8_t uart_chan, uint8_t i
ch->Di_index = ch->D_index = 1; ch->Di_index = ch->D_index = 1;
ch->wi = ISO7816_3_DEFAULT_WI; ch->wi = ISO7816_3_DEFAULT_WI;
ch->tc_chan = tc_chan;
ch->uart_chan = uart_chan; ch->uart_chan = uart_chan;
ch->waiting_time = ISO7816_3_INIT_WTIME; ch->waiting_time = ISO7816_3_INIT_WTIME;

View File

@@ -57,7 +57,7 @@ static void usb_write_cb(uint8_t *arg, uint8_t status, uint32_t transferred,
} }
/* check if the spcified IN endpoint is idle and submit the next buffer from queue */ /* check if the spcified IN endpoint is idle and submit the next buffer from queue */
static int usb_refill_to_host(uint8_t ep) int usb_refill_to_host(uint8_t ep)
{ {
struct usb_buffered_ep *bep = usb_get_buf_ep(ep); struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
struct msgb *msg; struct msgb *msg;
@@ -130,7 +130,7 @@ static void usb_read_cb(uint8_t *arg, uint8_t status, uint32_t transferred,
} }
/* refill the read queue for data received from host PC on OUT EP, if needed */ /* refill the read queue for data received from host PC on OUT EP, if needed */
static int usb_refill_from_host(uint8_t ep) int usb_refill_from_host(uint8_t ep)
{ {
struct usb_buffered_ep *bep = usb_get_buf_ep(ep); struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
struct msgb *msg; struct msgb *msg;
@@ -198,45 +198,3 @@ int usb_drain_queue(uint8_t ep)
return ret; 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);
}
}

View File

@@ -34,8 +34,6 @@
#define TRACE_ENTRY() TRACE_DEBUG("%s entering\r\n", __func__) #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 #ifdef PINS_CARDSIM
static const Pin pins_cardsim[] = PINS_CARDSIM; static const Pin pins_cardsim[] = PINS_CARDSIM;
#endif #endif
@@ -44,10 +42,6 @@ static const Pin pins_cardsim[] = PINS_CARDSIM;
static const Pin pins_usim1[] = {PINS_USIM1}; static const Pin pins_usim1[] = {PINS_USIM1};
static const Pin pin_usim1_rst = PIN_USIM1_nRST; static const Pin pin_usim1_rst = PIN_USIM1_nRST;
static const Pin pin_usim1_vcc = PIN_USIM1_VCC; static const Pin pin_usim1_vcc = PIN_USIM1_VCC;
#ifdef PIN_USIM1_IO_DIR
static const Pin pin_io_dir = PIN_USIM1_IO_DIR;
#endif
#ifdef CARDEMU_SECOND_UART #ifdef CARDEMU_SECOND_UART
static const Pin pins_usim2[] = {PINS_USIM2}; static const Pin pins_usim2[] = {PINS_USIM2};
@@ -70,7 +64,9 @@ struct cardem_inst {
bool half_time_notified; bool half_time_notified;
} wt; } wt;
int usb_pending_old; int usb_pending_old;
struct usb_if usb_if; uint8_t ep_out;
uint8_t ep_in;
uint8_t ep_int;
const Pin pin_insert; const Pin pin_insert;
#ifdef DETECT_VCC_BY_ADC #ifdef DETECT_VCC_BY_ADC
uint32_t vcc_uv; uint32_t vcc_uv;
@@ -90,16 +86,9 @@ struct cardem_inst cardem_inst[] = {
.id = ID_USART1, .id = ID_USART1,
.state = USART_RCV .state = USART_RCV
}, },
.usb_if = { .ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT,
.if_num = 0, .ep_in = SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,
.ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT, .ep_int = SIMTRACE_CARDEM_USB_EP_USIM1_INT,
.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 #ifdef PIN_SET_USIM1_PRES
.pin_insert = PIN_SET_USIM1_PRES, .pin_insert = PIN_SET_USIM1_PRES,
#endif #endif
@@ -112,16 +101,9 @@ struct cardem_inst cardem_inst[] = {
.id = ID_USART0, .id = ID_USART0,
.state = USART_RCV .state = USART_RCV
}, },
.usb_if = { .ep_out = SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT,
.if_num = 1, .ep_in = SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,
.ep_out = SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT, .ep_int = SIMTRACE_CARDEM_USB_EP_USIM2_INT,
.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 #ifdef PIN_SET_USIM2_PRES
.pin_insert = PIN_SET_USIM2_PRES, .pin_insert = PIN_SET_USIM2_PRES,
#endif #endif
@@ -161,27 +143,12 @@ void card_emu_uart_wait_tx_idle(uint8_t uart_chan)
wait_tx_idle(usart); wait_tx_idle(usart);
} }
static void card_emu_uart_set_direction(uint8_t uart_chan, bool tx)
{
/* only on some boards (octsimtest) we hae an external level
* shifter that requires us to switch the direction between RX and TX */
#ifdef PIN_USIM1_IO_DIR
if (uart_chan == 0) {
if (tx)
PIO_Set(&pin_io_dir);
else
PIO_Clear(&pin_io_dir);
}
#endif
}
/* call-back from card_emu.c to enable/disable transmit and/or receive */ /* call-back from card_emu.c to enable/disable transmit and/or receive */
void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx) void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
{ {
Usart *usart = get_usart_by_chan(uart_chan); Usart *usart = get_usart_by_chan(uart_chan);
switch (rxtx) { switch (rxtx) {
case ENABLE_TX: case ENABLE_TX:
card_emu_uart_set_direction(uart_chan, true);
USART_DisableIt(usart, ~(US_IER_TXRDY | US_IER_TIMEOUT)); USART_DisableIt(usart, ~(US_IER_TXRDY | US_IER_TIMEOUT));
/* as irritating as it is, we actually want to keep the /* as irritating as it is, we actually want to keep the
* receiver enabled during transmit */ * receiver enabled during transmit */
@@ -207,7 +174,6 @@ void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
* transmitter enabled during receive */ * transmitter enabled during receive */
USART_SetTransmitterEnabled(usart, 1); USART_SetTransmitterEnabled(usart, 1);
wait_tx_idle(usart); wait_tx_idle(usart);
card_emu_uart_set_direction(uart_chan, false);;
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
USART_EnableIt(usart, US_IER_RXRDY); USART_EnableIt(usart, US_IER_RXRDY);
USART_SetReceiverEnabled(usart, 1); USART_SetReceiverEnabled(usart, 1);
@@ -247,22 +213,6 @@ int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
return 1; return 1;
} }
static uint16_t compute_next_timeout(struct cardem_inst *ci)
{
uint32_t want_to_expire;
if (ci->wt.total == 0)
return 0;
if (!ci->wt.half_time_notified) {
/* we need to make sure to expire after half the total waiting time */
OSMO_ASSERT(ci->wt.remaining > (ci->wt.total / 2));
want_to_expire = ci->wt.remaining - (ci->wt.total / 2);
} else
want_to_expire = ci->wt.remaining;
/* if value exceeds the USART TO range, use the maximum possible value for one round */
return OSMO_MIN(want_to_expire, 0xffff);
}
/*! common handler if interrupt was received. /*! common handler if interrupt was received.
* \param[in] inst_num Instance number, range 0..1 (some boards only '0' permitted) */ * \param[in] inst_num Instance number, range 0..1 (some boards only '0' permitted) */
@@ -306,9 +256,6 @@ static void usart_irq_rx(uint8_t inst_num)
* how many etu have expired since we last sent a byte. See section * 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 */ * 33.7.3.11 "Receiver Time-out" of the SAM3S8 Data Sheet */
if (csr & US_CSR_TIMEOUT) { if (csr & US_CSR_TIMEOUT) {
/* clear timeout flag (and stop timeout until next character is received) */
usart->US_CR |= US_CR_STTTO;
/* RX has been inactive for some time */ /* RX has been inactive for some time */
if (ci->wt.remaining <= (usart->US_RTOR & 0xffff)) { if (ci->wt.remaining <= (usart->US_RTOR & 0xffff)) {
/* waiting time is over; will stop the timer */ /* waiting time is over; will stop the timer */
@@ -321,26 +268,17 @@ static void usart_irq_rx(uint8_t inst_num)
if (ci->wt.remaining == 0) { if (ci->wt.remaining == 0) {
/* let the FSM know that WT has expired */ /* let the FSM know that WT has expired */
card_emu_wtime_expired(ci->ch); card_emu_wtime_expired(ci->ch);
/* don't automatically re-start in this case */ } else if (ci->wt.remaining <= ci->wt.total / 2 && !ci->wt.half_time_notified) {
} else { /* let the FS know that half of the WT has expired */
bool half_time_just_reached = false; card_emu_wtime_half_expired(ci->ch);
ci->wt.half_time_notified = true;
if (ci->wt.remaining <= ci->wt.total / 2 && !ci->wt.half_time_notified) {
ci->wt.half_time_notified = true;
/* don't immediately call card_emu_wtime_half_expired(), as that
* in turn may calls card_emu_uart_update_wt() which will change
* the timeout but would be overridden 4 lines below */
half_time_just_reached = true;
}
/* update the counter no matter if we reached half time or not */
usart->US_RTOR = compute_next_timeout(ci);
/* restart the counter (if wt is 0, the timeout is not started) */
usart->US_CR |= US_CR_RETTO;
if (half_time_just_reached)
card_emu_wtime_half_expired(ci->ch);
} }
/* 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;
} }
} }
@@ -379,14 +317,10 @@ void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)
struct cardem_inst *ci = &cardem_inst[uart_chan]; struct cardem_inst *ci = &cardem_inst[uart_chan];
Usart *usart = get_usart_by_chan(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; ci->wt.total = wt;
/* reset and start the timer */ /* reset and start the timer */
card_emu_uart_reset_wt(uart_chan); card_emu_uart_reset_wt(uart_chan);
TRACE_INFO("%u: USART WT set to %lu ETU\r\n", uart_chan, wt);
} }
/*! Reset and re-start waiting timeout count down on USART peripheral. /*! Reset and re-start waiting timeout count down on USART peripheral.
@@ -400,7 +334,8 @@ void card_emu_uart_reset_wt(uint8_t uart_chan)
/* FIXME: guard against race with interrupt handler */ /* FIXME: guard against race with interrupt handler */
ci->wt.remaining = ci->wt.total; ci->wt.remaining = ci->wt.total;
ci->wt.half_time_notified = false; ci->wt.half_time_notified = false;
usart->US_RTOR = compute_next_timeout(ci); /* 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) */ /* restart the counter (if wt is 0, the timeout is not started) */
usart->US_CR |= US_CR_RETTO; usart->US_CR |= US_CR_RETTO;
} }
@@ -424,9 +359,6 @@ void card_emu_uart_interrupt(uint8_t uart_chan)
***********************************************************************/ ***********************************************************************/
#ifdef DETECT_VCC_BY_ADC #ifdef DETECT_VCC_BY_ADC
#if !defined(VCC_UV_THRESH_1V8) || !defined(VCC_UV_THRESH_3V)
#error "You must define VCC_UV_THRESH_{1V1,3V} if you use ADC VCC detection"
#endif
static volatile int adc_triggered = 0; static volatile int adc_triggered = 0;
static int adc_sam3s_reva_errata = 0; static int adc_sam3s_reva_errata = 0;
@@ -475,6 +407,9 @@ static int card_vcc_adc_init(void)
return 0; return 0;
} }
#define VCC_UV_THRESH_1V8 1500000
#define VCC_UV_THRESH_3V 2500000
static void process_vcc_adc(struct cardem_inst *ci) static void process_vcc_adc(struct cardem_inst *ci)
{ {
if (ci->vcc_uv >= VCC_UV_THRESH_3V && if (ci->vcc_uv >= VCC_UV_THRESH_3V &&
@@ -585,7 +520,20 @@ void mode_cardemu_init(void)
/* configure USART as ISO-7816 slave (e.g. card) */ /* configure USART as ISO-7816 slave (e.g. card) */
ISO7816_Init(&cardem_inst[0].usart_info, CLK_SLAVE); ISO7816_Init(&cardem_inst[0].usart_info, CLK_SLAVE);
#ifdef BOARD_simtrace
/* simtrace board uses uart timeouts */
/* don't use receive timeout timer for now */
cardem_inst[0].usart_info.base->US_RTOR = 0;
/* enable interrupts to indicate when data has been received or timeout occurred */
USART_EnableIt(cardem_inst[0].usart_info.base, US_IER_RXRDY | US_IER_TIMEOUT);
#else
/* enable interrupts to indicate when data has been received */
USART_EnableIt(cardem_inst[0].usart_info.base, US_IER_RXRDY );
#endif
/* enable interrupt requests for the USART peripheral */
NVIC_EnableIRQ(USART1_IRQn); NVIC_EnableIRQ(USART1_IRQn);
PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler); PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler);
PIO_EnableIt(&pin_usim1_rst); PIO_EnableIt(&pin_usim1_rst);
@@ -601,7 +549,7 @@ void mode_cardemu_init(void)
do {} while (!adc_triggered); /* wait for first ADC reading */ do {} while (!adc_triggered); /* wait for first ADC reading */
#endif /* DETECT_VCC_BY_ADC */ #endif /* DETECT_VCC_BY_ADC */
cardem_inst[0].ch = card_emu_init(0, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN, cardem_inst[0].ch = card_emu_init(0, 2, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,
SIMTRACE_CARDEM_USB_EP_USIM1_INT, cardem_inst[0].vcc_active, SIMTRACE_CARDEM_USB_EP_USIM1_INT, cardem_inst[0].vcc_active,
cardem_inst[0].rst_active, cardem_inst[0].vcc_active); cardem_inst[0].rst_active, cardem_inst[0].vcc_active);
sim_switch_use_physical(0, 1); sim_switch_use_physical(0, 1);
@@ -624,7 +572,7 @@ void mode_cardemu_init(void)
do {} while (!adc_triggered); /* wait for first ADC reading */ do {} while (!adc_triggered); /* wait for first ADC reading */
#endif /* DETECT_VCC_BY_ADC */ #endif /* DETECT_VCC_BY_ADC */
cardem_inst[1].ch = card_emu_init(1, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN, cardem_inst[1].ch = card_emu_init(1, 0, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,
SIMTRACE_CARDEM_USB_EP_USIM2_INT, cardem_inst[1].vcc_active, SIMTRACE_CARDEM_USB_EP_USIM2_INT, cardem_inst[1].vcc_active,
cardem_inst[1].rst_active, cardem_inst[1].vcc_active); cardem_inst[1].rst_active, cardem_inst[1].vcc_active);
sim_switch_use_physical(1, 1); sim_switch_use_physical(1, 1);
@@ -672,26 +620,6 @@ static void dispatch_usb_command_generic(struct msgb *msg, struct cardem_inst *c
usb_buf_free(msg); usb_buf_free(msg);
} }
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);
#else
if (!ci->pin_insert.pio) {
TRACE_INFO("%u: skipping unsupported card_insert to %s\r\n",
ci->num, card_insert ? "INSERTED" : "REMOVED");
return;
}
if (card_insert)
PIO_Set(&ci->pin_insert);
else
PIO_Clear(&ci->pin_insert);
#endif
}
/* handle a single USB command as received from the USB host */ /* handle a single USB command as received from the USB host */
static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci) static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci)
{ {
@@ -715,7 +643,18 @@ static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci
break; break;
case SIMTRACE_MSGT_DT_CEMU_CARDINSERT: case SIMTRACE_MSGT_DT_CEMU_CARDINSERT:
cardins = (struct cardemu_usb_msg_cardinsert *) msg->l2h; cardins = (struct cardemu_usb_msg_cardinsert *) msg->l2h;
process_card_insert(ci, cardins->card_insert); if (!ci->pin_insert.pio) {
TRACE_INFO("%u: skipping unsupported card_insert to %s\r\n",
ci->num, cardins->card_insert ? "INSERTED" : "REMOVED");
usb_buf_free(msg);
break;
}
TRACE_INFO("%u: set card_insert to %s\r\n", ci->num,
cardins->card_insert ? "INSERTED" : "REMOVED");
if (cardins->card_insert)
PIO_Set(&ci->pin_insert);
else
PIO_Clear(&ci->pin_insert);
usb_buf_free(msg); usb_buf_free(msg);
break; break;
case SIMTRACE_MSGT_BD_CEMU_STATUS: case SIMTRACE_MSGT_BD_CEMU_STATUS:
@@ -801,9 +740,8 @@ static void dispatch_usb_command_modem(struct msgb *msg, struct cardem_inst *ci)
} }
/* handle a single USB command as received from the USB host */ /* handle a single USB command as received from the USB host */
static void dispatch_usb_command(struct msgb *msg, const struct usb_if *usb_if) static void dispatch_usb_command(struct msgb *msg, struct cardem_inst *ci)
{ {
struct cardem_inst *ci = usb_if->data;
struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *) msg->l1h; struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *) msg->l1h;
if (msgb_length(msg) < sizeof(*sh)) { if (msgb_length(msg) < sizeof(*sh)) {
@@ -832,8 +770,7 @@ static void dispatch_usb_command(struct msgb *msg, const struct usb_if *usb_if)
} }
} }
/* handle a single USB transfer as received from the USB host */ static void dispatch_received_msg(struct msgb *msg, struct cardem_inst *ci)
static void dispatch_received_usb_msg(struct msgb *msg, const struct usb_if *usb_if)
{ {
struct msgb *segm; struct msgb *segm;
struct simtrace_msg_hdr *mh; struct simtrace_msg_hdr *mh;
@@ -844,7 +781,7 @@ static void dispatch_received_usb_msg(struct msgb *msg, const struct usb_if *usb
mh = (struct simtrace_msg_hdr *) msg->data; mh = (struct simtrace_msg_hdr *) msg->data;
if (mh->msg_len == msgb_length(msg)) { if (mh->msg_len == msgb_length(msg)) {
/* fast path: only one message in buffer */ /* fast path: only one message in buffer */
dispatch_usb_command(msg, usb_if); dispatch_usb_command(msg, ci);
return; return;
} }
@@ -853,23 +790,23 @@ static void dispatch_received_usb_msg(struct msgb *msg, const struct usb_if *usb
while (1) { while (1) {
mh = (struct simtrace_msg_hdr *) msg->data; mh = (struct simtrace_msg_hdr *) msg->data;
segm = usb_buf_alloc(usb_if->ep_out); segm = usb_buf_alloc(ci->ep_out);
if (!segm) { if (!segm) {
TRACE_ERROR("%u: ENOMEM during msg segmentation\r\n", TRACE_ERROR("%u: ENOMEM during msg segmentation\r\n",
usb_if->if_num); ci->num);
break; break;
} }
if (mh->msg_len > msgb_length(msg)) { if (mh->msg_len > msgb_length(msg)) {
TRACE_ERROR("%u: Unexpected large message (%u bytes)\r\n", TRACE_ERROR("%u: Unexpected large message (%u bytes)\r\n",
usb_if->if_num, mh->msg_len); ci->num, mh->msg_len);
usb_buf_free(segm); usb_buf_free(segm);
break; break;
} else { } else {
uint8_t *cur = msgb_put(segm, mh->msg_len); uint8_t *cur = msgb_put(segm, mh->msg_len);
segm->l1h = segm->head; segm->l1h = segm->head;
memcpy(cur, mh, mh->msg_len); memcpy(cur, mh, mh->msg_len);
dispatch_usb_command(segm, usb_if); dispatch_usb_command(segm, ci);
} }
/* pull this message */ /* pull this message */
msgb_pull(msg, mh->msg_len); msgb_pull(msg, mh->msg_len);
@@ -881,14 +818,35 @@ static void dispatch_received_usb_msg(struct msgb *msg, const struct usb_if *usb
usb_buf_free(msg); 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 */ /* main loop function, called repeatedly */
void mode_cardemu_run(void) void mode_cardemu_run(void)
{ {
struct llist_head *queue;
unsigned int i; unsigned int i;
for (i = 0; i < ARRAY_SIZE(cardem_inst); i++) { for (i = 0; i < ARRAY_SIZE(cardem_inst); i++) {
struct cardem_inst *ci = &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 */ /* drain the ring buffer from UART into card_emu */
while (1) { while (1) {
@@ -905,6 +863,16 @@ void mode_cardemu_run(void)
process_io_statechg(ci); process_io_statechg(ci);
usb_process(&ci->usb_if); /* 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);
} }
} }

View File

@@ -975,42 +975,20 @@ static void usb_send_change(uint32_t flags)
usb_msg_upd_len_and_submit(usb_msg); 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)
{
struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *) msg->l1h;
if (msgb_length(msg) < sizeof(*sh)) {
usb_buf_free(msg);
return;
}
msg->l2h = msg->l1h + sizeof(*sh);
switch (sh->msg_class) {
case SIMTRACE_MSGC_GENERIC:
break;
default:
break;
}
usb_buf_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 */ /* Main (idle/busy) loop of this USB configuration */
void Sniffer_run(void) void Sniffer_run(void)
{ {
/* Handle USB queue */ /* Handle USB queue */
usb_process(&sniffer_usb_if); /* 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);
*/
/* WARNING: the signal data and flags are not synchronized. We have to hope /* 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 * the processing is fast enough to not land in the wrong state while data

View File

@@ -46,7 +46,7 @@ static osmo_panic_handler_t osmo_panic_handler = (void*)0;
__attribute__ ((format (printf, 1, 0))) __attribute__ ((format (printf, 1, 0)))
static void osmo_panic_default(const char *fmt, va_list args) static void osmo_panic_default(const char *fmt, va_list args)
{ {
vfprintf_sync(stderr, fmt, args); vfprintf(stderr, fmt, args);
osmo_generate_backtrace(); osmo_generate_backtrace();
assert(0); assert(0);
} }

View File

@@ -13,20 +13,6 @@
#define PHONE_INT 2 #define PHONE_INT 2
#define PHONE_DATAOUT 3 #define PHONE_DATAOUT 3
/* stub for stdio */
signed int printf_sync(const char *pFormat, ...)
{
va_list ap;
signed int result;
va_start(ap, pFormat);
result = vprintf(pFormat, ap);
va_end(ap);
return result;
}
/*********************************************************************** /***********************************************************************
* stub functions required by card_emu.c * stub functions required by card_emu.c
***********************************************************************/ ***********************************************************************/
@@ -64,9 +50,6 @@ void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
case ENABLE_TX: case ENABLE_TX:
rts = "TX"; rts = "TX";
break; break;
case ENABLE_TX_TIMER_ONLY:
rts = "TX-TIMER-ONLY";
break;
case ENABLE_RX: case ENABLE_RX:
rts = "RX"; rts = "RX";
break; break;
@@ -83,14 +66,29 @@ void card_emu_uart_interrupt(uint8_t uart_chan)
printf("uart_interrupt(uart_chan=%u)\n", uart_chan); printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
} }
void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt) void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
{ {
printf("%s(uart_chan=%u, wtime=%u)\n", __func__, uart_chan, wt); printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
} }
void card_emu_uart_reset_wt(uint8_t uart_chan) void tc_etu_set_etu(uint8_t tc_chan, uint16_t etu)
{ {
printf("%s(uart_chan=%u\n", __func__, 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);
} }
@@ -138,7 +136,7 @@ static void io_start_card(struct card_handle *ch)
/* release from reset and verify th ATR */ /* release from reset and verify th ATR */
card_emu_io_statechg(ch, CARD_IO_RST, 0); card_emu_io_statechg(ch, CARD_IO_RST, 0);
/* simulate waiting time before ATR expired */ /* simulate waiting time before ATR expired */
card_emu_wtime_expired(ch); tc_etu_wtime_expired(ch);
verify_atr(ch); verify_atr(ch);
} }
@@ -410,7 +408,7 @@ int main(int argc, char **argv)
struct card_handle *ch; struct card_handle *ch;
unsigned int i; unsigned int i;
ch = card_emu_init(0, 42, PHONE_DATAIN, PHONE_INT, false, true, false); ch = card_emu_init(0, 23, 42, PHONE_DATAIN, PHONE_INT, false, true, false);
assert(ch); assert(ch);
usb_buf_init(); usb_buf_init();

View File

@@ -44,13 +44,9 @@
#include <osmocom/core/utils.h> #include <osmocom/core/utils.h>
#include <osmocom/core/socket.h> #include <osmocom/core/socket.h>
#include <osmocom/core/msgb.h> #include <osmocom/core/msgb.h>
#include <osmocom/core/logging.h>
#include <osmocom/sim/class_tables.h> #include <osmocom/sim/class_tables.h>
#include <osmocom/sim/sim.h> #include <osmocom/sim/sim.h>
#define LOGSLOT(slot, lvl, fmt, args...) \
LOGP(DLINP, lvl, "[%u] " fmt, (slot)->slot_nr, ## args)
/*********************************************************************** /***********************************************************************
* SIMTRACE core protocol * SIMTRACE core protocol
***********************************************************************/ ***********************************************************************/
@@ -145,6 +141,7 @@ int osmo_st2_slot_tx_msg(struct osmo_st2_slot *slot, struct msgb *msg,
OSMO_ASSERT(transp); OSMO_ASSERT(transp);
st_push_hdr(msg, msg_class, msg_type, slot->slot_nr); st_push_hdr(msg, msg_class, msg_type, slot->slot_nr);
printf("SIMtrace <- %s\n", msgb_hexdump(msg));
if (transp->udp_fd < 0) { if (transp->udp_fd < 0) {
if (transp->usb_async) if (transp->usb_async)
@@ -169,8 +166,6 @@ int osmo_st2_cardem_request_card_insert(struct osmo_st2_cardem_inst *ci, bool in
struct msgb *msg = st_msgb_alloc(); struct msgb *msg = st_msgb_alloc();
struct cardemu_usb_msg_cardinsert *cins; struct cardemu_usb_msg_cardinsert *cins;
LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(inserted=%d)\n", __func__, inserted);
cins = (struct cardemu_usb_msg_cardinsert *) msgb_put(msg, sizeof(*cins)); cins = (struct cardemu_usb_msg_cardinsert *) msgb_put(msg, sizeof(*cins));
memset(cins, 0, sizeof(*cins)); memset(cins, 0, sizeof(*cins));
if (inserted) if (inserted)
@@ -186,7 +181,7 @@ int osmo_st2_cardem_request_pb_and_rx(struct osmo_st2_cardem_inst *ci, uint8_t p
struct cardemu_usb_msg_tx_data *txd; struct cardemu_usb_msg_tx_data *txd;
txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
LOGSLOT(ci->slot, LOGL_DEBUG, "<= %s(pb=%02x, le=%u)\n", __func__, pb, le); printf("<= %s(%02x, %d)\n", __func__, pb, le);
memset(txd, 0, sizeof(*txd)); memset(txd, 0, sizeof(*txd));
txd->data_len = 1; txd->data_len = 1;
@@ -207,7 +202,7 @@ int osmo_st2_cardem_request_pb_and_tx(struct osmo_st2_cardem_inst *ci, uint8_t p
txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
LOGSLOT(ci->slot, LOGL_DEBUG, "<= %s(pb=%02x, tx=%s, len=%d)\n", __func__, pb, printf("<= %s(%02x, %s, %d)\n", __func__, pb,
osmo_hexdump(data, data_len_in), data_len_in); osmo_hexdump(data, data_len_in), data_len_in);
memset(txd, 0, sizeof(*txd)); memset(txd, 0, sizeof(*txd));
@@ -231,7 +226,7 @@ int osmo_st2_cardem_request_sw_tx(struct osmo_st2_cardem_inst *ci, const uint8_t
txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
LOGSLOT(ci->slot, LOGL_DEBUG, "<= %s(sw=%02x%02x)\n", __func__, sw[0], sw[1]); printf("<= %s(%02x %02x)\n", __func__, sw[0], sw[1]);
memset(txd, 0, sizeof(*txd)); memset(txd, 0, sizeof(*txd));
txd->data_len = 2; txd->data_len = 2;
@@ -251,7 +246,7 @@ int osmo_st2_cardem_request_set_atr(struct osmo_st2_cardem_inst *ci, const uint8
satr = (struct cardemu_usb_msg_set_atr *) msgb_put(msg, sizeof(*satr)); satr = (struct cardemu_usb_msg_set_atr *) msgb_put(msg, sizeof(*satr));
LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(%s)\n", __func__, osmo_hexdump(atr, atr_len)); printf("<= %s(%s)\n", __func__, osmo_hexdump(atr, atr_len));
memset(satr, 0, sizeof(*satr)); memset(satr, 0, sizeof(*satr));
satr->atr_len = atr_len; satr->atr_len = atr_len;
@@ -268,7 +263,7 @@ int osmo_st2_cardem_request_config(struct osmo_st2_cardem_inst *ci, uint32_t fea
cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg)); cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg));
LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(features=%08x)\n", __func__, features); printf("<= %s(%08x)\n", __func__, features);
memset(cfg, 0, sizeof(*cfg)); memset(cfg, 0, sizeof(*cfg));
cfg->features = features; cfg->features = features;
@@ -285,9 +280,6 @@ static int _modem_reset(struct osmo_st2_slot *slot, uint8_t asserted, uint16_t p
struct msgb *msg = st_msgb_alloc(); struct msgb *msg = st_msgb_alloc();
struct st_modem_reset *sr ; struct st_modem_reset *sr ;
LOGSLOT(slot, LOGL_NOTICE, "<= %s(asserted=%u, pulse_ms=%u)\n", __func__,
asserted, pulse_ms);
sr = (struct st_modem_reset *) msgb_put(msg, sizeof(*sr)); sr = (struct st_modem_reset *) msgb_put(msg, sizeof(*sr));
sr->asserted = asserted; sr->asserted = asserted;
sr->pulse_duration_msec = pulse_ms; sr->pulse_duration_msec = pulse_ms;
@@ -318,8 +310,6 @@ static int _modem_sim_select(struct osmo_st2_slot *slot, uint8_t remote_sim)
struct msgb *msg = st_msgb_alloc(); struct msgb *msg = st_msgb_alloc();
struct st_modem_sim_select *ss; struct st_modem_sim_select *ss;
LOGSLOT(slot, LOGL_NOTICE, "<= %s(remote_sim=%u)\n", __func__, remote_sim);
ss = (struct st_modem_sim_select *) msgb_put(msg, sizeof(*ss)); ss = (struct st_modem_sim_select *) msgb_put(msg, sizeof(*ss));
ss->remote_sim = remote_sim; ss->remote_sim = remote_sim;

View File

@@ -32,6 +32,5 @@ const struct dev_id osmo_st2_compatible_dev_ids[] = {
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_OWHW_SAM3 }, { USB_VENDOR_OPENMOKO, USB_PRODUCT_OWHW_SAM3 },
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_QMOD_SAM3 }, { USB_VENDOR_OPENMOKO, USB_PRODUCT_QMOD_SAM3 },
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 }, { USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_OCTSIMTEST },
{ 0, 0 } { 0, 0 }
}; };

View File

@@ -5,12 +5,10 @@ AM_LDFLAGS=$(COVERAGE_LDFLAGS)
LDADD= $(top_builddir)/lib/libosmo-simtrace2.la \ LDADD= $(top_builddir)/lib/libosmo-simtrace2.la \
$(LIBOSMOCORE_LIBS) $(LIBOSMOSIM_LIBS) $(LIBOSMOUSB_LIBS) $(LIBUSB_LIBS) $(LIBOSMOCORE_LIBS) $(LIBOSMOSIM_LIBS) $(LIBOSMOUSB_LIBS) $(LIBUSB_LIBS)
bin_PROGRAMS = simtrace2-cardem-pcsc simtrace2-list simtrace2-sniff simtrace2-tool bin_PROGRAMS = simtrace2-cardem-pcsc simtrace2-list simtrace2-sniff
simtrace2_cardem_pcsc_SOURCES = simtrace2-cardem-pcsc.c simtrace2_cardem_pcsc_SOURCES = simtrace2-cardem-pcsc.c
simtrace2_list_SOURCES = simtrace2_usb.c simtrace2_list_SOURCES = simtrace2_usb.c
simtrace2_sniff_SOURCES = simtrace2-sniff.c simtrace2_sniff_SOURCES = simtrace2-sniff.c
simtrace2_tool_SOURCES = simtrace2-tool.c

View File

@@ -1,7 +1,7 @@
/* simtrace2-cardem-pcsc - main program for the host PC to provide a remote SIM /* simtrace2-cardem-pcsc - main program for the host PC to provide a remote SIM
* using the SIMtrace 2 firmware in card emulation mode * using the SIMtrace 2 firmware in card emulation mode
* *
* (C) 2016-2021 by Harald Welte <hwelte@hmw-consulting.de> * (C) 2016-2020 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@@ -48,13 +48,32 @@
#include <osmocom/core/socket.h> #include <osmocom/core/socket.h>
#include <osmocom/core/msgb.h> #include <osmocom/core/msgb.h>
#include <osmocom/core/select.h> #include <osmocom/core/select.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/application.h>
#include <osmocom/sim/class_tables.h> #include <osmocom/sim/class_tables.h>
#include <osmocom/sim/sim.h> #include <osmocom/sim/sim.h>
#define ATR_MAX_LEN 33
#define LOGCI(ci, lvl, fmt, args ...) printf(fmt, ## args) #define LOGCI(ci, lvl, fmt, args ...) printf(fmt, ## args)
/* reasonable ATR offering all protocols and voltages
* smartphones might not care, but other readers do
*
* TS = 0x3B Direct Convention
* T0 = 0x80 Y(1): b1000, K: 0 (historical bytes)
* TD(1) = 0x80 Y(i+1) = b1000, Protocol T=0
* ----
* TD(2) = 0x81 Y(i+1) = b1000, Protocol T=1
* ----
* TD(3) = 0x1F Y(i+1) = b0001, Protocol T=15
* ----
* TA(4) = 0xC7 Clock stop: no preference - Class accepted by the card: (3G) A 5V B 3V C 1.8V
* ----
* Historical bytes
* TCK = 0x59 correct checksum
*/
#define DEFAULT_ATR_STR "3B8080811FC759"
static void atr_update_csum(uint8_t *atr, unsigned int atr_len) static void atr_update_csum(uint8_t *atr, unsigned int atr_len)
{ {
uint8_t csum = 0; uint8_t csum = 0;
@@ -66,37 +85,6 @@ static void atr_update_csum(uint8_t *atr, unsigned int atr_len)
atr[atr_len-1] = csum; atr[atr_len-1] = csum;
} }
static void cemu_flags2str(char *out, unsigned int out_len, uint32_t flags)
{
snprintf(out, out_len, "%s%s%s%s%s",
flags & CEMU_STATUS_F_RESET_ACTIVE ? "RESET " : "",
flags & CEMU_STATUS_F_VCC_PRESENT ? "VCC " : "",
flags & CEMU_STATUS_F_CLK_ACTIVE ? "CLK " : "",
flags & CEMU_STATUS_F_CARD_INSERT ? "CARD_PRES " : "",
flags & CEMU_STATUS_F_RCEMU_ACTIVE ? "RCEMU " : "");
}
static uint32_t last_flags = 0;
static void update_flags(struct osmo_st2_cardem_inst *ci, uint32_t flags)
{
struct osim_card_hdl *card = ci->chan->card;
if ((flags & CEMU_STATUS_F_VCC_PRESENT) && (flags & CEMU_STATUS_F_CLK_ACTIVE) &&
!(flags & CEMU_STATUS_F_RESET_ACTIVE)) {
if (last_flags & CEMU_STATUS_F_RESET_ACTIVE) {
/* a reset has just ended, forward it to the real card */
bool cold_reset = true;
if (last_flags & CEMU_STATUS_F_VCC_PRESENT)
cold_reset = false;
LOGCI(ci, LOGL_NOTICE, "%s Resetting card in reader...\n",
cold_reset ? "Cold" : "Warm");
osim_card_reset(card, cold_reset);
}
}
last_flags = flags;
}
/*********************************************************************** /***********************************************************************
* Incoming Messages * Incoming Messages
***********************************************************************/ ***********************************************************************/
@@ -104,15 +92,12 @@ static void update_flags(struct osmo_st2_cardem_inst *ci, uint32_t flags)
/*! \brief Process a STATUS message from the SIMtrace2 */ /*! \brief Process a STATUS message from the SIMtrace2 */
static int process_do_status(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len) static int process_do_status(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)
{ {
struct cardemu_usb_msg_status *status = (struct cardemu_usb_msg_status *) buf; struct cardemu_usb_msg_status *status;
char fbuf[80]; status = (struct cardemu_usb_msg_status *) buf;
cemu_flags2str(fbuf, sizeof(fbuf), status->flags); printf("=> STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",
printf("=> STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u (%s)\n",
status->flags, status->fi, status->di, status->wi, status->flags, status->fi, status->di, status->wi,
status->waiting_time, fbuf); status->waiting_time);
update_flags(ci, status->flags);
return 0; return 0;
} }
@@ -213,14 +198,10 @@ static int process_usb_msg(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int le
static int process_irq_status(struct osmo_st2_cardem_inst *ci, const uint8_t *buf, int len) static int process_irq_status(struct osmo_st2_cardem_inst *ci, const uint8_t *buf, int len)
{ {
const struct cardemu_usb_msg_status *status = (struct cardemu_usb_msg_status *) buf; const struct cardemu_usb_msg_status *status = (struct cardemu_usb_msg_status *) buf;
char fbuf[80];
cemu_flags2str(fbuf, sizeof(fbuf), status->flags); LOGCI(ci, LOGL_INFO, "SIMtrace IRQ STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",
LOGCI(ci, LOGL_INFO, "SIMtrace IRQ STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u (%s)\n", status->flags, status->F_index, status->D_index, status->wi,
status->flags, status->fi, status->di, status->wi, status->waiting_time);
status->waiting_time, fbuf);
update_flags(ci, status->flags);
return 0; return 0;
} }
@@ -427,8 +408,6 @@ static void signal_handler(int signal)
} }
} }
static struct log_info log_info = {};
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct osmo_st2_transport *transp = ci->slot->transp; struct osmo_st2_transport *transp = ci->slot->transp;
@@ -436,9 +415,9 @@ int main(int argc, char **argv)
int rc; int rc;
int c, ret = 1; int c, ret = 1;
int skip_atr = 0; int skip_atr = 0;
char *atr = NULL; char *atr = DEFAULT_ATR_STR;
uint8_t override_atr[OSIM_MAX_ATR_LEN]; uint8_t real_atr[ATR_MAX_LEN];
int override_atr_len = 0; int atr_len;
int keep_running = 0; int keep_running = 0;
int if_num = 0, vendor_id = -1, product_id = -1; int if_num = 0, vendor_id = -1, product_id = -1;
int config_id = -1, altsetting = 0, addr = -1; int config_id = -1, altsetting = 0, addr = -1;
@@ -455,8 +434,6 @@ int main(int argc, char **argv)
return rc; return rc;
} }
osmo_init_logging2(NULL, &log_info);
while (1) { while (1) {
int option_index = 0; int option_index = 0;
@@ -507,13 +484,11 @@ int main(int argc, char **argv)
} }
} }
if (atr) { atr_len = osmo_hexparse(atr,real_atr,ATR_MAX_LEN);
override_atr_len = osmo_hexparse(atr, override_atr, sizeof(override_atr)); if (atr_len < 2) {
if (override_atr_len < 2) { fprintf(stderr, "Invalid ATR - please omit a leading 0x and only use valid hex "
fprintf(stderr, "Invalid ATR - please omit a leading 0x and only use valid hex " "digits and whitespace. ATRs need to be between 2 and 33 bytes long.\n");
"digits and whitespace. ATRs need to be between 2 and 33 bytes long.\n"); goto do_exit;
goto do_exit;
}
} }
if (vendor_id < 0 || product_id < 0) { if (vendor_id < 0 || product_id < 0) {
@@ -570,20 +545,20 @@ int main(int argc, char **argv)
transp->usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm); transp->usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm);
if (!transp->usb_devh) { if (!transp->usb_devh) {
fprintf(stderr, "can't open USB device\n"); fprintf(stderr, "can't open USB device\n");
goto close; goto close_exit;
} }
rc = libusb_claim_interface(transp->usb_devh, if_num); rc = libusb_claim_interface(transp->usb_devh, if_num);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc); fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc);
goto close; goto close_exit;
} }
rc = osmo_libusb_get_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out, rc = osmo_libusb_get_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out,
&transp->usb_ep.in, &transp->usb_ep.irq_in); &transp->usb_ep.in, &transp->usb_ep.irq_in);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc); fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
goto close; goto close_exit;
} }
allocate_and_submit_irq(ci); allocate_and_submit_irq(ci);
@@ -601,14 +576,8 @@ int main(int argc, char **argv)
if (!skip_atr) { if (!skip_atr) {
/* set the ATR */ /* set the ATR */
if (override_atr_len) { atr_update_csum(real_atr, atr_len);
/* user has specified an override-ATR */ osmo_st2_cardem_request_set_atr(ci, real_atr, atr_len);
atr_update_csum(override_atr, override_atr_len);
osmo_st2_cardem_request_set_atr(ci, override_atr, override_atr_len);
} else {
/* use the real ATR of the card */
osmo_st2_cardem_request_set_atr(ci, card->atr, card->atr_len);
}
} }
/* select remote (forwarded) SIM */ /* select remote (forwarded) SIM */
@@ -618,20 +587,13 @@ int main(int argc, char **argv)
ret = 0; ret = 0;
libusb_release_interface(transp->usb_devh, 0); libusb_release_interface(transp->usb_devh, 0);
close_exit:
close: if (transp->usb_devh)
if (transp->usb_devh) {
libusb_close(transp->usb_devh); libusb_close(transp->usb_devh);
transp->usb_devh = NULL;
}
if (keep_running) if (keep_running)
sleep(1); sleep(1);
} while (keep_running); } while (keep_running);
close_exit:
if (transp->usb_devh)
libusb_close(transp->usb_devh);
libusb_exit(NULL); libusb_exit(NULL);
do_exit: do_exit:
return ret; return ret;

View File

@@ -1,338 +0,0 @@
/* simtrace2-tool - main program for the host PC to provide a remote SIM
* using the SIMtrace 2 firmware in card emulation mode
*
* (C) 2019 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#define _GNU_SOURCE
#include <getopt.h>
#include <sys/types.h>
#include <libusb.h>
#include <osmocom/usb/libusb.h>
#include <osmocom/simtrace2/simtrace2_api.h>
#include <osmocom/simtrace2/simtrace_prot.h>
#include <osmocom/simtrace2/gsmtap.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/msgb.h>
/***********************************************************************
* Incoming Messages
***********************************************************************/
static void print_welcome(void)
{
printf("simtrace2-tool\n"
"(C) 2019 Harald Welte <laforge@gnumonks.org>\n");
}
static void print_help(void)
{
printf( "simtrace2-tool [OPTIONS] COMMAND\n\n");
printf( "Options:\n"
"\t-h\t--help\n"
"\t-V\t--usb-vendor\tVENDOR_ID\n"
"\t-P\t--usb-product\tPRODUCT_ID\n"
"\t-C\t--usb-config\tCONFIG_ID\n"
"\t-I\t--usb-interface\tINTERFACE_ID\n"
"\t-S\t--usb-altsetting ALTSETTING_ID\n"
"\t-A\t--usb-address\tADDRESS\n"
"\t-H\t--usb-path\tPATH\n"
"\n"
);
printf( "Commands:\n"
"\tmodem reset (enable|disable|cycle)\n"
"\tmodem sim-switch (local|remote)\n"
"\n");
}
static const struct option opts[] = {
{ "help", 0, 0, 'h' },
{ "usb-vendor", 1, 0, 'V' },
{ "usb-product", 1, 0, 'P' },
{ "usb-config", 1, 0, 'C' },
{ "usb-interface", 1, 0, 'I' },
{ "usb-altsetting", 1, 0, 'S' },
{ "usb-address", 1, 0, 'A' },
{ "usb-path", 1, 0, 'H' },
{ NULL, 0, 0, 0 }
};
static void run_mainloop(struct osmo_st2_cardem_inst *ci)
{
struct osmo_st2_transport *transp = ci->slot->transp;
uint8_t buf[16*265];
int xfer_len;
int rc;
while (1) {
/* read data from SIMtrace2 device */
rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.in,
buf, sizeof(buf), &xfer_len, 100);
if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT &&
rc != LIBUSB_ERROR_INTERRUPTED &&
rc != LIBUSB_ERROR_IO) {
fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc);
return;
}
/* break the loop if no new messages arrive within 100ms */
if (rc == LIBUSB_ERROR_TIMEOUT)
return;
}
}
static struct osmo_st2_transport _transp;
static struct osmo_st2_slot _slot = {
.transp = &_transp,
.slot_nr = 0,
};
struct osmo_st2_cardem_inst _ci = {
.slot = &_slot,
};
struct osmo_st2_cardem_inst *ci = &_ci;
/* perform a modem reset */
static int do_modem_reset(int argc, char **argv)
{
char *command;
if (argc < 1)
command = "cycle";
else {
command = argv[0];
argc--;
argv++;
}
if (!strcmp(command, "enable")) {
printf("Activating Modem RESET\n");
return osmo_st2_modem_reset_active(ci->slot);
} else if (!strcmp(command, "disable")) {
printf("Deactivating Modem RESET\n");
return osmo_st2_modem_reset_inactive(ci->slot);
} else if (!strcmp(command, "cycle")) {
printf("Pulsing Modem RESET (1s)\n");
return osmo_st2_modem_reset_pulse(ci->slot, 1000);
} else {
fprintf(stderr, "Unsupported modem reset command: '%s'\n", command);
return -EINVAL;
}
return 0;
}
/* switch between local and remote (emulated) SIM */
static int do_modem_sim_switch(int argc, char **argv)
{
char *command;
if (argc < 1)
return -EINVAL;
command = argv[0];
argc--;
argv++;
if (!strcmp(command, "local")) {
printf("Setting SIM=LOCAL; Modem reset recommended\n");
return osmo_st2_modem_sim_select_local(ci->slot);
} else if (!strcmp(command, "remote")) {
printf("Setting SIM=REMOTE; Modem reset recommended\n");
return osmo_st2_modem_sim_select_remote(ci->slot);
} else {
fprintf(stderr, "Unsupported modem sim-switch command: '%s'\n", command);
return -EINVAL;
}
return 0;
}
static int do_subsys_modem(int argc, char **argv)
{
char *command;
int rc;
if (argc < 1)
return -EINVAL;
command = argv[0];
argc--;
argv++;
if (!strcmp(command, "reset")) {
rc = do_modem_reset(argc, argv);
} else if (!strcmp(command, "sim-switch")) {
rc = do_modem_sim_switch(argc, argv);
} else {
fprintf(stderr, "Unsupported command for subsystem modem: '%s'\n", command);
return -EINVAL;
}
return rc;
}
static int do_command(int argc, char **argv)
{
char *subsys;
int rc;
if (argc < 1)
return -EINVAL;
subsys = argv[0];
argc--;
argv++;
if (!strcmp(subsys, "modem"))
rc = do_subsys_modem(argc, argv);
else {
fprintf(stderr, "Unsupported subsystem '%s'\n", subsys);
rc = -EINVAL;
}
return rc;
}
int main(int argc, char **argv)
{
struct osmo_st2_transport *transp = ci->slot->transp;
int rc;
int c, ret = 1;
int if_num = 0, vendor_id = -1, product_id = -1;
int config_id = -1, altsetting = 0, addr = -1;
char *path = NULL;
while (1) {
int option_index = 0;
c = getopt_long(argc, argv, "hV:P:C:I:S:A:H:", opts, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_help();
exit(0);
break;
case 'V':
vendor_id = strtol(optarg, NULL, 16);
break;
case 'P':
product_id = strtol(optarg, NULL, 16);
break;
case 'C':
config_id = atoi(optarg);
break;
case 'I':
if_num = atoi(optarg);
break;
case 'S':
altsetting = atoi(optarg);
break;
case 'A':
addr = atoi(optarg);
break;
case 'H':
path = optarg;
break;
}
}
if ((vendor_id < 0 || product_id < 0)) {
fprintf(stderr, "You have to specify the vendor and product ID\n");
goto do_exit;
}
transp->udp_fd = -1;
rc = libusb_init(NULL);
if (rc < 0) {
fprintf(stderr, "libusb initialization failed\n");
goto do_exit;
}
print_welcome();
do {
if (transp->udp_fd < 0) {
struct usb_interface_match _ifm, *ifm = &_ifm;
ifm->vendor = vendor_id;
ifm->product = product_id;
ifm->configuration = config_id;
ifm->interface = if_num;
ifm->altsetting = altsetting;
ifm->addr = addr;
if (path)
osmo_strlcpy(ifm->path, path, sizeof(ifm->path));
transp->usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm);
if (!transp->usb_devh) {
fprintf(stderr, "can't open USB device\n");
goto close_exit;
}
rc = libusb_claim_interface(transp->usb_devh, if_num);
if (rc < 0) {
fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc);
goto close_exit;
}
rc = osmo_libusb_get_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out,
&transp->usb_ep.in, &transp->usb_ep.irq_in);
if (rc < 0) {
fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
goto close_exit;
}
}
if (argc - optind <= 0) {
fprintf(stderr, "You have to specify a command to execute\n");
exit(1);
}
rc = do_command(argc-optind, argv+optind);
switch (rc) {
case 0:
break;
case -EINVAL:
fprintf(stderr, "Error: Invalid command/syntax\n");
exit(1);
break;
default:
fprintf(stderr, "Error executing command: %d\n", rc);
exit(1);
break;
}
run_mainloop(ci);
ret = 0;
libusb_release_interface(transp->usb_devh, 0);
close_exit:
if (transp->usb_devh)
libusb_close(transp->usb_devh);
} while (0);
libusb_exit(NULL);
do_exit:
return ret;
}

View File

@@ -25,7 +25,13 @@
#include <osmocom/usb/libusb.h> #include <osmocom/usb/libusb.h>
#include <osmocom/simtrace2/simtrace_usb.h> #include <osmocom/simtrace2/simtrace_usb.h>
#include <osmocom/simtrace2/usb_util.h>
static const struct dev_id compatible_dev_ids[] = {
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_OWHW_SAM3 },
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_QMOD_SAM3 },
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },
{ 0, 0 }
};
static int find_devices(void) static int find_devices(void)
{ {
@@ -33,7 +39,7 @@ static int find_devices(void)
int rc, i, num_interfaces; int rc, i, num_interfaces;
/* scan for USB devices matching SIMtrace USB ID with proprietary class */ /* scan for USB devices matching SIMtrace USB ID with proprietary class */
rc = osmo_libusb_find_matching_interfaces(NULL, osmo_st2_compatible_dev_ids, rc = osmo_libusb_find_matching_interfaces(NULL, compatible_dev_ids,
USB_CLASS_PROPRIETARY, -1, -1, ifm, ARRAY_SIZE(ifm)); USB_CLASS_PROPRIETARY, -1, -1, ifm, ARRAY_SIZE(ifm));
printf("USB matches: %d\n", rc); printf("USB matches: %d\n", rc);
if (rc < 0) if (rc < 0)