71 Commits

Author SHA1 Message Date
Kévin Redon
f48aac560c sniffing: decrease USB IRQ prioprity to prevent USART overrun
Change-Id: I870a0aa8e251bbb53249c54bfcaa45de5b5a9486

Handling the USB message queue is done in an ISR and take quite some time.
This can cause a USART/SIM sniffing buffer overrun, resulting in data loss.
By setting the USB IRQ lower than the USART IRQ, the USB ISR can be
interrupted (for short) and no data gets lost.
2018-07-03 16:18:00 +02:00
Kévin Redon
d28d3fc4c0 sniffing: fix procedure byte handling and make TPDU parsing for strict
Change-Id: If991152f11c4b864ab1386f21dc13c335e6b281f
2018-07-03 16:17:00 +02:00
Kévin Redon
50d071fb0e sniffer: also send incomplete (e.g. timeout) data (PPS/ATR/TPDU)
Change-Id: Ib070aca181042b477f1ffec48d63dc56c1e4609a
2018-07-03 16:15:58 +02:00
Kévin Redon
36be182ea2 sniffing: move conversion convertion and flag processing from ISR to main loop to keep ISR fast and focus on data capture
Change-Id: Ieefa8a5f81dbcc12c1ad3059660dbffa0c1a4961
2018-07-03 16:10:04 +02:00
Kévin Redon
bdb0795e61 buffer: increase buffer size to 512 to cope with fast and long TPDUs
Change-Id: I194c90cf09306a982d80c5bf1222397af6e658a9
2018-07-03 16:03:17 +02:00
Kévin Redon
b65e4b6823 console: drop data to be send when buffer is already full
Change-Id: Ia625b09eb30bb7b43edd3989f697d8ef33200f28

don't wait for space to be available in the buffer since since would
prevent from processing non-console (e.g. debug) more important data
2018-07-03 15:59:57 +02:00
Kévin Redon
05cc8bd36a sniffer: display F and D values frim PPS
Change-Id: I3641dcb6c24695a6d3dd3a1ee4333f56a07c99f0
2018-07-03 15:57:03 +02:00
Kévin Redon
de6e3488a0 Merge branch 'kredon/simtrace' of ssh://gerrit.osmocom.org:29418/simtrace2 into kredon/simtrace
Change-Id: Id868520d6603f2bcb79a0aaaf6413dc83938524b
2018-07-01 19:02:40 +02:00
Kévin Redon
f6c2f4def3 host USB: add host application to receive and display USB sniffing messages sent by firmware
Change-Id: Idefbf21e0bbd2a1e3647fe9aebaf88d1b62dae2d
2018-07-01 18:33:28 +02:00
Kévin Redon
f9f1261c18 sniffer USB: implement USB communication and send parsed messages
Change-Id: Ice7817480705f2124b08c1ff9a8826558b6d8b2b
2018-07-01 18:33:28 +02:00
Kévin Redon
310ad81bad USB device: add USB message structure for sniffer communication
Change-Id: Id2c6f32ade2fec9b9ef91bd8c5e1fd195f2d7351
2018-07-01 18:33:28 +02:00
Kévin Redon
1c84e5e312 host USB: use central SIMtrace USB ID definition header
Change-Id: Id18e64fba0a2c308a8aef7d3865200bf0237cae9
2018-07-01 18:33:28 +02:00
Kévin Redon
c06b1d6f7c host usb_util fix: used provided class, sub-class, and interfave when finding matching interfaces
Change-Id: Ibc06e751e6ca0f9e9a40d82c4eeddfb975240f91
2018-07-01 18:33:28 +02:00
Kévin Redon
0c9079f1ae USB: add central file to define USB IDs, classes, and endpoints
Change-Id: Iba81f32a92c68a973e8e7adbc4c2a1064ba5290f
2018-07-01 18:33:28 +02:00
Kévin Redon
cb700ef087 reintroduce adc2uv used in boardver_adc.c and mode_cardemu.c
Change-Id: I52e3919adfd1d888eb130b5ec9298315c4e507c9
2018-07-01 18:33:28 +02:00
Kévin Redon
4635c71c06 minor: fix typos in comment
Change-Id: I01b49e047a586dff449d4e134751108e391a8822
2018-07-01 18:33:28 +02:00
Kévin Redon
6123460055 sniff: add WT timeout detection using USART timeout (TC is not required)
Change-Id: I4ec6e812e7e1eb91005027d2e864fc315550d79c
2018-07-01 18:33:28 +02:00
Kévin Redon
15a3384e9a sniff: add TPDU parsing (TPDUs become APDUs on the upper layer)
Change-Id: I09d050d95bd2ab140fe6b4926a37278eb08cc347
2018-07-01 18:33:28 +02:00
Kévin Redon
f40c10d2f2 sniff: print parsed ATR and PPS; use red LED to show main application is running; use green LED to indicate activity (message parsed)
Change-Id: I8e906bdbf2c91e608757ae442dfb241f981b8f1e
2018-07-01 18:33:28 +02:00
Kévin Redon
8fd88b8a59 LED: add short LED pulse blinking pattern
Change-Id: I0fdc2f902a3b92da6aa9b9c8500abae8a2f79447
2018-07-01 18:33:28 +02:00
Kévin Redon
10553e7f0c update_fidi: remove debug output since this function is called in time critical ISR
Change-Id: I08f407d407a18dae3f360ddc64769ddfaeb5b559
2018-07-01 18:33:28 +02:00
Kévin Redon
833a540efa DFU: switch green LED on to indicate DFU mode, and red LED to indicate flashing activity
Change-Id: I8e34fd869ed94ad122d6a17f5a432f5a09b820bb
2018-07-01 18:33:28 +02:00
Kévin Redon
23d7306ef0 board: fix LED pin definition
Change-Id: Ia6c80c0268dec708845e1dad281caaa42027f9db
2018-07-01 18:33:28 +02:00
Kévin Redon
4646e04d1f DFU: remove force bootloader button debug message since the console is output message is not initialized yet
Change-Id: Ibea0105929a8dc38b43dacd9d1e576d7b51d0c6a
2018-07-01 18:33:28 +02:00
Kévin Redon
216a2149e1 sniffer: use ISR to store sniffed data in buffer, add ATR and PPS parsing, and PPS related FiDi update 2018-07-01 18:33:28 +02:00
Kévin Redon
13f720b650 trace: increase watchdog for 500 to 2000 ms to provide more time handling buffered data 2018-07-01 18:33:28 +02:00
Kévin Redon
ae1ce57d4c ISO7816: change update_fidi to use provided USART, and disable write protection for USART register if required 2018-07-01 18:33:28 +02:00
Kévin Redon
5dce338c6b SIMtrace: enable interrupt on edge dection for SIM_RST pin to reset the sniffer ISO state 2018-07-01 18:33:28 +02:00
Kévin Redon
ad6e7eff00 SIMtrace: fix default SIM_RST pin state to allow phone controlled reset 2018-07-01 18:33:28 +02:00
Kévin Redon
5b63e437bc SIMtrace: only enable main sniffing mode on SIMtrace board 2018-07-01 18:33:28 +02:00
Kévin Redon
915f1636b0 sniffer: add state definitions, improve IRQ handling, update pins configuration 2018-07-01 18:33:28 +02:00
Kévin Redon
04a63b386e simtrace: add support for sniffing on both USART 2018-07-01 18:33:28 +02:00
Kévin Redon
b88c73bcfd board: comment USART definitions and add corresponding IRQ numbers 2018-07-01 18:33:28 +02:00
Kévin Redon
1225e41aad simtrace: add dedicated power pins configuration for sniffing 2018-07-01 18:33:28 +02:00
Kévin Redon
7ddf46ce1c sniff: use USART 0 instead of USART 1
Use USART 0 connected to the SIM card side to sniff the communication.
The card side can also measure ETU times.
Do proper pin initialization.
This code can already capture the ATR communication between phone and card.
2018-07-01 18:33:28 +02:00
Kévin Redon
5a7c848b43 SIMtrace board: comment and fix pin definition 2018-07-01 18:33:28 +02:00
Kévin Redon
aa70887ce0 sniff mode: handle USART 1 RX interrupt to show sniffer data 2018-07-01 18:33:28 +02:00
Kévin Redon
baff8d2c22 add more USB configuration checks and error messages 2018-07-01 18:33:28 +02:00
Kévin Redon
7bcbae3ad9 enable (empty) sniffer support for SIMtrace board 2018-07-01 18:33:28 +02:00
Kévin Redon
33d62aa17a copy working cardem app to trace
because the applications share the board capabilities defined in
libboard/*/include/board.h and USB configurations are enabled according
to the previously defined capabilities in libcommon/source.usb.c, all
applications actually offer the same functions.
thus creating the trace application is only mainly a cosmetic change, as the
sniffer function will also be present and enabled in the cardem application.
2018-07-01 18:33:28 +02:00
Kévin Redon
e4cd52c2e3 fix: remove unused code
adc2uv is not used in boardver_adc.c.
a FIXME comment says it should be shared with mode_cardemu.c.
the exact same code is already available in mode_cardemu.c
2018-07-01 18:33:28 +02:00
Kévin Redon
a484b02271 sniffer: use ISR to store sniffed data in buffer, add ATR and PPS parsing, and PPS related FiDi update 2018-06-25 16:00:33 +02:00
Kévin Redon
8643420daa trace: increase watchdog for 500 to 2000 ms to provide more time handling buffered data 2018-06-25 15:57:44 +02:00
Kévin Redon
0aafbac7eb ring buffer: increase buffer size from 128 to 256 to cope with large debug output 2018-06-25 15:56:33 +02:00
Kévin Redon
67e181fb15 console: use buffer and interrupts instead of busy loops for UART debug output 2018-06-25 15:55:33 +02:00
Kévin Redon
2bac56494f ISO7816: change update_fidi to use provided USART, and disable write protection for USART register if required 2018-06-25 15:53:19 +02:00
Kévin Redon
f908f659fc SIMtrace: enable interrupt on edge dection for SIM_RST pin to reset the sniffer ISO state 2018-06-25 15:49:28 +02:00
Kévin Redon
42af4949a7 SIMtrace: fix default SIM_RST pin state to allow phone controlled reset 2018-06-24 11:31:36 +02:00
Kévin Redon
4814b15bbf SIMtrace: only enable main sniffing mode on SIMtrace board 2018-06-24 11:30:31 +02:00
Kévin Redon
78a8ab71e1 DFU: fix typo in USB strings 2018-06-24 11:27:09 +02:00
Kévin Redon
6b38297e20 DFU: incread watchdog timeout and restart watchdog before writing in flash to prevent the watchdog to trigger while flashing 2018-06-17 22:36:44 +02:00
Kévin Redon
3f8a4c28e8 DFU: only boot the application if it has a valid start 2018-06-17 22:35:17 +02:00
Kévin Redon
41d01b9d54 DFU: uncomment print message when DFU is forced using the button 2018-06-17 22:34:47 +02:00
Kévin Redon
88b2b077ef DFU: unlock the flash before writing, verify written data, and relock it 2018-06-17 22:33:29 +02:00
Kévin Redon
9a921ac630 USB: implement USB reset by setting the on-board pull-up on D+ low 2018-06-17 22:31:21 +02:00
Kévin Redon
2ab8f8e3fd sniffer: add state definitions, improve IRQ handling, update pins configuration 2018-06-11 13:46:35 +02:00
Kévin Redon
a34471d923 simtrace: add support for sniffing on both USART 2018-06-11 13:45:16 +02:00
Kévin Redon
762276e271 board: comment USART definitions and add corresponding IRQ numbers 2018-06-11 13:43:27 +02:00
Kévin Redon
2d972f5910 simtrace: add dedicated power pins configuration for sniffing 2018-06-11 13:42:23 +02:00
Kévin Redon
d0b4a9da81 sniff: use USART 0 instead of USART 1
Use USART 0 connected to the SIM card side to sniff the communication.
The card side can also measure ETU times.
Do proper pin initialization.
This code can already capture the ATR communication between phone and card.
2018-06-07 18:56:47 +02:00
Kévin Redon
7f4f8983dd USBD: send empty packet when non-existing descriptor string is requested
Sometimes descriptor string 0xee is requested.
This is a mechanism used by Microsoft Windows to further identify the USB device.
Instead of stalling, as is the original code, leading to an USB reset, we send an empty packet.
I am not sure if sending an empty string would be better, but an empty packet seems sufficient.
2018-06-06 17:03:24 +02:00
Kévin Redon
86ea4faef6 SIMtrace board: comment and fix pin definition 2018-06-06 17:02:33 +02:00
Kévin Redon
a1f198276d sniff mode: handle USART 1 RX interrupt to show sniffer data 2018-06-06 16:13:48 +02:00
Kévin Redon
b53ab5b4ef add more USB configuration checks and error messages 2018-06-04 16:30:48 +02:00
Kévin Redon
38a467e630 enable (empty) sniffer support for SIMtrace board 2018-06-04 16:30:01 +02:00
Kévin Redon
7b51f72e83 copy working cardem app to trace
because the applications share the board capabilities defined in
libboard/*/include/board.h and USB configurations are enabled according
to the previously defined capabilities in libcommon/source.usb.c, all
applications actually offer the same functions.
thus creating the trace application is only mainly a cosmetic change, as the
sniffer function will also be present and enabled in the cardem application.
2018-06-04 16:21:34 +02:00
Kévin Redon
f79ae1c54a dfu: fix address destination check and add stack overwrite check in USBDFU_handle_dnload
During DFU download the destination start address is checked to not exceed the
RAM or flash end address, but it is also necessary to check if the end of the
data to be downloaded is also within the allowed range.
When downloading to RAM it is also necessary to check if the data to be
downloaded does not overwrite (i.e. corrupt) the stack.
2018-06-01 11:02:56 +02:00
Kévin Redon
de2d03ca22 README: rewrite to better explain environment variables and point to the wiki for flashing 2018-05-21 19:35:56 +02:00
Kévin Redon
fe72bf11fd fix pointer casting warning
fixes following warning:
libboard/common/source/board_cstartup_gnu.c:137:11: warning: assignment to 'void (*)(void)' from 'unsigned int' makes pointer from integer without a cast [-Wint-conversion]
  appReset = pSrc[1];
2018-05-21 19:34:01 +02:00
Kévin Redon
0471d2a390 fix: initialize uninitialized variable in USBDFU_DFU_RequestHandler 2018-05-21 18:52:06 +02:00
Kévin Redon
5be1b612f7 fix: remove unused code
adc2uv is not used in boardver_adc.c.
a FIXME comment says it should be shared with mode_cardemu.c.
the exact same code is already available in mode_cardemu.c
2018-05-21 17:51:34 +02:00
153 changed files with 9212 additions and 13659 deletions

1
.gitignore vendored
View File

@@ -21,4 +21,3 @@ host/simtrace2-list
host/simtrace2-remsim host/simtrace2-remsim
host/simtrace2-remsim-usb2udp host/simtrace2-remsim-usb2udp
usb_strings_generated.h usb_strings_generated.h
firmware/usbstring/usbstring

View File

@@ -1,32 +0,0 @@
all: fw utils
define RULES
fw-$(1)-$(2):
make -C firmware BOARD=$(1) APP=$(2)
fw-$(1)-$(2)-clean:
make -C firmware BOARD=$(1) APP=$(2) clean
endef
$(eval $(call RULES,simtrace,dfu))
$(eval $(call RULES,simtrace,trace))
$(eval $(call RULES,simtrace,cardem))
$(eval $(call RULES,qmod,dfu))
$(eval $(call RULES,qmod,cardem))
fw-clean: fw-simtrace-dfu-clean fw-simtrace-trace-clean fw-simtrace-cardem-clean fw-qmod-dfu-clean fw-qmod-cardem-clean
fw: fw-simtrace-dfu fw-simtrace-trace fw-simtrace-cardem fw-qmod-dfu fw-qmod-cardem
utils:
(cd host && \
autoreconf -fi && \
./configure --prefix=/usr --disable-werror && \
make)
clean: fw-clean
if [ -e host/Makefile ]; then \
make -C host clean; \
fi
install:
make -C firmware install
make -C host install

View File

@@ -9,7 +9,6 @@ fi
set -e set -e
publish="$1"
base="$PWD" base="$PWD"
deps="$base/deps" deps="$base/deps"
inst="$deps/install" inst="$deps/install"
@@ -25,7 +24,7 @@ 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/cardem simtrace/trace " # simtrace/triple_play BUILDS+="simtrace/dfu simtrace/cardem " # simtrace/trace simtrace/triple_play
BUILDS+="qmod/dfu qmod/cardem " BUILDS+="qmod/dfu qmod/cardem "
BUILDS+="owhw/dfu owhw/cardem " BUILDS+="owhw/dfu owhw/cardem "
@@ -36,6 +35,7 @@ for build in $BUILDS; do
echo echo
echo "=============== $board / $app START ==============" echo "=============== $board / $app START =============="
make BOARD="$board" APP="$app" make BOARD="$board" APP="$app"
make BOARD="$board" APP="$app" clean
echo "=============== $board / $app RES:$? ==============" echo "=============== $board / $app RES:$? =============="
done done
@@ -50,41 +50,8 @@ make clean
echo echo
echo "=============== HOST START ==============" echo "=============== HOST START =============="
cd $TOPDIR/host cd $TOPDIR/host
autoreconf --install --force make clean
./configure --enable-sanitize --enable-werror make
$MAKE $PARALLEL_MAKE make clean
#$MAKE distcheck || cat-testlogs.sh
make dist
#if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
# make -C "$base/doc/manuals" publish
#fi
if [ "x$publish" = "x--publish" ]; then
echo
echo "=============== UPLOAD BUILD =============="
cat > "/build/known_hosts" <<EOF
[rita.osmocom.org]:48 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDgQ9HntlpWNmh953a2Gc8NysKE4orOatVT1wQkyzhARnfYUerRuwyNr1GqMyBKdSI9amYVBXJIOUFcpV81niA7zQRUs66bpIMkE9/rHxBd81SkorEPOIS84W4vm3SZtuNqa+fADcqe88Hcb0ZdTzjKILuwi19gzrQyME2knHY71EOETe9Yow5RD2hTIpB5ecNxI0LUKDq+Ii8HfBvndPBIr0BWYDugckQ3Bocf+yn/tn2/GZieFEyFpBGF/MnLbAAfUKIdeyFRX7ufaiWWz5yKAfEhtziqdAGZaXNaLG6gkpy3EixOAy6ZXuTAk3b3Y0FUmDjhOHllbPmTOcKMry9
[rita.osmocom.org]:48 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPdWn1kEousXuKsZ+qJEZTt/NSeASxCrUfNDW3LWtH+d8Ust7ZuKp/vuyG+5pe5pwpPOgFu7TjN+0lVjYJVXH54=
[rita.osmocom.org]:48 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8iivY70EiR5NiGChV39gRLjNpC8lvu1ZdHtdMw2zuX
EOF
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@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@rita.osmocom.org:web-files/simtrace2/firmware/all/
fi
echo
echo "=============== HOST CLEAN =============="
$MAKE maintainer-clean
echo
echo "=============== FIRMWARE CLEAN =============="
cd $TOPDIR/firmware/
for build in $BUILDS; do
board=`echo $build | cut -d "/" -f 1`
app=`echo $build | cut -d "/" -f 2`
make BOARD="$board" APP="$app" clean
done
osmo-clean-workspace.sh osmo-clean-workspace.sh

17
debian/changelog vendored
View File

@@ -1,17 +0,0 @@
simtrace2 (0.5.2) UNRELEASED; urgency=medium
* adapt to host tools in autotools
-- Harald Welte <lafore@gnumonks.org> Thu, 28 Nov 2019 00:44:57 +0100
simtrace2 (0.5.1) unstable; urgency=medium
* Backwards-compatibility with older (released, non-master) libosmocore
-- Harald Welte <lafore@gnumonks.org> Sun, 26 Aug 2018 11:50:36 +0200
simtrace2 (0.5) unstable; urgency=medium
* Initial debian package release.
-- Harald Welte <lafore@gnumonks.org> Sun, 26 Aug 2018 10:37:19 +0200

1
debian/compat vendored
View File

@@ -1 +0,0 @@
9

65
debian/control vendored
View File

@@ -1,65 +0,0 @@
Source: simtrace2
Maintainer: Harald Welte <laforge@gnumonks.org>
Section: devel
Priority: optional
Build-Depends: debhelper (>= 9),
autotools-dev,
autoconf,
automake,
libtool,
pkg-config,
git,
dh-autoreconf,
libosmocore-dev,
libpcsclite-dev,
libnewlib-arm-none-eabi,
libusb-1.0-0-dev,
gcc-arm-none-eabi
Standards-Version: 3.9.8
Vcs-Git: git://git.osmocom.org/simtrace2.git
Vcs-Browser: http://git.osmocom.org/simtrace2/
Homepage: http://osmocom.org/projects/simtrace2/wiki
Package: simtrace2-firmware
Section: devel
Architecture: all
Recommends: dfu-util
Description: Firmware for SAM3 based SIMtrace2 USB Devices.
Open Source firmware for the Cortex-M3 microcontroller in the
"Osmocom SIMtrace2" USB-attached peripheral device. Will only work in
SAM3S-based SIMtrace2, not in its SAM7S-based predecessor SIMtrace!
Package: simtrace2-utils
Section: devel
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}, libosmo-simtrace2-0
Recommends: simtrace2-firmware
Description: Host utilities to communicate with SIMtrace2 USB Devices.
Package: libosmo-simtrace2-0
Section: libs
Architecture: any
Multi-Arch: same
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Osmocom SIMtrace2 library
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: libosmo-simtrace2-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends: libosmo-simtrace2-0, ${misc:Depends}
Description: Development headers for Osmocom SIMtrace2 library
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.
.
The header files provided by this package may be used to develop
with any of the libosmocore libraries.
.
Also static libraries are installed with this package.

View File

@@ -1 +0,0 @@
usr/lib/libosmo-simtrace2*.so.*

View File

@@ -1,5 +0,0 @@
usr/include/*
usr/lib/lib*.a
usr/lib/lib*.so
usr/lib/lib*.la
usr/lib/pkgconfig/*

19
debian/rules vendored
View File

@@ -1,19 +0,0 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
export DEB_LDFLAGS_MAINT_STRIP = -Wl,-Bsymbolic-functions
%:
dh $@
override_dh_autoreconf:
cd host && dh_autoreconf

View File

@@ -1 +0,0 @@
usr/share/simtrace2/*.bin

View File

@@ -1 +0,0 @@
usr/bin/simtrace2-*

View File

@@ -28,7 +28,6 @@
# Makefile for compiling the Getting Started with SAM3S Microcontrollers project # Makefile for compiling the Getting Started with SAM3S Microcontrollers project
GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# User-modifiable options # User-modifiable options
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@@ -37,16 +36,14 @@ GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers)
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line) # (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
CHIP ?= sam3s4 CHIP ?= sam3s4
BOARD ?= qmod BOARD ?= qmod
APP ?= dfu
# Defines which are the available memory targets for the SAM3S-EK board. # Defines which are the available memory targets for the SAM3S-EK board.
ifeq ($(APP), dfu) MEMORIES ?= flash dfu
MEMORIES ?= flash
else
MEMORIES ?= dfu
endif
# Output directories and filename # Output file basename
APP ?= dfu
# Output directories
OUTPUT = $(BOARD)-$(APP) OUTPUT = $(BOARD)-$(APP)
BIN = bin BIN = bin
OBJ = obj/$(BOARD) OBJ = obj/$(BOARD)
@@ -76,6 +73,7 @@ GDB = $(CROSS_COMPILE)gdb
NM = $(CROSS_COMPILE)nm NM = $(CROSS_COMPILE)nm
TOP=.. TOP=..
GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Files # Files
@@ -102,7 +100,7 @@ C_LIBUSB_DFU = dfu.c dfu_desc.c dfu_driver.c
C_LIBCOMMON = string.c stdio.c fputs.c usb_buf.c ringbuffer.c pseudo_talloc.c host_communication.c C_LIBCOMMON = string.c stdio.c fputs.c usb_buf.c ringbuffer.c pseudo_talloc.c host_communication.c
C_BOARD = $(notdir $(wildcard libboard/common/source/*.c)) C_BOARD = $(notdir $(wildcard libboard/common/source/*.c))
C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c)) C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c))
C_APPLEVEL = $(notdir $(wildcard apps/$(APP)/*.c)) C_APPLEVEL = $(notdir $(wildcard apps/$(APP)/*.c))
@@ -122,15 +120,15 @@ C_OBJECTS = $(C_FILES:%.c=%.o)
# TRACE_LEVEL_NO_TRACE 0 # TRACE_LEVEL_NO_TRACE 0
TRACE_LEVEL ?= 4 TRACE_LEVEL ?= 4
# allow asserting the peer SAM3S ERASE signal to completely erase the flash DEBUG_PHONE_SNIFF?=0
# only applicable for qmod board
ALLOW_PEER_ERASE?=0
#CFLAGS+=-DUSB_NO_DEBUG=1 #CFLAGS+=-DUSB_NO_DEBUG=1
# Optimization level, put in comment for debugging # Optimization level, put in comment for debugging
OPTIMIZATION ?= -Os OPTIMIZATION ?= -Os
# Flags # Flags
INCLUDES_USB = -I$(AT91LIB)/usb/include -I$(AT91LIB) INCLUDES_USB = -I$(AT91LIB)/usb/include -I$(AT91LIB)
@@ -143,12 +141,13 @@ INCLUDES += -Ilibosmocore/include
INCLUDES += -Isrc_simtrace -Iinclude INCLUDES += -Isrc_simtrace -Iinclude
INCLUDES += -Iapps/$(APP) INCLUDES += -Iapps/$(APP)
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int -Wformat=2 CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int #-Wformat=2
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs #-Wunused CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs #-Wunused
CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal #-Wundef CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal #-Wundef
CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
CFLAGS += -Waggregate-return #-Wsign-compare CFLAGS += -Waggregate-return #-Wsign-compare
CFLAGS += -Wformat=0
CFLAGS += -Wmissing-format-attribute -Wno-deprecated-declarations CFLAGS += -Wmissing-format-attribute -Wno-deprecated-declarations
CFLAGS += #-Wpacked CFLAGS += #-Wpacked
CFLAGS += -Wredundant-decls -Wnested-externs #-Winline -Wlong-long CFLAGS += -Wredundant-decls -Wnested-externs #-Winline -Wlong-long
@@ -165,7 +164,7 @@ CFLAGS += -Wno-suggest-attribute=noreturn
#CFLAGS += -Wa,-a,-ad #CFLAGS += -Wa,-a,-ad
CFLAGS += -D__ARM CFLAGS += -D__ARM
CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd
CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DALLOW_PEER_ERASE=$(ALLOW_PEER_ERASE) CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DDEBUG_PHONE_SNIFF=$(DEBUG_PHONE_SNIFF)
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)
@@ -173,7 +172,8 @@ ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP)
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,--warn-unresolved-symbols $(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,--warn-unresolved-symbols $(LIB)
#LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats #LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats
# Append BIN directories to output filename
# Append OBJ and BIN directories to output filename
OUTPUT := $(BIN)/$(OUTPUT) OUTPUT := $(BIN)/$(OUTPUT)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@@ -197,11 +197,7 @@ $(BIN) $(OBJ):
usbstring/usbstring: usbstring/usbstring.c usbstring/usbstring: usbstring/usbstring.c
gcc $^ -o $@ gcc $^ -o $@
.PHONY: apps/$(APP)/usb_strings.txt.patched apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt usbstring/usbstring
apps/$(APP)/usb_strings.txt.patched: apps/$(APP)/usb_strings.txt
sed "s/PRODUCT_STRING/$(shell cat libboard/$(BOARD)/product_string.txt)/" $< > $@
apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt.patched usbstring/usbstring
cat $< | usbstring/usbstring > $@ cat $< | usbstring/usbstring > $@
define RULES define RULES
@@ -210,12 +206,8 @@ ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS))
$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1)) $(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1))
@$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS) @$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS)
cp $(OUTPUT)-$$@.elf $(OUTPUT)-$$@-$(GIT_VERSION).elf
cp $(OUTPUT)-$$@.elf $(OUTPUT)-$$@-latest.elf
@$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt @$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt
@$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin @$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin
cp $(OUTPUT)-$$@.bin $(OUTPUT)-$$@-$(GIT_VERSION).bin
cp $(OUTPUT)-$$@.bin $(OUTPUT)-$$@-latest.bin
@$(SIZE) $$^ $(OUTPUT)-$$@.elf @$(SIZE) $$^ $(OUTPUT)-$$@.elf
$$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN) $$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN)
@@ -237,13 +229,8 @@ program:
SERIAL ?= /dev/ttyUSB0 SERIAL ?= /dev/ttyUSB0
log: log:
stty -F $(SERIAL) 921600 stty -F $(SERIAL) 115200
lsof $(SERIAL) && echo "log is already opened" || ( sed -u "s/\r//" $(SERIAL) | ts ) lsof $(SERIAL) && echo "log is already opened" || ( sed -u "s/\r//" $(SERIAL) | ts )
clean: clean:
-rm -f apps/$(APP)/usb_strings.txt.patched
-rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst `find . -name \*.p` -rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst `find . -name \*.p`
install:
mkdir -p $(DESTDIR)/usr/share/simtrace2
cp $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(DESTDIR)/usr/share/simtrace2

View File

@@ -24,7 +24,6 @@ Current boards supported are:
* `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware. * `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware.
* `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available * `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available
* `owhw`: An undisclosed sysmocom-internal board, not publicly available * `owhw`: An undisclosed sysmocom-internal board, not publicly available
* `octsimtest`: A sysmocom-proprietary production testing board, not publicly available
= Firmware = Firmware
@@ -52,7 +51,6 @@ Current applications supported are:
* `cardem`: To provide remote SIM operation capabilities. * `cardem`: To provide remote SIM operation capabilities.
* `trace`: To monitor the communication between a SIM card and a phone (corresponds to the functionality provide by the first SIMtrace) * `trace`: To monitor the communication between a SIM card and a phone (corresponds to the functionality provide by the first SIMtrace)
* `triple_play`: To support the three previous functionalities, using USB configurations. * `triple_play`: To support the three previous functionalities, using USB configurations.
* `gpio_test`: internal test code
== Memories == Memories
@@ -78,10 +76,6 @@ $ make TRACE_LEVEL=4
``` ```
Accepted values: 0 (NO_TRACE) to 5 (DEBUG) Accepted values: 0 (NO_TRACE) to 5 (DEBUG)
The qmod specific option `ALLOW_PEER_ERASE` controls if the UART debug command to assert the peer SAM3S ERASE line is present in the code.
Per default this is set to 0 to prevent accidentally erasing all firmware, including the DFU bootloader, which would then need to be flashed using SAM-BA or JTAG/SWD.
Setting `ALLOW_PEER_ERASE` to 1 enables back the debug command and should be used only for debugging or development purposes.
= Flashing = Flashing
To flash a firmware image follow the instructions provided in the [wiki](https://projects.osmocom.org/projects/simtrace2/wiki/). To flash a firmware image follow the instructions provided in the [wiki](https://projects.osmocom.org/projects/simtrace2/wiki/).

View File

@@ -1,22 +1,4 @@
/* SIMtrace 2 firmware card emulation application // FIXME: Copyright license here
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.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
*/
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -102,11 +84,7 @@ static volatile enum confNum simtrace_config = CFG_NUM_CCID;
void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
{ {
TRACE_INFO_WP("cfgChanged%d ", cfgnum); TRACE_INFO_WP("cfgChanged%d ", cfgnum);
if (cfgnum < ARRAY_SIZE(config_func_ptrs)) { simtrace_config = cfgnum;
simtrace_config = cfgnum;
} else {
TRACE_ERROR("trying to set out of bounds config %u\r\n", cfgnum);
}
} }
void USART1_IrqHandler(void) void USART1_IrqHandler(void)
@@ -130,8 +108,7 @@ static void check_exec_dbg_cmd(void)
return; return;
ch = UART_GetChar(); ch = UART_GetChar();
/* We must echo the character to make python fdexpect happy, which we use in factory testing */
fputc(ch, stdout);
board_exec_dbg_cmd(ch); board_exec_dbg_cmd(ch);
} }
@@ -148,39 +125,24 @@ extern int main(void)
led_init(); led_init();
led_blink(LED_RED, BLINK_3O_5F); led_blink(LED_RED, BLINK_3O_5F);
/* Enable watchdog for 2000ms, with no window */ /* Enable watchdog for 500ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000)); (WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500));
PIO_InitializeInterrupts(0); PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id); EEFC_ReadUniqueID(g_unique_id);
printf("\n\r\n\r" printf("\n\r\n\r"
"=============================================================================\n\r" "=============================================================================\n\r"
"SIMtrace2 firmware " GIT_VERSION "\n\r" "SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r"
"(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r"
"=============================================================================\n\r"); "=============================================================================\n\r");
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO) TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r", TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
g_unique_id[0], g_unique_id[1], g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]); g_unique_id[2], g_unique_id[3]);
uint8_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos; TRACE_INFO("Reset Cause: 0x%x\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
static const char* reset_causes[] = {
"general reset (first power-up reset)",
"backup reset (return from backup mode)",
"watchdog reset (watchdog fault occurred)",
"software reset (processor reset required by the software)",
"user reset (NRST pin detected low)",
};
if (reset_cause < ARRAY_SIZE(reset_causes)) {
TRACE_INFO("Reset Cause: %s\n\r", reset_causes[reset_cause]);
} else {
TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
}
#endif
board_main_top(); board_main_top();
@@ -209,9 +171,7 @@ extern int main(void)
} }
TRACE_INFO("calling init of config %u...\n\r", simtrace_config); TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
if (config_func_ptrs[simtrace_config].init) { config_func_ptrs[simtrace_config].init();
config_func_ptrs[simtrace_config].init();
}
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
TRACE_INFO("entering main loop...\n\r"); TRACE_INFO("entering main loop...\n\r");
@@ -239,17 +199,11 @@ extern int main(void)
if (last_simtrace_config != simtrace_config) { if (last_simtrace_config != simtrace_config) {
TRACE_INFO("USB config chg %u -> %u\n\r", TRACE_INFO("USB config chg %u -> %u\n\r",
last_simtrace_config, simtrace_config); last_simtrace_config, simtrace_config);
if (config_func_ptrs[last_simtrace_config].exit) { config_func_ptrs[last_simtrace_config].exit();
config_func_ptrs[last_simtrace_config].exit(); config_func_ptrs[simtrace_config].init();
}
if (config_func_ptrs[simtrace_config].init) {
config_func_ptrs[simtrace_config].init();
}
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
} else { } else {
if (config_func_ptrs[simtrace_config].run) { config_func_ptrs[simtrace_config].run();
config_func_ptrs[simtrace_config].run();
}
} }
} }
} }

View File

@@ -1,8 +1,8 @@
sysmocom - s.f.m.c. GmbH sysmocom - s.f.m.c. GmbH
PRODUCT_STRING SIMtrace 2 compatible device
SIMtrace Sniffer SIMtrace Sniffer
SIMtrace CCID SIMtrace CCID
SIMtrace Card Emulation SIMtrace Phone
SIMtrace MITM SIMtrace MITM
CardEmulator Modem 1 CardEmulator Modem 1
CardEmulator Modem 2 CardEmulator Modem 2

View File

@@ -1,28 +1,8 @@
/* SIMtrace 2 firmware USB DFU bootloader
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018-2019 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 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 "board.h" #include "board.h"
#include "utils.h" #include "utils.h"
#include "usb/device/dfu/dfu.h" #include "usb/device/dfu/dfu.h"
#include "usb/common/dfu/usb_dfu.h" #include "usb/common/dfu/usb_dfu.h"
#include "manifest.h" #include "manifest.h"
#include "USBD_HAL.h"
#include <osmocom/core/timer.h> #include <osmocom/core/timer.h>
@@ -66,11 +46,7 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
WDT_Restart(WDT); WDT_Restart(WDT);
} }
#if TRACE_LEVEL >= TRACE_LEVEL_INFO printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
TRACE_INFO("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
#else
printf("DL off=%u\n\r", offset);
#endif
#ifdef PINS_LEDS #ifdef PINS_LEDS
PIO_Clear(&pinsLeds[LED_NUM_RED]); PIO_Clear(&pinsLeds[LED_NUM_RED]);
@@ -118,6 +94,7 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
rc = DFU_RET_ZLP; rc = DFU_RET_ZLP;
break; break;
default: default:
/* FIXME: set error codes */
TRACE_ERROR("DFU download for unknown AltIf %d\n\r", altif); TRACE_ERROR("DFU download for unknown AltIf %d\n\r", altif);
rc = DFU_RET_STALL; rc = DFU_RET_STALL;
break; break;
@@ -183,30 +160,22 @@ WEAK int board_override_enter_dfu(void)
int USBDFU_OverrideEnterDFU(void) int USBDFU_OverrideEnterDFU(void)
{ {
uint32_t *app_part = (uint32_t *)FLASH_ADDR(0); uint32_t *app_part = (uint32_t *)FLASH_ADDR(0);
/* at the first call we are before the text segment has been relocated,
* so g_dfu is not initialized yet */
g_dfu = &_g_dfu;
if (USB_DFU_MAGIC == g_dfu->magic) {
return 1;
}
/* If the loopback jumper is set, we enter DFU mode */ /* If the loopback jumper is set, we enter DFU mode */
if (board_override_enter_dfu()) { if (board_override_enter_dfu())
return 2; return 1;
}
/* if the first word of the application partition doesn't look /* if the first word of the application partition doesn't look
* like a stack pointer (i.e. point to RAM), enter DFU mode */ * like a stack pointer (i.e. point to RAM), enter DFU mode */
if ((app_part[0] < IRAM_ADDR) || ((uint8_t *)app_part[0] > IRAM_END)) { if ((app_part[0] < IRAM_ADDR) ||
return 3; ((uint8_t *)app_part[0] > IRAM_END))
} return 1;
/* if the second word of the application partition doesn't look /* if the second word of the application partition doesn't look
* like a function from flash (reset vector), enter DFU mode */ * like a function from flash (reset vector), enter DFU mode */
if (((uint32_t *)app_part[1] < app_part) || if (((uint32_t *)app_part[1] < app_part) ||
((uint8_t *)app_part[1] > IFLASH_END)) { ((uint8_t *)app_part[1] > IFLASH_END))
return 4; return 1;
}
return 0; return 0;
} }
@@ -246,14 +215,17 @@ extern int main(void)
PIO_Clear(&pinsLeds[LED_NUM_GREEN]); PIO_Clear(&pinsLeds[LED_NUM_GREEN]);
#endif #endif
/* Enable watchdog for 500ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(500) << 16) | WDT_GetPeriod(500));
PIO_InitializeInterrupts(0); PIO_InitializeInterrupts(0);
EEFC_ReadUniqueID(g_unique_id); EEFC_ReadUniqueID(g_unique_id);
printf("\n\r\n\r" printf("\n\r\n\r"
"=============================================================================\n\r" "=============================================================================\n\r"
"DFU bootloader %s for board %s\n\r" "DFU bootloader %s for board %s (C) 2010-2017 by Harald Welte\n\r"
"(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r"
"=============================================================================\n\r", "=============================================================================\n\r",
manifest_revision, manifest_board); manifest_revision, manifest_board);
@@ -261,36 +233,7 @@ extern int main(void)
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r", TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
g_unique_id[0], g_unique_id[1], g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]); g_unique_id[2], g_unique_id[3]);
TRACE_INFO("Reset Cause: 0x%lx\n\r", reset_cause); TRACE_INFO("Reset Cause: 0x%x\n\r", reset_cause);
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
/* Find out why we are in the DFU bootloader, and not the main application */
TRACE_INFO("DFU bootloader start reason: ");
switch (USBDFU_OverrideEnterDFU()) {
case 0:
/* 0 normally means that there is no override, but we are in the bootloader,
* thus the first check in board_cstartup_gnu did return something else than 0.
* this can only be g_dfu->magic which is erased when the segment are
* relocated, which happens in board_cstartup_gnu just after USBDFU_OverrideEnterDFU.
* no static variable can be used to store this case since this will also be overwritten
*/
case 1:
TRACE_INFO_WP("DFU switch requested by main application\n\r");
break;
case 2:
TRACE_INFO_WP("bootloader forced (button pressed or jumper set)\n\r");
break;
case 3:
TRACE_INFO_WP("stack pointer (first application word) does no point in RAM\n\r");
break;
case 4: // the is no reason
TRACE_INFO_WP("reset vector (second application word) does no point in flash\n\r");
break;
default:
TRACE_INFO_WP("unknown\n\r");
break;
}
#endif
/* clear g_dfu on power-up reset */ /* clear g_dfu on power-up reset */
if (reset_cause == 0) if (reset_cause == 0)
@@ -300,17 +243,11 @@ extern int main(void)
TRACE_INFO("USB init...\n\r"); TRACE_INFO("USB init...\n\r");
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */ /* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
USBD_Disconnect();
#ifdef PIN_USB_PULLUP
const Pin usb_dp_pullup = PIN_USB_PULLUP; const Pin usb_dp_pullup = PIN_USB_PULLUP;
PIO_Configure(&usb_dp_pullup, 1); PIO_Configure(&usb_dp_pullup, 1);
PIO_Set(&usb_dp_pullup); PIO_Set(&usb_dp_pullup);
#endif mdelay(15);
mdelay(50);
#ifdef PIN_USB_PULLUP
PIO_Clear(&usb_dp_pullup); PIO_Clear(&usb_dp_pullup);
#endif
USBDFU_Initialize(&dfu_descriptors); USBDFU_Initialize(&dfu_descriptors);
while (USBD_GetState() < USBD_STATE_CONFIGURED) { while (USBD_GetState() < USBD_STATE_CONFIGURED) {
@@ -318,8 +255,8 @@ extern int main(void)
check_exec_dbg_cmd(); check_exec_dbg_cmd();
#if 1 #if 1
if (i >= MAX_USB_ITER * 3) { if (i >= MAX_USB_ITER * 3) {
TRACE_ERROR("Resetting board (USB could not be configured)\n\r"); TRACE_ERROR("Resetting board (USB could "
g_dfu->magic = USB_DFU_MAGIC; // start the bootloader after reboot "not be configured)\n\r");
USBD_Disconnect(); USBD_Disconnect();
NVIC_SystemReset(); NVIC_SystemReset();
} }

View File

@@ -1,5 +1,5 @@
sysmocom - s.f.m.c. GmbH sysmocom - s.f.m.c. GmbH
PRODUCT_STRING SIMtrace 2 compatible device
DFU (Device Firmware Upgrade) DFU (Device Firmware Upgrade)
RAM RAM
Flash (Application Partition) Flash (Application Partition)

View File

@@ -1,3 +0,0 @@
C_FILES += $(C_LIBUSB_RT)
C_FILES += freq_ctr.c

View File

@@ -1,55 +0,0 @@
#include <stdint.h>
#include "utils.h"
#include "tc_etu.h"
#include "chip.h"
/* pins for Channel 0 of TC-block 0 */
#define PIN_TIOA0 {PIO_PA0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/* pins for Channel 1 of TC-block 0 */
#define PIN_TIOA1 {PIO_PA15, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_TCLK1 {PIO_PA28, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
static const Pin pins_tc[] = { PIN_TIOA0, PIN_TIOA1, PIN_TCLK1 };
static TcChannel *tc1 = &TC0->TC_CHANNEL[1];
void TC1_IrqHandler(void)
{
uint32_t sr = tc1->TC_SR;
printf("TC1=%lu; SR=0x%08lx\r\n", tc1->TC_RA, sr);
}
void freq_ctr_init(void)
{
TcChannel *tc0 = &TC0->TC_CHANNEL[0];
PIO_Configure(pins_tc, ARRAY_SIZE(pins_tc));
PMC_EnablePeripheral(ID_TC0);
PMC_EnablePeripheral(ID_TC1);
/* route TCLK1 to XC1 */
TC0->TC_BMR &= ~TC_BMR_TC1XC1S_Msk;
TC0->TC_BMR |= TC_BMR_TC1XC1S_TCLK1;
/* TC0 in wveform mode: Run from SCLK. Raise TIOA on RA; lower TIOA on RC + trigger */
tc0->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK5 | TC_CMR_BURST_NONE |
TC_CMR_EEVTEDG_NONE | TC_CMR_WAVSEL_UP_RC | TC_CMR_WAVE |
TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR;
tc0->TC_RA = 16384; /* set high at 16384 */
tc0->TC_RC = 32786; /* set low at 32786 */
/* TC1 in capture mode: Run from XC1. Trigger on TIOA rising. Load RA on rising */
tc1->TC_CMR = TC_CMR_TCCLKS_XC1 | TC_CMR_BURST_NONE |
TC_CMR_ETRGEDG_RISING | TC_CMR_ABETRG | TC_CMR_LDRA_RISING;
/* Interrupt us if the external trigger happens */
tc1->TC_IER = TC_IER_ETRGS;
NVIC_EnableIRQ(TC1_IRQn);
TC0->TC_BCR = TC_BCR_SYNC;
tc0->TC_CCR = TC_CCR_CLKEN|TC_CCR_SWTRG;
tc1->TC_CCR = TC_CCR_CLKEN|TC_CCR_SWTRG;
}

View File

@@ -1,54 +0,0 @@
#include "board.h"
#include "utils.h"
#include "osmocom/core/timer.h"
extern void freq_ctr_init(void);
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
board_exec_dbg_cmd(ch);
}
extern int main(void)
{
led_init();
led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
/* Enable watchdog for 2000 ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
PIO_InitializeInterrupts(0);
printf("\n\r\n\r"
"=============================================================================\n\r"
"Freq Ctr firmware " GIT_VERSION " (C) 2019 by Harald Welte\n\r"
"=============================================================================\n\r");
board_main_top();
TRACE_INFO("starting frequency counter...\n\r");
freq_ctr_init();
TRACE_INFO("entering main loop...\n\r");
while (1) {
WDT_Restart(WDT);
check_exec_dbg_cmd();
osmo_timers_prepare();
osmo_timers_update();
}
}

View File

@@ -1,10 +0,0 @@
sysmocom - s.f.m.c. GmbH
PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
CardEmulator Modem 3
CardEmulator Modem 4

View File

@@ -1,3 +0,0 @@
C_FILES += $(C_LIBUSB_RT)
C_FILES += gpio_test.c

View File

@@ -1,8 +0,0 @@
#include <stdint.h>
#include "utils.h"
#include "chip.h"
void gpio_test_init(void)
{
printf("FIXME run tests here\n\r");
}

View File

@@ -1,54 +0,0 @@
#include "board.h"
#include "utils.h"
#include "osmocom/core/timer.h"
extern void gpio_test_init(void);
/* returns '1' in case we should break any endless loop */
static void check_exec_dbg_cmd(void)
{
int ch;
if (!UART_IsRxReady())
return;
ch = UART_GetChar();
board_exec_dbg_cmd(ch);
}
extern int main(void)
{
led_init();
led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
/* Enable watchdog for 2000 ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
PIO_InitializeInterrupts(0);
printf("\n\r\n\r"
"=============================================================================\n\r"
"GPIO Test firmware " GIT_VERSION " (C) 2019 Sysmocom GmbH\n\r"
"=============================================================================\n\r");
board_main_top();
TRACE_INFO("starting gpio test...\n\r");
gpio_test_init();
TRACE_INFO("entering main loop...\n\r");
while (1) {
WDT_Restart(WDT);
check_exec_dbg_cmd();
osmo_timers_prepare();
osmo_timers_update();
}
}

View File

@@ -1,10 +0,0 @@
sysmocom - s.f.m.c. GmbH
PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
CardEmulator Modem 3
CardEmulator Modem 4

View File

@@ -1,21 +1,21 @@
/* SIMtrace 2 firmware sniffer application /*
* (C) 2010-2017 by Harald Welte <hwelte@sysmocom.de>
* (C) 2018 by Kevin Redon <kredon@sysmocom.de>
* All Rights Reserved
* *
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de> * This program is free software; you can redistribute it and/or modify
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * it under the terms of the GNU Affero General Public License as published by
* * the Free Software Foundation; either version 3 of the License, or
* This program is free software; you can redistribute it and/or * (at your option) any later version.
* 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* 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.
*/ */
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
@@ -104,6 +104,9 @@ static volatile enum confNum simtrace_config = CFG_NUM_CCID;
void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
{ {
TRACE_INFO_WP("cfgChanged%d ", cfgnum); TRACE_INFO_WP("cfgChanged%d ", cfgnum);
if (cfgnum >= sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
TRACE_FATAL_WP("no functions defined for configuration %d\n\r", cfgnum);
}
simtrace_config = cfgnum; simtrace_config = cfgnum;
} }
@@ -142,15 +145,10 @@ extern int main(void)
enum confNum last_simtrace_config = simtrace_config; enum confNum last_simtrace_config = simtrace_config;
unsigned int i = 0; unsigned int i = 0;
/* Configure LED output /* Configure LED output (red = on, green = activity */
* red on = power
* red blink = error
* green on = running
* green blink = activity
*/
led_init(); led_init();
led_blink(LED_RED, BLINK_ALWAYS_ON); led_blink(LED_RED, BLINK_ALWAYS_ON);
led_blink(LED_GREEN, BLINK_ALWAYS_ON); led_blink(LED_GREEN, BLINK_ALWAYS_OFF);
/* Enable watchdog for 2000 ms, with no window */ /* Enable watchdog for 2000 ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
@@ -160,22 +158,23 @@ extern int main(void)
EEFC_ReadUniqueID(g_unique_id); EEFC_ReadUniqueID(g_unique_id);
printf("\n\r\n\r" printf("\n\r\n\r"
"=============================================================================\n\r" "=============================================================================\n\r"
"SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r" "SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r"
"=============================================================================\n\r"); "=============================================================================\n\r");
TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID); TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r", TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
g_unique_id[0], g_unique_id[1], g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]); g_unique_id[2], g_unique_id[3]);
TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos); TRACE_INFO("Reset Cause: 0x%x\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
TRACE_INFO("USB configuration used: %d\n\r", simtrace_config); TRACE_INFO("USB configuration used: %d\n\r", simtrace_config);
board_main_top(); board_main_top();
TRACE_INFO("USB init...\n\r"); TRACE_INFO("USB init...\n\r");
SIMtrace_USB_Initialize(); SIMtrace_USB_Initialize();
TRACE_INFO_WP("USBD_Inited\n\r");
while (USBD_GetState() < USBD_STATE_CONFIGURED) { while (USBD_GetState() < USBD_STATE_CONFIGURED) {
WDT_Restart(WDT); WDT_Restart(WDT);
@@ -192,13 +191,26 @@ extern int main(void)
} }
TRACE_INFO("calling configure of all configurations...\n\r"); TRACE_INFO("calling configure of all configurations...\n\r");
for (i = 1; i < ARRAY_SIZE(config_func_ptrs); i++) { for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]); ++i) {
if (config_func_ptrs[i].configure) if (config_func_ptrs[i].configure) {
config_func_ptrs[i].configure(); config_func_ptrs[i].configure();
} else {
TRACE_WARNING("no configure function defined for configuration %d\n\r", i);
}
} }
TRACE_INFO("cfg %d\n\r", simtrace_config);
TRACE_INFO("calling init of config %u...\n\r", simtrace_config); TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
config_func_ptrs[simtrace_config].init(); if (simtrace_config >= sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
TRACE_ERROR("no functions defined for configuration %d\n\r", simtrace_config);
} else {
if (config_func_ptrs[simtrace_config].init) {
config_func_ptrs[simtrace_config].init();
} else {
TRACE_ERROR("no init function defined for configuration %d\n\r", simtrace_config);
}
}
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
TRACE_INFO("entering main loop...\n\r"); TRACE_INFO("entering main loop...\n\r");
@@ -226,11 +238,31 @@ extern int main(void)
if (last_simtrace_config != simtrace_config) { if (last_simtrace_config != simtrace_config) {
TRACE_INFO("USB config chg %u -> %u\n\r", TRACE_INFO("USB config chg %u -> %u\n\r",
last_simtrace_config, simtrace_config); last_simtrace_config, simtrace_config);
config_func_ptrs[last_simtrace_config].exit(); if (last_simtrace_config < sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
config_func_ptrs[simtrace_config].init(); if (config_func_ptrs[last_simtrace_config].exit) {
config_func_ptrs[last_simtrace_config].exit();
} else {
TRACE_WARNING("exit not defined for configuration %d\n\r", last_simtrace_config);
}
} else {
TRACE_ERROR("no functions defined for configuration %d\n\r", last_simtrace_config);
}
if (simtrace_config < sizeof(config_func_ptrs)/sizeof(config_func_ptrs[0])) {
if (config_func_ptrs[simtrace_config].init) {
config_func_ptrs[simtrace_config].init();
} else {
TRACE_WARNING("init not defined for configuration %d\n\r", simtrace_config);
}
} else {
TRACE_FATAL("no functions defined for configuration %d\n\r", simtrace_config);
}
last_simtrace_config = simtrace_config; last_simtrace_config = simtrace_config;
} else { } else {
config_func_ptrs[simtrace_config].run(); if (config_func_ptrs[simtrace_config].run) {
config_func_ptrs[simtrace_config].run();
} else {
TRACE_ERROR("run not defined for configuration %d\n\r", simtrace_config);
}
} }
} }
} }

View File

@@ -1,8 +1,8 @@
sysmocom - s.f.m.c. GmbH sysmocom - s.f.m.c. GmbH
PRODUCT_STRING SIMtrace 2 compatible device
SIMtrace Sniffer SIMtrace Sniffer
SIMtrace CCID SIMtrace CCID
SIMtrace Card Emulation SIMtrace Phone
SIMtrace MITM SIMtrace MITM
CardEmulator Modem 1 CardEmulator Modem 1
CardEmulator Modem 2 CardEmulator Modem 2

View File

@@ -1,21 +1,4 @@
/* SIMtrace 2 firmware card emulation, CCID, and sniffer application // FIXME: Copyright license here
*
* (C) 2015-2017 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
*/
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -151,7 +134,7 @@ extern int main(void)
EEFC_ReadUniqueID(g_unique_id); EEFC_ReadUniqueID(g_unique_id);
printf("\r\n\r\n" printf("\r\n\r\n"
"=============================================================================\r\n" "=============================================================================\r\n"
"SIMtrace2 firmware " GIT_REVISION " (C) 2010-2017 by Harald Welte\r\n" "SIMtrace2 firmware " GIT_REVISION " (C) 2010-2017 by Harald Welte\r\n"
"=============================================================================\r\n"); "=============================================================================\r\n");

View File

@@ -2,7 +2,6 @@
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* All rights reserved. * All rights reserved.
* *
@@ -43,7 +42,6 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#define printf printf_sync
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions

View File

@@ -251,7 +251,7 @@ static void GetDescriptor(
switch (type) { switch (type) {
case USBGenericDescriptor_DEVICE: case USBGenericDescriptor_DEVICE:
TRACE_DEBUG_WP("Dev "); TRACE_INFO_WP("Dev ");
/* Adjust length and send descriptor */ /* Adjust length and send descriptor */
@@ -263,7 +263,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_CONFIGURATION: case USBGenericDescriptor_CONFIGURATION:
TRACE_DEBUG_WP("Cfg "); TRACE_INFO_WP("Cfg ");
/* Adjust length and send descriptor */ /* Adjust length and send descriptor */
@@ -280,7 +280,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_DEVICEQUALIFIER: case USBGenericDescriptor_DEVICEQUALIFIER:
TRACE_DEBUG_WP("Qua "); TRACE_INFO_WP("Qua ");
/* Check if descriptor exists */ /* Check if descriptor exists */
@@ -301,7 +301,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_OTHERSPEEDCONFIGURATION: case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
TRACE_DEBUG_WP("OSC "); TRACE_INFO_WP("OSC ");
/* Check if descriptor exists */ /* Check if descriptor exists */
@@ -327,7 +327,7 @@ static void GetDescriptor(
break; break;
case USBGenericDescriptor_STRING: case USBGenericDescriptor_STRING:
TRACE_DEBUG_WP("Str%d ", indexRDesc); TRACE_INFO_WP("Str%d ", indexRDesc);
/* Check if descriptor exists */ /* Check if descriptor exists */
@@ -504,13 +504,13 @@ void USBDDriver_RequestHandler(
uint32_t length; uint32_t length;
uint32_t address; uint32_t address;
TRACE_DEBUG_WP("Std "); TRACE_INFO_WP("Std ");
/* Check request code */ /* Check request code */
switch (USBGenericRequest_GetRequest(pRequest)) { switch (USBGenericRequest_GetRequest(pRequest)) {
case USBGenericRequest_GETDESCRIPTOR: case USBGenericRequest_GETDESCRIPTOR:
TRACE_DEBUG_WP("gDesc "); TRACE_INFO_WP("gDesc ");
/* Send the requested descriptor */ /* Send the requested descriptor */
type = USBGetDescriptorRequest_GetDescriptorType(pRequest); type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
@@ -520,7 +520,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETADDRESS: case USBGenericRequest_SETADDRESS:
TRACE_DEBUG_WP("sAddr "); TRACE_INFO_WP("sAddr ");
/* Sends a zero-length packet and then set the device address */ /* Sends a zero-length packet and then set the device address */
address = USBSetAddressRequest_GetAddress(pRequest); address = USBSetAddressRequest_GetAddress(pRequest);
@@ -528,7 +528,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETCONFIGURATION: case USBGenericRequest_SETCONFIGURATION:
TRACE_DEBUG_WP("sCfg "); TRACE_INFO_WP("sCfg ");
/* Set the requested configuration */ /* Set the requested configuration */
cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest); cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
@@ -536,27 +536,27 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_GETCONFIGURATION: case USBGenericRequest_GETCONFIGURATION:
TRACE_DEBUG_WP("gCfg "); TRACE_INFO_WP("gCfg ");
/* Send the current configuration number */ /* Send the current configuration number */
GetConfiguration(pDriver); GetConfiguration(pDriver);
break; break;
case USBGenericRequest_GETSTATUS: case USBGenericRequest_GETSTATUS:
TRACE_DEBUG_WP("gSta "); TRACE_INFO_WP("gSta ");
/* Check who is the recipient */ /* Check who is the recipient */
switch (USBGenericRequest_GetRecipient(pRequest)) { switch (USBGenericRequest_GetRecipient(pRequest)) {
case USBGenericRequest_DEVICE: case USBGenericRequest_DEVICE:
TRACE_DEBUG_WP("Dev "); TRACE_INFO_WP("Dev ");
/* Send the device status */ /* Send the device status */
GetDeviceStatus(pDriver); GetDeviceStatus(pDriver);
break; break;
case USBGenericRequest_ENDPOINT: case USBGenericRequest_ENDPOINT:
TRACE_DEBUG_WP("Ept "); TRACE_INFO_WP("Ept ");
/* Send the endpoint status */ /* Send the endpoint status */
eptnum = USBGenericRequest_GetEndpointNumber(pRequest); eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
@@ -572,13 +572,13 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_CLEARFEATURE: case USBGenericRequest_CLEARFEATURE:
TRACE_DEBUG_WP("cFeat "); TRACE_INFO_WP("cFeat ");
/* Check which is the requested feature */ /* Check which is the requested feature */
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) { switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_ENDPOINTHALT: case USBFeatureRequest_ENDPOINTHALT:
TRACE_DEBUG_WP("Hlt "); TRACE_INFO_WP("Hlt ");
/* Unhalt endpoint and send a zero-length packet */ /* Unhalt endpoint and send a zero-length packet */
USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest)); USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
@@ -586,7 +586,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBFeatureRequest_DEVICEREMOTEWAKEUP: case USBFeatureRequest_DEVICEREMOTEWAKEUP:
TRACE_DEBUG_WP("RmWU "); TRACE_INFO_WP("RmWU ");
/* Disable remote wake-up and send a zero-length packet */ /* Disable remote wake-up and send a zero-length packet */
pDriver->isRemoteWakeUpEnabled = 0; pDriver->isRemoteWakeUpEnabled = 0;
@@ -602,13 +602,13 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETFEATURE: case USBGenericRequest_SETFEATURE:
TRACE_DEBUG_WP("sFeat "); TRACE_INFO_WP("sFeat ");
/* Check which is the selected feature */ /* Check which is the selected feature */
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) { switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_DEVICEREMOTEWAKEUP: case USBFeatureRequest_DEVICEREMOTEWAKEUP:
TRACE_DEBUG_WP("RmWU "); TRACE_INFO_WP("RmWU ");
/* Enable remote wake-up and send a ZLP */ /* Enable remote wake-up and send a ZLP */
pDriver->isRemoteWakeUpEnabled = 1; pDriver->isRemoteWakeUpEnabled = 1;
@@ -616,25 +616,25 @@ void USBDDriver_RequestHandler(
break; break;
case USBFeatureRequest_ENDPOINTHALT: case USBFeatureRequest_ENDPOINTHALT:
TRACE_DEBUG_WP("Halt "); TRACE_INFO_WP("Halt ");
/* Halt endpoint */ /* Halt endpoint */
USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest)); USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
break; break;
case USBFeatureRequest_OTG_B_HNP_ENABLE: case USBFeatureRequest_OTG_B_HNP_ENABLE:
TRACE_DEBUG_WP("OTG_B_HNP_ENABLE "); TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
pDriver->otg_features_supported |= pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_B_HNP_ENABLE; 1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
break; break;
case USBFeatureRequest_OTG_A_HNP_SUPPORT: case USBFeatureRequest_OTG_A_HNP_SUPPORT:
TRACE_DEBUG_WP("OTG_A_HNP_SUPPORT "); TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
pDriver->otg_features_supported |= pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_A_HNP_SUPPORT; 1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
break; break;
case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT: case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
TRACE_DEBUG_WP("OTG_A_ALT_HNP_SUPPORT "); TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
pDriver->otg_features_supported |= pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT; 1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0); USBD_Write(0, 0, 0, 0, 0);
@@ -649,7 +649,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_SETINTERFACE: case USBGenericRequest_SETINTERFACE:
TRACE_DEBUG_WP("sInterface "); TRACE_INFO_WP("sInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest); infnum = USBInterfaceRequest_GetInterface(pRequest);
setting = USBInterfaceRequest_GetAlternateSetting(pRequest); setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
@@ -657,7 +657,7 @@ void USBDDriver_RequestHandler(
break; break;
case USBGenericRequest_GETINTERFACE: case USBGenericRequest_GETINTERFACE:
TRACE_DEBUG_WP("gInterface "); TRACE_INFO_WP("gInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest); infnum = USBInterfaceRequest_GetInterface(pRequest);
GetInterface(pDriver, infnum); GetInterface(pDriver, infnum);

View File

@@ -101,7 +101,7 @@ struct dfudata {
extern struct dfudata _g_dfu; extern struct dfudata _g_dfu;
extern struct dfudata *g_dfu; extern struct dfudata *g_dfu;
void set_usb_serial_str(void); void set_usb_serial_str(const uint8_t *serial_usbstr);
void DFURT_SwitchToDFU(void); void DFURT_SwitchToDFU(void);

View File

@@ -13,87 +13,14 @@
#include <usb/common/dfu/usb_dfu.h> #include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h> #include <usb/device/dfu/dfu.h>
#include "usb_strings_generated.h"
enum { enum {
STR_MANUF = 1, STR_MANUF = 1,
STR_PROD, STR_PROD,
STR_CONFIG, STR_CONFIG,
_STR_FIRST_ALT, _STR_FIRST_ALT,
// serial string
STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF), STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF),
// version string (on additional interface)
VERSION_CONF_STR,
VERSION_STR,
// count
STRING_DESC_CNT,
}; };
/* USB string for the serial (using 128-bit device ID) */
static unsigned char usb_string_serial[] = {
USBStringDescriptor_LENGTH(32),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('0'),
USBStringDescriptor_UNICODE('0'),
USBStringDescriptor_UNICODE('1'),
USBStringDescriptor_UNICODE('1'),
USBStringDescriptor_UNICODE('2'),
USBStringDescriptor_UNICODE('2'),
USBStringDescriptor_UNICODE('3'),
USBStringDescriptor_UNICODE('3'),
USBStringDescriptor_UNICODE('4'),
USBStringDescriptor_UNICODE('4'),
USBStringDescriptor_UNICODE('5'),
USBStringDescriptor_UNICODE('5'),
USBStringDescriptor_UNICODE('6'),
USBStringDescriptor_UNICODE('6'),
USBStringDescriptor_UNICODE('7'),
USBStringDescriptor_UNICODE('7'),
USBStringDescriptor_UNICODE('8'),
USBStringDescriptor_UNICODE('8'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('b'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('c'),
USBStringDescriptor_UNICODE('d'),
USBStringDescriptor_UNICODE('d'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('f'),
USBStringDescriptor_UNICODE('f'),
};
/* USB string for the version */
static const unsigned char usb_string_version_conf[] = {
USBStringDescriptor_LENGTH(16),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('f'),
USBStringDescriptor_UNICODE('i'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('m'),
USBStringDescriptor_UNICODE('w'),
USBStringDescriptor_UNICODE('a'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('v'),
USBStringDescriptor_UNICODE('e'),
USBStringDescriptor_UNICODE('r'),
USBStringDescriptor_UNICODE('s'),
USBStringDescriptor_UNICODE('i'),
USBStringDescriptor_UNICODE('o'),
USBStringDescriptor_UNICODE('n'),
};
static const char git_version[] = GIT_VERSION;
static unsigned char usb_string_version[2 + ARRAY_SIZE(git_version) * 2 - 2];
/** array of static (from usb_strings) and runtime (serial, version) USB strings */
static const unsigned char *usb_strings_extended[STRING_DESC_CNT];
static const USBDeviceDescriptor fsDevice = { static const USBDeviceDescriptor fsDevice = {
.bLength = sizeof(USBDeviceDescriptor), .bLength = sizeof(USBDeviceDescriptor),
.bDescriptorType = USBGenericDescriptor_DEVICE, .bDescriptorType = USBGenericDescriptor_DEVICE,
@@ -107,8 +34,12 @@ static const USBDeviceDescriptor fsDevice = {
.bcdDevice = BOARD_USB_RELEASE, .bcdDevice = BOARD_USB_RELEASE,
.iManufacturer = STR_MANUF, .iManufacturer = STR_MANUF,
.iProduct = STR_PROD, .iProduct = STR_PROD,
#ifdef BOARD_USB_SERIAL
.iSerialNumber = STR_SERIAL, .iSerialNumber = STR_SERIAL,
.bNumConfigurations = 2, // DFU + version configurations #else
.iSerialNumber = 0,
#endif
.bNumConfigurations = 1,
}; };
/* Alternate Interface Descriptor, we use one per partition/memory type */ /* Alternate Interface Descriptor, we use one per partition/memory type */
@@ -154,74 +85,17 @@ const struct dfu_desc dfu_cfg_descriptor = {
.func_dfu = DFU_FUNC_DESC .func_dfu = DFU_FUNC_DESC
}; };
void set_usb_serial_str(void) #include "usb_strings_generated.h"
#if 0
void set_usb_serial_str(const uint8_t *serial_usbstr)
{ {
unsigned int i; usb_strings[STR_SERIAL] = serial_usbstr;
// put device ID into USB serial number description
unsigned int device_id[4];
EEFC_ReadUniqueID(device_id);
char device_id_string[32 + 1];
snprintf(device_id_string, ARRAY_SIZE(device_id_string), "%08x%08x%08x%08x",
device_id[0], device_id[1], device_id[2], device_id[3]);
for (i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
usb_string_serial[2 + 2 * i] = device_id_string[i];
}
// put version into USB string
usb_string_version[0] = USBStringDescriptor_LENGTH(ARRAY_SIZE(git_version) - 1);
usb_string_version[1] = USBGenericDescriptor_STRING;
for (i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
usb_string_version[2 + i * 2 + 0] = git_version[i];
usb_string_version[2 + i * 2 + 1] = 0;
}
// fill extended USB strings
for (i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
usb_strings_extended[i] = usb_strings[i];
}
usb_strings_extended[STR_SERIAL] = usb_string_serial;
usb_strings_extended[VERSION_CONF_STR] = usb_string_version_conf;
usb_strings_extended[VERSION_STR] = usb_string_version;
} }
#endif
/* USB descriptor just to show the version */
typedef struct _SIMTraceDriverConfigurationDescriptorVersion {
/** Standard configuration descriptor. */
USBConfigurationDescriptor configuration;
USBInterfaceDescriptor version;
} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorVersion;
static const SIMTraceDriverConfigurationDescriptorVersion
configurationDescriptorVersion = {
/* Standard configuration descriptor for the interface descriptor*/
.configuration = {
.bLength = sizeof(USBConfigurationDescriptor),
.bDescriptorType = USBGenericDescriptor_CONFIGURATION,
.wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorVersion),
.bNumInterfaces = 1,
.bConfigurationValue = 2,
.iConfiguration = VERSION_CONF_STR,
.bmAttributes = USBD_BMATTRIBUTES,
.bMaxPower = USBConfigurationDescriptor_POWER(100),
},
/* Interface standard descriptor just holding the version information */
.version = {
.bLength = sizeof(USBInterfaceDescriptor),
.bDescriptorType = USBGenericDescriptor_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = USB_CLASS_PROPRIETARY,
.bInterfaceSubClass = 0xff,
.bInterfaceProtocol = 0,
.iInterface = VERSION_STR,
},
};
static const USBConfigurationDescriptor *conf_desc_arr[] = { static const USBConfigurationDescriptor *conf_desc_arr[] = {
&dfu_cfg_descriptor.ucfg, &dfu_cfg_descriptor.ucfg,
&configurationDescriptorVersion.configuration,
}; };
const USBDDriverDescriptors dfu_descriptors = { const USBDDriverDescriptors dfu_descriptors = {
@@ -234,6 +108,6 @@ const USBDDriverDescriptors dfu_descriptors = {
.pHsConfiguration = NULL, .pHsConfiguration = NULL,
.pHsQualifier = NULL, .pHsQualifier = NULL,
.pHsOtherSpeed = NULL, .pHsOtherSpeed = NULL,
.pStrings = usb_strings_extended, .pStrings = usb_strings,
.numStrings = ARRAY_SIZE(usb_strings_extended), .numStrings = ARRAY_SIZE(usb_strings),
}; };

View File

@@ -447,7 +447,6 @@ void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors)
/* We already start in DFU idle mode */ /* We already start in DFU idle mode */
g_dfu->state = DFU_STATE_dfuIDLE; g_dfu->state = DFU_STATE_dfuIDLE;
set_usb_serial_str();
USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings); USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings);
USBD_Init(); USBD_Init();
USBD_Connect(); USBD_Connect();

View File

@@ -208,7 +208,7 @@ void DFURT_SwitchToDFU(void)
* activate itself, rather than boot into the application */ * activate itself, rather than boot into the application */
g_dfu->magic = USB_DFU_MAGIC; g_dfu->magic = USB_DFU_MAGIC;
/* Disconnect the USB by removing the pull-up */ /* Disconnect the USB by remoting the pull-up */
USBD_Disconnect(); USBD_Disconnect();
__disable_irq(); __disable_irq();

View File

@@ -1,22 +1,3 @@
/* SIMtrace 2 common board pin definitions
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.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 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
*/
#ifndef _BOARD_ #ifndef _BOARD_
#define _BOARD_ #define _BOARD_
@@ -56,12 +37,18 @@
/** Core definition */ /** Core definition */
#define cortexm3 #define cortexm3
/* LEDs are used to indicate the status #define BOARD_MCK 48000000
* the LED definition is board specific
* most boards have two LEDs, one green and one red #define PIO_LED_RED PIO_PA17
* the red LED indicates of the main firmware is ready (on) or if there is an error (blinking) #define PIO_LED_GREEN PIO_PA18
* the green LED indicates if the firmware is idling (on) or if there is activity (blinking)
*/ #define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
#define LED_NUM_RED 0
#define LED_NUM_GREEN 1
/** USART0 pin RX */ /** USART0 pin RX */
#define PIN_USART0_RXD {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PIN_USART0_RXD {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** USART0 pin TX */ /** USART0 pin TX */
@@ -76,8 +63,8 @@
#define PINS_UART { PIO_PA9A_URXD0|PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} #define PINS_UART { PIO_PA9A_URXD0|PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** UART0 */ /** UART0 */
/** Console baud rate in bps */ /** Console baudrate always using 115200. */
#define CONSOLE_BAUDRATE 921600 #define CONSOLE_BAUDRATE 115200
/** UART peripheral used by the console (UART0). */ /** UART peripheral used by the console (UART0). */
#define CONSOLE_UART UART0 #define CONSOLE_UART UART0
/** UART peripheral ID used by the console (UART0). */ /** UART peripheral ID used by the console (UART0). */
@@ -108,8 +95,18 @@
/* Interrupt request ID of USART peripheral connected to the phone */ /* Interrupt request ID of USART peripheral connected to the phone */
#define IRQ_USART_PHONE USART1_IRQn #define IRQ_USART_PHONE USART1_IRQn
#define SIM_PWEN PIO_PA5
#define VCC_FWD PIO_PA26
/** Pin configuration to control USB pull-up on D+
* @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
*/
#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
// Board has UDP controller // Board has UDP controller
#define BOARD_USB_UDP #define BOARD_USB_UDP
// D+ has external pull-up
#define BOARD_USB_PULLUP_EXTERNAL
#define BOARD_USB_DFU #define BOARD_USB_DFU
#define BOARD_DFU_BOOT_SIZE (16 * 1024) #define BOARD_DFU_BOOT_SIZE (16 * 1024)

View File

@@ -26,6 +26,7 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *

View File

@@ -1,18 +1,4 @@
/* 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
*/
#pragma once #pragma once
int get_board_version_adc(void);
uint32_t adc2uv(uint16_t adc); uint32_t adc2uv(uint16_t adc);
int get_board_version_adc(void);

View File

@@ -1,17 +1,3 @@
/* 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
*/
#pragma once #pragma once
enum led { enum led {
@@ -31,7 +17,6 @@ enum led_pattern {
BLINK_200O_F = 7, BLINK_200O_F = 7,
BLINK_600O_F = 8, BLINK_600O_F = 8,
BLINK_CUSTOM = 9, BLINK_CUSTOM = 9,
BLINK_2F_O,
_NUM_LED_BLINK _NUM_LED_BLINK
}; };

View File

@@ -1,17 +1,4 @@
/* 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
*/
#ifndef _MANIFEST_H #ifndef _MANIFEST_H
#define _MANIFEST_H #define _MANIFEST_H

View File

@@ -1,17 +1,3 @@
/* 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
*/
#pragma once #pragma once
int sim_switch_use_physical(unsigned int nr, int physical); int sim_switch_use_physical(unsigned int nr, int physical);

View File

@@ -2,7 +2,6 @@
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* All rights reserved. * All rights reserved.
* *
@@ -27,17 +26,19 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#ifndef _UART_CONSOLE_ #ifndef _UART_CONSOLE_
#define _UART_CONSOLE_ #define _UART_CONSOLE_
#include <stdint.h> #include <stdint.h>
extern void UART_Configure( uint32_t dwBaudrate, uint32_t dwMasterClock ) ; extern void UART_Configure( uint32_t dwBaudrate, uint32_t dwMasterClock ) ;
extern void UART_Exit( void ) ;
extern void UART_PutChar( uint8_t uc ) ; extern void UART_PutChar( uint8_t uc ) ;
extern void UART_PutChar_Sync( uint8_t uc ) ;
extern uint32_t UART_GetChar( void ) ; extern uint32_t UART_GetChar( void ) ;
extern uint32_t UART_IsRxReady( void ) ; extern uint32_t UART_IsRxReady( void ) ;
extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) ; extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) ;
extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) ; extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) ;
extern uint32_t UART_GetInteger( uint32_t* pdwValue ) ; extern uint32_t UART_GetInteger( uint32_t* pdwValue ) ;

View File

@@ -2,8 +2,7 @@
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation * Copyright (c) 2010, Atmel Corporation
* Copyright (c) 2017, Harald Welte <laforge@gnumonks.org> * Copyright (C) 2017, Harald Welte <laforge@gnumonks.org>
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* All rights reserved. * All rights reserved.
* *
@@ -71,59 +70,59 @@ void ResetException( void ) ;
__attribute__((section(".vectors"))) __attribute__((section(".vectors")))
IntFunc exception_table[] = { IntFunc exception_table[] = {
/* Configure Initial Stack Pointer, using linker-generated symbols */ /* Configure Initial Stack Pointer, using linker-generated symbols */
(IntFunc)(&pdwStack[STACK_SIZE-1]), (IntFunc)(&pdwStack[STACK_SIZE-1]),
ResetException, ResetException,
NMI_Handler, NMI_Handler,
HardFault_Handler, HardFault_Handler,
MemManage_Handler, MemManage_Handler,
BusFault_Handler, BusFault_Handler,
UsageFault_Handler, UsageFault_Handler,
0, 0, 0, 0, /* Reserved */ 0, 0, 0, 0, /* Reserved */
SVC_Handler, SVC_Handler,
DebugMon_Handler, DebugMon_Handler,
0, /* Reserved */ 0, /* Reserved */
PendSV_Handler, PendSV_Handler,
SysTick_Handler, SysTick_Handler,
/* Configurable interrupts */ /* Configurable interrupts */
SUPC_IrqHandler, /* 0 Supply Controller */ SUPC_IrqHandler, /* 0 Supply Controller */
RSTC_IrqHandler, /* 1 Reset Controller */ RSTC_IrqHandler, /* 1 Reset Controller */
RTC_IrqHandler, /* 2 Real Time Clock */ RTC_IrqHandler, /* 2 Real Time Clock */
RTT_IrqHandler, /* 3 Real Time Timer */ RTT_IrqHandler, /* 3 Real Time Timer */
WDT_IrqHandler, /* 4 Watchdog Timer */ WDT_IrqHandler, /* 4 Watchdog Timer */
PMC_IrqHandler, /* 5 PMC */ PMC_IrqHandler, /* 5 PMC */
EEFC_IrqHandler, /* 6 EEFC */ EEFC_IrqHandler, /* 6 EEFC */
IrqHandlerNotUsed, /* 7 Reserved */ IrqHandlerNotUsed, /* 7 Reserved */
UART0_IrqHandler, /* 8 UART0 */ UART0_IrqHandler, /* 8 UART0 */
UART1_IrqHandler, /* 9 UART1 */ UART1_IrqHandler, /* 9 UART1 */
SMC_IrqHandler, /* 10 SMC */ SMC_IrqHandler, /* 10 SMC */
PIOA_IrqHandler, /* 11 Parallel IO Controller A */ PIOA_IrqHandler, /* 11 Parallel IO Controller A */
PIOB_IrqHandler, /* 12 Parallel IO Controller B */ PIOB_IrqHandler, /* 12 Parallel IO Controller B */
PIOC_IrqHandler, /* 13 Parallel IO Controller C */ PIOC_IrqHandler, /* 13 Parallel IO Controller C */
USART0_IrqHandler, /* 14 USART 0 */ USART0_IrqHandler, /* 14 USART 0 */
USART1_IrqHandler, /* 15 USART 1 */ USART1_IrqHandler, /* 15 USART 1 */
IrqHandlerNotUsed, /* 16 Reserved */ IrqHandlerNotUsed, /* 16 Reserved */
IrqHandlerNotUsed, /* 17 Reserved */ IrqHandlerNotUsed, /* 17 Reserved */
MCI_IrqHandler, /* 18 MCI */ MCI_IrqHandler, /* 18 MCI */
TWI0_IrqHandler, /* 19 TWI 0 */ TWI0_IrqHandler, /* 19 TWI 0 */
TWI1_IrqHandler, /* 20 TWI 1 */ TWI1_IrqHandler, /* 20 TWI 1 */
SPI_IrqHandler, /* 21 SPI */ SPI_IrqHandler, /* 21 SPI */
SSC_IrqHandler, /* 22 SSC */ SSC_IrqHandler, /* 22 SSC */
TC0_IrqHandler, /* 23 Timer Counter 0 */ TC0_IrqHandler, /* 23 Timer Counter 0 */
TC1_IrqHandler, /* 24 Timer Counter 1 */ TC1_IrqHandler, /* 24 Timer Counter 1 */
TC2_IrqHandler, /* 25 Timer Counter 2 */ TC2_IrqHandler, /* 25 Timer Counter 2 */
TC3_IrqHandler, /* 26 Timer Counter 3 */ TC3_IrqHandler, /* 26 Timer Counter 3 */
TC4_IrqHandler, /* 27 Timer Counter 4 */ TC4_IrqHandler, /* 27 Timer Counter 4 */
TC5_IrqHandler, /* 28 Timer Counter 5 */ TC5_IrqHandler, /* 28 Timer Counter 5 */
ADC_IrqHandler, /* 29 ADC controller */ ADC_IrqHandler, /* 29 ADC controller */
DAC_IrqHandler, /* 30 DAC controller */ DAC_IrqHandler, /* 30 DAC controller */
PWM_IrqHandler, /* 31 PWM */ PWM_IrqHandler, /* 31 PWM */
CRCCU_IrqHandler, /* 32 CRC Calculation Unit */ CRCCU_IrqHandler, /* 32 CRC Calculation Unit */
ACC_IrqHandler, /* 33 Analog Comparator */ ACC_IrqHandler, /* 33 Analog Comparator */
USBD_IrqHandler, /* 34 USB Device Port */ USBD_IrqHandler, /* 34 USB Device Port */
IrqHandlerNotUsed /* 35 not used */ IrqHandlerNotUsed /* 35 not used */
}; };
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) #if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
@@ -134,11 +133,7 @@ static void BootIntoApp(void)
void (*appReset)(void); void (*appReset)(void);
pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE); pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE);
/* set vector table to application vector table (store at the beginning of the application) */ SCB->VTOR = ((unsigned int)(pSrc)) | (0x0 << 7);
SCB->VTOR = (unsigned int)(pSrc);
/* set stack pointer to address provided in the beginning of the application (loaded into a register first) */
__asm__ volatile ("MSR msp,%0" : :"r"(*pSrc));
/* start application (by jumping to the reset function which address is stored as second entry of the vector table) */
appReset = (void(*)(void))pSrc[1]; appReset = (void(*)(void))pSrc[1];
g_dfu->state = DFU_STATE_appIDLE; g_dfu->state = DFU_STATE_appIDLE;
@@ -153,56 +148,68 @@ static void BootIntoApp(void)
*/ */
void ResetException( void ) void ResetException( void )
{ {
uint32_t *pSrc, *pDest ; uint32_t *pSrc, *pDest ;
/* Low level Initialize */ /* Low level Initialize */
LowLevelInit() ; LowLevelInit() ;
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) #if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
if (!USBDFU_OverrideEnterDFU()) { /* we are before the text segment has been relocated, so g_dfu is
UART_Exit(); * not initialized yet */
__disable_irq(); g_dfu = &_g_dfu;
BootIntoApp(); if ((g_dfu->magic != USB_DFU_MAGIC) && !USBDFU_OverrideEnterDFU()) {
/* Infinite loop */ /* start application if valid
while ( 1 ) ; * the application starts with the vector table
} * the first entry in the vector table is the initial stack pointer (SP) address
* the stack will be placed in RAM, which begins at 0x2000 0000
* there is up to 48 KB of RAM (0xc000)
* since the stack grown "downwards" it should start at the end of the RAM: max 0x2000 c000
* if the SP is not in this range (e.g. flash has been erased) there is no valid application
* the second entry in the vector table is the reset address, corresponding to the application start
*/
if (((*((uint32_t*)(IFLASH_ADDR+BOARD_DFU_BOOT_SIZE)))&0xFFFF0000)==0x20000000) {
BootIntoApp();
/* Infinite loop */
while ( 1 ) ;
}
}
#endif #endif
/* Initialize the relocate segment */ /* Initialize the relocate segment */
pSrc = &_etext ; pSrc = &_etext ;
pDest = &_srelocate ; pDest = &_srelocate ;
if ( pSrc != pDest ) if ( pSrc != pDest )
{ {
for ( ; pDest < &_erelocate ; ) for ( ; pDest < &_erelocate ; )
{ {
*pDest++ = *pSrc++ ; *pDest++ = *pSrc++ ;
} }
} }
/* Clear the zero segment */ /* Clear the zero segment */
for ( pDest = &_szero ; pDest < &_ezero ; ) for ( pDest = &_szero ; pDest < &_ezero ; )
{ {
*pDest++ = 0; *pDest++ = 0;
} }
/* Set the vector table base address */ /* Set the vector table base address */
pSrc = (uint32_t *)&_sfixed; pSrc = (uint32_t *)&_sfixed;
SCB->VTOR = ( (uint32_t)pSrc & SCB_VTOR_TBLOFF_Msk ) ; SCB->VTOR = ( (uint32_t)pSrc & SCB_VTOR_TBLOFF_Msk ) ;
if ( ((uint32_t)pSrc >= IRAM_ADDR) && ((uint32_t)pSrc < IRAM_ADDR+IRAM_SIZE) ) if ( ((uint32_t)pSrc >= IRAM_ADDR) && ((uint32_t)pSrc < IRAM_ADDR+IRAM_SIZE) )
{ {
SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ; SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ;
} }
/* App should have disabled interrupts during the transition */ /* App should have disabled interrupts during the transition */
__enable_irq(); __enable_irq();
/* Branch to main function */ /* Branch to main function */
main() ; main() ;
/* Infinite loop */ /* Infinite loop */
while ( 1 ) ; while ( 1 ) ;
} }

View File

@@ -2,7 +2,6 @@
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* All rights reserved. * All rights reserved.
* *
@@ -47,39 +46,39 @@
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8)) #define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK) #define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
/** configure PLL to generate main clock based on main oscillator frequency */ #if (BOARD_MCK == 48000000)
#if (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 48000000) #if (BOARD_MAINOSC == 18432000)
/* Clock settings at 48MHz for 18 MHz crystal */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(8-1) \ | CKGR_PLLAR_MULA(13-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2)) | CKGR_PLLAR_DIVA(5))
#elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 58000000) #elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 8 (96 MHz) and divide by 2 */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(29-1) \ | CKGR_PLLAR_MULA(8-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(6)) | CKGR_PLLAR_DIVA(2))
#elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 60000000)
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(10-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 47923200)
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(13-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(5))
#elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 58982400)
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(16-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(5))
#elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 64512000)
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(7-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#else #else
#error "Please define PLLA config for your BOARD_MCK/MAINOSC frequency" #error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */
#elif (BOARD_MCK == 64000000)
#if (BOARD_MAINOSC == 18432000)
/* Clock settings at 64MHz for 18 MHz crystal: 64.512 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(7-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 10 / div by 2: 60 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(10-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2))
#error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */
#else
#error "No PLL settings for current BOARD_MCK."
#endif #endif
#if (BOARD_MAINOSC == 12000000) #if (BOARD_MAINOSC == 12000000)
@@ -118,88 +117,85 @@ static void _ConfigureUsbClock(void)
*/ */
extern WEAK void LowLevelInit( void ) extern WEAK void LowLevelInit( void )
{ {
uint32_t timeout = 0; uint32_t timeout = 0;
/* Configure the Supply Monitor to reset the CPU in case VDDIO is /* Configure the Supply Monitor to reset the CPU in case VDDIO is
* lower than 3.0V. As we run the board on 3.3V, any lower voltage * lower than 3.0V. As we run the board on 3.3V, any lower voltage
* might be some kind of leakage that creeps in some way, but is not * might be some kind of leakage that creeps in some way, but is not
* the "official" power supply */ * the "official" power supply */
SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM | SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM |
SUPC_SMMR_SMRSTEN_ENABLE; SUPC_SMMR_SMRSTEN_ENABLE;
/* disable ERASE pin to prevent accidental flash erase */ /* enable both LED and green LED */
MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO12; PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN;
/* enable both LED and green LED */ /* Set 3 FWS for Embedded Flash Access */
PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN; EFC->EEFC_FMR = EEFC_FMR_FWS(3);
PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN;
/* Set 3 FWS for Embedded Flash Access */ /* Select external slow clock */
EFC->EEFC_FMR = EEFC_FMR_FWS(3);
/* Select external slow clock */
/* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) /* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST)
{ {
SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5)); SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5));
timeout = 0; timeout = 0;
while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) ); while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) );
} }
*/ */
#ifndef qmod #ifndef qmod
/* Initialize main oscillator */ /* Initialize main oscillator */
if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
{ {
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
timeout = 0; timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT)); while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT));
} }
/* Switch to 3-20MHz Xtal oscillator */ /* Switch to 3-20MHz Xtal oscillator */
PIOB->PIO_PDR = (1 << 8) | (1 << 9); PIOB->PIO_PDR = (1 << 8) | (1 << 9);
PIOB->PIO_PUDR = (1 << 8) | (1 << 9); PIOB->PIO_PUDR = (1 << 8) | (1 << 9);
PIOB->PIO_PPDDR = (1 << 8) | (1 << 9); PIOB->PIO_PPDDR = (1 << 8) | (1 << 9);
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
/* wait for Main XTAL oscillator stabilization */ /* wait for Main XTAL oscillator stabilization */
timeout = 0; timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT)); while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT));
#else #else
/* QMOD has external 12MHz clock source */ /* QMOD has external 12MHz clock source */
PIOB->PIO_PDR = (1 << 9); PIOB->PIO_PDR = (1 << 9);
PIOB->PIO_PUDR = (1 << 9); PIOB->PIO_PUDR = (1 << 9);
PIOB->PIO_PPDDR = (1 << 9); PIOB->PIO_PPDDR = (1 << 9);
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL; PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL;
#endif #endif
/* disable the red LED after main clock initialization */ /* disable the red LED after main clock initialization */
PIOA->PIO_SODR = PIO_LED_RED; PIOA->PIO_SODR = PIO_LED_RED;
/* "switch" to main clock as master clock source (should already be the case */ /* "switch" to main clock as master clock source (should already be the case */
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
/* wait for master clock to be ready */ /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Initialize PLLA */ /* Initialize PLLA */
PMC->CKGR_PLLAR = BOARD_PLLAR; PMC->CKGR_PLLAR = BOARD_PLLAR;
/* Wait for PLLA to lock */ /* Wait for PLLA to lock */
timeout = 0; timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT)); while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT));
/* Switch to main clock (again ?!?) */ /* Switch to main clock (again ?!?) */
PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
/* wait for master clock to be ready */ /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* switch to PLLA as master clock source */ /* switch to PLLA as master clock source */
PMC->PMC_MCKR = BOARD_MCKR ; PMC->PMC_MCKR = BOARD_MCKR ;
/* wait for master clock to be ready */ /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Configure SysTick for 1ms */ /* Configure SysTick for 1ms */
SysTick_Config(BOARD_MCK/1000); SysTick_Config(BOARD_MCK/1000);
_ConfigureUsbClock(); _ConfigureUsbClock();
} }
/* SysTick based delay function */ /* SysTick based delay function */

View File

@@ -1,21 +1,7 @@
/* 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 "board.h"
#include "boardver_adc.h" #include "boardver_adc.h"
#define UV_PER_LSB ((3300 * 1000) / 4096) #define UV_PER_LSB ((3300 * 1000) / 4096)
uint32_t adc2uv(uint16_t adc) uint32_t adc2uv(uint16_t adc)
{ {
uint32_t uv = (uint32_t) adc * UV_PER_LSB; uint32_t uv = (uint32_t) adc * UV_PER_LSB;
@@ -86,7 +72,7 @@ int get_board_version_adc(void)
/* convert to voltage */ /* convert to voltage */
sample = ADC->ADC_CDR[2]; sample = ADC->ADC_CDR[2];
uv = adc2uv(sample); uv = adc2uv(sample);
TRACE_INFO("VERSION_DET ADC=%u => %lu uV\r\n", sample, uv); TRACE_INFO("VERSION_DET ADC=%u => %u uV\r\n", sample, uv);
/* FIXME: convert to board version based on thresholds */ /* FIXME: convert to board version based on thresholds */

View File

@@ -1,22 +1,3 @@
/* LED control
*
* (C) 2015-2017 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
* 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 <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
@@ -35,9 +16,9 @@ static void led_set(enum led led, int on)
ASSERT(led < PIO_LISTSIZE(pinsLeds)); ASSERT(led < PIO_LISTSIZE(pinsLeds));
if (on) if (on)
PIO_Clear(&pinsLeds[led]); PIO_Clear(&pinsLeds[led]);
else else
PIO_Set(&pinsLeds[led]); PIO_Set(&pinsLeds[led]);
} }
/* LED blinking code */ /* LED blinking code */
@@ -73,23 +54,16 @@ static const struct blink_state bs_3on_1off_3on_30off[] = {
static const struct blink_state bs_3on_1off_3on_1off_3on_30off[] = { static const struct blink_state bs_3on_1off_3on_1off_3on_30off[] = {
{ 300, 1 }, { 100, 0 }, { 300, 1 }, { 100, 0 }, { 300, 1 }, { 3000, 0 } { 300, 1 }, { 100, 0 }, { 300, 1 }, { 100, 0 }, { 300, 1 }, { 3000, 0 }
}; };
static const struct blink_state bs_2on_off[] = { static const struct blink_state bs_2on_off[] = {
{ 200, 1 }, { 0, 0 }, { 200, 1 }, { 0, 0 },
}; };
static const struct blink_state bs_200on_off[] = { static const struct blink_state bs_200on_off[] = {
{ 20000, 1 }, { 0, 0 }, { 20000, 1 }, { 0, 0 },
}; };
static const struct blink_state bs_600on_off[] = { static const struct blink_state bs_600on_off[] = {
{ 60000, 1 }, { 0, 0 }, { 60000, 1 }, { 0, 0 },
}; };
static const struct blink_state bs_2off_on[] = {
{ 200, 0 }, { 0, 1 },
};
/* a blink pattern is an array of blink_states */ /* a blink pattern is an array of blink_states */
struct blink_pattern { struct blink_pattern {
@@ -135,11 +109,6 @@ static const struct blink_pattern patterns[] = {
.states = bs_600on_off, .states = bs_600on_off,
.size = ARRAY_SIZE(bs_600on_off), .size = ARRAY_SIZE(bs_600on_off),
}, },
[BLINK_2F_O] = {
.states = bs_2off_on,
.size = ARRAY_SIZE(bs_2off_on),
},
}; };
struct led_state { struct led_state {

View File

@@ -1,17 +1,4 @@
/* 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 "manifest.h" #include "manifest.h"
const char *manifest_application = APPLICATION; const char *manifest_application = APPLICATION;

View File

@@ -1,21 +1,5 @@
/* Code to switch between local (physical) and remote (emulated) SIM /* Code to switch between local (physical) and remote (emulated) SIM */
*
* (C) 2015-2017 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 "board.h"
#include "trace.h" #include "trace.h"
#include "led.h" #include "led.h"

View File

@@ -2,7 +2,6 @@
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* All rights reserved. * All rights reserved.
* *
@@ -67,62 +66,41 @@ static ringbuf uart_tx_buffer;
*/ */
extern void UART_Configure( uint32_t baudrate, uint32_t masterClock) extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
{ {
const Pin pPins[] = CONSOLE_PINS; const Pin pPins[] = CONSOLE_PINS;
Uart *pUart = CONSOLE_UART; Uart *pUart = CONSOLE_UART;
/* Configure PIO */ /* Configure PIO */
PIO_Configure(pPins, PIO_LISTSIZE(pPins)); PIO_Configure(pPins, PIO_LISTSIZE(pPins));
/* Configure PMC */ /* Configure PMC */
PMC->PMC_PCER0 = 1 << CONSOLE_ID; PMC->PMC_PCER0 = 1 << CONSOLE_ID;
/* Reset and disable receiver & transmitter */ /* Reset and disable receiver & transmitter */
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
| UART_CR_RXDIS | UART_CR_TXDIS; | UART_CR_RXDIS | UART_CR_TXDIS;
/* Configure mode */ /* Configure mode */
pUart->UART_MR = UART_MR_PAR_NO; pUart->UART_MR = UART_MR_PAR_NO;
/* Configure baudrate */ /* Configure baudrate */
/* Asynchronous, no oversampling */ /* Asynchronous, no oversampling */
//pUart->UART_BRGR = (masterClock / baudrate) / 16; pUart->UART_BRGR = (masterClock / baudrate) / 16;
if ((masterClock / baudrate) % 16 >= 7) {
pUart->UART_BRGR = ( masterClock / baudrate) / 16 + 1;
} else {
pUart->UART_BRGR = ( masterClock / baudrate) / 16 + 0;
}
/* Disable PDC channel */ /* Disable PDC channel */
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
/* Reset transmit ring buffer */ /* Reset transmit ring buffer */
rbuf_reset(&uart_tx_buffer); rbuf_reset(&uart_tx_buffer);
/* Enable TX interrupts */ /* Enable TX interrupts */
pUart->UART_IER = UART_IER_TXRDY; pUart->UART_IER = UART_IER_TXRDY;
NVIC_EnableIRQ(CONSOLE_IRQ); NVIC_EnableIRQ(CONSOLE_IRQ);
/* Enable receiver and transmitter */ /* Enable receiver and transmitter */
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
/* Remember the configuration is complete */ /* Remember the configuration is complete */
_ucIsConsoleInitialized=1 ; _ucIsConsoleInitialized=1 ;
}
/**
* \brief Disables the USART peripheral and related IRQ
*/
void UART_Exit(void)
{
if (!_ucIsConsoleInitialized) {
return;
}
Uart *pUart = CONSOLE_UART;
pUart->UART_IDR = UART_IDR_TXRDY;
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
PMC->PMC_PCDR0 = 1 << CONSOLE_ID;
NVIC_DisableIRQ(CONSOLE_IRQ);
} }
/** Interrupt Service routine to transmit queued data */ /** Interrupt Service routine to transmit queued data */
@@ -131,6 +109,7 @@ void CONSOLE_ISR(void)
Uart *uart = CONSOLE_UART; Uart *uart = CONSOLE_UART;
if (uart->UART_SR & UART_SR_TXRDY) { if (uart->UART_SR & UART_SR_TXRDY) {
if (!rbuf_is_empty(&uart_tx_buffer)) { if (!rbuf_is_empty(&uart_tx_buffer)) {
//uart->UART_IER = UART_IER_TXRDY;
uart->UART_THR = rbuf_read(&uart_tx_buffer); uart->UART_THR = rbuf_read(&uart_tx_buffer);
} else { } else {
uart->UART_IDR = UART_IER_TXRDY; uart->UART_IDR = UART_IER_TXRDY;
@@ -141,48 +120,31 @@ void CONSOLE_ISR(void)
/** /**
* \brief Outputs a character on the UART line. * \brief Outputs a character on the UART line.
* *
* \note This function is asynchronous (i.e. uses a buffer and interrupt to complete the transfer). * \note This function is synchronous (i.e. uses polling).
* \param c Character to send. * \param c Character to send.
*/ */
void UART_PutChar( uint8_t uc ) extern void UART_PutChar( uint8_t c )
{ {
Uart *pUart = CONSOLE_UART ; Uart *pUart = CONSOLE_UART ;
/* Initialize console is not already done */ /* Initialize console is not already done */
if ( !_ucIsConsoleInitialized ) if ( !_ucIsConsoleInitialized )
{ {
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
} }
if (!rbuf_is_full(&uart_tx_buffer)) { /* Only store input if buffer is not full, else drop it */
rbuf_write(&uart_tx_buffer, uc); bool trigger_isr = false;
if (!(pUart->UART_IMR & UART_IMR_TXRDY)) { if (rbuf_is_empty(&uart_tx_buffer)) {
pUart->UART_IER = UART_IER_TXRDY; trigger_isr = true;
CONSOLE_ISR(); }
} if (!rbuf_is_full(&uart_tx_buffer)) {
} rbuf_write(&uart_tx_buffer, c);
} }
if (trigger_isr) {
/** pUart->UART_IER = UART_IER_TXRDY;
* \brief Outputs a character on the UART line. CONSOLE_ISR();
* }
* \note This function is synchronous (i.e. uses polling and blocks until the transfer is complete).
* \param c Character to send.
*/
void UART_PutChar_Sync( uint8_t uc )
{
Uart *pUart = CONSOLE_UART ;
/* Initialize console is not already done */
if ( !_ucIsConsoleInitialized )
{
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
}
while (!(pUart->UART_SR & UART_SR_TXRDY)); /* Wait for transfer buffer to be empty */
pUart->UART_THR = uc; /* Send data to UART peripheral */
while (!(pUart->UART_SR & UART_SR_TXRDY)); /* Wait for transfer buffer to transferred to shift register */
while (!(pUart->UART_SR & UART_SR_TXEMPTY)); /* Wait for transfer shift register to be empty (i.e. transfer is complete) */
} }
/** /**
@@ -193,17 +155,17 @@ void UART_PutChar_Sync( uint8_t uc )
*/ */
extern uint32_t UART_GetChar( void ) extern uint32_t UART_GetChar( void )
{ {
Uart *pUart = CONSOLE_UART ; Uart *pUart = CONSOLE_UART ;
if ( !_ucIsConsoleInitialized ) if ( !_ucIsConsoleInitialized )
{ {
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
} }
while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 ) while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 )
WDT_Restart(WDT); WDT_Restart(WDT);
return pUart->UART_RHR ; return pUart->UART_RHR ;
} }
/** /**
@@ -213,14 +175,14 @@ extern uint32_t UART_GetChar( void )
*/ */
extern uint32_t UART_IsRxReady( void ) extern uint32_t UART_IsRxReady( void )
{ {
Uart *pUart = CONSOLE_UART; Uart *pUart = CONSOLE_UART;
if ( !_ucIsConsoleInitialized ) if ( !_ucIsConsoleInitialized )
{ {
UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ; UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ;
} }
return (pUart->UART_SR & UART_SR_RXRDY) > 0 ; return (pUart->UART_SR & UART_SR_RXRDY) > 0 ;
} }
/** /**
@@ -231,14 +193,14 @@ extern uint32_t UART_IsRxReady( void )
*/ */
extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize )
{ {
uint32_t dw ; uint32_t dw ;
for ( dw=0 ; dw < dwSize ; dw++ ) for ( dw=0 ; dw < dwSize ; dw++ )
{ {
printf( "%02X ", pucFrame[dw] ) ; printf( "%02X ", pucFrame[dw] ) ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
} }
/** /**
@@ -250,62 +212,62 @@ extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize )
*/ */
extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress )
{ {
uint32_t i ; uint32_t i ;
uint32_t j ; uint32_t j ;
uint32_t dwLastLineStart ; uint32_t dwLastLineStart ;
uint8_t* pucTmp ; uint8_t* pucTmp ;
for ( i=0 ; i < (dwSize / 16) ; i++ ) for ( i=0 ; i < (dwSize / 16) ; i++ )
{ {
printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ; printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ;
pucTmp = (uint8_t*)&pucBuffer[i*16] ; pucTmp = (uint8_t*)&pucBuffer[i*16] ;
for ( j=0 ; j < 4 ; j++ ) for ( j=0 ; j < 4 ; j++ )
{ {
printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ; printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ;
pucTmp += 4 ; pucTmp += 4 ;
} }
pucTmp=(uint8_t*)&pucBuffer[i*16] ; pucTmp=(uint8_t*)&pucBuffer[i*16] ;
for ( j=0 ; j < 16 ; j++ ) for ( j=0 ; j < 16 ; j++ )
{ {
UART_PutChar( *pucTmp++ ) ; UART_PutChar( *pucTmp++ ) ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
} }
if ( (dwSize%16) != 0 ) if ( (dwSize%16) != 0 )
{ {
dwLastLineStart=dwSize - (dwSize%16) ; dwLastLineStart=dwSize - (dwSize%16) ;
printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ; printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ;
for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ ) for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ )
{ {
if ( (j!=dwLastLineStart) && (j%4 == 0) ) if ( (j!=dwLastLineStart) && (j%4 == 0) )
{ {
printf( " " ) ; printf( " " ) ;
} }
if ( j < dwSize ) if ( j < dwSize )
{ {
printf( "%02X", pucBuffer[j] ) ; printf( "%02X", pucBuffer[j] ) ;
} }
else else
{ {
printf(" ") ; printf(" ") ;
} }
} }
printf( " " ) ; printf( " " ) ;
for ( j=dwLastLineStart ; j < dwSize ; j++ ) for ( j=dwLastLineStart ; j < dwSize ; j++ )
{ {
UART_PutChar( pucBuffer[j] ) ; UART_PutChar( pucBuffer[j] ) ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
} }
} }
/** /**
@@ -315,46 +277,46 @@ extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAdd
*/ */
extern uint32_t UART_GetInteger( uint32_t* pdwValue ) extern uint32_t UART_GetInteger( uint32_t* pdwValue )
{ {
uint8_t ucKey ; uint8_t ucKey ;
uint8_t ucNbNb=0 ; uint8_t ucNbNb=0 ;
uint32_t dwValue=0 ; uint32_t dwValue=0 ;
while ( 1 ) while ( 1 )
{ {
ucKey=UART_GetChar() ; ucKey=UART_GetChar() ;
UART_PutChar( ucKey ) ; UART_PutChar( ucKey ) ;
if ( ucKey >= '0' && ucKey <= '9' ) if ( ucKey >= '0' && ucKey <= '9' )
{ {
dwValue = (dwValue * 10) + (ucKey - '0'); dwValue = (dwValue * 10) + (ucKey - '0');
ucNbNb++ ; ucNbNb++ ;
} }
else else
{ {
if ( ucKey == 0x0D || ucKey == ' ' ) if ( ucKey == 0x0D || ucKey == ' ' )
{ {
if ( ucNbNb == 0 ) if ( ucNbNb == 0 )
{ {
printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ; printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ;
return 0 ; return 0 ;
} }
else else
{ {
printf( "\n\r" ) ; printf( "\n\r" ) ;
*pdwValue=dwValue ; *pdwValue=dwValue ;
return 1 ; return 1 ;
} }
} }
else else
{ {
printf( "\n\r'%c' not a number!\n\r", ucKey ) ; printf( "\n\r'%c' not a number!\n\r", ucKey ) ;
return 0 ; return 0 ;
} }
} }
WDT_Restart(WDT); WDT_Restart(WDT);
} }
} }
/** /**
@@ -366,25 +328,25 @@ extern uint32_t UART_GetInteger( uint32_t* pdwValue )
*/ */
extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax ) extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax )
{ {
uint32_t dwValue=0 ; uint32_t dwValue=0 ;
if ( UART_GetInteger( &dwValue ) == 0 ) if ( UART_GetInteger( &dwValue ) == 0 )
{ {
return 0 ; return 0 ;
} }
if ( dwValue < dwMin || dwValue > dwMax ) if ( dwValue < dwMin || dwValue > dwMax )
{ {
printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ; printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ;
return 0 ; return 0 ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
*pdwValue = dwValue ; *pdwValue = dwValue ;
return 1 ; return 1 ;
} }
/** /**
@@ -394,45 +356,45 @@ extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint3
*/ */
extern uint32_t UART_GetHexa32( uint32_t* pdwValue ) extern uint32_t UART_GetHexa32( uint32_t* pdwValue )
{ {
uint8_t ucKey ; uint8_t ucKey ;
uint32_t dw = 0 ; uint32_t dw = 0 ;
uint32_t dwValue = 0 ; uint32_t dwValue = 0 ;
for ( dw=0 ; dw < 8 ; dw++ ) for ( dw=0 ; dw < 8 ; dw++ )
{ {
ucKey = UART_GetChar() ; ucKey = UART_GetChar() ;
UART_PutChar( ucKey ) ; UART_PutChar( ucKey ) ;
if ( ucKey >= '0' && ucKey <= '9' ) if ( ucKey >= '0' && ucKey <= '9' )
{ {
dwValue = (dwValue * 16) + (ucKey - '0') ; dwValue = (dwValue * 16) + (ucKey - '0') ;
} }
else else
{ {
if ( ucKey >= 'A' && ucKey <= 'F' ) if ( ucKey >= 'A' && ucKey <= 'F' )
{ {
dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ; dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ;
} }
else else
{ {
if ( ucKey >= 'a' && ucKey <= 'f' ) if ( ucKey >= 'a' && ucKey <= 'f' )
{ {
dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ; dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ;
} }
else else
{ {
printf( "\n\rIt is not a hexa character!\n\r" ) ; printf( "\n\rIt is not a hexa character!\n\r" ) ;
return 0 ; return 0 ;
} }
} }
} }
} }
printf("\n\r" ) ; printf("\n\r" ) ;
*pdwValue = dwValue ; *pdwValue = dwValue ;
return 1 ; return 1 ;
} }
#if defined __ICCARM__ /* IAR Ewarm 5.41+ */ #if defined __ICCARM__ /* IAR Ewarm 5.41+ */
@@ -445,9 +407,9 @@ extern uint32_t UART_GetHexa32( uint32_t* pdwValue )
*/ */
extern WEAK signed int putchar( signed int c ) extern WEAK signed int putchar( signed int c )
{ {
UART_PutChar( c ) ; UART_PutChar( c ) ;
return c ; return c ;
} }
#endif // defined __ICCARM__ #endif // defined __ICCARM__

View File

@@ -1,170 +0,0 @@
/* octSIMtest with SAM3S board definition
*
* (C) 2019 by sysmocom -s.f.m.c. GmbH, Author:Joachim Steiger <jsteiger@sysmocom.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
*/
#pragma once
#include "board_common.h"
#include "simtrace_usb.h"
/* Name of the board */
#define BOARD_NAME "OCTSIMTEST"
/* Board definition */
#define octsimtest
/** oscillator used as main clock source (in Hz) */
#define BOARD_MAINOSC 18432000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58982400 // 18.432 * 16 / 5
/** Pin configuration **/
/** there is no red LED, but the code needs this second LED, thus we provide an unused pin */
#define PIO_LED_RED PIO_PB13
/** MCU pin connected to green LED, which is actually amber, and the logic is inverted since it is connected to an NPN transistor (used as open drain) */
#define PIO_LED_GREEN PIO_PA4
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOB, ID_PIOB, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/* Button to force bootloader start (shorted to ground when pressed */
#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
/* Card presence pin */
#define SW_SIM PIO_PA11
/* 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 USIM slot 1 VCC pin (VCC_PHONE in schematic) */
#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) */
#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) */
#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Phone CLK clock input (CLK_PHONE in schematic) */
#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* 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
/* 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}
/* 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}
/** 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 **/
/* SPI MISO pin definition */
#define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
/* SPI MOSI pin definition */
#define PIN_SPI_MOSI {PIO_PA13A_MOSI, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI SCK pin definition */
#define PIN_SPI_SCK {PIO_PA14A_SPCK, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI pins definition. Contains MISO, MOSI & SCK */
#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SCK
/* SPI chip select 0 pin definition */
#define PIN_SPI_NPCS0 {PIO_PA11A_NPCS0, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI flash write protect pin (active low, pulled low) */
#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/** Pin configuration to control USB pull-up on D+
* @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
*/
#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/** USB definitions */
/* OpenMoko SIMtrace 2 USB vendor ID */
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2
/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU
/* USB release number (bcdDevice, shown as 0.00) */
#define BOARD_USB_RELEASE 0x000
/* Indicate SIMtrace is bus power in USB attributes */
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
/** Supported modes */
/* SIMtrace board supports sniffer mode */
//#define HAVE_SNIFFER
/* SIMtrace board supports CCID mode */
//#define HAVE_CCID
/* SIMtrace board supports card emulation mode */
//#define HAVE_CARDEM
/* SIMtrace board supports man-in-the-middle mode */
//#define HAVE_MITM
/* octsimtest board supports gpio_test mode */
#define HAVE_GPIO_TEST

View File

@@ -1,28 +0,0 @@
/* I2C EEPROM memory read and write utilities
*
* 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
*/
#pragma once
#include <stdbool.h>
void i2c_pin_init(void);
bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte);
uint8_t i2c_read_byte(bool nack, bool send_stop);
void i2c_stop_cond(void);
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
int eeprom_read_byte(uint8_t slave, uint8_t addr);

View File

@@ -1,25 +0,0 @@
/* mcp23017 i2c gpio expander read and write utilities
*
* 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
*/
#pragma once
#define MCP23017_ADDRESS 0x20
int mcp23017_init(uint8_t slave);
int mcp23017_test(uint8_t slave);
int mcp23017_toggle(uint8_t slave);
//int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
//int mcp23017_read_byte(uint8_t slave, uint8_t addr);

View File

@@ -1 +0,0 @@
sysmoOCTSIM-Tester

View File

@@ -1,81 +0,0 @@
/* SIMtrace with SAM3S specific application code
*
* (C) 2017 by Harald Welte <laforge@gnumonks.org>
* (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
* 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 "simtrace.h"
#include "utils.h"
#include "sim_switch.h"
#include <osmocom/core/timer.h>
#include "usb_buf.h"
#include "i2c.h"
#include "mcp23017.h"
void board_exec_dbg_cmd(int ch)
{
switch (ch) {
case '?':
printf("\t?\thelp\n\r");
printf("\tR\treset SAM3\n\r");
printf("\tm\trun mcp23017 test\n\r");
printf("\tR\ttoggle MSB of gpio on mcp23017\n\r");
break;
case 'R':
printf("Asking NVIC to reset us\n\r");
USBD_Disconnect();
NVIC_SystemReset();
break;
case 'm':
mcp23017_test(MCP23017_ADDRESS);
break;
case 't':
mcp23017_toggle(MCP23017_ADDRESS);
break;
default:
printf("Unknown command '%c'\n\r", ch);
break;
}
}
void board_main_top(void)
{
#ifndef APPLICATION_dfu
usb_buf_init();
i2c_pin_init();
if (!mcp23017_init(MCP23017_ADDRESS))
printf("mcp23017 not found!\n\r");
/* Initialize checking for card insert/remove events */
//card_present_init();
#endif
}
int board_override_enter_dfu(void)
{
const Pin bl_sw_pin = PIN_BOOTLOADER_SW;
PIO_Configure(&bl_sw_pin, 1);
/* Enter DFU bootloader in case the respective button is pressed */
if (PIO_Get(&bl_sw_pin) == 0) {
/* do not print to early since the console is not initialized yet */
//printf("BOOTLOADER switch pressed -> Force DFU\n\r");
return 1;
} else
return 0;
}

View File

@@ -1,225 +0,0 @@
/* I2C EEPROM memory read and write utilities
*
* 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 <stdbool.h>
/* Low-Level I2C Routines */
static const Pin pin_sda = {PIO_PA30, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static const Pin pin_sda_in = {PIO_PA30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT };
static const Pin pin_scl = {PIO_PA31, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
static void i2c_delay()
{
volatile int v;
int i;
/* 100 cycles results in SCL peak length of 44us, so it's about
* 440ns per cycle here */
for (i = 0; i < 14; i++) {
v = 0;
}
}
void i2c_pin_init(void)
{
PIO_Configure(&pin_scl, PIO_LISTSIZE(pin_scl));
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
}
static void set_scl(void)
{
PIO_Set(&pin_scl);
i2c_delay();
}
static void set_sda(void)
{
PIO_Set(&pin_sda);
i2c_delay();
}
static void clear_scl(void)
{
PIO_Clear(&pin_scl);
i2c_delay();
}
static void clear_sda(void)
{
PIO_Clear(&pin_sda);
i2c_delay();
}
static bool read_sda(void)
{
bool ret;
PIO_Configure(&pin_sda_in, PIO_LISTSIZE(pin_sda_in));
if (PIO_Get(&pin_sda_in))
ret = true;
else
ret = false;
PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
return ret;
}
/* Core I2C Routines */
static bool i2c_started = false;
static void i2c_start_cond(void)
{
if (i2c_started) {
set_sda();
set_scl();
}
clear_sda();
i2c_delay();
clear_scl();
i2c_started = true;
}
void i2c_stop_cond(void)
{
clear_sda();
set_scl();
set_sda();
i2c_delay();
i2c_started = false;
}
static void i2c_write_bit(bool bit)
{
if (bit)
set_sda();
else
clear_sda();
i2c_delay(); // ?
set_scl();
clear_scl();
}
static bool i2c_read_bit(void)
{
bool bit;
set_sda();
set_scl();
bit = read_sda();
clear_scl();
return bit;
}
bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
{
uint8_t bit;
bool nack;
if (send_start)
i2c_start_cond();
for (bit = 0; bit < 8; bit++) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if (send_stop)
i2c_stop_cond();
return nack;
}
uint8_t i2c_read_byte(bool nack, bool send_stop)
{
uint8_t byte = 0;
uint8_t bit;
for (bit = 0; bit < 8; bit++) {
byte = (byte << 1) | i2c_read_bit();
}
i2c_write_bit(nack);
if (send_stop)
i2c_stop_cond();
return byte;
}
/* EEPROM related code */
int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
{
bool nack;
WDT_Restart(WDT);
/* Write slave address */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, true, byte);
if (nack)
goto out_stop;
/* Wait tWR time to ensure EEPROM is writing correctly (tWR = 5 ms for AT24C02) */
mdelay(5);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int eeprom_read_byte(uint8_t slave, uint8_t addr)
{
bool nack;
WDT_Restart(WDT);
/* dummy write cycle */
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
/* Re-start with read */
nack = i2c_write_byte(true, false, (slave << 1) | 1);
if (nack)
goto out_stop;
return i2c_read_byte(true, true);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}

View File

@@ -1,140 +0,0 @@
#include "board.h"
#include <stdbool.h>
#include "i2c.h"
#include "mcp23017.h"
//defines from https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h under BSD license
// registers
#define MCP23017_IODIRA 0x00
#define MCP23017_IPOLA 0x02
#define MCP23017_GPINTENA 0x04
#define MCP23017_DEFVALA 0x06
#define MCP23017_INTCONA 0x08
#define MCP23017_IOCONA 0x0A
#define MCP23017_GPPUA 0x0C
#define MCP23017_INTFA 0x0E
#define MCP23017_INTCAPA 0x10
#define MCP23017_GPIOA 0x12
#define MCP23017_OLATA 0x14
#define MCP23017_IODIRB 0x01
#define MCP23017_IPOLB 0x03
#define MCP23017_GPINTENB 0x05
#define MCP23017_DEFVALB 0x07
#define MCP23017_INTCONB 0x09
#define MCP23017_IOCONB 0x0B
#define MCP23017_GPPUB 0x0D
#define MCP23017_INTFB 0x0F
#define MCP23017_INTCAPB 0x11
#define MCP23017_GPIOB 0x13
#define MCP23017_OLATB 0x15
#define MCP23017_INT_ERR 255
//bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
//uint8_t i2c_read_byte(bool nack, bool send_stop)
//static void i2c_stop_cond(void)
int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
{
bool nack;
WDT_Restart(WDT);
// Write slave address
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, true, byte);
if (nack)
goto out_stop;
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int mcp23017_read_byte(uint8_t slave, uint8_t addr)
{
bool nack;
WDT_Restart(WDT);
// dummy write cycle
nack = i2c_write_byte(true, false, slave << 1);
if (nack)
goto out_stop;
nack = i2c_write_byte(false, false, addr);
if (nack)
goto out_stop;
// Re-start with read
nack = i2c_write_byte(true, false, (slave << 1) | 1);
if (nack)
goto out_stop;
return i2c_read_byte(true, true);
out_stop:
i2c_stop_cond();
if (nack)
return -1;
else
return 0;
}
int mcp23017_init(uint8_t slave)
{
printf("mcp23017_init\n\r");
// all gpio input
if (mcp23017_write_byte(slave, MCP23017_IODIRA, 0xff))
return false;
// msb of portb output, rest input
if (mcp23017_write_byte(slave, MCP23017_IODIRB, 0x7f))
return false;
if (mcp23017_write_byte(slave, MCP23017_IOCONA, 0x20)) //disable SEQOP (autoinc addressing)
return false;
printf("mcp23017 found\n\r");
return true;
}
int mcp23017_test(uint8_t slave)
{
printf("mcp23017_test\n\r");
printf("GPIOA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_GPIOA));
printf("GPIOB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_GPIOB));
printf("IODIRA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IODIRA));
printf("IODIRB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IODIRB));
printf("IOCONA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IOCONA));
printf("IOCONB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IOCONB));
return 0;
}
int mcp23017_toggle(uint8_t slave)
{
// example writing MSB of gpio
static bool foo=false;
if (foo)
{
printf("+\n\r");
mcp23017_write_byte(slave, MCP23017_OLATB, 0x80);
foo=false;
}
else
{
printf("-\n\r");
mcp23017_write_byte(slave, MCP23017_OLATB, 0x00);
foo=true;
}
return 0;
}

View File

@@ -1,22 +1,3 @@
/* OWHW board definition
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.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 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
*/
#pragma once #pragma once
#include "board_common.h" #include "board_common.h"
#include "simtrace_usb.h" #include "simtrace_usb.h"
@@ -26,28 +7,7 @@
/** Board definition */ /** Board definition */
#define owhw #define owhw
/** oscillator used as main clock source (in Hz) */
#define BOARD_MAINOSC 18432000 #define BOARD_MAINOSC 18432000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58982400 // 18.432 * 16 / 5
/** MCU pin connected to red LED */
#define PIO_LED_RED PIO_PA17
/** MCU pin connected to green LED */
#define PIO_LED_GREEN PIO_PA18
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/* pin connected to the SIMTRACE_BOOTLOADER signal. set high to force DFU bootloader start */
#define PIN_BOOTLOADER {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
/* USIM 2 interface (USART) */ /* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} #define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}

View File

@@ -1 +0,0 @@
OWHW

View File

@@ -1,55 +1,28 @@
/* Card simulator specific functions /* Card simulator specific functions */
/* (C) 2015 by Harald Welte <hwelte@hmw-consulting.de>
* *
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de> * This program is free software; you can redistribute it and/or modify
* (C) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * 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 free software; you can redistribute it and/or modify * This program is distributed in the hope that it will be useful,
* it under the terms of the GNU General Public License as published by * but WITHOUT ANY WARRANTY; without even the implied warranty of
* the Free Software Foundation; either version 2 of the License, or * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* (at your option) any later version. * GNU General Public License for more details.
* *
* This program is distributed in the hope that it will be useful, * You should have received a copy of the GNU General Public License
* but WITHOUT ANY WARRANTY; without even the implied warranty of * along with this program; if not, write to the Free Software
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* 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 "chip.h" #include "chip.h"
#include "board.h" #include "board.h"
#include "utils.h" #include "utils.h"
#include "usb_buf.h"
static const Pin pins_cardsim[] = PINS_CARDSIM; static const Pin pins_cardsim[] = PINS_CARDSIM;
void board_exec_dbg_cmd(int ch)
{
switch (ch) {
case '?':
printf("\t?\thelp\n\r");
printf("\tR\treset SAM3\n\r");
break;
case 'R':
printf("Asking NVIC to reset us\n\r");
USBD_Disconnect();
NVIC_SystemReset();
break;
default:
printf("Unknown command '%c'\n\r", ch);
break;
}
}
void board_main_top(void)
{
#ifndef APPLICATION_dfu
usb_buf_init();
#endif
}
void cardsim_set_simpres(uint8_t slot, int present) void cardsim_set_simpres(uint8_t slot, int present)
{ {
if (slot > 1) if (slot > 1)
@@ -63,18 +36,5 @@ void cardsim_set_simpres(uint8_t slot, int present)
void cardsim_gpio_init(void) void cardsim_gpio_init(void)
{ {
PIO_Configure(pins_cardsim, ARRAY_SIZE(pins_cardsim)); PIO_Configure(&pins_cardsim, ARRAY_SIZE(pins_cardsim));
}
int board_override_enter_dfu(void)
{
const Pin bl_pin = PIN_BOOTLOADER;
PIO_Configure(&bl_pin, 1);
if (PIO_Get(&bl_pin) == 0) { // signal low
return 0; // do not override enter DFU
} else {
return 1; // override enter DFU
}
} }

View File

@@ -1,53 +1,16 @@
/* sysmocom quad-modem sysmoQMOD board definition
*
* (C) 2016-2017 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
*/
#pragma once #pragma once
#include "board_common.h" #include "board_common.h"
#include "simtrace_usb.h" #include "simtrace_usb.h"
#define LED_USIM1 LED_GREEN
#define LED_USIM2 LED_RED
/** Name of the board */ /** Name of the board */
#define BOARD_NAME "QMOD" #define BOARD_NAME "QMOD"
/** Board definition */ /** Board definition */
#define qmod #define qmod
/** oscillator used as main clock source (in Hz) */
#define BOARD_MAINOSC 12000000 #define BOARD_MAINOSC 12000000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58000000 // 18.432 * 29 / 6
/** MCU pin connected to red LED */
#define PIO_LED_RED PIO_PA17
/** MCU pin connected to green LED */
#define PIO_LED_GREEN PIO_PA18
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/** the green LED is actually red and used as indication for USIM1 */
#define LED_USIM1 LED_GREEN
/** the green LED is actually red and used as indication for USIM2 */
#define LED_USIM2 LED_RED
/* USIM 2 interface (USART) */ /* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT} #define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}

View File

@@ -1,21 +1,3 @@
/* card presence utilities
*
* (C) 2016-2017 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
*/
#pragma once #pragma once
int is_card_present(int port); int is_card_present(int port);

View File

@@ -1,19 +1,3 @@
/* I2C EEPROM memory read and write utilities
*
* 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
*/
#pragma once #pragma once
void i2c_pin_init(void); void i2c_pin_init(void);

View File

@@ -1,19 +1,3 @@
/* Code to read/track the status of the WWAN LEDs of attached modems
*
* 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
*/
#pragma once #pragma once
int wwan_led_active(int wwan); int wwan_led_active(int wwan);

View File

@@ -1,19 +1,3 @@
/* Code to control the PERST lines of attached modems
*
* 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
*/
#pragma once #pragma once
int wwan_perst_set(int modem_nr, int active); int wwan_perst_set(int modem_nr, int active);

View File

@@ -1 +0,0 @@
sysmoQMOD (Quad Modem)

View File

@@ -1,26 +1,9 @@
/* sysmocom quad-modem sysmoQMOD application code /* Quad-modem speciic application code */
* /* (C) 2016-2016 by Harald Welte <laforge@gnumonks.org> */
* (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.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 "board.h"
#include "simtrace.h" #include "simtrace.h"
#include "utils.h" #include "utils.h"
#include "led.h"
#include "wwan_led.h" #include "wwan_led.h"
#include "wwan_perst.h" #include "wwan_perst.h"
#include "sim_switch.h" #include "sim_switch.h"
@@ -28,7 +11,6 @@
#include "card_pres.h" #include "card_pres.h"
#include <osmocom/core/timer.h> #include <osmocom/core/timer.h>
#include "usb_buf.h" #include "usb_buf.h"
#include "i2c.h"
static const Pin pin_hubpwr_override = PIN_PRTPWR_OVERRIDE; static const Pin pin_hubpwr_override = PIN_PRTPWR_OVERRIDE;
static const Pin pin_hub_rst = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}; static const Pin pin_hub_rst = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
@@ -47,7 +29,6 @@ static int qmod_sam3_is_12(void)
return 0; return 0;
} }
#if (ALLOW_PEER_ERASE > 0)
const unsigned char __eeprom_bin[256] = { const unsigned char __eeprom_bin[256] = {
USB_VENDOR_OPENMOKO & 0xff, USB_VENDOR_OPENMOKO & 0xff,
USB_VENDOR_OPENMOKO >> 8, USB_VENDOR_OPENMOKO >> 8,
@@ -71,8 +52,11 @@ const unsigned char __eeprom_bin[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x56, 0x23, 0x71, 0x04, 0x00, /* 0xf0 - 0xff */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x56, 0x23, 0x71, 0x04, 0x00, /* 0xf0 - 0xff */
}; };
#include "i2c.h"
static int write_hub_eeprom(void) static int write_hub_eeprom(void)
{ {
const unsigned int __eeprom_bin_len = 256;
int i; int i;
/* wait */ /* wait */
@@ -80,25 +64,22 @@ static int write_hub_eeprom(void)
TRACE_INFO("Writing EEPROM...\n\r"); TRACE_INFO("Writing EEPROM...\n\r");
/* write the EEPROM once */ /* write the EEPROM once */
for (i = 0; i < ARRAY_SIZE(__eeprom_bin); i++) { for (i = 0; i < 256; i++) {
int rc = eeprom_write_byte(0x50, i, __eeprom_bin[i]); int rc = eeprom_write_byte(0x50, i, __eeprom_bin[i]);
if (rc < 0) { /* if the result was negative, repeat that write */
TRACE_ERROR("Writing EEPROM failed at byte %u: 0x%02x\n\r", if (rc < 0)
i, __eeprom_bin[i]); i--;
return 1;
}
} }
/* then pursue re-reading it again and again */ /* then pursue re-reading it again and again */
TRACE_INFO("Verifying EEPROM...\n\r"); TRACE_INFO("Verifying EEPROM...\n\r");
for (i = 0; i < ARRAY_SIZE(__eeprom_bin); i++) { for (i = 0; i < 256; i++) {
int byte = eeprom_read_byte(0x50, i); int byte = eeprom_read_byte(0x50, i);
TRACE_DEBUG("0x%02x: %02x\n\r", i, byte); TRACE_INFO("0x%02x: %02x\n\r", i, byte);
if (byte != __eeprom_bin[i]) if (byte != __eeprom_bin[i])
TRACE_ERROR("Byte %u is wrong, expected 0x%02x, found 0x%02x\n\r", TRACE_ERROR("Byte %u is wrong, expected 0x%02x, found 0x%02x\n\r",
i, __eeprom_bin[i], byte); i, __eeprom_bin[i], byte);
} }
TRACE_INFO("EEPROM written\n\r");
/* FIXME: Release PIN_PRTPWR_OVERRIDE after we know the hub is /* FIXME: Release PIN_PRTPWR_OVERRIDE after we know the hub is
* again powering us up */ * again powering us up */
@@ -106,29 +87,6 @@ static int write_hub_eeprom(void)
return 0; return 0;
} }
static int erase_hub_eeprom(void)
{
int i;
/* wait */
mdelay(100);
TRACE_INFO("Erasing EEPROM...\n\r");
/* write the EEPROM once */
for (i = 0; i < 256; i++) {
int rc = eeprom_write_byte(0x50, i, 0xff);
if (rc < 0) {
TRACE_ERROR("Erasing EEPROM failed at byte %u: 0x%02x\n\r",
i, __eeprom_bin[i]);
return 1;
}
}
TRACE_INFO("EEPROM erased\n\r");
return 0;
}
#endif /* ALLOW_PEER_ERASE */
static void board_exec_dbg_cmd_st12only(int ch) static void board_exec_dbg_cmd_st12only(int ch)
{ {
uint32_t addr, val; uint32_t addr, val;
@@ -138,14 +96,9 @@ static void board_exec_dbg_cmd_st12only(int ch)
return; return;
switch (ch) { switch (ch) {
#if (ALLOW_PEER_ERASE > 0)
case 'E': case 'E':
write_hub_eeprom(); write_hub_eeprom();
break; break;
case 'e':
erase_hub_eeprom();
break;
#endif /* ALLOW_PEER_ERASE */
case 'O': case 'O':
printf("Setting PRTPWR_OVERRIDE\n\r"); printf("Setting PRTPWR_OVERRIDE\n\r");
PIO_Set(&pin_hubpwr_override); PIO_Set(&pin_hubpwr_override);
@@ -154,7 +107,6 @@ static void board_exec_dbg_cmd_st12only(int ch)
printf("Clearing PRTPWR_OVERRIDE\n\r"); printf("Clearing PRTPWR_OVERRIDE\n\r");
PIO_Clear(&pin_hubpwr_override); PIO_Clear(&pin_hubpwr_override);
break; break;
#if (ALLOW_PEER_ERASE > 0)
case 'H': case 'H':
printf("Clearing _HUB_RESET -> HUB_RESET high (inactive)\n\r"); printf("Clearing _HUB_RESET -> HUB_RESET high (inactive)\n\r");
PIO_Clear(&pin_hub_rst); PIO_Clear(&pin_hub_rst);
@@ -171,14 +123,13 @@ static void board_exec_dbg_cmd_st12only(int ch)
UART_GetIntegerMinMax(&addr, 0, 255); UART_GetIntegerMinMax(&addr, 0, 255);
printf("Please enter EEPROM value:\n\r"); printf("Please enter EEPROM value:\n\r");
UART_GetIntegerMinMax(&val, 0, 255); UART_GetIntegerMinMax(&val, 0, 255);
printf("Writing value 0x%02lx to EEPROM offset 0x%02lx\n\r", val, addr); printf("Writing value 0x%02x to EEPROM offset 0x%02x\n\r", val, addr);
eeprom_write_byte(0x50, addr, val); eeprom_write_byte(0x50, addr, val);
break; break;
#endif /* ALLOW_PEER_ERASE */
case 'r': case 'r':
printf("Please enter EEPROM offset:\n\r"); printf("Please enter EEPROM offset:\n\r");
UART_GetIntegerMinMax(&addr, 0, 255); UART_GetIntegerMinMax(&addr, 0, 255);
printf("EEPROM[0x%02lx] = 0x%02x\n\r", addr, eeprom_read_byte(0x50, addr)); printf("EEPROM[0x%02x] = 0x%02x\n\r", addr, eeprom_read_byte(0x50, addr));
break; break;
default: default:
printf("Unknown command '%c'\n\r", ch); printf("Unknown command '%c'\n\r", ch);
@@ -189,24 +140,12 @@ static void board_exec_dbg_cmd_st12only(int ch)
/* returns '1' in case we should break any endless loop */ /* returns '1' in case we should break any endless loop */
void board_exec_dbg_cmd(int ch) void board_exec_dbg_cmd(int ch)
{ {
#if (ALLOW_PEER_ERASE > 0)
/* this variable controls if it is allowed to assert/release the ERASE line.
this is done to prevent accidental ERASE on noisy serial input since only one character can trigger the ERASE.
*/
static bool allow_erase = false;
#endif
switch (ch) { switch (ch) {
case '?': case '?':
printf("\t?\thelp\n\r"); printf("\t?\thelp\n\r");
printf("\tR\treset SAM3\n\r"); printf("\tR\treset SAM3\n\r");
printf("\tl\tswitch off LED 1\n\r");
printf("\tL\tswitch off LED 1\n\r");
printf("\tg\tswitch off LED 2\n\r");
printf("\tG\tswitch off LED 2\n\r");
if (qmod_sam3_is_12()) { if (qmod_sam3_is_12()) {
printf("\tE\tprogram EEPROM\n\r"); printf("\tE\tprogram EEPROM\n\r");
printf("\te\tErase EEPROM\n\r");
printf("\tO\tEnable PRTPWR_OVERRIDE\n\r"); printf("\tO\tEnable PRTPWR_OVERRIDE\n\r");
printf("\to\tDisable PRTPWR_OVERRIDE\n\r"); printf("\to\tDisable PRTPWR_OVERRIDE\n\r");
printf("\tH\tRelease HUB RESET (high)\n\r"); printf("\tH\tRelease HUB RESET (high)\n\r");
@@ -216,11 +155,8 @@ void board_exec_dbg_cmd(int ch)
} }
printf("\tX\tRelease peer SAM3 from reset\n\r"); printf("\tX\tRelease peer SAM3 from reset\n\r");
printf("\tx\tAssert peer SAM3 reset\n\r"); printf("\tx\tAssert peer SAM3 reset\n\r");
#if (ALLOW_PEER_ERASE > 0)
printf("\tY\tRelease peer SAM3 ERASE signal\n\r"); printf("\tY\tRelease peer SAM3 ERASE signal\n\r");
printf("\ta\tAllow asserting peer SAM3 ERASE signal\n\r");
printf("\ty\tAssert peer SAM3 ERASE signal\n\r"); printf("\ty\tAssert peer SAM3 ERASE signal\n\r");
#endif
printf("\tU\tProceed to USB Initialization\n\r"); printf("\tU\tProceed to USB Initialization\n\r");
printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r"); printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");
printf("\t2\tGenerate 1ms reset pulse on WWAN2\n\r"); printf("\t2\tGenerate 1ms reset pulse on WWAN2\n\r");
@@ -230,22 +166,6 @@ void board_exec_dbg_cmd(int ch)
USBD_Disconnect(); USBD_Disconnect();
NVIC_SystemReset(); NVIC_SystemReset();
break; break;
case 'l':
led_blink(LED_GREEN, BLINK_ALWAYS_OFF);
printf("LED 1 switched off\n\r");
break;
case 'L':
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
printf("LED 1 switched on\n\r");
break;
case 'g':
led_blink(LED_RED, BLINK_ALWAYS_OFF);
printf("LED 2 switched off\n\r");
break;
case 'G':
led_blink(LED_RED, BLINK_ALWAYS_ON);
printf("LED 2 switched on\n\r");
break;
case 'X': case 'X':
printf("Clearing _SIMTRACExx_RST -> SIMTRACExx_RST high (inactive)\n\r"); printf("Clearing _SIMTRACExx_RST -> SIMTRACExx_RST high (inactive)\n\r");
PIO_Clear(&pin_peer_rst); PIO_Clear(&pin_peer_rst);
@@ -254,24 +174,14 @@ void board_exec_dbg_cmd(int ch)
printf("Setting _SIMTRACExx_RST -> SIMTRACExx_RST low (active)\n\r"); printf("Setting _SIMTRACExx_RST -> SIMTRACExx_RST low (active)\n\r");
PIO_Set(&pin_peer_rst); PIO_Set(&pin_peer_rst);
break; break;
#if (ALLOW_PEER_ERASE > 0)
case 'Y': case 'Y':
printf("Clearing SIMTRACExx_ERASE (inactive)\n\r"); printf("Clearing SIMTRACExx_ERASE (inactive)\n\r");
PIO_Clear(&pin_peer_erase); PIO_Clear(&pin_peer_erase);
break; break;
case 'a':
printf("Asserting SIMTRACExx_ERASE allowed on next command\n\r");
allow_erase = true;
break;
case 'y': case 'y':
if (allow_erase) { printf("Seetting SIMTRACExx_ERASE (active)\n\r");
printf("Setting SIMTRACExx_ERASE (active)\n\r"); PIO_Set(&pin_peer_erase);
PIO_Set(&pin_peer_erase);
} else {
printf("Please first allow setting SIMTRACExx_ERASE\n\r");
}
break; break;
#endif
case '1': case '1':
printf("Resetting Modem 1 (of this SAM3)\n\r"); printf("Resetting Modem 1 (of this SAM3)\n\r");
wwan_perst_do_reset_pulse(0, 300); wwan_perst_do_reset_pulse(0, 300);
@@ -293,13 +203,6 @@ void board_exec_dbg_cmd(int ch)
board_exec_dbg_cmd_st12only(ch); board_exec_dbg_cmd_st12only(ch);
break; break;
} }
#if (ALLOW_PEER_ERASE > 0)
// set protection back so it can only run for one command
if ('a' != ch) {
allow_erase = false;
}
#endif
} }
void board_main_top(void) void board_main_top(void)
@@ -332,13 +235,11 @@ void board_main_top(void)
TRACE_INFO("Detected Quad-Modem ST12\n\r"); TRACE_INFO("Detected Quad-Modem ST12\n\r");
} else { } else {
TRACE_INFO("Detected Quad-Modem ST34\n\r"); TRACE_INFO("Detected Quad-Modem ST34\n\r");
#ifndef APPLICATION_dfu
/* make sure we use the second set of USB Strings /* make sure we use the second set of USB Strings
* calling the interfaces "Modem 3" and "Modem 4" rather * calling the interfaces "Modem 3" and "Modem 4" rather
* than 1+2 */ * than 1+2 */
usb_strings[7] = usb_strings[9]; usb_strings[7] = usb_strings[9];
usb_strings[8] = usb_strings[10]; usb_strings[8] = usb_strings[10];
#endif
} }
/* Obtain the circuit board version (currently just prints voltage */ /* Obtain the circuit board version (currently just prints voltage */
@@ -360,32 +261,20 @@ static int uart_has_loopback_jumper(void)
/* Configure UART pins as I/O */ /* Configure UART pins as I/O */
PIO_Configure(uart_loopback_pins, PIO_LISTSIZE(uart_loopback_pins)); PIO_Configure(uart_loopback_pins, PIO_LISTSIZE(uart_loopback_pins));
/* Send pattern over UART TX and check if it is received on RX
* If the loop doesn't get interrupted, RxD always follows TxD and thus a
* loopback jumper has been placed on RxD/TxD, and we will boot
* into DFU unconditionally
*/
int has_loopback_jumper = 1;
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
/* Set TxD high; abort if RxD doesn't go high either */ /* Set TxD high; abort if RxD doesn't go high either */
PIO_Set(&uart_loopback_pins[1]); PIO_Set(&uart_loopback_pins[1]);
if (!PIO_Get(&uart_loopback_pins[0])) { if (!PIO_Get(&uart_loopback_pins[0]))
has_loopback_jumper = 0; return 0;
break;
}
/* Set TxD low, abort if RxD doesn't go low either */ /* Set TxD low, abort if RxD doesn't go low either */
PIO_Clear(&uart_loopback_pins[1]); PIO_Clear(&uart_loopback_pins[1]);
if (PIO_Get(&uart_loopback_pins[0])) { if (PIO_Get(&uart_loopback_pins[0]))
has_loopback_jumper = 0; return 0;
break;
}
} }
/* if we reached here, RxD always follows TxD and thus a
/* Put pins back to UART mode */ * loopback jumper has been placed on RxD/TxD, and we will boot
const Pin uart_pins[] = {PINS_UART}; * into DFU unconditionally */
PIO_Configure(uart_pins, PIO_LISTSIZE(uart_pins)); return 1;
return has_loopback_jumper;
} }
int board_override_enter_dfu(void) int board_override_enter_dfu(void)

View File

@@ -1,21 +1,3 @@
/* card presence utilities
*
* (C) 2016-2017 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 <osmocom/core/timer.h> #include <osmocom/core/timer.h>
#include "board.h" #include "board.h"
#include "utils.h" #include "utils.h"

View File

@@ -1,19 +1,3 @@
/* I2C EEPROM memory read and write utilities
*
* 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 "board.h"
#include <stdbool.h> #include <stdbool.h>
@@ -185,8 +169,6 @@ int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
nack = i2c_write_byte(false, true, byte); nack = i2c_write_byte(false, true, byte);
if (nack) if (nack)
goto out_stop; goto out_stop;
/* Wait tWR time to ensure EEPROM is writing correctly (tWR = 5 ms for AT24C02) */
mdelay(5);
out_stop: out_stop:
i2c_stop_cond(); i2c_stop_cond();

View File

@@ -1,24 +1,11 @@
/* Code to read/track the status of the WWAN LEDs of attached modems /* Code to read/track the status of the WWAN LEDs of attached modems
* *
* This program is free software; you can redistribute it and/or modify * Depending on the board this is running on, it might be possible
* 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
*/
/* Depending on the board this is running on, it might be possible
* for the controller to read the status of the WWAN LED output lines of * for the controller to read the status of the WWAN LED output lines of
* the cellular modem. If the board supports this, it sets the * the cellular modem. If the board supports this, it sets the
* PIN_WWAN1 and/or PIN_WWAN2 defines in its board.h file. * PIN_WWAN1 and/or PIN_WWAN2 defines in its board.h file.
*/ */
#include "board.h" #include "board.h"
#include "wwan_led.h" #include "wwan_led.h"

View File

@@ -1,24 +1,11 @@
/* Code to control the PERST lines of attached modems /* Code to control the PERST lines of attached modems
* *
* This program is free software; you can redistribute it and/or modify * Depending on the board this is running on, it might be possible
* 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
*/
/* Depending on the board this is running on, it might be possible
* for the controller to set the status of the PERST input line of * for the controller to set the status of the PERST input line of
* the cellular modem. If the board supports this, it sets the * the cellular modem. If the board supports this, it sets the
* PIN_PERST1 and/or PIN_PERST2 defines in its board.h file. * PIN_PERST1 and/or PIN_PERST2 defines in its board.h file.
*/ */
#include "board.h" #include "board.h"
#include "trace.h" #include "trace.h"
#include "wwan_perst.h" #include "wwan_perst.h"

View File

@@ -1,163 +0,0 @@
/* Olimiex SAM3S-P256 board definition
*
* (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include "board_common.h"
#include "simtrace_usb.h"
/* Name of the board */
#define BOARD_NAME "SAM3S-P256"
/* Board definition */
#define simtrace
/** oscillator used as main clock source (in Hz) */
#define BOARD_MAINOSC 12000000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58000000
/** MCU pin connected to yellow LED2 */
#define PIO_LED_RED PIO_PA17
/** MCU pin connected to green LED1 */
#define PIO_LED_GREEN PIO_PA18
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/** Pin configuration **/
/* Button to force bootloader start (shorted to ground when pressed */
#define PIN_BOOTLOADER_SW {PIO_PA20, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
#if 0
/* Enable powering the card using the second 3.3 V output of the LDO (active high) */
#define SIM_PWEN_PIN {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Enable powering the SIM card */
#define PWR_PINS SIM_PWEN_PIN
/* Card presence pin */
#define SW_SIM PIO_PA8
/* 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 **/
/* Card RST reset signal input (active low; RST_SIM in schematic) */
#define PIN_SIM_RST {PIO_PA7, 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}
/* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */
#define PIN_SIM_CLK_INPUT {PIO_PA4B_TCLK0, 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 USIM slot 1 VCC pin (VCC_PHONE in schematic) */
#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) */
#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) */
#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Phone CLK clock input (CLK_PHONE in schematic) */
#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* 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
/* 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}
/* 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}
/** 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 **/
/* SPI MISO pin definition */
#define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
/* SPI MOSI pin definition */
#define PIN_SPI_MOSI {PIO_PA13A_MOSI, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI SCK pin definition */
#define PIN_SPI_SCK {PIO_PA14A_SPCK, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI pins definition. Contains MISO, MOSI & SCK */
#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SCK
/* SPI chip select 0 pin definition */
#define PIN_SPI_NPCS0 {PIO_PA11A_NPCS0, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* SPI flash write protect pin (active low, pulled low) */
#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#endif
/** Pin configuration to control USB pull-up on D+
* @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
*/
#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/** USB definitions */
/* OpenMoko SIMtrace 2 USB vendor ID */
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2
/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU
/* USB release number (bcdDevice, shown as 0.00) */
#define BOARD_USB_RELEASE 0x000
/* Indicate SIMtrace is bus power in USB attributes */
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
/** Supported modes */
/* SIMtrace board supports sniffer mode */
#define HAVE_SNIFFER
/* SIMtrace board supports CCID mode */
//#define HAVE_CCID
/* SIMtrace board supports card emulation mode */
//#define HAVE_CARDEM
/* SIMtrace board supports man-in-the-middle mode */
//#define HAVE_MITM

View File

@@ -1,68 +0,0 @@
/* Olimex SAM3S-P256 specific application code
*
* (C) 2017,2019 by Harald Welte <laforge@gnumonks.org>
* (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
* 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 "simtrace.h"
#include "utils.h"
#include "sim_switch.h"
#include <osmocom/core/timer.h>
#include "usb_buf.h"
void board_exec_dbg_cmd(int ch)
{
switch (ch) {
case '?':
printf("\t?\thelp\n\r");
printf("\tR\treset SAM3\n\r");
break;
case 'R':
printf("Asking NVIC to reset us\n\r");
USBD_Disconnect();
NVIC_SystemReset();
break;
default:
printf("Unknown command '%c'\n\r", ch);
break;
}
}
void board_main_top(void)
{
#ifndef APPLICATION_dfu
usb_buf_init();
/* Initialize checking for card insert/remove events */
//card_present_init();
#endif
}
int board_override_enter_dfu(void)
{
const Pin bl_sw_pin = PIN_BOOTLOADER_SW;
PIO_Configure(&bl_sw_pin, 1);
/* Enter DFU bootloader in case the respective button is pressed */
if (PIO_Get(&bl_sw_pin) == 0) {
/* do not print to early since the console is not initialized yet */
//printf("BOOTLOADER switch pressed -> Force DFU\n\r");
return 1;
} else
return 0;
}

View File

@@ -1,22 +1,3 @@
/* SIMtrace with SAM3S board definition
*
* (C) 2016-2017 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
* 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
*/
#pragma once #pragma once
#include "board_common.h" #include "board_common.h"
#include "simtrace_usb.h" #include "simtrace_usb.h"
@@ -26,31 +7,14 @@
/* Board definition */ /* Board definition */
#define simtrace #define simtrace
/** oscillator used as main clock source (in Hz) */ /* Board main oscillator frequency (in Hz) */
#define BOARD_MAINOSC 18432000 #define BOARD_MAINOSC 18432000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58982400 // 18.432 * 16 / 5
/** MCU pin connected to red LED */
#define PIO_LED_RED PIO_PA17
/** MCU pin connected to green LED */
#define PIO_LED_GREEN PIO_PA18
/** red LED pin definition */
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** green LED pin definition */
#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LEDs pin definition */
#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
/** index for red LED in LEDs pin definition array */
#define LED_NUM_RED 0
/** index for green LED in LEDs pin definition array */
#define LED_NUM_GREEN 1
/** Pin configuration **/ /** Pin configuration **/
/* 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_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP} #define PIN_BOOTLOADER_SW {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
/* Enable powering the card using the second 3.3 V output of the LDO (active high) */ /* Enable powering the card using the second 3.3 V output of the LDO (active high) */
#define SIM_PWEN_PIN {PIO_PA5, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} #define SIM_PWEN_PIN {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Enable powering the SIM card */ /* Enable powering the SIM card */
#define PWR_PINS SIM_PWEN_PIN #define PWR_PINS SIM_PWEN_PIN
/* Card presence pin */ /* Card presence pin */
@@ -74,9 +38,9 @@
/** 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_IT_EDGE | PIO_DEGLITCH } #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) */
@@ -108,9 +72,9 @@
/* Pins used to sniff phone-card communication */ /* Pins used to sniff phone-card communication */
#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF #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) */ /* Disable power converter 4.5-6V to 3.3V (active high) */
#define PIN_SIM_PWEN_SNIFF {PIO_PA5, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} #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) */ /* Enable power switch to forward VCC_PHONE to VCC_SIM (active high) */
#define PIN_VCC_FWD_SNIFF {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} #define PIN_VCC_FWD_SNIFF {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Use phone VCC to power card */ /* Use phone VCC to power card */
#define PINS_PWR_SNIFF PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF #define PINS_PWR_SNIFF PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF
@@ -134,11 +98,6 @@
/* SPI flash write protect pin (active low, pulled low) */ /* SPI flash write protect pin (active low, pulled low) */
#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT} #define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/** Pin configuration to control USB pull-up on D+
* @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
*/
#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/** USB definitions */ /** USB definitions */
/* 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

View File

@@ -1 +0,0 @@
SIMtrace 2

View File

@@ -1,22 +1,6 @@
/* SIMtrace with SAM3S specific application code /* SIMtrace specific application code */
* /* (C) 2017 by Harald Welte <laforge@gnumonks.org> */
* (C) 2017 by Harald Welte <laforge@gnumonks.org>
* (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
* 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 "board.h"
#include "simtrace.h" #include "simtrace.h"
#include "utils.h" #include "utils.h"

View File

@@ -65,41 +65,41 @@
// Definitions // Definitions
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#if defined(NOASSERT) #if defined(NOASSERT)
#define ASSERT(...) #define ASSERT(...)
#define SANITY_CHECK(...) #define SANITY_CHECK(...)
#else #else
#if (TRACE_LEVEL == 0) #if (TRACE_LEVEL == 0)
/// Checks that the given condition is true, /// Checks that the given condition is true,
/// otherwise stops the program execution. /// otherwise stops the program execution.
/// \param condition Condition to verify. /// \param condition Condition to verify.
#define ASSERT(condition) { \ #define ASSERT(condition) { \
if (!(condition)) { \ if (!(condition)) { \
while (1); \ while (1); \
} \ } \
} }
/// Performs the same duty as the ASSERT() macro /// Performs the same duty as the ASSERT() macro
/// \param condition Condition to verify. /// \param condition Condition to verify.
#define SANITY_CHECK(condition) ASSERT(condition, ...) #define SANITY_CHECK(condition) ASSERT(condition, ...)
#else #else
/// Checks that the given condition is true, otherwise displays an error /// Checks that the given condition is true, otherwise displays an error
/// message and stops the program execution. /// message and stops the program execution.
/// \param condition Condition to verify. /// \param condition Condition to verify.
#define ASSERT(condition) { \ #define ASSERT(condition) { \
if (!(condition)) { \ if (!(condition)) { \
printf("-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); \
} \ } \
} }
#define SANITY_ERROR "Sanity check failed at %s:%d\n\r" #define SANITY_ERROR "Sanity check failed at %s:%d\n\r"
/// Performs the same duty as the ASSERT() macro, except a default error /// Performs the same duty as the ASSERT() macro, except a default error
/// message is output if the condition is false. /// message is output if the condition is false.
/// \param condition Condition to verify. /// \param condition Condition to verify.
#define SANITY_CHECK(condition) ASSERT(condition, SANITY_ERROR, __FILE__, __LINE__) #define SANITY_CHECK(condition) ASSERT(condition, SANITY_ERROR, __FILE__, __LINE__)
#endif #endif
#endif #endif

View File

@@ -1,22 +1,3 @@
/* ISO7816-3 state machine for the card side
*
* (C) 2010-2017 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
* 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
*/
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
@@ -29,18 +10,8 @@ enum card_io {
CARD_IO_CLK, CARD_IO_CLK,
}; };
/** initialise card slot struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan,
* @param[in] slot_num slot number (arbitrary number) uint8_t in_ep, uint8_t irq_ep);
* @param[in] tc_chan timer counter channel (to measure the ETU)
* @param[in] uart_chan UART peripheral channel
* @param[in] in_ep USB IN end point number
* @param[in] irq_ep USB INTerrupt end point number
* @param[in] vcc_active initial VCC signal state (true = on)
* @param[in] in_reset initial RST signal state (true = reset asserted)
* @param[in] clocked initial CLK signat state (true = active)
* @return main card handle reference
*/
struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked);
/* 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);
@@ -65,4 +36,3 @@ int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi);
int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte); int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte);
void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx); void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx);
void card_emu_uart_wait_tx_idle(uint8_t uart_chan); void card_emu_uart_wait_tx_idle(uint8_t uart_chan);
void card_emu_uart_interrupt(uint8_t uart_chan);

View File

@@ -145,129 +145,129 @@ typedef struct
/// 6.1.11.2 PIN Verification Data Structure /// 6.1.11.2 PIN Verification Data Structure
typedef struct typedef struct
{ {
/// Number of seconds. /// Number of seconds.
unsigned char bTimerOut; unsigned char bTimerOut;
/// Several parameters for the PIN format options /// Several parameters for the PIN format options
unsigned char bmFormatString; unsigned char bmFormatString;
/// Define the length of the PIN to present in the APDU command /// Define the length of the PIN to present in the APDU command
unsigned char bmPINBlockString; unsigned char bmPINBlockString;
/// Allows the length PIN insertion in the APDU command /// Allows the length PIN insertion in the APDU command
unsigned char bmPINLengthFormat; unsigned char bmPINLengthFormat;
/// Minimum PIN size in digit and Maximum PIN size in digit /// Minimum PIN size in digit and Maximum PIN size in digit
unsigned char wPINMaxExtraDigit; unsigned char wPINMaxExtraDigit;
/// The value is a bit wise OR operation. /// The value is a bit wise OR operation.
unsigned char bEntryValidationCondition; unsigned char bEntryValidationCondition;
/// Number of messages to display for the PIN modify command /// Number of messages to display for the PIN modify command
unsigned char bNumberMessage; unsigned char bNumberMessage;
/// Language used to display the messages. /// Language used to display the messages.
unsigned char wLangId; unsigned char wLangId;
/// Message index in the Reader message table /// Message index in the Reader message table
unsigned char bMsgIndex; unsigned char bMsgIndex;
/// T=1 I-block prologue field to use /// T=1 I-block prologue field to use
unsigned char bTeoPrologue[3]; unsigned char bTeoPrologue[3];
/// APDU to send to the ICC /// APDU to send to the ICC
unsigned char abPINApdu[255]; unsigned char abPINApdu[255];
}__attribute__ ((packed)) S_ccid_PIN_Verification; }__attribute__ ((packed)) S_ccid_PIN_Verification;
/// 6.1.11.7 PIN Modification Data Structure /// 6.1.11.7 PIN Modification Data Structure
typedef struct typedef struct
{ {
/// Number of seconds. If 00h then CCID default value is used. /// Number of seconds. If 00h then CCID default value is used.
unsigned char bTimeOut; unsigned char bTimeOut;
/// Several parameters for the PIN format options (defined in § 6.1.11.4) /// Several parameters for the PIN format options (defined in § 6.1.11.4)
unsigned char bmFormatString4; unsigned char bmFormatString4;
/// Define the length of the PIN to present in the APDU command /// Define the length of the PIN to present in the APDU command
unsigned char bmPINBlockString; unsigned char bmPINBlockString;
/// Allows the length PIN insertion in the APDU command (defined in § 6.1.11.6) /// Allows the length PIN insertion in the APDU command (defined in § 6.1.11.6)
unsigned char bmPinLengthFormat; unsigned char bmPinLengthFormat;
/// Insertion position offset in byte for the current PIN /// Insertion position offset in byte for the current PIN
unsigned char bInsertionOffsetOld; unsigned char bInsertionOffsetOld;
/// Insertion position offset in byte for the new PIN /// Insertion position offset in byte for the new PIN
unsigned char bInsertionOffsetNew; unsigned char bInsertionOffsetNew;
/// XXYYh /// XXYYh
/// XX: Minimum PIN size in digit /// XX: Minimum PIN size in digit
/// YY: Maximum PIN size in digit /// YY: Maximum PIN size in digit
unsigned char wPINMaxExtraDigit; unsigned char wPINMaxExtraDigit;
/// 00h,01h,02h,03h /// 00h,01h,02h,03h
/// Indicates if a confirmation is requested before acceptance of a new PIN (meaning that the user has to enter this new PIN twice before it is accepted) /// Indicates if a confirmation is requested before acceptance of a new PIN (meaning that the user has to enter this new PIN twice before it is accepted)
/// Indicates if the current PIN must be entered and set in the same APDU field of not. /// Indicates if the current PIN must be entered and set in the same APDU field of not.
unsigned char bConfirmPIN; unsigned char bConfirmPIN;
/// The value is a bit wise OR operation. /// The value is a bit wise OR operation.
/// 01h Max size reached /// 01h Max size reached
/// 02h Validation key pressed /// 02h Validation key pressed
/// 04h Timeout occurred /// 04h Timeout occurred
unsigned char bEntryValidationCondition; unsigned char bEntryValidationCondition;
/// 00h,01h,02h,03h,or FFh /// 00h,01h,02h,03h,or FFh
/// Number of messages to display for the PIN modify command. /// Number of messages to display for the PIN modify command.
unsigned char bNumberMessage; unsigned char bNumberMessage;
/// Language used to display the messages. The 16 bit /// Language used to display the messages. The 16 bit
unsigned char wLangId; unsigned char wLangId;
/// Message index in the Reader message table (should be 00h or 01h). /// Message index in the Reader message table (should be 00h or 01h).
unsigned char bMsgIndex1; unsigned char bMsgIndex1;
/// Message index in the Reader message table (should be 01h or 02h). /// Message index in the Reader message table (should be 01h or 02h).
unsigned char bMsgIndex2; unsigned char bMsgIndex2;
/// Message index in the Reader message table (should be 02h). /// Message index in the Reader message table (should be 02h).
unsigned char bMsgIndex3; unsigned char bMsgIndex3;
/// T=1 I-block prologue field to use. Significant only if protocol in use is T=1. /// T=1 I-block prologue field to use. Significant only if protocol in use is T=1.
unsigned char bTeoPrologue[3]; unsigned char bTeoPrologue[3];
/// Byte array APDU to send to the ICC /// Byte array APDU to send to the ICC
unsigned char abPINApdu[255]; unsigned char abPINApdu[255];
}__attribute__ ((packed)) S_ccid_PIN_Modification; }__attribute__ ((packed)) S_ccid_PIN_Modification;
/// Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h) /// Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h)
typedef struct typedef struct
{ {
/// B7-4 FI Index into the table 7 in ISO/IEC 7816-3:1997 selecting a /// B7-4 FI Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
/// clock rate conversion factor /// clock rate conversion factor
/// B3-0 DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a /// B3-0 DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
/// baud rate conversion factor /// baud rate conversion factor
unsigned char bmFindexDindex; unsigned char bmFindexDindex;
/// For T=0 ,B0 0b, B7-2 000000b /// For T=0 ,B0 0b, B7-2 000000b
/// B1 Convention used (b1=0 for direct, b1=1 for inverse) /// B1 Convention used (b1=0 for direct, b1=1 for inverse)
unsigned char bmTCCKST0; // 0 to 2 unsigned char bmTCCKST0; // 0 to 2
/// Extra Guardtime between two characters. Add 0 to 254 etu to the normal /// Extra Guardtime between two characters. Add 0 to 254 etu to the normal
/// guardtime of 12etu. FFh is the same as 00h. /// guardtime of 12etu. FFh is the same as 00h.
unsigned char bGuardTimeT0; // 0 to FF unsigned char bGuardTimeT0; // 0 to FF
/// WI for T=0 used to define WWT /// WI for T=0 used to define WWT
unsigned char bWaitingIntegerT0; // 0 to FF unsigned char bWaitingIntegerT0; // 0 to FF
/// ICC Clock Stop Support /// ICC Clock Stop Support
/// 00 = Stopping the Clock is not allowed /// 00 = Stopping the Clock is not allowed
/// 01 = Stop with Clock signal Low /// 01 = Stop with Clock signal Low
/// 02 = Stop with Clock signal High /// 02 = Stop with Clock signal High
/// 03 = Stop with Clock either High or Low /// 03 = Stop with Clock either High or Low
unsigned char bClockStop; // 0 to 3 unsigned char bClockStop; // 0 to 3
} __attribute__ ((packed)) S_ccid_protocol_t0; } __attribute__ ((packed)) S_ccid_protocol_t0;
/// Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h) /// Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h)
typedef struct typedef struct
{ {
/// B7-4 FI Index into the table 7 in ISO/IEC 7816-3:1997 selecting a /// B7-4 FI Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
/// clock rate conversion factor /// clock rate conversion factor
/// B3-0 DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a /// B3-0 DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
/// baud rate conversion factor /// baud rate conversion factor
unsigned char bmFindexDindex; unsigned char bmFindexDindex;
/// For T=1, B7-2 000100b /// For T=1, B7-2 000100b
/// B0 Checksum type (b0=0 for LRC, b0=1 for CRC /// B0 Checksum type (b0=0 for LRC, b0=1 for CRC
/// B1 Convention used (b1=0 for direct, b1=1 for inverse) /// B1 Convention used (b1=0 for direct, b1=1 for inverse)
unsigned char bmTCCKST1; // 10h, 11h, 12h, 13h unsigned char bmTCCKST1; // 10h, 11h, 12h, 13h
/// Extra Guardtime (0 to 254 etu between two characters). /// Extra Guardtime (0 to 254 etu between two characters).
/// If value is FFh, then guardtime is reduced by 1. /// If value is FFh, then guardtime is reduced by 1.
unsigned char bGuardTimeT1; // 0 to FF unsigned char bGuardTimeT1; // 0 to FF
/// B7-4 = BWI /// B7-4 = BWI
/// B3-0 = CWI /// B3-0 = CWI
unsigned char bmWaitingIntegersT1; // 0 to 9 unsigned char bmWaitingIntegersT1; // 0 to 9
/// ICC Clock Stop Support /// ICC Clock Stop Support
/// 00 = Stopping the Clock is not allowed /// 00 = Stopping the Clock is not allowed
/// 01 = Stop with Clock signal Low /// 01 = Stop with Clock signal Low
/// 02 = Stop with Clock signal High /// 02 = Stop with Clock signal High
/// 03 = Stop with Clock either High or Low /// 03 = Stop with Clock either High or Low
unsigned char bClockStop; // 0 to 3 unsigned char bClockStop; // 0 to 3
/// Size of negotiated IFSC /// Size of negotiated IFSC
unsigned char bIFSC; // 0 to FE unsigned char bIFSC; // 0 to FE
/// Nad value used by CCID /// Nad value used by CCID
unsigned char bNadValue; // 0 to FF unsigned char bNadValue; // 0 to FF
} __attribute__ ((packed)) S_ccid_protocol_t1; } __attribute__ ((packed)) S_ccid_protocol_t1;
@@ -357,8 +357,8 @@ typedef struct
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
extern unsigned char RDRtoPCHardwareError( unsigned char bSlot, extern unsigned char RDRtoPCHardwareError( unsigned char bSlot,
unsigned char bSeq, unsigned char bSeq,
unsigned char bHardwareErrorCode ); unsigned char bHardwareErrorCode );
/* /*
#if !defined(NOAUTOCALLBACK) #if !defined(NOAUTOCALLBACK)
@@ -368,13 +368,13 @@ extern void USBDCallbacks_RequestReceived(const USBGenericRequest *request);
extern void CCID_SmartCardRequest( void ); extern void CCID_SmartCardRequest( void );
extern void CCIDDriver_Initialize( void ); extern void CCIDDriver_Initialize( void );
extern unsigned char CCID_Read(void *pBuffer, extern unsigned char CCID_Read(void *pBuffer,
unsigned int dLength, unsigned int dLength,
TransferCallback fCallback, TransferCallback fCallback,
void *pArgument); void *pArgument);
extern unsigned char CCID_Write(void *pBuffer, extern unsigned char CCID_Write(void *pBuffer,
unsigned int dLength, unsigned int dLength,
TransferCallback fCallback, TransferCallback fCallback,
void *pArgument); void *pArgument);
extern unsigned char CCID_Insertion( void ); extern unsigned char CCID_Insertion( void );
extern unsigned char CCID_Removal( void ); extern unsigned char CCID_Removal( void );

View File

@@ -76,9 +76,9 @@ extern uint32_t ISO7816_GetChar( uint8_t *pCharToReceive, Usart_info *usart);
extern void ISO7816_IccPowerOff(void); extern void ISO7816_IccPowerOff(void);
extern uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU, extern uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
uint8_t *pMessage, uint8_t *pMessage,
uint16_t wLength, uint16_t wLength,
uint16_t *retlen); uint16_t *retlen);
extern void ISO7816_Escape( void ); extern void ISO7816_Escape( void );
extern void ISO7816_RestartClock(void); extern void ISO7816_RestartClock(void);
extern void ISO7816_StopClock( void ); extern void ISO7816_StopClock( void );

View File

@@ -1,21 +1,3 @@
/* ISO7816-3 Fi/Di tables + computation
*
* (C) 2010-2015 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
*/
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>

View File

@@ -1,21 +1,3 @@
/* IRQ-safe linked lists
*
* (C) 2015-2017 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
*/
#pragma once #pragma once
#include <osmocom/core/linuxlist.h> #include <osmocom/core/linuxlist.h>

View File

@@ -1,19 +1,3 @@
/* Ring buffer
*
* 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
*/
#ifndef SIMTRACE_RINGBUF_H #ifndef SIMTRACE_RINGBUF_H
#define SIMTRACE_RINGBUF_H #define SIMTRACE_RINGBUF_H
@@ -32,7 +16,7 @@ typedef struct ringbuf {
void rbuf_reset(volatile ringbuf * rb); void rbuf_reset(volatile ringbuf * rb);
uint8_t rbuf_read(volatile ringbuf * rb); uint8_t rbuf_read(volatile ringbuf * rb);
uint8_t rbuf_peek(volatile ringbuf * rb); uint8_t rbuf_peek(volatile ringbuf * rb);
int rbuf_write(volatile ringbuf * rb, uint8_t item); void rbuf_write(volatile ringbuf * rb, uint8_t item);
bool rbuf_is_empty(volatile ringbuf * rb); bool rbuf_is_empty(volatile ringbuf * rb);
bool rbuf_is_full(volatile ringbuf * rb); bool rbuf_is_full(volatile ringbuf * rb);

View File

@@ -1,22 +1,3 @@
/* SIMtrace 2 mode definitions
*
* Copyright (c) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* Copyright (c) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.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
*/
#ifndef SIMTRACE_H #ifndef SIMTRACE_H
#define SIMTRACE_H #define SIMTRACE_H
@@ -58,7 +39,6 @@ enum confNum {
#ifdef HAVE_MITM #ifdef HAVE_MITM
CFG_NUM_MITM, CFG_NUM_MITM,
#endif #endif
CFG_NUM_VERSION,
NUM_CONF NUM_CONF
}; };
@@ -67,19 +47,19 @@ enum confNum {
/// device using the CCID driver. /// device using the CCID driver.
typedef struct { typedef struct {
/// Configuration descriptor /// Configuration descriptor
USBConfigurationDescriptor configuration; USBConfigurationDescriptor configuration;
/// Interface descriptor /// Interface descriptor
USBInterfaceDescriptor interface; USBInterfaceDescriptor interface;
/// CCID descriptor /// CCID descriptor
CCIDDescriptor ccid; CCIDDescriptor ccid;
/// Bulk OUT endpoint descriptor /// Bulk OUT endpoint descriptor
USBEndpointDescriptor bulkOut; USBEndpointDescriptor bulkOut;
/// Bulk IN endpoint descriptor /// Bulk IN endpoint descriptor
USBEndpointDescriptor bulkIn; USBEndpointDescriptor bulkIn;
/// Interrupt OUT endpoint descriptor /// Interrupt OUT endpoint descriptor
USBEndpointDescriptor interruptIn; USBEndpointDescriptor interruptIn;
DFURT_IF_DESCRIPTOR_STRUCT DFURT_IF_DESCRIPTOR_STRUCT
} __attribute__ ((packed)) CCIDDriverConfigurationDescriptors; } __attribute__ ((packed)) CCIDDriverConfigurationDescriptors;
extern const USBConfigurationDescriptor *configurationDescriptorsArr[]; extern const USBConfigurationDescriptor *configurationDescriptorsArr[];
@@ -88,7 +68,7 @@ extern const USBConfigurationDescriptor *configurationDescriptorsArr[];
* @param[io] usart USART peripheral base address * @param[io] usart USART peripheral base address
* @param[in] fidi FiDi value as provided in TA interface byte * @param[in] fidi FiDi value as provided in TA interface byte
*/ */
void update_fidi(Usart_info *usart, uint8_t fidi); void update_fidi(Usart *usart, uint8_t fidi);
void ISR_PhoneRST( const Pin *pPin); void ISR_PhoneRST( const Pin *pPin);

View File

@@ -1,21 +1,21 @@
/* SIMtrace2 USB protocol /* SIMtrace2 USB protocol */
/* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
* *
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de> * This program is free software; you can redistribute it and/or modify
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * 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 free software; you can redistribute it and/or modify * This program is distributed in the hope that it will be useful,
* it under the terms of the GNU General Public License as published by * but WITHOUT ANY WARRANTY; without even the implied warranty of
* the Free Software Foundation; either version 2 of the License, or * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* (at your option) any later version. * GNU General Public License for more details.
* *
* This program is distributed in the hope that it will be useful, * You should have received a copy of the GNU General Public License
* but WITHOUT ANY WARRANTY; without even the implied warranty of * along with this program; if not, write to the Free Software
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* 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
*/ */
#pragma once #pragma once
@@ -291,13 +291,9 @@ struct st_modem_status {
/* SIMTRACE_MSGT_SNIFF_CHANGE flags */ /* SIMTRACE_MSGT_SNIFF_CHANGE flags */
#define SNIFF_CHANGE_FLAG_CARD_INSERT (1<<0) #define SNIFF_CHANGE_FLAG_CARD_INSERT (1<<0)
#define SNIFF_CHANGE_FLAG_CARD_EJECT (1<<1) #define SNIFF_CHANGE_FLAG_CARD_EJECT (1<<1)
#define SNIFF_CHANGE_FLAG_RESET_ASSERT (1<<2) #define SNIFF_CHANGE_FLAG_RESET_HOLD (1<<2)
#define SNIFF_CHANGE_FLAG_RESET_DEASSERT (1<<3) #define SNIFF_CHANGE_FLAG_RESET_RELEASE (1<<3)
#define SNIFF_CHANGE_FLAG_TIMEOUT_WT (1<<4) #define SNIFF_CHANGE_FLAG_TIMEOUT_WT (1<<4)
/* SIMTRACE_MSGT_SNIFF_ATR, SIMTRACE_MSGT_SNIFF_PPS, SIMTRACE_MSGT_SNIFF_TPDU flags */
#define SNIFF_DATA_FLAG_ERROR_INCOMPLETE (1<<5)
#define SNIFF_DATA_FLAG_ERROR_MALFORMED (1<<6)
#define SNIFF_DATA_FLAG_ERROR_CHECKSUM (1<<7)
/* SIMTRACE_MSGT_SNIFF_CHANGE */ /* SIMTRACE_MSGT_SNIFF_CHANGE */
struct sniff_change { struct sniff_change {
@@ -313,8 +309,8 @@ struct sniff_fidi {
/* SIMTRACE_MSGT_SNIFF_ATR, SIMTRACE_MSGT_SNIFF_PPS, SIMTRACE_MSGT_SNIFF_TPDU */ /* SIMTRACE_MSGT_SNIFF_ATR, SIMTRACE_MSGT_SNIFF_PPS, SIMTRACE_MSGT_SNIFF_TPDU */
struct sniff_data { struct sniff_data {
/* data flags */ /* if the data is complete (an error might have occurred during transmission */
uint32_t flags; bool complete;
/* data length */ /* data length */
uint16_t length; uint16_t length;
/* data */ /* data */

View File

@@ -1,21 +1,20 @@
/* SIMtrace 2 USB definitions /* This program is free software; you can redistribute it and/or modify
* * it under the terms of the GNU Affero General Public License as published by
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * the Free Software Foundation; either version 3 of the License, or
*
* 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. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program; if not, write to the Free Software * along with this program. If not, see <http://www.gnu.org/licenses/>.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *
* (C) 2018 by Kevin Redon <kredon@sysmocom.de>
* All Rights Reserved
*/ */
/* SIMtrace USB IDs */ /* SIMtrace USB IDs */
#define USB_VENDOR_OPENMOKO 0x1d50 #define USB_VENDOR_OPENMOKO 0x1d50
#define USB_PRODUCT_OWHW_SAM3_DFU 0x4001 /* was 0x4000 */ #define USB_PRODUCT_OWHW_SAM3_DFU 0x4001 /* was 0x4000 */

View File

@@ -1,31 +1,3 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#pragma once #pragma once
#include <stddef.h> #include <stddef.h>
#include <stdarg.h> #include <stdarg.h>
@@ -52,14 +24,9 @@ signed int printf(const char *pFormat, ...);
signed int sprintf(char *pStr, const char *pFormat, ...); signed int sprintf(char *pStr, const char *pFormat, ...);
signed int puts(const char *pStr); signed int puts(const char *pStr);
int fputc(int c, FILE *stream); int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream); int fputs(const char *s, FILE *stream);
#define putc(c, stream) fputc(c, stream) #define putc(c, stream) fputc(c, stream)
#define putchar(c) fputc(c, stdout) #define putchar(c) fputc(c, stdout)
signed int vfprintf_sync(FILE *pStream, const char *pFormat, va_list ap);
signed int vprintf_sync(const char *pFormat, va_list ap);
signed int printf_sync(const char *pFormat, ...);
int fputc_sync(int c, FILE *stream);
int fputs_sync(const char *s, FILE *stream);

View File

@@ -1,19 +1,3 @@
/* Memory allocation library
*
* 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
*/
#pragma once #pragma once
#include <stdlib.h> #include <stdlib.h>

View File

@@ -1,19 +1,3 @@
/* USB buffer library
*
* 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
*/
#pragma once #pragma once
#include <osmocom/core/linuxlist.h> #include <osmocom/core/linuxlist.h>

View File

@@ -1,19 +1,3 @@
/* General utilities
*
* 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
*/
#pragma once #pragma once
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

View File

@@ -1,22 +1,24 @@
/* ISO7816-3 state machine for the card side /* ISO7816-3 state machine for the card side */
/* (C) 2010-2017 by Harald Welte <hwelte@hmw-consulting.de>
* *
* (C) 2010-2017 by Harald Welte <laforge@gnumonks.org> * This program is free software; you can redistribute it and/or modify
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * 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 free software; you can redistribute it and/or modify * This program is distributed in the hope that it will be useful,
* it under the terms of the GNU General Public License as published by * but WITHOUT ANY WARRANTY; without even the implied warranty of
* the Free Software Foundation; either version 2 of the License, or * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* (at your option) any later version. * GNU General Public License for more details.
* *
* This program is distributed in the hope that it will be useful, * You should have received a copy of the GNU General Public License
* but WITHOUT ANY WARRANTY; without even the implied warranty of * along with this program; if not, write to the Free Software
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* 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
*/ */
//#define TRACE_LEVEL 6
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
@@ -54,46 +56,6 @@ enum iso7816_3_card_state {
ISO_S_IN_TPDU, /* inside a TPDU */ ISO_S_IN_TPDU, /* inside a TPDU */
}; };
const struct value_string iso7816_3_card_state_names[] = {
{
.value = ISO_S_WAIT_POWER,
.str = "WAIT_POWER",
},
{
.value = ISO_S_WAIT_CLK,
.str = "WAIT_CLK",
},
{
.value = ISO_S_WAIT_RST,
.str = "WAIT_RST",
},
{
.value = ISO_S_WAIT_ATR,
.str = "WAIT_ATR",
},
{
.value = ISO_S_IN_ATR,
.str = "IN_ATR",
},
{
.value = ISO_S_IN_PTS,
.str = "IN_PTS",
},
{
.value = ISO_S_WAIT_TPDU,
.str = "WAIT_TPDU",
},
{
.value = ISO_S_IN_TPDU,
.str = "IN_TPDU",
},
{
.value = 0,
.str = NULL,
},
};
/* detailed sub-states of ISO_S_IN_PTS */ /* detailed sub-states of ISO_S_IN_PTS */
enum pts_state { enum pts_state {
PTS_S_WAIT_REQ_PTSS, PTS_S_WAIT_REQ_PTSS,
@@ -110,7 +72,6 @@ enum pts_state {
PTS_S_WAIT_RESP_PCK = PTS_S_WAIT_REQ_PCK | 0x10, PTS_S_WAIT_RESP_PCK = PTS_S_WAIT_REQ_PCK | 0x10,
}; };
/* PTS field byte index */
#define _PTSS 0 #define _PTSS 0
#define _PTS0 1 #define _PTS0 1
#define _PTS1 2 #define _PTS1 2
@@ -126,50 +87,10 @@ enum tpdu_state {
TPDU_S_WAIT_P2, /* waiting for P2 byte from reader */ TPDU_S_WAIT_P2, /* waiting for P2 byte from reader */
TPDU_S_WAIT_P3, /* waiting for P3 byte from reader */ TPDU_S_WAIT_P3, /* waiting for P3 byte from reader */
TPDU_S_WAIT_PB, /* waiting for Tx of procedure byte */ TPDU_S_WAIT_PB, /* waiting for Tx of procedure byte */
TPDU_S_WAIT_RX, /* waiting for more data from reader */ TPDU_S_WAIT_RX, /* waiitng for more data from reader */
TPDU_S_WAIT_TX, /* waiting for more data to reader */ TPDU_S_WAIT_TX, /* waiting for more data to reader */
}; };
const struct value_string tpdu_state_names[] = {
{
.value = TPDU_S_WAIT_CLA,
.str = "WAIT_CLA",
},
{
.value = TPDU_S_WAIT_INS,
.str = "WAIT_INS",
},
{
.value = TPDU_S_WAIT_P1,
.str = "WAIT_P1",
},
{
.value = TPDU_S_WAIT_P2,
.str = "WAIT_P2",
},
{
.value = TPDU_S_WAIT_P3,
.str = "WAIT_P3",
},
{
.value = TPDU_S_WAIT_PB,
.str = "WAIT_PB",
},
{
.value = TPDU_S_WAIT_RX,
.str = "WAIT_RX",
},
{
.value = TPDU_S_WAIT_TX,
.str = "WAIT_TX",
},
{
.value = 0,
.str = NULL,
},
};
/* TPDU field byte index */
#define _CLA 0 #define _CLA 0
#define _INS 1 #define _INS 1
#define _P1 2 #define _P1 2
@@ -177,14 +98,14 @@ const struct value_string tpdu_state_names[] = {
#define _P3 4 #define _P3 4
struct card_handle { struct card_handle {
unsigned int num; uint32_t num;
enum iso7816_3_card_state state; enum iso7816_3_card_state state;
/* signal levels */ /* signal levels */
bool vcc_active; /*< if VCC is active (true = active/ON) */ uint8_t vcc_active; /* 1 = on, 0 = off */
bool in_reset; /*< if card is in reset (true = RST low/asserted, false = RST high/ released) */ uint8_t in_reset; /* 1 = RST low, 0 = RST high */
bool clocked; /*< if clock is active ( true = active, false = inactive) */ uint8_t clocked; /* 1 = active, 0 = inactive */
/* timing parameters, from PTS */ /* timing parameters, from PTS */
uint8_t fi; uint8_t fi;
@@ -254,35 +175,12 @@ void usb_buf_upd_len_and_submit(struct msgb *msg)
/* Allocate USB buffer and push + initialize simtrace_msg_hdr */ /* Allocate USB buffer and push + initialize simtrace_msg_hdr */
struct msgb *usb_buf_alloc_st(uint8_t ep, uint8_t msg_class, uint8_t msg_type) struct msgb *usb_buf_alloc_st(uint8_t ep, uint8_t msg_class, uint8_t msg_type)
{ {
struct msgb *msg = NULL; struct msgb *msg;
struct simtrace_msg_hdr *sh; struct simtrace_msg_hdr *sh;
while (!msg) { msg = usb_buf_alloc(ep);
msg = usb_buf_alloc(ep); // try to allocate some memory if (!msg)
if (!msg) { // allocation failed, we might be out of memory return NULL;
struct llist_head *queue = usb_get_queue(ep);
if (!queue) {
TRACE_ERROR("ep %u: %s queue does not exist\n\r",
ep, __func__);
return NULL;
}
if (llist_empty(queue)) {
TRACE_ERROR("ep %u: %s EOMEM (queue already empty)\n\r",
ep, __func__);
return NULL;
}
msg = msgb_dequeue(queue);
if (!msg) {
TRACE_ERROR("ep %u: %s no msg in non-empty queue\n\r",
ep, __func__);
return NULL;
}
usb_buf_free(msg);
msg = NULL;
TRACE_DEBUG("ep %u: %s queue msg dropped\n\r",
ep, __func__);
}
}
msg->l1h = msgb_put(msg, sizeof(*sh)); msg->l1h = msgb_put(msg, sizeof(*sh));
sh = (struct simtrace_msg_hdr *) msg->l1h; sh = (struct simtrace_msg_hdr *) msg->l1h;
@@ -294,7 +192,7 @@ struct msgb *usb_buf_alloc_st(uint8_t ep, uint8_t msg_class, uint8_t msg_type)
return msg; return msg;
} }
/* Update cardemu_usb_msg_rx_data length + submit buffer */ /* Update cardemu_usb_msg_rx_data length + submit bufffer */
static void flush_rx_buffer(struct card_handle *ch) static void flush_rx_buffer(struct card_handle *ch)
{ {
struct msgb *msg; struct msgb *msg;
@@ -307,17 +205,14 @@ static void flush_rx_buffer(struct card_handle *ch)
ch->uart_rx_msg = NULL; ch->uart_rx_msg = NULL;
/* store length of data payload field in header */ /* store length of data payload fild in header */
rd = (struct cardemu_usb_msg_rx_data *) msg->l2h; rd = (struct cardemu_usb_msg_rx_data *) msg->l2h;
rd->data_len = msgb_l2len(msg) - sizeof(*rd); rd->data_len = msgb_l2len(msg) - sizeof(*rd);
TRACE_INFO("%u: %s (%u)\n\r",
ch->num, __func__, rd->data_len);
usb_buf_upd_len_and_submit(msg); usb_buf_upd_len_and_submit(msg);
} }
/* convert a non-contiguous PTS request/response into a contiguous /* convert a non-contiguous PTS request/responsei into a contiguous
* buffer, returning the number of bytes used in the buffer */ * buffer, returning the number of bytes used in the buffer */
static int serialize_pts(uint8_t *out, const uint8_t *in) static int serialize_pts(uint8_t *out, const uint8_t *in)
{ {
@@ -392,9 +287,8 @@ static void card_set_state(struct card_handle *ch,
if (ch->state == new_state) if (ch->state == new_state)
return; return;
TRACE_DEBUG("%u: 7816 card state %s -> %s\r\n", ch->num, TRACE_DEBUG("%u: 7816 card state %u -> %u\r\n", ch->num,
get_value_string(iso7816_3_card_state_names, ch->state), ch->state, new_state);
get_value_string(iso7816_3_card_state_names, new_state));
ch->state = new_state; ch->state = new_state;
switch (new_state) { switch (new_state) {
@@ -403,48 +297,34 @@ static void card_set_state(struct card_handle *ch,
case ISO_S_WAIT_RST: case ISO_S_WAIT_RST:
/* disable Rx and Tx of UART */ /* disable Rx and Tx of UART */
card_emu_uart_enable(ch->uart_chan, 0); card_emu_uart_enable(ch->uart_chan, 0);
/* check end activation state (only necessary if the reader to not respect the activation sequence) */
if (ch->vcc_active && ch->clocked && !ch->in_reset) {
/* enable the TC/ETU counter once reset has been released */
tc_etu_enable(ch->tc_chan);
/* prepare to send the ATR */
card_set_state(ch, ISO_S_WAIT_ATR);
}
break; break;
case ISO_S_WAIT_ATR: case ISO_S_WAIT_ATR:
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
/* Reset to initial Fi / Di ratio */ /* Reset to initial Fi / Di ratio */
ch->fi = 1; ch->fi = 1;
ch->di = 1; ch->di = 1;
emu_update_fidi(ch); emu_update_fidi(ch);
/* the ATR should only be sent 400 to 40k clock cycles after the RESET. /* initialize todefault WI, this will be overwritten if we
* we use the tc_etu mechanism to wait this time. * receive TC2, and it will be programmed into hardware after
* since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.
*/
tc_etu_set_wtime(ch->tc_chan, 2);
/* ensure the TC_ETU timer is enabled */
tc_etu_enable(ch->tc_chan);
break;
case ISO_S_IN_ATR:
/* initialize to default WI, this will be overwritten if we
* send TC2, and it will be programmed into hardware after
* ATR is finished */ * ATR is finished */
ch->wi = ISO7816_3_DEFAULT_WI; ch->wi = ISO7816_3_DEFAULT_WI;
/* 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 */
tc_etu_set_wtime(ch->tc_chan, ch->waiting_time); tc_etu_set_wtime(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 */ //set_atr_state(ch, ATR_S_WAIT_TS);
/* Notice that we are just coming out of reset */
//ch->sh.flags |= SIMTRACE_FLAG_ATR;
card_emu_uart_enable(ch->uart_chan, ENABLE_TX); card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
/* trigger USART TX IRQ to sent first ATR byte TS */ break;
card_emu_uart_interrupt(ch->uart_chan);
break; break;
case ISO_S_WAIT_TPDU: case ISO_S_WAIT_TPDU:
/* enable the receiver, disable transmitter */ /* enable the receiver, disable transmitter */
set_tpdu_state(ch, TPDU_S_WAIT_CLA); set_tpdu_state(ch, TPDU_S_WAIT_CLA);
card_emu_uart_enable(ch->uart_chan, ENABLE_RX); card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
break; break;
case ISO_S_IN_ATR:
case ISO_S_IN_PTS: case ISO_S_IN_PTS:
case ISO_S_IN_TPDU: case ISO_S_IN_TPDU:
/* do nothing */ /* do nothing */
@@ -452,80 +332,12 @@ static void card_set_state(struct card_handle *ch,
} }
} }
/**********************************************************************
* ATR handling
**********************************************************************/
/*! Transmit ATR data to reader
* @param[in] ch card interface connected to reader
* @return numbers of bytes transmitted
*/
static int tx_byte_atr(struct card_handle *ch)
{
if (NULL == ch) {
TRACE_ERROR("ATR TX: no card handle provided\n\r");
return 0;
}
if (ISO_S_IN_ATR != ch->state) {
TRACE_ERROR("%u: ATR TX: no in ATR state\n\r", ch->num);
return 0;
}
/* Transmit ATR */
if (ch->atr.idx < ch->atr.len) {
uint8_t byte = ch->atr.atr[ch->atr.idx++];
card_emu_uart_tx(ch->uart_chan, byte);
return 1;
} else { /* The ATR has been completely transmitted */
/* search for TC2 to updated WI */
ch->wi = ISO7816_3_DEFAULT_WI;
if (ch->atr.len >= 2 && ch->atr.atr[1] & 0xf0) { /* Y1 has some data */
uint8_t atr_td1 = 2;
if (ch->atr.atr[1] & 0x10) { /* TA1 is present */
atr_td1++;
}
if (ch->atr.atr[1] & 0x20) { /* TB1 is present */
atr_td1++;
}
if (ch->atr.atr[1] & 0x40) { /* TC1 is present */
atr_td1++;
}
if (ch->atr.atr[1] & 0x80) { /* TD1 is present */
if (ch->atr.len > atr_td1 && ch->atr.atr[atr_td1] & 0xf0) { /* Y2 has some data */
uint8_t atr_tc2 = atr_td1+1;
if (ch->atr.atr[atr_td1] & 0x10) { /* TA2 is present */
atr_tc2++;
}
if (ch->atr.atr[atr_td1] & 0x20) { /* TB2 is present */
atr_tc2++;
}
if (ch->atr.atr[atr_td1] & 0x40) { /* TC2 is present */
if (ch->atr.len > atr_tc2 && ch->atr.atr[atr_tc2]) { /* TC2 encodes WI */
ch->wi = ch->atr.atr[atr_tc2]; /* set WI */
}
}
}
}
}
/* update waiting time (see ISO 7816-3 10.2) */
ch->waiting_time = ch->wi * 960 * ch->fi;
tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
/* reset PTS to initial state */
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
/* go to next state */
card_set_state(ch, ISO_S_WAIT_TPDU);
return 0;
}
/* return number of bytes transmitted */
return 1;
}
/********************************************************************** /**********************************************************************
* PTS / PPS handling * PTS / PPS handling
**********************************************************************/ **********************************************************************/
/* Update the PTS sub-state */ /* Update the ATR sub-state */
static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss) static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss)
{ {
TRACE_DEBUG("%u: 7816 PTS state %u -> %u\r\n", TRACE_DEBUG("%u: 7816 PTS state %u -> %u\r\n",
@@ -746,9 +558,9 @@ static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts)
if (ch->tpdu.state == new_ts) if (ch->tpdu.state == new_ts)
return; return;
TRACE_DEBUG("%u: 7816 TPDU state %s -> %s\r\n", ch->num, TRACE_DEBUG("%u: 7816 TPDU state %u -> %u\r\n", ch->num,
get_value_string(tpdu_state_names, ch->tpdu.state), ch->tpdu.state, new_ts);
get_value_string(tpdu_state_names, new_ts));
ch->tpdu.state = new_ts; ch->tpdu.state = new_ts;
switch (new_ts) { switch (new_ts) {
@@ -906,7 +718,7 @@ static int tx_byte_tpdu(struct card_handle *ch)
card_emu_uart_tx(ch->uart_chan, byte); card_emu_uart_tx(ch->uart_chan, byte);
/* this must happen _after_ the byte has been transmitted */ /* this must happen _after_ the byte has been transmittd */
switch (ch->tpdu.state) { switch (ch->tpdu.state) {
case TPDU_S_WAIT_PB: case TPDU_S_WAIT_PB:
/* if we just transmitted the procedure byte, we need to decide /* if we just transmitted the procedure byte, we need to decide
@@ -953,6 +765,14 @@ void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte)
ch->stats.rx_bytes++; ch->stats.rx_bytes++;
switch (ch->state) { switch (ch->state) {
case ISO_S_WAIT_POWER:
case ISO_S_WAIT_CLK:
case ISO_S_WAIT_RST:
case ISO_S_WAIT_ATR:
TRACE_ERROR("%u: Received UART char in invalid 7816 state "
"%u\r\n", ch->num, ch->state);
/* we shouldn't receive any data from the reader yet! */
break;
case ISO_S_WAIT_TPDU: case ISO_S_WAIT_TPDU:
if (byte == 0xff) { if (byte == 0xff) {
new_state = process_byte_pts(ch, byte); new_state = process_byte_pts(ch, byte);
@@ -966,10 +786,6 @@ void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte)
case ISO_S_IN_PTS: case ISO_S_IN_PTS:
new_state = process_byte_pts(ch, byte); new_state = process_byte_pts(ch, byte);
goto out_silent; goto out_silent;
default:
TRACE_ERROR("%u: Received UART char in invalid 7816 state "
"%u\r\n", ch->num, ch->state);
break;
} }
out_silent: out_silent:
@@ -984,7 +800,17 @@ int card_emu_tx_byte(struct card_handle *ch)
switch (ch->state) { switch (ch->state) {
case ISO_S_IN_ATR: case ISO_S_IN_ATR:
rc = tx_byte_atr(ch); if (ch->atr.idx < ch->atr.len) {
uint8_t byte;
byte = ch->atr.atr[ch->atr.idx++];
rc = 1;
card_emu_uart_tx(ch->uart_chan, byte);
/* detect end of ATR */
if (ch->atr.idx >= ch->atr.len)
card_set_state(ch, ISO_S_WAIT_TPDU);
}
break; break;
case ISO_S_IN_PTS: case ISO_S_IN_PTS:
rc = tx_byte_pts(ch); rc = tx_byte_pts(ch);
@@ -1079,8 +905,9 @@ void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
if (ch->vcc_active && ch->clocked) { if (ch->vcc_active && ch->clocked) {
/* enable the TC/ETU counter once reset has been released */ /* enable the TC/ETU counter once reset has been released */
tc_etu_enable(ch->tc_chan); tc_etu_enable(ch->tc_chan);
/* prepare to send the ATR */
card_set_state(ch, ISO_S_WAIT_ATR); card_set_state(ch, ISO_S_WAIT_ATR);
/* FIXME: wait 400 to 40k clock cycles before sending ATR */
card_set_state(ch, ISO_S_IN_ATR);
} }
} else if (active && !ch->in_reset) { } else if (active && !ch->in_reset) {
TRACE_INFO("%u: RST asserted\r\n", ch->num); TRACE_INFO("%u: RST asserted\r\n", ch->num);
@@ -1101,15 +928,7 @@ int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len)
ch->atr.len = len; ch->atr.len = len;
ch->atr.idx = 0; ch->atr.idx = 0;
#if TRACE_LEVEL >= TRACE_LEVEL_INFO /* FIXME: race condition with trasmitting ATR to reader? */
uint8_t i;
TRACE_INFO("%u: ATR set: ", ch->num);
for (i = 0; i < ch->atr.len; i++) {
TRACE_INFO_WP("%02x ", atr[i]);
}
TRACE_INFO_WP("\n\r");
#endif
/* FIXME: race condition with transmitting ATR to reader? */
return 0; return 0;
} }
@@ -1140,23 +959,16 @@ void tc_etu_wtime_half_expired(void *handle)
void tc_etu_wtime_expired(void *handle) void tc_etu_wtime_expired(void *handle)
{ {
struct card_handle *ch = handle; struct card_handle *ch = handle;
switch (ch->state) { TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
case ISO_S_WAIT_ATR:
/* ISO 7816-3 6.2.1 time tc has passed, we can now send the ATR */
card_set_state(ch, ISO_S_IN_ATR);
break;
default:
TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
break;
}
} }
/* shortest ATR possible (uses default speed and no options) */ /* shortest ATR found in smartcard_list.txt */
static const uint8_t default_atr[] = { 0x3B, 0x00 }; static const uint8_t default_atr[] = { 0x3B, 0x02, 0x14, 0x50 };
static struct card_handle card_handles[NUM_SLOTS]; static struct card_handle card_handles[NUM_SLOTS];
struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked) struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan,
uint8_t in_ep, uint8_t irq_ep)
{ {
struct card_handle *ch; struct card_handle *ch;
@@ -1169,13 +981,14 @@ struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uar
INIT_LLIST_HEAD(&ch->uart_tx_queue); INIT_LLIST_HEAD(&ch->uart_tx_queue);
/* initialize the card_handle with reasonabe defaults */
ch->num = slot_num; ch->num = slot_num;
ch->irq_ep = irq_ep; ch->irq_ep = irq_ep;
ch->in_ep = in_ep; ch->in_ep = in_ep;
ch->state = ISO_S_WAIT_POWER; ch->state = ISO_S_WAIT_POWER;
ch->vcc_active = vcc_active; ch->vcc_active = 0;
ch->in_reset = in_reset; ch->in_reset = 1;
ch->clocked = clocked; ch->clocked = 0;
ch->fi = 0; ch->fi = 0;
ch->di = 1; ch->di = 1;

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,3 @@
/* UART print output
*
* 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 <stdio.h> #include <stdio.h>
#include "uart_console.h" #include "uart_console.h"
@@ -26,19 +10,6 @@ int fputc(int c, FILE *stream)
int fputs(const char *s, FILE *stream) int fputs(const char *s, FILE *stream)
{ {
while (*s != '\0') while (*s != '\0')
fputc(*s++, stream); UART_PutChar(*s++);
return 0;
}
int fputc_sync(int c, FILE *stream)
{
UART_PutChar_Sync(c);
return c;
}
int fputs_sync(const char *s, FILE *stream)
{
while (*s != '\0')
fputc_sync(*s++, stream);
return 0; return 0;
} }

View File

@@ -1,19 +1,3 @@
/* USB communication methods
*
* 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 "board.h"
#include "llist_irqsafe.h" #include "llist_irqsafe.h"
#include "usb_buf.h" #include "usb_buf.h"
@@ -150,7 +134,7 @@ int usb_refill_from_host(uint8_t ep)
rc = USBD_Read(ep, msg->head, msgb_tailroom(msg), rc = USBD_Read(ep, msg->head, msgb_tailroom(msg),
(TransferCallback) &usb_read_cb, msg); (TransferCallback) &usb_read_cb, msg);
if (rc != USBD_STATUS_SUCCESS) { if (rc != USBD_STATUS_SUCCESS) {
TRACE_ERROR("%s error %d\n", __func__, rc); TRACE_ERROR("%s error %s\n", __func__, rc);
usb_buf_free(msg); usb_buf_free(msg);
bep->in_progress = 0; bep->in_progress = 0;
} }

View File

@@ -76,45 +76,45 @@ struct Usart_info usart_sim = {.base = USART_SIM, .id = ID_USART_SIM, .state = U
*/ */
uint32_t ISO7816_GetChar( uint8_t *pCharToReceive, Usart_info *usart) uint32_t ISO7816_GetChar( uint8_t *pCharToReceive, Usart_info *usart)
{ {
uint32_t status; uint32_t status;
uint32_t timeout=0; uint32_t timeout=0;
Usart *us_base = usart->base; Usart *us_base = usart->base;
uint32_t us_id = usart->id; uint32_t us_id = usart->id;
if( usart->state == USART_SEND ) { if( usart->state == USART_SEND ) {
while((us_base->US_CSR & US_CSR_TXEMPTY) == 0) {} while((us_base->US_CSR & US_CSR_TXEMPTY) == 0) {}
us_base->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; us_base->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
usart->state = USART_RCV; usart->state = USART_RCV;
} }
/* Wait USART ready for reception */ /* Wait USART ready for reception */
while( ((us_base->US_CSR & US_CSR_RXRDY) == 0) ) { while( ((us_base->US_CSR & US_CSR_RXRDY) == 0) ) {
WDT_Restart(WDT); WDT_Restart(WDT);
if(timeout++ > 12000 * (BOARD_MCK/1000000)) { if(timeout++ > 12000 * (BOARD_MCK/1000000)) {
TRACE_WARNING("TimeOut\n\r"); TRACE_WARNING("TimeOut\n\r");
return( 0 ); return( 0 );
} }
} }
/* At least one complete character has been received and US_RHR has not yet been read. */ /* At least one complete character has been received and US_RHR has not yet been read. */
/* Get a char */ /* Get a char */
*pCharToReceive = ((us_base->US_RHR) & 0xFF); *pCharToReceive = ((us_base->US_RHR) & 0xFF);
status = (us_base->US_CSR&(US_CSR_OVRE|US_CSR_FRAME| status = (us_base->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK| US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
(1<<10))); (1<<10)));
if (status != 0 ) { if (status != 0 ) {
TRACE_DEBUG("R:0x%" PRIX32 "\n\r", status); TRACE_DEBUG("R:0x%" PRIX32 "\n\r", status);
TRACE_DEBUG("R:0x%" PRIX32 "\n\r", us_base->US_CSR); TRACE_DEBUG("R:0x%" PRIX32 "\n\r", us_base->US_CSR);
TRACE_DEBUG("Nb:0x%" PRIX32 "\n\r", us_base->US_NER ); TRACE_DEBUG("Nb:0x%" PRIX32 "\n\r", us_base->US_NER );
us_base->US_CR = US_CR_RSTSTA; us_base->US_CR = US_CR_RSTSTA;
} }
/* Return status */ /* Return status */
return( status ); return( status );
} }
@@ -125,50 +125,50 @@ uint32_t ISO7816_GetChar( uint8_t *pCharToReceive, Usart_info *usart)
*/ */
uint32_t ISO7816_SendChar( uint8_t CharToSend, Usart_info *usart ) uint32_t ISO7816_SendChar( uint8_t CharToSend, Usart_info *usart )
{ {
uint32_t status; uint32_t status;
Usart *us_base = usart->base; Usart *us_base = usart->base;
uint32_t us_id = usart->id; uint32_t us_id = usart->id;
if( usart->state == USART_RCV ) { if( usart->state == USART_RCV ) {
us_base->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; us_base->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
usart->state = USART_SEND; usart->state = USART_SEND;
} }
/* Wait USART ready for transmit */ /* Wait USART ready for transmit */
int i = 0; int i = 0;
while((us_base->US_CSR & (US_CSR_TXRDY)) == 0) { while((us_base->US_CSR & (US_CSR_TXRDY)) == 0) {
i++; i++;
if (!(i%1000000)) { if (!(i%1000000)) {
printf("s: %lx ", us_base->US_CSR); printf("s: %x ", us_base->US_CSR);
printf("s: %lx\r\n", us_base->US_RHR & 0xFF); printf("s: %x\r\n", us_base->US_RHR & 0xFF);
us_base->US_CR = US_CR_RSTTX; us_base->US_CR = US_CR_RSTTX;
us_base->US_CR = US_CR_RSTRX; us_base->US_CR = US_CR_RSTRX;
} }
} }
/* There is no character in the US_THR */ /* There is no character in the US_THR */
/* Transmit a char */ /* Transmit a char */
us_base->US_THR = CharToSend; us_base->US_THR = CharToSend;
TRACE_ERROR("Sx%02X\r\n", CharToSend); TRACE_ERROR("Sx%02X\r\n", CharToSend);
status = (us_base->US_CSR&(US_CSR_OVRE|US_CSR_FRAME| status = (us_base->US_CSR&(US_CSR_OVRE|US_CSR_FRAME|
US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK| US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK|
(1<<10))); (1<<10)));
if (status != 0 ) { if (status != 0 ) {
TRACE_INFO("******* status: 0x%" PRIX32 " (Overrun: %" PRIX32 TRACE_INFO("******* status: 0x%" PRIX32 " (Overrun: %" PRIX32
", NACK: %" PRIX32 ", Timeout: %" PRIX32 ", underrun: %" PRIX32 ")\n\r", ", NACK: %" PRIX32 ", Timeout: %" PRIX32 ", underrun: %" PRIX32 ")\n\r",
status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13), status, ((status & US_CSR_OVRE)>> 5), ((status & US_CSR_NACK) >> 13),
((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10)); ((status & US_CSR_TIMEOUT) >> 8), ((status & (1 << 10)) >> 10));
TRACE_INFO("E (USART CSR reg):0x%" PRIX32 "\n\r", us_base->US_CSR); TRACE_INFO("E (USART CSR reg):0x%" PRIX32 "\n\r", us_base->US_CSR);
TRACE_INFO("Nb (Number of errors):0x%" PRIX32 "\n\r", us_base->US_NER ); TRACE_INFO("Nb (Number of errors):0x%" PRIX32 "\n\r", us_base->US_NER );
us_base->US_CR = US_CR_RSTSTA; us_base->US_CR = US_CR_RSTSTA;
} }
/* Return status */ /* Return status */
return( status ); return( status );
} }
@@ -177,10 +177,10 @@ uint32_t ISO7816_SendChar( uint8_t CharToSend, Usart_info *usart )
*/ */
static void ISO7816_IccPowerOn( void ) static void ISO7816_IccPowerOn( void )
{ {
/* Set RESET Master Card */ /* Set RESET Master Card */
if (st_pinIso7816RstMC) { if (st_pinIso7816RstMC) {
PIO_Set(st_pinIso7816RstMC); PIO_Set(st_pinIso7816RstMC);
} }
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
@@ -192,10 +192,10 @@ static void ISO7816_IccPowerOn( void )
*/ */
void ISO7816_IccPowerOff( void ) void ISO7816_IccPowerOff( void )
{ {
/* Clear RESET Master Card */ /* Clear RESET Master Card */
if (st_pinIso7816RstMC) { if (st_pinIso7816RstMC) {
PIO_Clear(st_pinIso7816RstMC); PIO_Clear(st_pinIso7816RstMC);
} }
} }
/** /**
@@ -207,159 +207,159 @@ void ISO7816_IccPowerOff( void )
* \return 0 on success, content of US_CSR otherwise * \return 0 on success, content of US_CSR otherwise
*/ */
uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU, uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
uint8_t *pMessage, uint8_t *pMessage,
uint16_t wLength, uint16_t wLength,
uint16_t *retlen ) uint16_t *retlen )
{ {
uint16_t NeNc; uint16_t NeNc;
uint16_t indexApdu = 4; uint16_t indexApdu = 4;
uint16_t indexMsg = 0; uint16_t indexMsg = 0;
uint8_t SW1 = 0; uint8_t SW1 = 0;
uint8_t procByte; uint8_t procByte;
uint8_t cmdCase; uint8_t cmdCase;
uint32_t status = 0; uint32_t status = 0;
TRACE_INFO("pAPDU[0]=0x%X\n\r",pAPDU[0]); TRACE_INFO("pAPDU[0]=0x%X\n\r",pAPDU[0]);
TRACE_INFO("pAPDU[1]=0x%X\n\r",pAPDU[1]); TRACE_INFO("pAPDU[1]=0x%X\n\r",pAPDU[1]);
TRACE_INFO("pAPDU[2]=0x%X\n\r",pAPDU[2]); TRACE_INFO("pAPDU[2]=0x%X\n\r",pAPDU[2]);
TRACE_INFO("pAPDU[3]=0x%X\n\r",pAPDU[3]); TRACE_INFO("pAPDU[3]=0x%X\n\r",pAPDU[3]);
TRACE_INFO("pAPDU[4]=0x%X\n\r",pAPDU[4]); TRACE_INFO("pAPDU[4]=0x%X\n\r",pAPDU[4]);
TRACE_INFO("pAPDU[5]=0x%X\n\r",pAPDU[5]); TRACE_INFO("pAPDU[5]=0x%X\n\r",pAPDU[5]);
TRACE_INFO("wlength=%d\n\r",wLength); TRACE_INFO("wlength=%d\n\r",wLength);
ISO7816_SendChar( pAPDU[0], &usart_sim ); /* CLA */ ISO7816_SendChar( pAPDU[0], &usart_sim ); /* CLA */
ISO7816_SendChar( pAPDU[1], &usart_sim ); /* INS */ ISO7816_SendChar( pAPDU[1], &usart_sim ); /* INS */
ISO7816_SendChar( pAPDU[2], &usart_sim ); /* P1 */ ISO7816_SendChar( pAPDU[2], &usart_sim ); /* P1 */
ISO7816_SendChar( pAPDU[3], &usart_sim ); /* P2 */ ISO7816_SendChar( pAPDU[3], &usart_sim ); /* P2 */
ISO7816_SendChar( pAPDU[4], &usart_sim ); /* P3 */ ISO7816_SendChar( pAPDU[4], &usart_sim ); /* P3 */
/* Handle the four structures of command APDU */ /* Handle the four structures of command APDU */
indexApdu = 5; indexApdu = 5;
if( wLength == 4 ) { if( wLength == 4 ) {
cmdCase = CASE1; cmdCase = CASE1;
NeNc = 0; NeNc = 0;
} }
else if( wLength == 5) { else if( wLength == 5) {
cmdCase = CASE2; cmdCase = CASE2;
NeNc = pAPDU[4]; /* C5 */ NeNc = pAPDU[4]; /* C5 */
if (NeNc == 0) { if (NeNc == 0) {
NeNc = 256; NeNc = 256;
} }
} }
else if( wLength == 6) { else if( wLength == 6) {
NeNc = pAPDU[4]; /* C5 */ NeNc = pAPDU[4]; /* C5 */
cmdCase = CASE3; cmdCase = CASE3;
} }
else if( wLength == 7) { else if( wLength == 7) {
NeNc = pAPDU[4]; /* C5 */ NeNc = pAPDU[4]; /* C5 */
if( NeNc == 0 ) { if( NeNc == 0 ) {
cmdCase = CASE2; cmdCase = CASE2;
NeNc = (pAPDU[5]<<8)+pAPDU[6]; NeNc = (pAPDU[5]<<8)+pAPDU[6];
} }
else { else {
cmdCase = CASE3; cmdCase = CASE3;
} }
} }
else { else {
NeNc = pAPDU[4]; /* C5 */ NeNc = pAPDU[4]; /* C5 */
if( NeNc == 0 ) { if( NeNc == 0 ) {
cmdCase = CASE3; cmdCase = CASE3;
NeNc = (pAPDU[5]<<8)+pAPDU[6]; NeNc = (pAPDU[5]<<8)+pAPDU[6];
} }
else { else {
cmdCase = CASE3; cmdCase = CASE3;
} }
} }
TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc); TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc);
/* Handle Procedure Bytes */ /* Handle Procedure Bytes */
do { do {
status = ISO7816_GetChar(&procByte, &usart_sim); status = ISO7816_GetChar(&procByte, &usart_sim);
if (status != 0) { if (status != 0) {
return status; return status;
} }
TRACE_INFO("procByte: 0x%X\n\r", procByte); TRACE_INFO("procByte: 0x%X\n\r", procByte);
/* Handle NULL */ /* Handle NULL */
if ( procByte == ISO_NULL_VAL ) { if ( procByte == ISO_NULL_VAL ) {
TRACE_INFO("INS\n\r"); TRACE_INFO("INS\n\r");
continue; continue;
} }
/* Handle SW1 */ /* Handle SW1 */
else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) { else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) {
TRACE_INFO("SW1\n\r"); TRACE_INFO("SW1\n\r");
SW1 = 1; SW1 = 1;
} }
/* Handle INS */ /* Handle INS */
else if ( pAPDU[1] == procByte) { else if ( pAPDU[1] == procByte) {
TRACE_INFO("HdlINS\n\r"); TRACE_INFO("HdlINS\n\r");
if (cmdCase == CASE2) { if (cmdCase == CASE2) {
/* receive data from card */ /* receive data from card */
do { do {
status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim);
} while(( 0 != --NeNc) && (status == 0) ); } while(( 0 != --NeNc) && (status == 0) );
if (status != 0) { if (status != 0) {
return status; return status;
} }
} }
else { else {
/* Send data */ /* Send data */
do { do {
TRACE_INFO("Send %X", pAPDU[indexApdu]); TRACE_INFO("Send %X", pAPDU[indexApdu]);
ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim); ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim);
} while( 0 != --NeNc ); } while( 0 != --NeNc );
} }
} }
/* Handle INS ^ 0xff */ /* Handle INS ^ 0xff */
else else
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wsign-compare"
if ( pAPDU[1] == (procByte ^ 0xff)) { if ( pAPDU[1] == (procByte ^ 0xff)) {
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
TRACE_INFO("HdlINS+\n\r"); TRACE_INFO("HdlINS+\n\r");
if (cmdCase == CASE2) { if (cmdCase == CASE2) {
/* receive data from card */ /* receive data from card */
status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim);
if (status != 0) { if (status != 0) {
return status; return status;
} }
TRACE_INFO("Rcv: 0x%X\n\r", pMessage[indexMsg-1]); TRACE_INFO("Rcv: 0x%X\n\r", pMessage[indexMsg-1]);
} }
else { else {
status = ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim); status = ISO7816_SendChar(pAPDU[indexApdu++], &usart_sim);
if (status != 0) { if (status != 0) {
return status; return status;
} }
} }
NeNc--; NeNc--;
} }
else { else {
/* ?? */ /* ?? */
TRACE_INFO("procByte=0x%X\n\r", procByte); TRACE_INFO("procByte=0x%X\n\r", procByte);
break; break;
} }
} while (NeNc != 0); } while (NeNc != 0);
/* Status Bytes */ /* Status Bytes */
if (SW1 == 0) { if (SW1 == 0) {
status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW1 */ status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW1 */
if (status != 0) { if (status != 0) {
return status; return status;
} }
} }
else { else {
pMessage[indexMsg++] = procByte; pMessage[indexMsg++] = procByte;
} }
status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW2 */ status = ISO7816_GetChar(&pMessage[indexMsg++], &usart_sim); /* SW2 */
if (status != 0) { if (status != 0) {
return status; return status;
} }
TRACE_WARNING("SW1=0x%X, SW2=0x%X\n\r", pMessage[indexMsg-2], pMessage[indexMsg-1]); TRACE_WARNING("SW1=0x%X, SW2=0x%X\n\r", pMessage[indexMsg-2], pMessage[indexMsg-1]);
*retlen = indexMsg; *retlen = indexMsg;
return status; return status;
} }
@@ -368,7 +368,7 @@ uint32_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU,
*/ */
void ISO7816_Escape( void ) void ISO7816_Escape( void )
{ {
TRACE_DEBUG("For user, if needed\n\r"); TRACE_DEBUG("For user, if needed\n\r");
} }
/** /**
@@ -376,8 +376,8 @@ void ISO7816_Escape( void )
*/ */
void ISO7816_RestartClock( void ) void ISO7816_RestartClock( void )
{ {
TRACE_DEBUG("ISO7816_RestartClock\n\r"); TRACE_DEBUG("ISO7816_RestartClock\n\r");
USART_SIM->US_BRGR = 13; USART_SIM->US_BRGR = 13;
} }
/** /**
@@ -385,8 +385,8 @@ void ISO7816_RestartClock( void )
*/ */
void ISO7816_StopClock( void ) void ISO7816_StopClock( void )
{ {
TRACE_DEBUG("ISO7816_StopClock\n\r"); TRACE_DEBUG("ISO7816_StopClock\n\r");
USART_SIM->US_BRGR = 0; USART_SIM->US_BRGR = 0;
} }
/** /**
@@ -394,8 +394,8 @@ void ISO7816_StopClock( void )
*/ */
void ISO7816_toAPDU( void ) void ISO7816_toAPDU( void )
{ {
TRACE_DEBUG("ISO7816_toAPDU\n\r"); TRACE_DEBUG("ISO7816_toAPDU\n\r");
TRACE_DEBUG("Not supported at this time\n\r"); TRACE_DEBUG("Not supported at this time\n\r");
} }
/** /**
@@ -406,64 +406,64 @@ void ISO7816_toAPDU( void )
*/ */
uint32_t ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength ) uint32_t ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
{ {
uint32_t i; uint32_t i;
uint32_t j; uint32_t j;
uint32_t y; uint32_t y;
uint32_t status = 0; uint32_t status = 0;
*pLength = 0; *pLength = 0;
/* Read ATR TS */ /* Read ATR TS */
// FIXME: There should always be a check for the GetChar return value..0 means timeout // FIXME: There should always be a check for the GetChar return value..0 means timeout
status = ISO7816_GetChar(&pAtr[0], &usart_sim); status = ISO7816_GetChar(&pAtr[0], &usart_sim);
if (status != 0) { if (status != 0) {
return status; return status;
} }
/* Read ATR T0 */ /* Read ATR T0 */
status = ISO7816_GetChar(&pAtr[1], &usart_sim); status = ISO7816_GetChar(&pAtr[1], &usart_sim);
if (status != 0) { if (status != 0) {
return status; return status;
} }
y = pAtr[1] & 0xF0; y = pAtr[1] & 0xF0;
i = 2; i = 2;
/* Read ATR Ti */ /* Read ATR Ti */
while (y && (status == 0)) { while (y && (status == 0)) {
if (y & 0x10) { /* TA[i] */ if (y & 0x10) { /* TA[i] */
status = ISO7816_GetChar(&pAtr[i++], &usart_sim); status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
} }
if (y & 0x20) { /* TB[i] */ if (y & 0x20) { /* TB[i] */
status = ISO7816_GetChar(&pAtr[i++], &usart_sim); status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
} }
if (y & 0x40) { /* TC[i] */ if (y & 0x40) { /* TC[i] */
status = ISO7816_GetChar(&pAtr[i++], &usart_sim); status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
} }
if (y & 0x80) { /* TD[i] */ if (y & 0x80) { /* TD[i] */
status = ISO7816_GetChar(&pAtr[i], &usart_sim); status = ISO7816_GetChar(&pAtr[i], &usart_sim);
y = pAtr[i++] & 0xF0; y = pAtr[i++] & 0xF0;
} }
else { else {
y = 0; y = 0;
} }
} }
if (status != 0) { if (status != 0) {
return status; return status;
} }
/* Historical Bytes */ /* Historical Bytes */
y = pAtr[1] & 0x0F; y = pAtr[1] & 0x0F;
for( j=0; (j < y) && (status == 0); j++ ) { for( j=0; (j < y) && (status == 0); j++ ) {
status = ISO7816_GetChar(&pAtr[i++], &usart_sim); status = ISO7816_GetChar(&pAtr[i++], &usart_sim);
} }
if (status != 0) { if (status != 0) {
return status; return status;
} }
*pLength = i; *pLength = i;
return status; return status;
} }
/** /**
@@ -473,18 +473,18 @@ uint32_t ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength )
*/ */
void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate ) void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate )
{ {
uint8_t ClockFrequency; uint8_t ClockFrequency;
/* Define the baud rate divisor register */ /* Define the baud rate divisor register */
/* CD = MCK / SCK */ /* CD = MCK / SCK */
/* SCK = FIDI x BAUD = 372 x 9600 */ /* SCK = FIDI x BAUD = 372 x 9600 */
/* BOARD_MCK */ /* BOARD_MCK */
/* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */ /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
USART_SIM->US_BRGR = BOARD_MCK / (dwClockFrequency*1000); USART_SIM->US_BRGR = BOARD_MCK / (dwClockFrequency*1000);
ClockFrequency = BOARD_MCK / USART_SIM->US_BRGR; ClockFrequency = BOARD_MCK / USART_SIM->US_BRGR;
USART_SIM->US_FIDI = (ClockFrequency)/dwDataRate; USART_SIM->US_FIDI = (ClockFrequency)/dwDataRate;
} }
@@ -494,10 +494,10 @@ void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t d
*/ */
uint8_t ISO7816_StatusReset( void ) uint8_t ISO7816_StatusReset( void )
{ {
if (st_pinIso7816RstMC) { if (st_pinIso7816RstMC) {
return PIO_Get(st_pinIso7816RstMC); return PIO_Get(st_pinIso7816RstMC);
} }
return 0; return 0;
} }
/** /**
@@ -505,16 +505,16 @@ uint8_t ISO7816_StatusReset( void )
*/ */
void ISO7816_cold_reset( void ) void ISO7816_cold_reset( void )
{ {
volatile uint32_t i; volatile uint32_t i;
/* tb: wait ??? cycles*/ /* tb: wait ??? cycles*/
for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) { for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) {
} }
USART_SIM->US_RHR; USART_SIM->US_RHR;
USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
ISO7816_IccPowerOn(); ISO7816_IccPowerOn();
} }
/** /**
@@ -522,20 +522,20 @@ void ISO7816_cold_reset( void )
*/ */
void ISO7816_warm_reset( void ) void ISO7816_warm_reset( void )
{ {
volatile uint32_t i; volatile uint32_t i;
// Clears Reset // Clears Reset
ISO7816_IccPowerOff(); ISO7816_IccPowerOff();
/* tb: wait ??? cycles */ /* tb: wait ??? cycles */
for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) { for( i=0; i<(400*(BOARD_MCK/1000000)); i++ ) {
} }
USART_SIM->US_RHR; USART_SIM->US_RHR;
USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; USART_SIM->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
// Sets Reset // Sets Reset
ISO7816_IccPowerOn(); ISO7816_IccPowerOn();
} }
/** /**
@@ -544,99 +544,99 @@ void ISO7816_warm_reset( void )
*/ */
void ISO7816_Decode_ATR( uint8_t* pAtr ) void ISO7816_Decode_ATR( uint8_t* pAtr )
{ {
uint32_t i; uint32_t i;
uint32_t j; uint32_t j;
uint32_t y; uint32_t y;
uint8_t offset; uint8_t offset;
printf("\n\r"); printf("\n\r");
printf("ATR: Answer To Reset:\n\r"); printf("ATR: Answer To Reset:\n\r");
printf("TS = 0x%X Initial character ",pAtr[0]); printf("TS = 0x%X Initial character ",pAtr[0]);
if( pAtr[0] == 0x3B ) { if( pAtr[0] == 0x3B ) {
printf("Direct Convention\n\r"); printf("Direct Convention\n\r");
} }
else { else {
if( pAtr[0] == 0x3F ) { if( pAtr[0] == 0x3F ) {
printf("Inverse Convention\n\r"); printf("Inverse Convention\n\r");
} }
else { else {
printf("BAD Convention\n\r"); printf("BAD Convention\n\r");
} }
} }
printf("T0 = 0x%X Format caracter\n\r",pAtr[1]); printf("T0 = 0x%X Format caracter\n\r",pAtr[1]);
printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F); printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F);
printf(" Presence further interface byte:\n\r"); printf(" Presence further interface byte:\n\r");
if( pAtr[1]&0x80 ) { if( pAtr[1]&0x80 ) {
printf("TA "); printf("TA ");
} }
if( pAtr[1]&0x40 ) { if( pAtr[1]&0x40 ) {
printf("TB "); printf("TB ");
} }
if( pAtr[1]&0x20 ) { if( pAtr[1]&0x20 ) {
printf("TC "); printf("TC ");
} }
if( pAtr[1]&0x10 ) { if( pAtr[1]&0x10 ) {
printf("TD "); printf("TD ");
} }
if( pAtr[1] != 0 ) { if( pAtr[1] != 0 ) {
printf(" present\n\r"); printf(" present\n\r");
} }
i = 2; i = 2;
y = pAtr[1] & 0xF0; y = pAtr[1] & 0xF0;
/* Read ATR Ti */ /* Read ATR Ti */
offset = 1; offset = 1;
while (y) { while (y) {
if (y & 0x10) { /* TA[i] */ if (y & 0x10) { /* TA[i] */
printf("TA[%d] = 0x%X ", offset, pAtr[i]); printf("TA[%d] = 0x%X ", offset, pAtr[i]);
if( offset == 1 ) { if( offset == 1 ) {
printf("FI = %d ", (pAtr[i]>>8)); printf("FI = %d ", (pAtr[i]>>8));
printf("DI = %d", (pAtr[i]&0x0F)); printf("DI = %d", (pAtr[i]&0x0F));
} }
printf("\n\r"); printf("\n\r");
i++; i++;
} }
if (y & 0x20) { /* TB[i] */ if (y & 0x20) { /* TB[i] */
printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]); printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]);
i++; i++;
} }
if (y & 0x40) { /* TC[i] */ if (y & 0x40) { /* TC[i] */
printf("TC[%d] = 0x%X ", offset, pAtr[i]); printf("TC[%d] = 0x%X ", offset, pAtr[i]);
if( offset == 1 ) { if( offset == 1 ) {
printf("Extra Guard Time: N = %d", pAtr[i]); printf("Extra Guard Time: N = %d", pAtr[i]);
} }
printf("\n\r"); printf("\n\r");
i++; i++;
} }
if (y & 0x80) { /* TD[i] */ if (y & 0x80) { /* TD[i] */
printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]); printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]);
y = pAtr[i++] & 0xF0; y = pAtr[i++] & 0xF0;
} }
else { else {
y = 0; y = 0;
} }
offset++; offset++;
} }
/* Historical Bytes */ /* Historical Bytes */
printf("Historical bytes:\n\r"); printf("Historical bytes:\n\r");
y = pAtr[1] & 0x0F; y = pAtr[1] & 0x0F;
for( j=0; j < y; j++ ) { for( j=0; j < y; j++ ) {
printf(" 0x%X", pAtr[i]); printf(" 0x%X", pAtr[i]);
i++; i++;
} }
printf("\n\r\n\r"); printf("\n\r\n\r");
} }
void ISO7816_Set_Reset_Pin(const Pin *pPinIso7816RstMC) { void ISO7816_Set_Reset_Pin(const Pin *pPinIso7816RstMC) {
/* Pin ISO7816 initialize */ /* Pin ISO7816 initialize */
st_pinIso7816RstMC = (Pin *)pPinIso7816RstMC; st_pinIso7816RstMC = (Pin *)pPinIso7816RstMC;
} }
/** Initializes a ISO driver /** Initializes a ISO driver
@@ -644,46 +644,46 @@ void ISO7816_Set_Reset_Pin(const Pin *pPinIso7816RstMC) {
*/ */
void ISO7816_Init( Usart_info *usart, bool master_clock ) void ISO7816_Init( Usart_info *usart, bool master_clock )
{ {
uint32_t clk; uint32_t clk;
TRACE_DEBUG("ISO_Init\n\r"); TRACE_DEBUG("ISO_Init\n\r");
Usart *us_base = usart->base; Usart *us_base = usart->base;
uint32_t us_id = usart->id; uint32_t us_id = usart->id;
if (master_clock == true) { if (master_clock == true) {
clk = US_MR_USCLKS_MCK; clk = US_MR_USCLKS_MCK;
} else { } else {
clk = US_MR_USCLKS_SCK; clk = US_MR_USCLKS_SCK;
} }
USART_Configure( us_base, USART_Configure( us_base,
US_MR_USART_MODE_IS07816_T_0 US_MR_USART_MODE_IS07816_T_0
| clk | clk
| US_MR_NBSTOP_1_BIT | US_MR_NBSTOP_1_BIT
| US_MR_PAR_EVEN | US_MR_PAR_EVEN
| US_MR_CHRL_8_BIT | US_MR_CHRL_8_BIT
| US_MR_CLKO | US_MR_CLKO
| US_MR_INACK /* Inhibit errors */ | US_MR_INACK /* Inhibit errors */
| (3<<24), /* MAX_ITERATION */ | (3<<24), /* MAX_ITERATION */
1, 1,
0); 0);
/* Disable interrupts */ /* Disable interrupts */
us_base->US_IDR = (uint32_t) -1; us_base->US_IDR = (uint32_t) -1;
/* Configure USART */ /* Configure USART */
PMC_EnablePeripheral(us_id); PMC_EnablePeripheral(us_id);
us_base->US_FIDI = 372; /* by default */ us_base->US_FIDI = 372; /* by default */
/* Define the baud rate divisor register */ /* Define the baud rate divisor register */
/* CD = MCK / SCK */ /* CD = MCK / SCK */
/* SCK = FIDI x BAUD = 372 x 9600 */ /* SCK = FIDI x BAUD = 372 x 9600 */
/* BOARD_MCK */ /* BOARD_MCK */
/* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */ /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */
if (master_clock == true) { if (master_clock == true) {
us_base->US_BRGR = BOARD_MCK / (372*9600); us_base->US_BRGR = BOARD_MCK / (372*9600);
} else { } else {
us_base->US_BRGR = US_BRGR_CD(1); us_base->US_BRGR = US_BRGR_CD(1);
} }
} }

View File

@@ -1,21 +1,22 @@
/* ISO7816-3 Fi/Di tables + computation /* ISO7816-3 Fi/Di tables + computation */
/* (C) 2010-2015 by Harald Welte <hwelte@hmw-consulting.de>
* *
* (C) 2010-2015 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 free software; you can redistribute it and/or modify * This program is distributed in the hope that it will be useful,
* it under the terms of the GNU General Public License as published by * but WITHOUT ANY WARRANTY; without even the implied warranty of
* the Free Software Foundation; either version 2 of the License, or * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* (at your option) any later version. * GNU General Public License for more details.
* *
* This program is distributed in the hope that it will be useful, * You should have received a copy of the GNU General Public License
* but WITHOUT ANY WARRANTY; without even the implied warranty of * along with this program; if not, write to the Free Software
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* 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 <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>

View File

@@ -1,22 +1,5 @@
/* card emulation mode //#define TRACE_LEVEL 6
*
* (C) 2015-2017 by Harald Welte <laforge@gnumonks.org>
* (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
* 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 "board.h"
#include "boardver_adc.h" #include "boardver_adc.h"
#include "simtrace.h" #include "simtrace.h"
@@ -44,13 +27,13 @@ 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 CARDEMU_SECOND_UART #ifdef CARDEMU_SECOND_UART
static const Pin pins_usim2[] = {PINS_USIM2}; static const Pin pins_usim2[] = {PINS_USIM2};
static const Pin pin_usim2_rst = PIN_USIM2_nRST; static const Pin pin_usim2_rst = PIN_USIM2_nRST;
static const Pin pin_usim2_vcc = PIN_USIM2_VCC; static const Pin pin_usim2_vcc = PIN_USIM2_VCC;
#endif #endif
struct cardem_inst { struct cardem_inst {
unsigned int num; uint32_t num;
struct card_handle *ch; struct card_handle *ch;
struct llist_head usb_out_queue; struct llist_head usb_out_queue;
struct ringbuf rb; struct ringbuf rb;
@@ -99,11 +82,15 @@ struct cardem_inst cardem_inst[] = {
static Usart *get_usart_by_chan(uint8_t uart_chan) static Usart *get_usart_by_chan(uint8_t uart_chan)
{ {
if (uart_chan < ARRAY_SIZE(cardem_inst)) { switch (uart_chan) {
return cardem_inst[uart_chan].usart_info.base; case 0:
} else { return USART1;
return NULL; #ifdef CARDEMU_SECOND_UART
case 1:
return USART0;
#endif
} }
return NULL;
} }
/*********************************************************************** /***********************************************************************
@@ -117,7 +104,7 @@ static void wait_tx_idle(Usart *usart)
/* wait until last char has been fully transmitted */ /* wait until last char has been fully transmitted */
while ((usart->US_CSR & (US_CSR_TXEMPTY)) == 0) { while ((usart->US_CSR & (US_CSR_TXEMPTY)) == 0) {
if (!(i%1000000)) { if (!(i%1000000)) {
TRACE_ERROR("s: %lx \r\n", usart->US_CSR); TRACE_ERROR("s: %x \r\n", usart->US_CSR);
} }
i++; i++;
} }
@@ -174,7 +161,7 @@ int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
int i = 1; int i = 1;
while ((usart->US_CSR & (US_CSR_TXRDY)) == 0) { while ((usart->US_CSR & (US_CSR_TXRDY)) == 0) {
if (!(i%1000000)) { if (!(i%1000000)) {
TRACE_ERROR("%u: s: %lx %02lX\r\n", TRACE_ERROR("%u: s: %x %02X\r\n",
uart_chan, usart->US_CSR, uart_chan, usart->US_CSR,
usart->US_RHR & 0xFF); usart->US_RHR & 0xFF);
usart->US_CR = US_CR_RSTTX; usart->US_CR = US_CR_RSTTX;
@@ -200,9 +187,8 @@ static void usart_irq_rx(uint8_t inst_num)
csr = usart->US_CSR & usart->US_IMR; csr = usart->US_CSR & usart->US_IMR;
if (csr & US_CSR_RXRDY) { if (csr & US_CSR_RXRDY) {
byte = (usart->US_RHR) & 0xFF; byte = (usart->US_RHR) & 0xFF;
if (rbuf_write(&ci->rb, byte) < 0) rbuf_write(&ci->rb, byte);
TRACE_ERROR("rbuf overrun\r\n");
} }
if (csr & US_CSR_TXRDY) { if (csr & US_CSR_TXRDY) {
@@ -213,7 +199,7 @@ static void usart_irq_rx(uint8_t inst_num)
if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE| if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|
US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) { US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) {
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
TRACE_ERROR("%u e 0x%x st: 0x%lx\n", ci->num, byte, csr); TRACE_ERROR("%u e 0x%x st: 0x%x\n", ci->num, byte, csr);
} }
} }
@@ -241,20 +227,6 @@ int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
return 0; return 0;
} }
/* call-back from card_emu.c to force a USART interrupt */
void card_emu_uart_interrupt(uint8_t uart_chan)
{
Usart *usart = get_usart_by_chan(uart_chan);
if (!usart) {
return;
}
if (USART0 == usart) {
NVIC_SetPendingIRQ(USART0_IRQn);
} else if (USART1 == usart) {
NVIC_SetPendingIRQ(USART1_IRQn);
}
}
/*********************************************************************** /***********************************************************************
* ADC for VCC voltage detection * ADC for VCC voltage detection
***********************************************************************/ ***********************************************************************/
@@ -309,7 +281,7 @@ static int card_vcc_adc_init(void)
} }
#define VCC_UV_THRESH_1V8 1500000 #define VCC_UV_THRESH_1V8 1500000
#define VCC_UV_THRESH_3V 2500000 #define VCC_UV_THRESH_3V 2800000
static void process_vcc_adc(struct cardem_inst *ci) static void process_vcc_adc(struct cardem_inst *ci)
{ {
@@ -352,19 +324,19 @@ void ADC_IrqHandler(void)
#endif /* DETECT_VCC_BY_ADC */ #endif /* DETECT_VCC_BY_ADC */
/*********************************************************************** /***********************************************************************
* Core USB / main loop integration * Core USB / mainloop integration
***********************************************************************/ ***********************************************************************/
static void usim1_rst_irqhandler(const Pin *pPin) static void usim1_rst_irqhandler(const Pin *pPin)
{ {
bool active = PIO_Get(&pin_usim1_rst) ? false : true; int active = PIO_Get(&pin_usim1_rst) ? 0 : 1;
card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_RST, active); card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_RST, active);
} }
#ifndef DETECT_VCC_BY_ADC #ifndef DETECT_VCC_BY_ADC
static void usim1_vcc_irqhandler(const Pin *pPin) static void usim1_vcc_irqhandler(const Pin *pPin)
{ {
bool active = PIO_Get(&pin_usim1_vcc) ? true : false; int active = PIO_Get(&pin_usim1_vcc) ? 1 : 0;
card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_VCC, active); card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_VCC, active);
/* FIXME do this for real */ /* FIXME do this for real */
card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_CLK, active); card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_CLK, active);
@@ -374,14 +346,14 @@ static void usim1_vcc_irqhandler(const Pin *pPin)
#ifdef CARDEMU_SECOND_UART #ifdef CARDEMU_SECOND_UART
static void usim2_rst_irqhandler(const Pin *pPin) static void usim2_rst_irqhandler(const Pin *pPin)
{ {
bool active = PIO_Get(&pin_usim2_rst) ? false : true; int active = PIO_Get(&pin_usim2_rst) ? 0 : 1;
card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_RST, active); card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_RST, active);
} }
#ifndef DETECT_VCC_BY_ADC #ifndef DETECT_VCC_BY_ADC
static void usim2_vcc_irqhandler(const Pin *pPin) static void usim2_vcc_irqhandler(const Pin *pPin)
{ {
bool active = PIO_Get(&pin_usim2_vcc) ? true : false; int active = PIO_Get(&pin_usim2_vcc) ? 1 : 0;
card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_VCC, active); card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_VCC, active);
/* FIXME do this for real */ /* FIXME do this for real */
card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_CLK, active); card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_CLK, active);
@@ -420,7 +392,7 @@ void mode_cardemu_init(void)
PIO_ConfigureIt(&pin_usim1_vcc, usim1_vcc_irqhandler); PIO_ConfigureIt(&pin_usim1_vcc, usim1_vcc_irqhandler);
PIO_EnableIt(&pin_usim1_vcc); PIO_EnableIt(&pin_usim1_vcc);
#endif /* DETECT_VCC_BY_ADC */ #endif /* DETECT_VCC_BY_ADC */
cardem_inst[0].ch = card_emu_init(0, 2, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN, SIMTRACE_CARDEM_USB_EP_USIM1_INT, PIO_Get(&pin_usim1_vcc) ? true : false, PIO_Get(&pin_usim1_rst) ? false : true, PIO_Get(&pin_usim1_vcc) ? true : false); cardem_inst[0].ch = card_emu_init(0, 2, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN, SIMTRACE_CARDEM_USB_EP_USIM1_INT);
sim_switch_use_physical(0, 1); sim_switch_use_physical(0, 1);
#ifdef CARDEMU_SECOND_UART #ifdef CARDEMU_SECOND_UART
@@ -435,9 +407,10 @@ void mode_cardemu_init(void)
PIO_ConfigureIt(&pin_usim2_vcc, usim2_vcc_irqhandler); PIO_ConfigureIt(&pin_usim2_vcc, usim2_vcc_irqhandler);
PIO_EnableIt(&pin_usim2_vcc); PIO_EnableIt(&pin_usim2_vcc);
#endif /* DETECT_VCC_BY_ADC */ #endif /* DETECT_VCC_BY_ADC */
cardem_inst[1].ch = card_emu_init(1, 0, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN, SIMTRACE_CARDEM_USB_EP_USIM2_INT, PIO_Get(&pin_usim2_vcc) ? true : false, PIO_Get(&pin_usim2_rst) ? false : true, PIO_Get(&pin_usim2_vcc) ? true : false); cardem_inst[1].ch = card_emu_init(1, 0, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN, SIMTRACE_CARDEM_USB_EP_USIM2_INT);
sim_switch_use_physical(1, 1); sim_switch_use_physical(1, 1);
#endif /* CARDEMU_SECOND_UART */ #endif /* CARDEMU_SECOND_UART */
} }
/* called if config is deactivated */ /* called if config is deactivated */
@@ -603,7 +576,6 @@ static void dispatch_usb_command(struct msgb *msg, struct cardem_inst *ci)
usb_buf_free(msg); usb_buf_free(msg);
return; return;
} }
msg->l2h = msg->l1h + sizeof(*sh);
switch (sh->msg_class) { switch (sh->msg_class) {
case SIMTRACE_MSGC_GENERIC: case SIMTRACE_MSGC_GENERIC:
@@ -615,6 +587,7 @@ static void dispatch_usb_command(struct msgb *msg, struct cardem_inst *ci)
case SIMTRACE_MSGC_MODEM: case SIMTRACE_MSGC_MODEM:
/* FIXME: Find out why this fails if used for != /* FIXME: Find out why this fails if used for !=
* MSGC_MODEM ?!? */ * MSGC_MODEM ?!? */
msg->l2h = msg->l1h + sizeof(*sh);
dispatch_usb_command_modem(msg, ci); dispatch_usb_command_modem(msg, ci);
break; break;
default: default:

View File

@@ -84,11 +84,11 @@ static const Pin pinSmartCard = SMARTCARD_CONNECT_PIN;
static void ISR_PioSmartCard(const Pin * pPin) static void ISR_PioSmartCard(const Pin * pPin)
{ {
/* FIXME: why is pinSmartCard.pio->PIO_ISR the wrong number? /* FIXME: why is pinSmartCard.pio->PIO_ISR the wrong number?
printf("+++++ Trying to check for pending interrupts (PIO ISR: 0x%X)\n\r", pinSmartCard.pio->PIO_ISR); printf("+++++ Trying to check for pending interrupts (PIO ISR: 0x%X)\n\r", pinSmartCard.pio->PIO_ISR);
printf("+++++ Mask: 0x%X\n\r", pinSmartCard.mask); printf("+++++ Mask: 0x%X\n\r", pinSmartCard.mask);
Output: Output:
+++++ Trying to check for pending interrupts (PIO ISR: 0x400)) = 1<<10 +++++ Trying to check for pending interrupts (PIO ISR: 0x400)) = 1<<10
+++++ Mask: 0x100 = 1<<8 +++++ Mask: 0x100 = 1<<8
*/ */
// PA10 is DTXD, which is the debug uart transmit pin // PA10 is DTXD, which is the debug uart transmit pin

View File

@@ -1,19 +1,3 @@
/* Memory allocation library
*
* 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 <stdint.h> #include <stdint.h>
#include "talloc.h" #include "talloc.h"
@@ -62,7 +46,7 @@ int _talloc_free(void *ptr, const char *location)
for (i = 0; i < ARRAY_SIZE(msgb_inuse); i++) { for (i = 0; i < ARRAY_SIZE(msgb_inuse); i++) {
if (ptr == msgb_data[i]) { if (ptr == msgb_data[i]) {
if (!msgb_inuse[i]) { if (!msgb_inuse[i]) {
TRACE_ERROR("%s: double_free by %s\r\n", __func__, location); TRACE_ERROR("%s: double_free by \r\n", __func__, location);
} else { } else {
msgb_inuse[i] = 0; msgb_inuse[i] = 0;
} }

View File

@@ -1,27 +1,7 @@
/* Ring buffer
*
* 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 "ringbuffer.h" #include "ringbuffer.h"
#include "trace.h" #include "trace.h"
#include "utils.h" #include "utils.h"
/* WARNING: Since console output is internally using this ringbuffer to implement
* buffered writes, we cannot use any TRACE_*() or printf() style functions here,
* as it would create infinite recursion! */
void rbuf_reset(volatile ringbuf * rb) void rbuf_reset(volatile ringbuf * rb)
{ {
unsigned long state; unsigned long state;
@@ -72,7 +52,7 @@ bool rbuf_is_full(volatile ringbuf * rb)
return rc; return rc;
} }
int rbuf_write(volatile ringbuf * rb, uint8_t item) void rbuf_write(volatile ringbuf * rb, uint8_t item)
{ {
unsigned long state; unsigned long state;
@@ -81,10 +61,9 @@ int rbuf_write(volatile ringbuf * rb, uint8_t item)
rb->buf[rb->iwr] = item; rb->buf[rb->iwr] = item;
rb->iwr = (rb->iwr + 1) % RING_BUFLEN; rb->iwr = (rb->iwr + 1) % RING_BUFLEN;
local_irq_restore(state); local_irq_restore(state);
return 0;
} else { } else {
local_irq_restore(state); local_irq_restore(state);
return -1; TRACE_ERROR("Ringbuffer full, losing bytes!");
} }
} }

View File

@@ -58,7 +58,7 @@ void ISR_PhoneRST(const Pin * pPin)
{ {
int ret; int ret;
// FIXME: no printfs in ISRs? // FIXME: no printfs in ISRs?
printf("+++ Int!! %lx\n\r", pinPhoneRST.pio->PIO_ISR); printf("+++ Int!! %x\n\r", pinPhoneRST.pio->PIO_ISR);
if (((pinPhoneRST.pio->PIO_ISR & pinPhoneRST.mask) != 0)) { if (((pinPhoneRST.pio->PIO_ISR & pinPhoneRST.mask) != 0)) {
if (PIO_Get(&pinPhoneRST) == 0) { if (PIO_Get(&pinPhoneRST) == 0) {
printf(" 0 "); printf(" 0 ");
@@ -80,7 +80,7 @@ void ISR_PhoneRST(const Pin * pPin)
} }
/* /*
* char_stat is zero if no error occurred. * char_stat is zero if no error occured.
* Otherwise it is filled with the content of the status register. * Otherwise it is filled with the content of the status register.
*/ */
void mode_trace_usart1_irq(void) void mode_trace_usart1_irq(void)
@@ -110,14 +110,14 @@ void mode_trace_usart1_irq(void)
rbuf_write(&sim_rcv_buf, c); rbuf_write(&sim_rcv_buf, c);
} else { } else {
TRACE_DEBUG("e %x st: %x\n", c, stat); TRACE_DEBUG("e %x st: %x\n", c, stat);
} /* else: error occurred */ } /* else: error occured */
char_stat = stat; char_stat = stat;
} }
} }
/* FIDI update functions */ /* FIDI update functions */
void update_fidi(Usart_info *usart, uint8_t fidi) void update_fidi(Usart *usart, uint8_t fidi)
{ {
if (NULL==usart) { if (NULL==usart) {
return; return;
@@ -129,14 +129,14 @@ void update_fidi(Usart_info *usart, uint8_t fidi)
if (ratio > 0 && ratio < 0x8000) { if (ratio > 0 && ratio < 0x8000) {
/* make sure USART uses new F/D ratio */ /* make sure USART uses new F/D ratio */
usart->base->US_CR |= US_CR_RXDIS | US_CR_RSTRX; usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX;
/* disable write protection */ /* disable write protection */
if (usart->base->US_WPMR) { if (usart->US_WPMR) {
usart->base->US_WPMR = US_WPMR_WPKEY(0x555341); usart->US_WPMR = US_WPMR_WPKEY(0x555341);
} }
usart->base->US_FIDI = (ratio & 0x7ff); usart->US_FIDI = (ratio & 0x7ff);
usart->base->US_CR |= US_CR_RXEN | US_CR_STTTO; usart->US_CR |= US_CR_RXEN | US_CR_STTTO;
//TRACE_INFO("updated USART(%u) Fi(%u)/Di(%u) ratio(%d): %u\n\r", usart->id, fi, di, ratio, usart->base->US_FIDI); //TRACE_INFO("updated USART Fi(%u)/Di(%u) ratio(%d): %u\n\r", fi, di, ratio, usart->US_FIDI); /* don't print since this is function is also called by ISRs */
} else { } else {
//TRACE_WARNING("computed Fi/Di ratio %d unsupported\n\r", ratio); /* don't print since this is function is also called by ISRs */ //TRACE_WARNING("computed Fi/Di ratio %d unsupported\n\r", ratio); /* don't print since this is function is also called by ISRs */
} }

View File

@@ -1,29 +1,25 @@
/* SIMtrace 2 sniffer mode /*
* * (C) 2010-2017 by Harald Welte <hwelte@sysmocom.de>
* (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de> * (C) 2018 by Kevin Redon <kredon@sysmocom.de>
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * All Rights Reserved
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
* 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
*/ */
/* This code implement the Sniffer mode to sniff the communication between a /* This code implement the Sniffer mode to sniff the communication between a SIM card (or any ISO 7816 smart card) and a phone (or any ISO 7816 card reader).
* SIM card (or any ISO 7816 smart card) and a phone (or any ISO 7816 card * For historical reasons (i.e. SIMtrace hardware) the USART peripheral connected to the SIM card is used.
* reader). * TODO put common ISO7816-3 code is separate library (and combine clean with iso7816_4)
* For historical reasons (i.e. SIMtrace hardware) the USART peripheral
* connected to the SIM card is used.
* TODO put common ISO7816-3 code is separate library (and combine clean with
* iso7816_4)
*/ */
#include "board.h" #include "board.h"
#include "simtrace.h" #include "simtrace.h"
@@ -182,11 +178,6 @@ uint8_t tpdu_packet[5+256+2];
/*! Current index in TPDU packet */ /*! Current index in TPDU packet */
uint16_t tpdu_packet_i = 0; uint16_t tpdu_packet_i = 0;
/*! Waiting Time (WT)
* @note defined in ISO/IEC 7816-3:2006(E) section 8.1 and 10.2
*/
uint32_t wt = 9600;
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Internal functions * Internal functions
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
@@ -197,75 +188,13 @@ uint32_t wt = 9600;
*/ */
static const uint8_t convention_convert_lut[256] = { 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f, 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07, 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b, 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03, 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d, 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05, 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09, 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01, 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e, 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06, 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a, 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02, 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c, 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04, 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08, 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00, }; static const uint8_t convention_convert_lut[256] = { 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f, 0xf7, 0x77, 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07, 0xfb, 0x7b, 0xbb, 0x3b, 0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b, 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, 0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03, 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d, 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65, 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05, 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29, 0xc9, 0x49, 0x89, 0x09, 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, 0x81, 0x01, 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e, 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06, 0xfa, 0x7a, 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a, 0xf2, 0x72, 0xb2, 0x32, 0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02, 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, 0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c, 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04, 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08, 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, 0xc0, 0x40, 0x80, 0x00, };
/*! Update Waiting Time (WT)
* @param[in] wi Waiting Integer (0 if unchanged)
* @param[in] d Baud Rate divider (0 if unchanged)
* @note set wt to be used by the receiver timeout
* @note defined in ISO/IEC 7816-3:2006(E) section 8.1 and 10.2
*/
static void update_wt(uint8_t wi, uint8_t d)
{
static uint8_t wt_wi = 10; /* Waiting time Integer (WI), used to calculate the Waiting Time (WT) */
static uint8_t wt_d = 1; /* baud rate adjustment integer (the actual value, not the table index) */
if (0 != wi) {
wt_wi = wi;
}
if (0 != d) {
wt_d = d;
}
wt = wt_wi * 960UL * wt_d;
TRACE_INFO("WT updated to %lu ETU\n\r", wt);
}
/*! Allocate USB buffer and push + initialize simtrace_msg_hdr
* @param[in] ep USB IN endpoint where the message will be sent to
* @param[in] msg_class SIMtrace USB message class
* @param[in] msg_type SIMtrace USB message type
* @return USB message with allocated ans initialized header, or NULL if allocation failed
*/
static struct msgb *usb_msg_alloc_hdr(uint8_t ep, uint8_t msg_class, uint8_t msg_type)
{
/* Only allocate message if not too many are already in the queue */
struct llist_head *head = usb_get_queue(SIMTRACE_USB_EP_CARD_DATAIN);
if (!head) {
return NULL;
}
if (llist_count(head) > 5) {
return NULL;
}
struct msgb *usb_msg = usb_buf_alloc(SIMTRACE_USB_EP_CARD_DATAIN);
if (!usb_msg) {
return NULL;
}
struct simtrace_msg_hdr *usb_msg_header;
usb_msg->l1h = msgb_put(usb_msg, sizeof(*usb_msg_header));
usb_msg_header = (struct simtrace_msg_hdr *) usb_msg->l1h;
memset(usb_msg_header, 0, sizeof(*usb_msg_header));
usb_msg_header->msg_class = msg_class;
usb_msg_header->msg_type = msg_type;
usb_msg->l2h = usb_msg->l1h + sizeof(*usb_msg_header);
return usb_msg;
}
/* update SIMtrace header msg_len and submit USB buffer
* param[in] usb_msg USB message to update and send
*/
void usb_msg_upd_len_and_submit(struct msgb *usb_msg)
{
struct simtrace_msg_hdr *usb_msg_header = (struct simtrace_msg_hdr *) usb_msg->l1h;
usb_msg_header->msg_len = msgb_length(usb_msg);
usb_buf_submit(usb_msg);
}
/*! Update the ISO 7816-3 state /*! Update the ISO 7816-3 state
* @param[in] iso_state_new new ISO 7816-3 state to update to * @param[in] iso_state_new new ISO 7816-3 state to update to
*/ */
static void change_state(enum iso7816_3_sniff_state iso_state_new) static void change_state(enum iso7816_3_sniff_state iso_state_new)
{ {
/* sanity check */ /* sanity check */
if (iso_state_new == iso_state) { if (iso_state_new==iso_state) {
TRACE_WARNING("Already in ISO 7816 state %u\n\r", iso_state); TRACE_WARNING("Already in ISO 7816 state %u\n\r", iso_state);
return; return;
} }
@@ -273,11 +202,12 @@ static void change_state(enum iso7816_3_sniff_state iso_state_new)
/* handle actions to perform when switching state */ /* handle actions to perform when switching state */
switch (iso_state_new) { switch (iso_state_new) {
case ISO7816_S_RESET: case ISO7816_S_RESET:
update_fidi(&sniff_usart, 0x11); /* reset baud rate to default Di/Fi values */ update_fidi(sniff_usart.base, 0x11); /* reset baud rate to default Di/Fi values */
update_wt(10, 1); /* reset WT time-out */ change_flags |= SNIFF_CHANGE_FLAG_RESET_HOLD; /* set flag and let main loop send it */
break; break;
case ISO7816_S_WAIT_ATR: case ISO7816_S_WAIT_ATR:
rbuf_reset(&sniff_buffer); /* reset buffer for new communication */ rbuf_reset(&sniff_buffer); /* reset buffer for new communication */
change_flags |= SNIFF_CHANGE_FLAG_RESET_RELEASE; /* set flag and let main loop send it */
break; break;
case ISO7816_S_IN_ATR: case ISO7816_S_IN_ATR:
atr_i = 0; atr_i = 0;
@@ -299,110 +229,55 @@ static void change_state(enum iso7816_3_sniff_state iso_state_new)
/* save new state */ /* save new state */
iso_state = iso_state_new; iso_state = iso_state_new;
TRACE_INFO("Changed to ISO 7816-3 state %u\n\r", iso_state); //TRACE_INFO("Changed to ISO 7816-3 state %u\n\r", iso_state); /* don't print since this is function is also called by ISRs */
}
const struct value_string data_flags[] = {
{
.value = SNIFF_DATA_FLAG_ERROR_INCOMPLETE,
.str = "incomplete",
},
{
.value = SNIFF_DATA_FLAG_ERROR_MALFORMED,
.str = "malformed",
},
{
.value = SNIFF_DATA_FLAG_ERROR_CHECKSUM,
.str = "checksum error",
},
{
.value = 0,
.str = NULL,
},
};
static void print_flags(const struct value_string* flag_meanings, uint32_t nb_flags, uint32_t flags) {
uint32_t i;
for (i = 0; i < nb_flags; i++) {
if (flags & flag_meanings[i].value) {
printf("%s", flag_meanings[i].str);
flags &= ~flag_meanings[i].value;
if (flags) {
printf(", ");
}
}
}
}
static void usb_send_data(enum simtrace_msg_type_sniff type, const uint8_t* data, uint16_t length, uint32_t flags)
{
/* Sanity check */
if (type != SIMTRACE_MSGT_SNIFF_ATR && type != SIMTRACE_MSGT_SNIFF_PPS && type != SIMTRACE_MSGT_SNIFF_TPDU) {
return;
}
/* Show activity on LED */
led_blink(LED_GREEN, BLINK_2F_O);
/* Print message */
switch (type) {
case SIMTRACE_MSGT_SNIFF_ATR:
printf("ATR");
break;
case SIMTRACE_MSGT_SNIFF_PPS:
printf("PPS");
break;
case SIMTRACE_MSGT_SNIFF_TPDU:
printf("TPDU");
break;
default:
printf("???");
break;
}
if (flags) {
printf(" (");
print_flags(data_flags, ARRAY_SIZE(data_flags), flags);
putchar(')');
}
printf(": ");
uint16_t i;
for (i = 0; i < length; i++) {
printf("%02x ", data[i]);
}
printf("\n\r");
/* Send data over USB */
struct msgb *usb_msg = usb_msg_alloc_hdr(SIMTRACE_USB_EP_CARD_DATAIN, SIMTRACE_MSGC_SNIFF, type);
if (!usb_msg) {
return;
}
struct sniff_data *usb_sniff_data = (struct sniff_data *) msgb_put(usb_msg, sizeof(*usb_sniff_data));
usb_sniff_data->flags = flags;
usb_sniff_data->length = length;
uint8_t *sniff_data = msgb_put(usb_msg, usb_sniff_data->length);
memcpy(sniff_data, data, length);
usb_msg_upd_len_and_submit(usb_msg);
} }
/*! Send current ATR over USB /*! Send current ATR over USB
* @param[in] flags SNIFF_DATA_FLAG_ data flags * @param[in] complete if the ATR is complete
* @note Also print the ATR to debug console * @note Also print the ATR to debug console
*/ */
static void usb_send_atr(uint32_t flags) static void usb_send_atr(bool complete)
{ {
/* Check state */ /* Check state */
if (ISO7816_S_IN_ATR != iso_state) { if (ISO7816_S_IN_ATR!=iso_state) {
TRACE_WARNING("Can't print ATR in ISO 7816-3 state %u\n\r", iso_state); TRACE_WARNING("Can't print ATR in ISO 7816-3 state %u\n\r", iso_state);
return; return;
} }
if (atr_i >= ARRAY_SIZE(atr)) { if (atr_i>=ARRAY_SIZE(atr)) {
TRACE_ERROR("ATR buffer overflow\n\r"); TRACE_ERROR("ATR buffer overflow\n\r");
return; return;
} }
/* Show activity on LED */
led_blink(LED_GREEN, BLINK_2O_F);
/* Print ATR */
printf("ATR%s: ", complete ? "" : " (incomplete)");
for (uint8_t i=0; i<atr_i; i++) {
printf("%02x ", atr[i]);
}
printf("\n\r");
/* Send ATR over USB */ /* Send ATR over USB */
usb_send_data(SIMTRACE_MSGT_SNIFF_ATR, atr, atr_i, flags); struct msgb *usb_msg = usb_buf_alloc(SIMTRACE_USB_EP_CARD_DATAIN);
if (!usb_msg) {
return;
}
struct simtrace_msg_hdr *usb_msg_header;
usb_msg->l1h = msgb_put(usb_msg, sizeof(*usb_msg_header));
usb_msg_header = (struct simtrace_msg_hdr *) usb_msg->l1h;
memset(usb_msg_header, 0, sizeof(*usb_msg_header));
usb_msg_header->msg_class = SIMTRACE_MSGC_SNIFF;
usb_msg_header->msg_type = SIMTRACE_MSGT_SNIFF_ATR;
usb_msg->l2h = usb_msg->l1h + sizeof(*usb_msg_header);
struct sniff_data *usb_sniff_data_atr;
usb_sniff_data_atr = (struct sniff_data *) msgb_put(usb_msg, sizeof(*usb_sniff_data_atr));
usb_sniff_data_atr->complete = complete;
usb_sniff_data_atr->length = atr_i;
uint8_t *data = msgb_put(usb_msg, usb_sniff_data_atr->length);
memcpy(data, atr, atr_i);
usb_msg_header->msg_len = msgb_length(usb_msg);
usb_buf_submit(usb_msg);
} }
/*! Process ATR byte /*! Process ATR byte
@@ -412,15 +287,13 @@ static void process_byte_atr(uint8_t byte)
{ {
static uint8_t atr_hist_len = 0; /* store the number of expected historical bytes */ static uint8_t atr_hist_len = 0; /* store the number of expected historical bytes */
static uint8_t y = 0; /* last mask of the upcoming TA, TB, TC, TD interface bytes */ static uint8_t y = 0; /* last mask of the upcoming TA, TB, TC, TD interface bytes */
static uint8_t i = 0; /* interface byte subgroup number */
static uint32_t flags = 0; /* error flag */
/* sanity check */ /* sanity check */
if (ISO7816_S_IN_ATR != iso_state) { if (ISO7816_S_IN_ATR!=iso_state) {
TRACE_ERROR("Processing ATR data in wrong ISO 7816-3 state %u\n\r", iso_state); TRACE_ERROR("Processing ATR data in wrong ISO 7816-3 state %u\n\r", iso_state);
return; return;
} }
if (atr_i >= ARRAY_SIZE(atr)) { if (atr_i>=ARRAY_SIZE(atr)) {
TRACE_ERROR("ATR data overflow\n\r"); TRACE_ERROR("ATR data overflow\n\r");
return; return;
} }
@@ -431,7 +304,6 @@ static void process_byte_atr(uint8_t byte)
/* handle ATR byte depending on current state */ /* handle ATR byte depending on current state */
switch (atr_state) { switch (atr_state) {
case ATR_S_WAIT_TS: /* see ISO/IEC 7816-3:2006 section 8.1 */ case ATR_S_WAIT_TS: /* see ISO/IEC 7816-3:2006 section 8.1 */
flags = 0;
switch (byte) { switch (byte) {
case 0x23: /* direct convention used, but decoded using inverse convention (a parity error should also have occurred) */ case 0x23: /* direct convention used, but decoded using inverse convention (a parity error should also have occurred) */
case 0x30: /* inverse convention used, but decoded using direct convention (a parity error should also have occurred) */ case 0x30: /* inverse convention used, but decoded using direct convention (a parity error should also have occurred) */
@@ -441,47 +313,34 @@ static void process_byte_atr(uint8_t byte)
atr_state = ATR_S_WAIT_T0; /* wait for format byte */ atr_state = ATR_S_WAIT_T0; /* wait for format byte */
break; break;
default: default:
atr_i--; /* revert last byte */
TRACE_WARNING("Invalid TS received\n\r"); TRACE_WARNING("Invalid TS received\n\r");
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_atr(SNIFF_DATA_FLAG_ERROR_MALFORMED); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_ATR); /* reset state */
break;
} }
i = 0; /* first interface byte sub-group is coming (T0 is kind of TD0) */
break; break;
case ATR_S_WAIT_T0: /* see ISO/IEC 7816-3:2006 section 8.2.2 */ case ATR_S_WAIT_T0: /* see ISO/IEC 7816-3:2006 section 8.2.2 */
case ATR_S_WAIT_TD: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ case ATR_S_WAIT_TD: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
if (ATR_S_WAIT_T0 == atr_state) { if (ATR_S_WAIT_T0==atr_state) {
atr_hist_len = (byte & 0x0f); /* save the number of historical bytes */ atr_hist_len = (byte&0x0f); /* save the number of historical bytes */
} else if (ATR_S_WAIT_TD == atr_state) { } else if (ATR_S_WAIT_TD==atr_state) {
t_protocol_support |= (1<<(byte & 0x0f)); /* remember supported protocol to know if TCK will be present */ t_protocol_support |= (1<<(byte&0x0f)); /* remember supported protocol to know if TCK will be present */
} }
y = (byte & 0xf0); /* remember upcoming interface bytes */ y = (byte&0xf0); /* remember upcoming interface bytes */
i++; /* next interface byte sub-group is coming */ if (y&0x10) {
if (y & 0x10) {
atr_state = ATR_S_WAIT_TA; /* wait for interface byte TA */ atr_state = ATR_S_WAIT_TA; /* wait for interface byte TA */
break; break;
} }
case ATR_S_WAIT_TA: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ case ATR_S_WAIT_TA: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
if (y & 0x20) { if (y&0x20) {
atr_state = ATR_S_WAIT_TB; /* wait for interface byte TB */ atr_state = ATR_S_WAIT_TB; /* wait for interface byte TB */
break; break;
} }
case ATR_S_WAIT_TB: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ case ATR_S_WAIT_TB: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
if (y & 0x40) { if (y&0x40) {
atr_state = ATR_S_WAIT_TC; /* wait for interface byte TC */ atr_state = ATR_S_WAIT_TC; /* wait for interface byte TC */
break; break;
} }
case ATR_S_WAIT_TC: /* see ISO/IEC 7816-3:2006 section 8.2.3 */ case ATR_S_WAIT_TC: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
/* retrieve WI encoded in TC2*/ if (y&0x80) {
if (ATR_S_WAIT_TC==atr_state && 2==i) {
if (0 == byte) {
update_wt(10, 0);
} else {
update_wt(byte, 0);
}
}
if (y & 0x80) {
atr_state = ATR_S_WAIT_TD; /* wait for interface byte TD */ atr_state = ATR_S_WAIT_TD; /* wait for interface byte TD */
break; break;
} else if (atr_hist_len) { } else if (atr_hist_len) {
@@ -492,8 +351,8 @@ static void process_byte_atr(uint8_t byte)
if (atr_hist_len) { if (atr_hist_len) {
atr_hist_len--; atr_hist_len--;
} }
if (0 == atr_hist_len) { if (0==atr_hist_len) {
if (t_protocol_support > 1) { if (t_protocol_support>1) {
atr_state = ATR_S_WAIT_TCK; /* wait for check bytes */ atr_state = ATR_S_WAIT_TCK; /* wait for check bytes */
break; break;
} }
@@ -501,21 +360,8 @@ static void process_byte_atr(uint8_t byte)
break; break;
} }
case ATR_S_WAIT_TCK: /* see ISO/IEC 7816-3:2006 section 8.2.5 */ case ATR_S_WAIT_TCK: /* see ISO/IEC 7816-3:2006 section 8.2.5 */
/* verify checksum if present */ /* we could verify the checksum, but we are just here to sniff */
if (ATR_S_WAIT_TCK == atr_state) { usb_send_atr(true); /* send ATR to host software using USB */
uint8_t ui;
uint8_t checksum = 0;
for (ui = 1; ui < atr_i; ui++) {
checksum ^= atr[ui];
}
if (checksum) {
flags |= SNIFF_DATA_FLAG_ERROR_CHECKSUM;
/* 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)
*/
}
}
usb_send_atr(flags); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* go to next state */ change_state(ISO7816_S_WAIT_TPDU); /* go to next state */
break; break;
default: default:
@@ -524,17 +370,17 @@ static void process_byte_atr(uint8_t byte)
} }
/*! Send current PPS over USB /*! Send current PPS over USB
* @param[in] flags SNIFF_DATA_FLAG_ data flags * @param[in] complete if the PPS is complete
* @note Also print the PPS over the debug console * @note Also print the PPS over the debug console
*/ */
static void usb_send_pps(uint32_t flags) static void usb_send_pps(bool complete)
{ {
uint8_t *pps_cur; /* current PPS (request or response) */ uint8_t *pps_cur; /* current PPS (request or response) */
/* Sanity check */ /* Sanity check */
if (ISO7816_S_IN_PPS_REQ == iso_state) { if (ISO7816_S_IN_PPS_REQ==iso_state) {
pps_cur = pps_req; pps_cur = pps_req;
} else if (ISO7816_S_IN_PPS_RSP == iso_state) { } else if (ISO7816_S_IN_PPS_RSP==iso_state) {
pps_cur = pps_rsp; pps_cur = pps_rsp;
} else { } else {
TRACE_ERROR("Can't print PPS in ISO 7816-3 state %u\n\r", iso_state); TRACE_ERROR("Can't print PPS in ISO 7816-3 state %u\n\r", iso_state);
@@ -544,27 +390,55 @@ static void usb_send_pps(uint32_t flags)
/* Get only relevant data */ /* Get only relevant data */
uint8_t pps[6]; uint8_t pps[6];
uint8_t pps_i = 0; uint8_t pps_i = 0;
if (pps_state > PPS_S_WAIT_PPSS) { if (pps_state>PPS_S_WAIT_PPSS) {
pps[pps_i++] = pps_cur[0]; pps[pps_i++] = pps_cur[0];
} }
if (pps_state > PPS_S_WAIT_PPS0) { if (pps_state>PPS_S_WAIT_PPS0) {
pps[pps_i++] = pps_cur[1]; pps[pps_i++] = pps_cur[1];
} }
if (pps_state > PPS_S_WAIT_PPS1 && pps_cur[1] & 0x10) { if (pps_state>PPS_S_WAIT_PPS1 && pps_cur[1]&0x10) {
pps[pps_i++] = pps_cur[2]; pps[pps_i++] = pps_cur[2];
} }
if (pps_state > PPS_S_WAIT_PPS2 && pps_cur[1] & 0x20) { if (pps_state>PPS_S_WAIT_PPS2 && pps_cur[1]&0x20) {
pps[pps_i++] = pps_cur[3]; pps[pps_i++] = pps_cur[3];
} }
if (pps_state > PPS_S_WAIT_PPS3 && pps_cur[1] & 0x40) { if (pps_state>PPS_S_WAIT_PPS3 && pps_cur[1]&0x40) {
pps[pps_i++] = pps_cur[4]; pps[pps_i++] = pps_cur[4];
} }
if (pps_state > PPS_S_WAIT_PCK) { if (pps_state>PPS_S_WAIT_PCK) {
pps[pps_i++] = pps_cur[5]; pps[pps_i++] = pps_cur[5];
} }
/* Show activity on LED */
led_blink(LED_GREEN, BLINK_2O_F);
/* Print PPS */
printf("PPS%s: ", complete ? "" : " (incomplete)");
for (uint8_t i=0; i<pps_i; i++) {
printf("%02x ", pps[i]);
}
printf("\n\r");
/* Send message over USB */ /* Send message over USB */
usb_send_data(SIMTRACE_MSGT_SNIFF_PPS, pps, pps_i, flags); struct msgb *usb_msg = usb_buf_alloc(SIMTRACE_USB_EP_CARD_DATAIN);
if (!usb_msg) {
return;
}
struct simtrace_msg_hdr *usb_msg_header;
usb_msg->l1h = msgb_put(usb_msg, sizeof(*usb_msg_header));
usb_msg_header = (struct simtrace_msg_hdr *) usb_msg->l1h;
memset(usb_msg_header, 0, sizeof(*usb_msg_header));
usb_msg_header->msg_class = SIMTRACE_MSGC_SNIFF;
usb_msg_header->msg_type = SIMTRACE_MSGT_SNIFF_PPS;
usb_msg->l2h = usb_msg->l1h + sizeof(*usb_msg_header);
struct sniff_data *usb_sniff_data_pps;
usb_sniff_data_pps = (struct sniff_data *) msgb_put(usb_msg, sizeof(*usb_sniff_data_pps));
usb_sniff_data_pps->complete = complete;
usb_sniff_data_pps->length = pps_i;
uint8_t *data = msgb_put(usb_msg, usb_sniff_data_pps->length);
memcpy(data, pps, pps_i);
usb_msg_header->msg_len = msgb_length(usb_msg);
usb_buf_submit(usb_msg);
} }
/*! Send Fi/Di change over USB /*! Send Fi/Di change over USB
@@ -573,24 +447,32 @@ static void usb_send_pps(uint32_t flags)
static void usb_send_fidi(uint8_t fidi) static void usb_send_fidi(uint8_t fidi)
{ {
/* Send message over USB */ /* Send message over USB */
struct msgb *usb_msg = usb_msg_alloc_hdr(SIMTRACE_USB_EP_CARD_DATAIN, SIMTRACE_MSGC_SNIFF, SIMTRACE_MSGT_SNIFF_FIDI); struct msgb *usb_msg = usb_buf_alloc(SIMTRACE_USB_EP_CARD_DATAIN);
if (!usb_msg) { if (!usb_msg) {
return; return;
} }
struct sniff_fidi *usb_sniff_fidi = (struct sniff_fidi *) msgb_put(usb_msg, sizeof(*usb_sniff_fidi)); struct simtrace_msg_hdr *usb_msg_header;
usb_msg->l1h = msgb_put(usb_msg, sizeof(*usb_msg_header));
usb_msg_header = (struct simtrace_msg_hdr *) usb_msg->l1h;
memset(usb_msg_header, 0, sizeof(*usb_msg_header));
usb_msg_header->msg_class = SIMTRACE_MSGC_SNIFF;
usb_msg_header->msg_type = SIMTRACE_MSGT_SNIFF_FIDI;
usb_msg->l2h = usb_msg->l1h + sizeof(*usb_msg_header);
struct sniff_fidi *usb_sniff_fidi;
usb_sniff_fidi = (struct sniff_fidi *) msgb_put(usb_msg, sizeof(*usb_sniff_fidi));
usb_sniff_fidi->fidi = fidi; usb_sniff_fidi->fidi = fidi;
usb_msg_upd_len_and_submit(usb_msg); usb_msg_header->msg_len = msgb_length(usb_msg);
usb_buf_submit(usb_msg);
} }
static void process_byte_pps(uint8_t byte) static void process_byte_pps(uint8_t byte)
{ {
uint8_t *pps_cur; /* current PPS (request or response) */ uint8_t *pps_cur; /* current PPS (request or response) */
static uint32_t flags = 0; /* error flag */
/* sanity check */ /* sanity check */
if (ISO7816_S_IN_PPS_REQ == iso_state) { if (ISO7816_S_IN_PPS_REQ==iso_state) {
pps_cur = pps_req; pps_cur = pps_req;
} else if (ISO7816_S_IN_PPS_RSP == iso_state) { } else if (ISO7816_S_IN_PPS_RSP==iso_state) {
pps_cur = pps_rsp; pps_cur = pps_rsp;
} else { } else {
TRACE_ERROR("Processing PPS data in wrong ISO 7816-3 state %u\n\r", iso_state); TRACE_ERROR("Processing PPS data in wrong ISO 7816-3 state %u\n\r", iso_state);
@@ -600,32 +482,29 @@ static void process_byte_pps(uint8_t byte)
/* handle PPS byte depending on current state */ /* handle PPS byte depending on current state */
switch (pps_state) { /* see ISO/IEC 7816-3:2006 section 9.2 */ switch (pps_state) { /* see ISO/IEC 7816-3:2006 section 9.2 */
case PPS_S_WAIT_PPSS: /*!< initial byte */ case PPS_S_WAIT_PPSS: /*!< initial byte */
flags = 0;
if (0xff) { if (0xff) {
pps_cur[0] = byte; pps_cur[0] = byte;
pps_state = PPS_S_WAIT_PPS0; /* go to next state */ pps_state = PPS_S_WAIT_PPS0; /* go to next state */
} else { } else {
TRACE_INFO("Invalid PPSS received\n\r"); TRACE_INFO("Invalid PPSS received\n\r");
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
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 */ change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
} }
break; break;
case PPS_S_WAIT_PPS0: /*!< format byte */ case PPS_S_WAIT_PPS0: /*!< format byte */
pps_cur[1] = byte; pps_cur[1] = byte;
if (pps_cur[1] & 0x10) { if (pps_cur[1]&0x10) {
pps_state = PPS_S_WAIT_PPS1; /* go to next state */ pps_state = PPS_S_WAIT_PPS1; /* go to next state */
break; break;
} }
case PPS_S_WAIT_PPS1: /*!< first parameter byte */ case PPS_S_WAIT_PPS1: /*!< first parameter byte */
pps_cur[2] = byte; /* not always right but doesn't affect the process */ pps_cur[2] = byte; /* not always right but doesn't affect the process */
if (pps_cur[1] & 0x20) { if (pps_cur[1]&0x20) {
pps_state = PPS_S_WAIT_PPS2; /* go to next state */ pps_state = PPS_S_WAIT_PPS2; /* go to next state */
break; break;
} }
case PPS_S_WAIT_PPS2: /*!< second parameter byte */ case PPS_S_WAIT_PPS2: /*!< second parameter byte */
pps_cur[3] = byte; /* not always right but doesn't affect the process */ pps_cur[3] = byte; /* not always right but doesn't affect the process */
if (pps_cur[1] & 0x40) { if (pps_cur[1]&0x40) {
pps_state = PPS_S_WAIT_PPS3; /* go to next state */ pps_state = PPS_S_WAIT_PPS3; /* go to next state */
break; break;
} }
@@ -639,40 +518,36 @@ static void process_byte_pps(uint8_t byte)
uint8_t check = 0; uint8_t check = 0;
check ^= pps_cur[0]; check ^= pps_cur[0];
check ^= pps_cur[1]; check ^= pps_cur[1];
if (pps_cur[1] & 0x10) { if (pps_cur[1]&0x10) {
check ^= pps_cur[2]; check ^= pps_cur[2];
} }
if (pps_cur[1] & 0x20) { if (pps_cur[1]&0x20) {
check ^= pps_cur[3]; check ^= pps_cur[3];
} }
if (pps_cur[1] & 0x40) { if (pps_cur[1]&0x40) {
check ^= pps_cur[4]; check ^= pps_cur[4];
} }
check ^= pps_cur[5]; check ^= pps_cur[5];
if (check) {
flags |= SNIFF_DATA_FLAG_ERROR_CHECKSUM;
}
pps_state = PPS_S_WAIT_END; pps_state = PPS_S_WAIT_END;
usb_send_pps(flags); /* send PPS to host software using USB */ usb_send_pps(true); /* send PPS to host software using USB */
if (ISO7816_S_IN_PPS_REQ == iso_state) { if (ISO7816_S_IN_PPS_REQ==iso_state) {
if (0 == check) { /* checksum is valid */ if (0==check) { /* checksum is valid */
change_state(ISO7816_S_WAIT_PPS_RSP); /* go to next state */ change_state(ISO7816_S_WAIT_PPS_RSP); /* go to next state */
} else { /* checksum is invalid */ } else { /* checksum is invalid */
change_state(ISO7816_S_WAIT_TPDU); /* go to next state */ change_state(ISO7816_S_WAIT_TPDU); /* go to next state */
} }
} else if (ISO7816_S_IN_PPS_RSP == iso_state) { } else if (ISO7816_S_IN_PPS_RSP==iso_state) {
if (0 == check) { /* checksum is valid */ if (0==check) { /* checksum is valid */
uint8_t fn, dn; uint8_t fn, dn;
if (pps_cur[1] & 0x10) { if (pps_cur[1]&0x10) {
fn = (pps_cur[2] >> 4); fn = (pps_cur[2]>>4);
dn = (pps_cur[2] & 0x0f); dn = (pps_cur[2]&0x0f);
} else { } else {
fn = 1; fn = 1;
dn = 1; dn = 1;
} }
TRACE_INFO("PPS negotiation successful: Fn=%u Dn=%u\n\r", fi_table[fn], di_table[dn]); TRACE_INFO("PPS negotiation successful: Fn=%u Dn=%u\n\r", fi_table[fn], di_table[dn]);
update_fidi(&sniff_usart, pps_cur[2]); update_fidi(sniff_usart.base, pps_cur[2]);
update_wt(0, di_table[dn]);
usb_send_fidi(pps_cur[2]); /* send Fi/Di change notification to host software over USB */ usb_send_fidi(pps_cur[2]); /* send Fi/Di change notification to host software over USB */
} else { /* checksum is invalid */ } else { /* checksum is invalid */
TRACE_INFO("PPS negotiation failed\n\r"); TRACE_INFO("PPS negotiation failed\n\r");
@@ -690,29 +565,57 @@ static void process_byte_pps(uint8_t byte)
} }
/*! Send current TPDU over USB /*! Send current TPDU over USB
* @param[in] flags SNIFF_DATA_FLAG_ data flags * @param[in] complete if the TPDU is complete
* @note Also print the TPDU over the debug console * @note Also print the TPDU over the debug console
*/ */
static void usb_send_tpdu(uint32_t flags) static void usb_send_tpdu(bool complete)
{ {
/* Check state */ /* Check state */
if (ISO7816_S_IN_TPDU != iso_state) { if (ISO7816_S_IN_TPDU!=iso_state) {
TRACE_WARNING("Can't print TPDU in ISO 7816-3 state %u\n\r", iso_state); TRACE_WARNING("Can't print TPDU in ISO 7816-3 state %u\n\r", iso_state);
return; return;
} }
/* Show activity on LED */
led_blink(LED_GREEN, BLINK_2O_F);
/* Print TPDU */
printf("TPDU%s: ", complete ? "" : " (incomplete)");
for (uint16_t i=0; i<tpdu_packet_i && i<ARRAY_SIZE(tpdu_packet); i++) {
printf("%02x ", tpdu_packet[i]);
}
printf("\n\r");
/* Send ATR over USB */ /* Send ATR over USB */
usb_send_data(SIMTRACE_MSGT_SNIFF_TPDU, tpdu_packet, tpdu_packet_i, flags); struct msgb *usb_msg = usb_buf_alloc(SIMTRACE_USB_EP_CARD_DATAIN);
if (!usb_msg) {
return;
}
struct simtrace_msg_hdr *usb_msg_header;
usb_msg->l1h = msgb_put(usb_msg, sizeof(*usb_msg_header));
usb_msg_header = (struct simtrace_msg_hdr *) usb_msg->l1h;
memset(usb_msg_header, 0, sizeof(*usb_msg_header));
usb_msg_header->msg_class = SIMTRACE_MSGC_SNIFF;
usb_msg_header->msg_type = SIMTRACE_MSGT_SNIFF_TPDU;
usb_msg->l2h = usb_msg->l1h + sizeof(*usb_msg_header);
struct sniff_data *usb_sniff_data_tpdu;
usb_sniff_data_tpdu = (struct sniff_data *) msgb_put(usb_msg, sizeof(*usb_sniff_data_tpdu));
usb_sniff_data_tpdu->complete = complete;
usb_sniff_data_tpdu->length = tpdu_packet_i;
uint8_t *data = msgb_put(usb_msg, usb_sniff_data_tpdu->length);
memcpy(data, tpdu_packet, tpdu_packet_i);
usb_msg_header->msg_len = msgb_length(usb_msg);
usb_buf_submit(usb_msg);
} }
static void process_byte_tpdu(uint8_t byte) static void process_byte_tpdu(uint8_t byte)
{ {
/* sanity check */ /* sanity check */
if (ISO7816_S_IN_TPDU != iso_state) { if (ISO7816_S_IN_TPDU!=iso_state) {
TRACE_ERROR("Processing TPDU data in wrong ISO 7816-3 state %u\n\r", iso_state); TRACE_ERROR("Processing TPDU data in wrong ISO 7816-3 state %u\n\r", iso_state);
return; return;
} }
if (tpdu_packet_i >= ARRAY_SIZE(tpdu_packet)) { if (tpdu_packet_i>=ARRAY_SIZE(tpdu_packet)) {
TRACE_ERROR("TPDU data overflow\n\r"); TRACE_ERROR("TPDU data overflow\n\r");
return; return;
} }
@@ -720,10 +623,8 @@ static void process_byte_tpdu(uint8_t byte)
/* handle TPDU byte depending on current state */ /* handle TPDU byte depending on current state */
switch (tpdu_state) { switch (tpdu_state) {
case TPDU_S_CLA: case TPDU_S_CLA:
if (0xff == byte) { if (0xff==byte) {
TRACE_WARNING("0xff is not a valid class byte\n\r"); TRACE_WARNING("0xff is not a valid class byte\n\r");
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
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 */ change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return; return;
} }
@@ -732,10 +633,8 @@ static void process_byte_tpdu(uint8_t byte)
tpdu_state = TPDU_S_INS; tpdu_state = TPDU_S_INS;
break; break;
case TPDU_S_INS: case TPDU_S_INS:
if ((0x60 == (byte & 0xf0)) || (0x90 == (byte & 0xf0))) { if ((0x60==(byte&0xf0)) || (0x90==(byte&0xf0))) {
TRACE_WARNING("invalid CLA 0x%02x\n\r", byte); TRACE_WARNING("invalid CLA 0x%02x\n\r", byte);
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
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 */ change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return; return;
} }
@@ -759,45 +658,43 @@ static void process_byte_tpdu(uint8_t byte)
tpdu_state = TPDU_S_PROCEDURE; tpdu_state = TPDU_S_PROCEDURE;
break; break;
case TPDU_S_PROCEDURE: case TPDU_S_PROCEDURE:
if (0x60 == byte) { /* wait for next procedure byte */ if (0x60==byte) { /* wait for next procedure byte */
break; break;
} else if (tpdu_packet[1] == byte) { /* get all remaining data bytes */ } else if (tpdu_packet[1]==byte) { /* get all remaining data bytes */
tpdu_state = TPDU_S_DATA_REMAINING; tpdu_state = TPDU_S_DATA_REMAINING;
break; break;
} else if ((~tpdu_packet[1]) == byte) { /* get single data byte */ } else if ((~tpdu_packet[1])==byte) { /* get single data byte */
tpdu_state = TPDU_S_DATA_SINGLE; tpdu_state = TPDU_S_DATA_SINGLE;
break; break;
} }
case TPDU_S_SW1: case TPDU_S_SW1:
if ((0x60 == (byte & 0xf0)) || (0x90 == (byte & 0xf0))) { /* this procedure byte is SW1 */ if ((0x60==(byte&0xf0)) || (0x90==(byte&0xf0))) { /* this procedure byte is SW1 */
tpdu_packet[tpdu_packet_i++] = byte; tpdu_packet[tpdu_packet_i++] = byte;
tpdu_state = TPDU_S_SW2; tpdu_state = TPDU_S_SW2;
} else { } else {
TRACE_WARNING("invalid SW1 0x%02x\n\r", byte); TRACE_WARNING("invalid SW1 0x%02x\n\r", byte);
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
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 */ change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return; return;
} }
break; break;
case TPDU_S_SW2: case TPDU_S_SW2:
tpdu_packet[tpdu_packet_i++] = byte; tpdu_packet[tpdu_packet_i++] = byte;
usb_send_tpdu(0); /* send TPDU to host software using USB */ usb_send_tpdu(true); /* send TPDU to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* this is the end of the TPDU */ change_state(ISO7816_S_WAIT_TPDU); /* this is the end of the TPDU */
break; break;
case TPDU_S_DATA_SINGLE: case TPDU_S_DATA_SINGLE:
case TPDU_S_DATA_REMAINING: case TPDU_S_DATA_REMAINING:
tpdu_packet[tpdu_packet_i++] = byte; tpdu_packet[tpdu_packet_i++] = byte;
if (0 == tpdu_packet[4]) { if (0==tpdu_packet[4]) {
if (5+256 <= tpdu_packet_i) { if (5+256<=tpdu_packet_i) {
tpdu_state = TPDU_S_PROCEDURE; tpdu_state = TPDU_S_PROCEDURE;
} }
} else { } else {
if (5+tpdu_packet[4] <= tpdu_packet_i) { if (5+tpdu_packet[4]<=tpdu_packet_i) {
tpdu_state = TPDU_S_PROCEDURE; tpdu_state = TPDU_S_PROCEDURE;
} }
} }
if (TPDU_S_DATA_SINGLE == tpdu_state) { if (TPDU_S_DATA_SINGLE==tpdu_state) {
tpdu_state = TPDU_S_PROCEDURE; tpdu_state = TPDU_S_PROCEDURE;
} }
break; break;
@@ -809,9 +706,6 @@ static void process_byte_tpdu(uint8_t byte)
/*! Interrupt Service Routine called on USART activity */ /*! Interrupt Service Routine called on USART activity */
void Sniffer_usart_isr(void) void Sniffer_usart_isr(void)
{ {
/* Remaining Waiting Time (WI) counter (>16 bits) */
static volatile uint32_t wt_remaining = 9600;
/* Read channel status register */ /* Read channel status register */
uint32_t csr = sniff_usart.base->US_CSR; uint32_t csr = sniff_usart.base->US_CSR;
/* Verify if there was an error */ /* Verify if there was an error */
@@ -823,13 +717,10 @@ void Sniffer_usart_isr(void)
TRACE_WARNING("USART framing error\n\r"); TRACE_WARNING("USART framing error\n\r");
sniff_usart.base->US_CR |= US_CR_RSTSTA; sniff_usart.base->US_CR |= US_CR_RSTSTA;
} }
/* Verify if character has been received */ /* Verify if character has been received */
if (csr & US_CSR_RXRDY) { if (csr & US_CSR_RXRDY) {
/* Read communication data byte between phone and SIM */ /* Read communication data byte between phone and SIM */
uint8_t byte = sniff_usart.base->US_RHR; uint8_t byte = sniff_usart.base->US_RHR;
/* Reset WT timer */
wt_remaining = wt;
/* Store sniffed data into buffer (also clear interrupt */ /* Store sniffed data into buffer (also clear interrupt */
if (rbuf_is_full(&sniff_buffer)) { if (rbuf_is_full(&sniff_buffer)) {
TRACE_ERROR("USART buffer full\n\r"); TRACE_ERROR("USART buffer full\n\r");
@@ -840,25 +731,10 @@ void Sniffer_usart_isr(void)
/* Verify it WT timeout occurred, to detect unresponsive card */ /* Verify it WT timeout occurred, to detect unresponsive card */
if (csr & US_CSR_TIMEOUT) { if (csr & US_CSR_TIMEOUT) {
if (wt_remaining <= (sniff_usart.base->US_RTOR & 0xffff)) { /* Stop timeout until next character is received */
/* Just set the flag and let the main loop handle it */
change_flags |= SNIFF_CHANGE_FLAG_TIMEOUT_WT;
/* Reset timeout value */
wt_remaining = wt;
} 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 */
}
if (wt_remaining > 0xffff) {
sniff_usart.base->US_RTOR = 0xffff;
} else {
sniff_usart.base->US_RTOR = wt_remaining;
}
/* Stop timeout until next character is received (and clears the timeout flag) */
sniff_usart.base->US_CR |= US_CR_STTTO; sniff_usart.base->US_CR |= US_CR_STTTO;
if (!(change_flags & SNIFF_CHANGE_FLAG_TIMEOUT_WT)) { /* Just set the flag and let the main loop handle it */
/* Immediately restart the counter it the WT timeout did not occur (needs the timeout flag to be cleared) */ change_flags |= SNIFF_CHANGE_FLAG_TIMEOUT_WT;
sniff_usart.base->US_CR |= US_CR_RETTO;
}
} }
} }
@@ -867,15 +743,19 @@ void Sniffer_usart_isr(void)
static void Sniffer_reset_isr(const Pin* pPin) static void Sniffer_reset_isr(const Pin* pPin)
{ {
/* Ensure an edge on the reset pin cause the interrupt */ /* Ensure an edge on the reset pin cause the interrupt */
if (pPin->id != pin_rst.id || 0 == (pPin->mask & pin_rst.mask)) { if (pPin->id!=pin_rst.id || 0==(pPin->mask&pin_rst.mask)) {
TRACE_ERROR("Pin other than reset caused a interrupt\n\r"); TRACE_ERROR("Pin other than reset caused a interrupt\n\r");
return; return;
} }
/* Update the ISO state according to the reset change (reset is active low) */ /* Update the ISO state according to the reset change */
if (PIO_Get(&pin_rst)) { if (PIO_Get(&pin_rst)) {
change_flags |= SNIFF_CHANGE_FLAG_RESET_DEASSERT; /* set flag and let main loop send it */ if (ISO7816_S_WAIT_ATR!=iso_state) {
change_state(ISO7816_S_WAIT_ATR);
}
} else { } else {
change_flags |= SNIFF_CHANGE_FLAG_RESET_ASSERT; /* set flag and let main loop send it */ if (ISO7816_S_RESET!=iso_state) {
change_state(ISO7816_S_RESET);
}
} }
} }
@@ -885,14 +765,14 @@ static void Sniffer_reset_isr(const Pin* pPin)
void Sniffer_usart1_irq(void) void Sniffer_usart1_irq(void)
{ {
if (ID_USART1 == sniff_usart.id) { if (ID_USART1==sniff_usart.id) {
Sniffer_usart_isr(); Sniffer_usart_isr();
} }
} }
void Sniffer_usart0_irq(void) void Sniffer_usart0_irq(void)
{ {
if (ID_USART0 == sniff_usart.id) { if (ID_USART0==sniff_usart.id) {
Sniffer_usart_isr(); Sniffer_usart_isr();
} }
} }
@@ -945,45 +825,55 @@ void Sniffer_init(void)
ISO7816_Init(&sniff_usart, CLK_SLAVE); ISO7816_Init(&sniff_usart, CLK_SLAVE);
/* Only receive data when sniffing */ /* Only receive data when sniffing */
USART_SetReceiverEnabled(sniff_usart.base, 1); USART_SetReceiverEnabled(sniff_usart.base, 1);
/* Enable Receiver time-out to detect waiting time (WT) time-out (e.g. unresponsive cards) */ /* Enable Receiver time-out WT to detect unresponsive cards */
sniff_usart.base->US_RTOR = wt; sniff_usart.base->US_RTOR = 9600-12; /* -12 because the timer starts at the end of the 12 ETU frame */
/* Enable interrupt to indicate when data has been received or timeout occurred */ /* Enable interrupt to indicate when data has been received or timeout occurred */
USART_EnableIt(sniff_usart.base, US_IER_RXRDY | US_IER_TIMEOUT); USART_EnableIt(sniff_usart.base, US_IER_RXRDY | US_IER_TIMEOUT);
/* Set USB priority lower than USART to not miss sniffing data (both at 0 per default) */ /* Set USB priority lower than USART to not miss sniffing data (both at 0 per default) */
if (NVIC_GetPriority(IRQ_USART_SIM) >= NVIC_GetPriority(UDP_IRQn)) { if (NVIC_GetPriority(IRQ_USART_SIM)>=NVIC_GetPriority(UDP_IRQn)) {
NVIC_SetPriority(UDP_IRQn, NVIC_GetPriority(IRQ_USART_SIM) + 2); NVIC_SetPriority(UDP_IRQn, NVIC_GetPriority(IRQ_USART_SIM)+2);
} }
/* Enable interrupt requests for the USART peripheral */ /* Enable interrupt requests for the USART peripheral */
NVIC_EnableIRQ(IRQ_USART_SIM); NVIC_EnableIRQ(IRQ_USART_SIM);
/* Reset state */ /* Reset state */
if (ISO7816_S_RESET != iso_state) { if (ISO7816_S_RESET!=iso_state) {
change_state(ISO7816_S_RESET); change_state(ISO7816_S_RESET);
} }
} }
/*! Send card change flags over USB /*! Send card change flags over USB
* @param[in] flags change flags corresponding to SIMTRACE_MSGT_SNIFF_CHANGE * @param[in] flags change flags corresponding to SIMTRACE_MSGT_SNIFF_CHANGE
* @note Also print the TPDU over the debug console
*/ */
static void usb_send_change(uint32_t flags) static void usb_send_change(uint32_t flags)
{ {
/* Check flags */ /* Check flags */
if(0 == flags) { /* no changes */ if(0==flags) { /* no changes */
return; return;
} }
if (flags & SNIFF_CHANGE_FLAG_TIMEOUT_WT) { if (flags&SNIFF_CHANGE_FLAG_TIMEOUT_WT) {
printf("waiting time (WT) timeout\n\r"); printf("waiting time (WT) timeout\n\r");
} }
/* Send message over USB */ /* Send message over USB */
struct msgb *usb_msg = usb_msg_alloc_hdr(SIMTRACE_USB_EP_CARD_DATAIN, SIMTRACE_MSGC_SNIFF, SIMTRACE_MSGT_SNIFF_CHANGE); struct msgb *usb_msg = usb_buf_alloc(SIMTRACE_USB_EP_CARD_DATAIN);
if (!usb_msg) { if (!usb_msg) {
return; return;
} }
struct sniff_change *usb_sniff_change = (struct sniff_change *) msgb_put(usb_msg, sizeof(*usb_sniff_change)); struct simtrace_msg_hdr *usb_msg_header;
usb_msg->l1h = msgb_put(usb_msg, sizeof(*usb_msg_header));
usb_msg_header = (struct simtrace_msg_hdr *) usb_msg->l1h;
memset(usb_msg_header, 0, sizeof(*usb_msg_header));
usb_msg_header->msg_class = SIMTRACE_MSGC_SNIFF;
usb_msg_header->msg_type = SIMTRACE_MSGT_SNIFF_CHANGE;
usb_msg->l2h = usb_msg->l1h + sizeof(*usb_msg_header);
struct sniff_change *usb_sniff_change;
usb_sniff_change = (struct sniff_change *) msgb_put(usb_msg, sizeof(*usb_sniff_change));
usb_sniff_change->flags = flags; usb_sniff_change->flags = flags;
usb_msg_upd_len_and_submit(usb_msg); usb_msg_header->msg_len = msgb_length(usb_msg);
usb_buf_submit(usb_msg);
} }
/* Main (idle/busy) loop of this USB configuration */ /* Main (idle/busy) loop of this USB configuration */
@@ -1001,10 +891,6 @@ void Sniffer_run(void)
process_any_usb_commands(queue); process_any_usb_commands(queue);
*/ */
/* 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
* is remaining
*/
/* Handle sniffed data */ /* Handle sniffed data */
if (!rbuf_is_empty(&sniff_buffer)) { /* use if instead of while to let the main loop restart the watchdog */ if (!rbuf_is_empty(&sniff_buffer)) { /* use if instead of while to let the main loop restart the watchdog */
uint8_t byte = rbuf_read(&sniff_buffer); uint8_t byte = rbuf_read(&sniff_buffer);
@@ -1023,8 +909,8 @@ void Sniffer_run(void)
break; break;
case ISO7816_S_WAIT_TPDU: /* After the ATR we expect TPDU or PPS data */ case ISO7816_S_WAIT_TPDU: /* After the ATR we expect TPDU or PPS data */
case ISO7816_S_WAIT_PPS_RSP: case ISO7816_S_WAIT_PPS_RSP:
if (0xff == byte) { if (byte == 0xff) {
if (ISO7816_S_WAIT_PPS_RSP == iso_state) { if (ISO7816_S_WAIT_PPS_RSP==iso_state) {
change_state(ISO7816_S_IN_PPS_RSP); /* Go to PPS state */ change_state(ISO7816_S_IN_PPS_RSP); /* Go to PPS state */
} else { } else {
change_state(ISO7816_S_IN_PPS_REQ); /* Go to PPS state */ change_state(ISO7816_S_IN_PPS_REQ); /* Go to PPS state */
@@ -1033,7 +919,7 @@ void Sniffer_run(void)
break; break;
} }
case ISO7816_S_IN_TPDU: /* More TPDU data incoming */ case ISO7816_S_IN_TPDU: /* More TPDU data incoming */
if (ISO7816_S_WAIT_TPDU == iso_state) { if (ISO7816_S_WAIT_TPDU==iso_state) {
change_state(ISO7816_S_IN_TPDU); change_state(ISO7816_S_IN_TPDU);
} }
process_byte_tpdu(byte); process_byte_tpdu(byte);
@@ -1049,52 +935,20 @@ void Sniffer_run(void)
/* Handle flags */ /* Handle flags */
if (change_flags) { /* WARNING this is not synced with the data buffer handling */ if (change_flags) { /* WARNING this is not synced with the data buffer handling */
if (change_flags & SNIFF_CHANGE_FLAG_RESET_ASSERT) { if (change_flags&SNIFF_CHANGE_FLAG_TIMEOUT_WT) {
switch (iso_state) {
case ISO7816_S_IN_ATR:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_atr(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete ATR to host software using USB */
break;
case ISO7816_S_IN_TPDU:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete PPS to host software using USB */
break;
case ISO7816_S_IN_PPS_REQ:
case ISO7816_S_IN_PPS_RSP:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_pps(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete TPDU to host software using USB */
break;
default:
break;
}
if (ISO7816_S_RESET != iso_state) {
change_state(ISO7816_S_RESET);
printf("reset asserted\n\r");
}
}
if (change_flags & SNIFF_CHANGE_FLAG_RESET_DEASSERT) {
if (ISO7816_S_WAIT_ATR != iso_state) {
change_state(ISO7816_S_WAIT_ATR);
printf("reset de-asserted\n\r");
}
}
if (change_flags & SNIFF_CHANGE_FLAG_TIMEOUT_WT) {
/* Use timeout to detect interrupted data transmission */ /* Use timeout to detect interrupted data transmission */
switch (iso_state) { switch (iso_state) {
case ISO7816_S_IN_ATR: case ISO7816_S_IN_ATR:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */ usb_send_atr(false); /* send incomplete ATR to host software using USB */
usb_send_atr(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete ATR to host software using USB */
change_state(ISO7816_S_WAIT_ATR); change_state(ISO7816_S_WAIT_ATR);
break; break;
case ISO7816_S_IN_TPDU: case ISO7816_S_IN_TPDU:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */ usb_send_tpdu(false); /* send incomplete PPS to host software using USB */
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete PPS to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); change_state(ISO7816_S_WAIT_TPDU);
break; break;
case ISO7816_S_IN_PPS_REQ: case ISO7816_S_IN_PPS_REQ:
case ISO7816_S_IN_PPS_RSP: case ISO7816_S_IN_PPS_RSP:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */ usb_send_pps(false); /* send incomplete TPDU to host software using USB */
usb_send_pps(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete TPDU to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); change_state(ISO7816_S_WAIT_TPDU);
break; break;
default: default:

Some files were not shown because too many files have changed in this diff Show More