mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-19 23:08:34 +03:00
Compare commits
203 Commits
0.4
...
kevin/card
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b149ea3039 | ||
|
|
6b0afb3761 | ||
|
|
90abc09cf3 | ||
|
|
76c2eebae2 | ||
|
|
e3d516745d | ||
|
|
0cbe9a4fb6 | ||
|
|
1a88fd8066 | ||
|
|
73d4d49b83 | ||
|
|
558f25237e | ||
|
|
7fd7674577 | ||
|
|
7a060da30f | ||
|
|
5b2ade08dd | ||
|
|
6470d999b7 | ||
|
|
46a1f167f7 | ||
|
|
0954e3b283 | ||
|
|
c2a3836777 | ||
|
|
a2b2df235a | ||
|
|
af7544aa9d | ||
|
|
f6f507ab3c | ||
|
|
844c6608cf | ||
|
|
8ed780ec35 | ||
|
|
ad3414fdf7 | ||
|
|
2fdcf3b38d | ||
|
|
7e5cda5732 | ||
|
|
032fc5f844 | ||
|
|
b1f99c909c | ||
|
|
53b4e593aa | ||
|
|
dc85fbc3e1 | ||
|
|
66ffb6d493 | ||
|
|
5b5d24ebf3 | ||
|
|
faf1e88e48 | ||
|
|
64f69fc4ac | ||
|
|
6303c39a00 | ||
|
|
ad0958e9e3 | ||
|
|
4f3a0356a4 | ||
|
|
7d5d011095 | ||
|
|
1dbcf62295 | ||
|
|
e5f891a825 | ||
|
|
a6bd7178b5 | ||
|
|
ba15387b09 | ||
|
|
c171112994 | ||
|
|
29200c6223 | ||
|
|
80d9476602 | ||
|
|
e2b0f971e5 | ||
|
|
e07640c35a | ||
|
|
82b628524f | ||
|
|
cb78b55c26 | ||
|
|
77ff745cca | ||
|
|
bd9d94994d | ||
|
|
95fac3aeab | ||
|
|
c17bf77ecc | ||
|
|
c394109964 | ||
|
|
888f196595 | ||
|
|
f7f61cd10f | ||
|
|
0e95f53588 | ||
|
|
76ef811a4e | ||
|
|
fecfa2aa51 | ||
|
|
c428516efa | ||
|
|
37e7861c4d | ||
|
|
ff3d84922d | ||
|
|
9547e419eb | ||
|
|
8daba9cc9a | ||
|
|
d5f583da60 | ||
|
|
04ccb770fd | ||
|
|
910e6830b9 | ||
|
|
9cccb2bab5 | ||
|
|
8a4fba5ea2 | ||
|
|
1b39fd31ee | ||
|
|
0f4abf5eaa | ||
|
|
1836ac0761 | ||
|
|
dd36d9b010 | ||
|
|
8b8e58b00e | ||
|
|
8f70c3eb1f | ||
|
|
ebe672e926 | ||
|
|
d8ebd6ab77 | ||
|
|
738a04aefb | ||
|
|
2a44dc598d | ||
|
|
ec396bf402 | ||
|
|
697199676e | ||
|
|
8e84f8125c | ||
|
|
d1c6536154 | ||
|
|
352809992c | ||
|
|
a71a6f48cb | ||
|
|
57b60d23cf | ||
|
|
b60538888f | ||
|
|
680bdaba96 | ||
|
|
f66af0c640 | ||
|
|
5f6b8717a4 | ||
|
|
ac0843af83 | ||
|
|
31ed8029b7 | ||
|
|
3b7624c120 | ||
|
|
f000831d72 | ||
|
|
b37bda0b55 | ||
|
|
c6b968067d | ||
|
|
a95bb1e85d | ||
|
|
da5578bd85 | ||
|
|
d975411511 | ||
|
|
a2fccba96c | ||
|
|
411428eb5e | ||
|
|
f82f0f6eff | ||
|
|
55f0612c8e | ||
|
|
33d1eb73fd | ||
|
|
93717e43b3 | ||
|
|
9a12d68c74 | ||
|
|
efbcf38afb | ||
|
|
9918c2840e | ||
|
|
d24e9bde26 | ||
|
|
2bdaa73aff | ||
|
|
fcf2743552 | ||
|
|
d44cb80bc5 | ||
|
|
9e29a3eb37 | ||
|
|
bf6b1b1a3e | ||
|
|
4cbdc7cf18 | ||
|
|
86f48fc962 | ||
|
|
1200a5228f | ||
|
|
fe763b7698 | ||
|
|
c9bd715289 | ||
|
|
35e8bdf879 | ||
|
|
709a431ab9 | ||
|
|
30f90a78fc | ||
|
|
7406337a7f | ||
|
|
6e3f1121e6 | ||
|
|
de97fd25bd | ||
|
|
012940f48e | ||
|
|
e2f84f6a8b | ||
|
|
4d6a4b949c | ||
|
|
a1012b170a | ||
|
|
42bd026416 | ||
|
|
638cec820f | ||
|
|
00ec89d73f | ||
|
|
cf59919494 | ||
|
|
11914d9658 | ||
|
|
3113e3d2e5 | ||
|
|
9def7631ba | ||
|
|
ca9e4bf4ba | ||
|
|
8210ec3f62 | ||
|
|
8fa6ff5979 | ||
|
|
866d20b10e | ||
|
|
4fe99fad59 | ||
|
|
7be52ec1ce | ||
|
|
a2b367633c | ||
|
|
927ffb46eb | ||
|
|
d7a6de57d2 | ||
|
|
353351ddf4 | ||
|
|
4091d78c4b | ||
|
|
ee62a9da56 | ||
|
|
45ad62d8d4 | ||
|
|
2c4e2af21f | ||
|
|
7b73462442 | ||
|
|
36abece0b1 | ||
|
|
f9997e9d26 | ||
|
|
05cc7f6531 | ||
|
|
46893451de | ||
|
|
cb6e20596e | ||
|
|
bb2eb19fb1 | ||
|
|
9d90d284ed | ||
|
|
ebe8b2069c | ||
|
|
105c1dce4f | ||
|
|
1cfc2614dd | ||
|
|
a9bca48914 | ||
|
|
eac1bec428 | ||
|
|
51c128bc35 | ||
|
|
869dbfafe4 | ||
|
|
80303c135b | ||
|
|
d86cab0080 | ||
|
|
b73f0a00bc | ||
|
|
f5869d4a59 | ||
|
|
4136c242a8 | ||
|
|
318309f30f | ||
|
|
0828b914e7 | ||
|
|
76be7c806e | ||
|
|
a38a126361 | ||
|
|
6822716428 | ||
|
|
a93f7273b3 | ||
|
|
432ba5140e | ||
|
|
849d20e29e | ||
|
|
e48d6f2321 | ||
|
|
af616ec4e2 | ||
|
|
6051e126da | ||
|
|
7f62c24532 | ||
|
|
75cf93e04d | ||
|
|
2afd57f00a | ||
|
|
0633b25974 | ||
|
|
c1e2254854 | ||
|
|
27f5fc681c | ||
|
|
7b250bfc8d | ||
|
|
ed75c62acf | ||
|
|
5c081911a9 | ||
|
|
5e6e8dcbde | ||
|
|
c35998e20d | ||
|
|
ba2ad563cc | ||
|
|
fc87c24326 | ||
|
|
f231541601 | ||
|
|
119624f46f | ||
|
|
7b36306113 | ||
|
|
eb50c9f914 | ||
|
|
965d5c918a | ||
|
|
514c6d1da0 | ||
|
|
e7f2f9a5e0 | ||
|
|
4e837d45db | ||
|
|
b52b886186 | ||
|
|
c47fc5febf | ||
|
|
02d0ec6e08 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,3 +21,4 @@ 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
|
||||||
|
|||||||
27
Makefile
Normal file
27
Makefile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
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:
|
||||||
|
make -C host
|
||||||
|
|
||||||
|
clean: fw-clean
|
||||||
|
make -C host clean
|
||||||
|
|
||||||
|
install:
|
||||||
|
make -C firmware install
|
||||||
|
make -C host install
|
||||||
39
README.md
Normal file
39
README.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
SIMtrace v2.0
|
||||||
|
=============
|
||||||
|
|
||||||
|
This is the repository for the next-generation SIMtrace devices,
|
||||||
|
providing abilities to trace the communication between (U)SIM card and
|
||||||
|
phone, remote (U)SIM card forward, (U)SIM man-in-the-middle, and more.
|
||||||
|
|
||||||
|
This is under heavy development, and right now it is not surprising if
|
||||||
|
things still break on a daily basis.
|
||||||
|
|
||||||
|
NOTE: Nothing in this repository applies to the SIMtrace v1.x hardware
|
||||||
|
or its associated firmware. SIMtrace v1.x is based on a different CPU /
|
||||||
|
microcontroller architecture and uses a completely different software
|
||||||
|
stack and host software.
|
||||||
|
|
||||||
|
Supported Hardware
|
||||||
|
------------------
|
||||||
|
|
||||||
|
At this point, the primary development target is still the OWHW + sysmoQMOD
|
||||||
|
device, but we expect to add support for a SAM3 based SIMtrace hardware
|
||||||
|
board soon.
|
||||||
|
|
||||||
|
The goal is to support the following devices:
|
||||||
|
|
||||||
|
* Osmocom SIMtrace 1.x with SAM3 controller
|
||||||
|
** this is open hardware and schematics / PCB design is published
|
||||||
|
* sysmocom sysmoQMOD (with 4 Modems, 4 SIM slots and 2 SAM3)
|
||||||
|
** this is a proprietary device, publicly available from sysmocom
|
||||||
|
* sysmocom OWHW (with 2 Modems and 1 SAM3 onboard)
|
||||||
|
** this is not publicly available hardware, but still supported
|
||||||
|
|
||||||
|
This Repository
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This repository contains several directory
|
||||||
|
|
||||||
|
* firmware - the firmware to run on the actual devices
|
||||||
|
* hardware - some information related to the hardware
|
||||||
|
* host - Programs to use on the USB host to interface with the hardware
|
||||||
79
contrib/jenkins.sh
Executable file
79
contrib/jenkins.sh
Executable file
@@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
TOPDIR=`pwd`
|
||||||
|
|
||||||
|
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
|
||||||
|
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
publish="$1"
|
||||||
|
base="$PWD"
|
||||||
|
deps="$base/deps"
|
||||||
|
inst="$deps/install"
|
||||||
|
export deps inst
|
||||||
|
|
||||||
|
osmo-clean-workspace.sh
|
||||||
|
|
||||||
|
mkdir "$deps" || true
|
||||||
|
|
||||||
|
osmo-build-dep.sh libosmocore "" '--disable-doxygen --enable-gnutls'
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
export LD_LIBRARY_PATH="$inst/lib"
|
||||||
|
|
||||||
|
BUILDS=""
|
||||||
|
BUILDS+="simtrace/dfu simtrace/trace simtrace/cardem "
|
||||||
|
BUILDS+="qmod/dfu qmod/cardem "
|
||||||
|
BUILDS+="owhw/dfu owhw/cardem "
|
||||||
|
|
||||||
|
cd $TOPDIR/firmware
|
||||||
|
for build in $BUILDS; do
|
||||||
|
board=`echo $build | cut -d "/" -f 1`
|
||||||
|
app=`echo $build | cut -d "/" -f 2`
|
||||||
|
echo
|
||||||
|
echo "=============== $board / $app START =============="
|
||||||
|
make BOARD="$board" APP="$app"
|
||||||
|
echo "=============== $board / $app RES:$? =============="
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=============== FIRMWARE TESTS ==========="
|
||||||
|
cd $TOPDIR/firmware/test
|
||||||
|
make clean
|
||||||
|
make
|
||||||
|
./card_emu_test
|
||||||
|
make clean
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=============== HOST START =============="
|
||||||
|
cd $TOPDIR/host
|
||||||
|
make clean
|
||||||
|
make
|
||||||
|
make clean
|
||||||
|
|
||||||
|
if [ "x$publish" = "x--publish" ]; then
|
||||||
|
echo
|
||||||
|
echo "=============== UPLOAD BUILD =============="
|
||||||
|
|
||||||
|
cat > "$WORKSPACE/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=$WORKSPACE/known_hosts' -p 48"
|
||||||
|
rsync -avz --delete -e "$SSH_COMMAND" $TOPDIR/firmware/bin/*.bin binaries@rita.osmocom.org:web-files/simtrace2/firmware/
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
11
debian/changelog
vendored
Normal file
11
debian/changelog
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
9
|
||||||
31
debian/control
vendored
Normal file
31
debian/control
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
Source: simtrace2
|
||||||
|
Maintainer: Harald Welte <laforge@gnumonks.org>
|
||||||
|
Section: devel
|
||||||
|
Priority: optional
|
||||||
|
Build-Depends: debhelper (>= 9),
|
||||||
|
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}
|
||||||
|
Recommends: simtrace2-firmware
|
||||||
|
Description: Host utilities to communicate with SIMtrace2 USB Devices.
|
||||||
4
debian/rules
vendored
Executable file
4
debian/rules
vendored
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
1
debian/simtrace2-firmware.install
vendored
Normal file
1
debian/simtrace2-firmware.install
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
usr/share/simtrace2/*.bin
|
||||||
1
debian/simtrace2-utils.install
vendored
Normal file
1
debian/simtrace2-utils.install
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
usr/bin/simtrace2-*
|
||||||
@@ -141,13 +141,12 @@ 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 += -Wsign-compare -Waggregate-return
|
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
|
||||||
@@ -192,7 +191,7 @@ $(OUTPUT)-combined.bin: $(BIN)/$(BOARD)-dfu-flash-padded.bin $(OUTPUT)-dfu.bin
|
|||||||
cat $^ > $@
|
cat $^ > $@
|
||||||
|
|
||||||
$(BIN) $(OBJ):
|
$(BIN) $(OBJ):
|
||||||
mkdir $@
|
mkdir -p $@
|
||||||
|
|
||||||
usbstring/usbstring: usbstring/usbstring.c
|
usbstring/usbstring: usbstring/usbstring.c
|
||||||
gcc $^ -o $@
|
gcc $^ -o $@
|
||||||
@@ -229,8 +228,12 @@ program:
|
|||||||
|
|
||||||
SERIAL ?= /dev/ttyUSB0
|
SERIAL ?= /dev/ttyUSB0
|
||||||
log:
|
log:
|
||||||
stty -F $(SERIAL) 115200
|
stty -F $(SERIAL) 921600
|
||||||
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 -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
|
||||||
|
|||||||
@@ -1,70 +1,81 @@
|
|||||||
|
This is the source code for SIMtrace 2 firmwares.
|
||||||
|
|
||||||
== BOARDS
|
= Hardware
|
||||||
|
|
||||||
A board defines a given circuit board, i.e. SIMtrace, OWHW, QMOD
|
== Micro-Controller
|
||||||
|
|
||||||
It defines the given hardware model for which the program is to be
|
The firmware is for Microchip (formerly Atmel) ATSAM3S4B micro-controllers (MCU).
|
||||||
compiled.
|
Product page: https://www.microchip.com/wwwproducts/en/ATSAM3S4B
|
||||||
|
Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-6500-32-bit-Cortex-M3-Microcontroller-SAM3S4-SAM3S2-SAM3S1_Datasheet.pdf
|
||||||
|
|
||||||
|
Note: The SAM3S is now not recommended for new designs.
|
||||||
|
It can be replaced by the pin-compatible SAM4S.
|
||||||
|
The MCU can be specified using the environment variable `CHIP` (set to `sam3s4` per default) for future MCU support.
|
||||||
|
|
||||||
|
== Boards
|
||||||
|
|
||||||
|
The SIMtrace 2 firmware supports multiple boards.
|
||||||
|
A board defines a given circuit board.
|
||||||
|
While compiling the firmware, set the target board using the `BOARD` environment variable (set to `qmod` per default).
|
||||||
|
The supported boards correspond to sub-folders under `libboard`.
|
||||||
|
|
||||||
Current boards supported are:
|
Current boards supported are:
|
||||||
* simtrace: The good old Osmocom SIMtrace PCB with SAM3 instead of
|
|
||||||
SAM7, open hardware.
|
|
||||||
* qmod: A sysmocom-proprietary quad mPCIe carrier board, publicly available
|
|
||||||
* owhw: An undisclosed sysmocom-internal board, not publicly available
|
|
||||||
|
|
||||||
== APPLICATIONS
|
* `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware.
|
||||||
|
* `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available
|
||||||
|
* `owhw`: An undisclosed sysmocom-internal board, not publicly available
|
||||||
|
|
||||||
An application is a specific piece of software with given
|
= Firmware
|
||||||
functionality.
|
|
||||||
|
|
||||||
== ENVIRONMENTS
|
== Library
|
||||||
|
|
||||||
|
The firmware uses the manufacturer provided Software Package (SoftPack) micro-controller library.
|
||||||
|
The original library is available at https://www.microchip.com/design-centers/32-bit/softpacks/legacy-softpacks .
|
||||||
|
Version 2.1 from 2001 is used: http://ww1.microchip.com/downloads/en/DeviceDoc/SAM3S_softpack_2.1_for_CodeSourcery_2010q1.zip
|
||||||
|
The SIMtrace 2 project uses the `libboard_sam3s-ek`, `libchip_sam3s`, and `usb` sub-libraries, saved in `atmel_softpack_libraries` (with local modifications).
|
||||||
|
|
||||||
|
Note: SoftPack is the legacy micro-controller library.
|
||||||
|
This library is now replaced by the Advanced Software Framework (ASF): https://www.microchip.com/avr-support/advanced-software-framework-(asf) .
|
||||||
|
The SAM3S ASF documentation is available at http://asf.atmel.com/docs/latest/sam3s/html/index.html .
|
||||||
|
|
||||||
|
== Applications
|
||||||
|
|
||||||
|
An application is a specific piece of software with given functionality.
|
||||||
|
While compiling the firmware, set the target application using the `APP` environment variable (set to `dfu` per default).
|
||||||
|
The supported applications correspond to sub-folder under `apps`.
|
||||||
|
|
||||||
|
Current applications supported are:
|
||||||
|
|
||||||
|
* `dfu`: The USB DFU bootloader to flash further main appliction firmwares.
|
||||||
|
* `ccid`: To use SIMtrace 2 as USB CCID smartcard reader.
|
||||||
|
* `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)
|
||||||
|
* `triple_play`: To support the three previous functionalities, using USB configurations.
|
||||||
|
|
||||||
|
== Memories
|
||||||
|
|
||||||
|
Firmwares can be run from several memory locations:
|
||||||
|
|
||||||
An environment is a runtime environment, typically defined by a linker
|
|
||||||
script. The current runtime environments include
|
|
||||||
* flash: Run natively from start of flash memory
|
* flash: Run natively from start of flash memory
|
||||||
* dfu: Run after a DFU bootloader from an offset after the first 16k
|
* dfu: Run after a DFU bootloader from an offset after the first 16k of flash (the first 16k are reserved for the bootloader)
|
||||||
of flash (the first 16k are reserved for the bootloader)
|
|
||||||
* ram: Run from within the RAM of the chip, downloaded via JTAG/SWD
|
* ram: Run from within the RAM of the chip, downloaded via JTAG/SWD
|
||||||
|
|
||||||
|
|
||||||
== Building
|
== Building
|
||||||
|
|
||||||
A given software build is made for a specific combination of an APP
|
A given firmware build is made for a specific combination of an application `APP` running in a certain memory `MEM` on a given board `BOARD`.
|
||||||
running in a certain ENVIRONMENT on a given BOARD.
|
When building using `make`, set the target application using the `APP` environment variable and target board using the `BOARD` environment variable, e.g.:
|
||||||
|
|
||||||
A Makefile is provided. It will create output files in the format
|
|
||||||
bin/$(BOARD)-$(APP)-$(ENV).{elf,bin}
|
|
||||||
|
|
||||||
You can specify the APP and BOARD to build when calling make, like
|
|
||||||
e.g.
|
|
||||||
* make APP=cardem BOARD=qmod
|
* make APP=cardem BOARD=qmod
|
||||||
* make APP=dfu BOARD=qmod
|
* make APP=dfu BOARD=qmod
|
||||||
|
|
||||||
|
The Makefile will create output files in the format: `bin/$(BOARD)-$(APP)-$(MEM).{elf,bin}`
|
||||||
|
|
||||||
The level of debug messages can be altered at compile time:
|
The level of debug messages can be altered at compile time:
|
||||||
```
|
```
|
||||||
$ make TRACE_LEVEL=4
|
$ make TRACE_LEVEL=4
|
||||||
```
|
```
|
||||||
Accepted values: 0 (NO_TRACE) to 5 (DEBUG)
|
Accepted values: 0 (NO_TRACE) to 5 (DEBUG)
|
||||||
|
|
||||||
== Flashing
|
= Flashing
|
||||||
|
|
||||||
For flashing the firmware, there are at least two options.
|
To flash a firmware image follow the instructions provided in the [wiki](https://projects.osmocom.org/projects/simtrace2/wiki/).
|
||||||
|
|
||||||
=== Using JTAG + OpenOCD to flash the DFU bootloader
|
|
||||||
|
|
||||||
The first one is using openocd and a JTAG key.
|
|
||||||
For this option, a JTAG connector has to be soldered onto the board, which is not attached per default.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ openocd -f openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/$(BOARD)-dfu-flash.bin 0" -c "reset" -c "shutdown"
|
|
||||||
```
|
|
||||||
|
|
||||||
=== Using bossac to flash the DFU bootloader
|
|
||||||
|
|
||||||
The second option is using rumba for flashing. No further hardware has to be provided for this option.
|
|
||||||
|
|
||||||
FIXME
|
|
||||||
|
|
||||||
=== Using DFU to flash application
|
|
||||||
|
|
||||||
FIXME
|
|
||||||
|
|||||||
22
firmware/TODO.txt
Normal file
22
firmware/TODO.txt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
== Important DFU topics / reliability ==
|
||||||
|
x some kind of DFU fallback / boot cycle counter ?
|
||||||
|
* CRC check of image before attempting to execute it ?
|
||||||
|
x Keep WDT running while in DFU or app
|
||||||
|
? USB control request for flash erase
|
||||||
|
|
||||||
|
== QModem related ==
|
||||||
|
x new vendor/product ID for hub and SAM3s
|
||||||
|
* board-specfic string descriptors
|
||||||
|
* re-mapping of USB ports in EEPROM
|
||||||
|
|
||||||
|
== Lower Priority ==
|
||||||
|
* unique serial number in iSerial?
|
||||||
|
* printing of banner from generic function
|
||||||
|
* board_main_top() automatically before calling main()
|
||||||
|
x compile-time USB string generation
|
||||||
|
* shared USB strings for DFU and runtime
|
||||||
|
* version detection voltage ranges
|
||||||
|
* locking of bootloader pages?
|
||||||
|
* debug console command for switch-to-dfu
|
||||||
|
* read CPU reset cause (and time?) via USB
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
C_FILES += $(C_LIBUSB_RT)
|
C_FILES += $(C_LIBUSB_RT)
|
||||||
|
|
||||||
C_FILES += card_emu.c ccid.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
|
C_FILES += card_emu.c iso7816_3.c iso7816_4.c mode_cardemu.c simtrace_iso7816.c usb.c
|
||||||
|
|||||||
@@ -1,4 +1,22 @@
|
|||||||
// FIXME: Copyright license here
|
/* SIMtrace 2 firmware card emulation application
|
||||||
|
*
|
||||||
|
* (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
|
||||||
*------------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------------*/
|
||||||
@@ -6,7 +24,7 @@
|
|||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "simtrace.h"
|
#include "simtrace.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "osmocom/core/timer.h"
|
#include <osmocom/core/timer.h>
|
||||||
|
|
||||||
unsigned int g_unique_id[4];
|
unsigned int g_unique_id[4];
|
||||||
|
|
||||||
@@ -84,16 +102,22 @@ 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)
|
||||||
{
|
{
|
||||||
|
if (config_func_ptrs[simtrace_config].usart1_irq)
|
||||||
config_func_ptrs[simtrace_config].usart1_irq();
|
config_func_ptrs[simtrace_config].usart1_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
void USART0_IrqHandler(void)
|
void USART0_IrqHandler(void)
|
||||||
{
|
{
|
||||||
|
if (config_func_ptrs[simtrace_config].usart0_irq)
|
||||||
config_func_ptrs[simtrace_config].usart0_irq();
|
config_func_ptrs[simtrace_config].usart0_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +130,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +146,12 @@ extern int main(void)
|
|||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
|
|
||||||
led_init();
|
led_init();
|
||||||
led_blink(LED_RED, BLINK_3O_5F);
|
led_blink(LED_RED, BLINK_ALWAYS_ON);
|
||||||
|
led_blink(LED_GREEN, BLINK_ALWAYS_ON);
|
||||||
|
|
||||||
/* Enable watchdog for 500ms, with no window */
|
/* Enable watchdog for 2000ms, 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(500) << 16) | WDT_GetPeriod(500));
|
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
|
||||||
|
|
||||||
PIO_InitializeInterrupts(0);
|
PIO_InitializeInterrupts(0);
|
||||||
|
|
||||||
@@ -133,14 +159,29 @@ extern int main(void)
|
|||||||
|
|
||||||
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 "\n\r"
|
||||||
|
"(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r"
|
||||||
"=============================================================================\n\r");
|
"=============================================================================\n\r");
|
||||||
|
|
||||||
TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
|
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
|
||||||
|
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]);
|
||||||
TRACE_INFO("Reset Cause: 0x%x\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
|
uint8_t reset_cause = (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();
|
||||||
|
|
||||||
@@ -169,7 +210,9 @@ 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");
|
||||||
@@ -197,11 +240,17 @@ 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();
|
||||||
|
}
|
||||||
|
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;
|
||||||
} else {
|
} else {
|
||||||
|
if (config_func_ptrs[simtrace_config].run) {
|
||||||
config_func_ptrs[simtrace_config].run();
|
config_func_ptrs[simtrace_config].run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,28 @@
|
|||||||
|
/* 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>
|
||||||
|
|
||||||
@@ -10,6 +30,14 @@
|
|||||||
#define ALTIF_FLASH 1
|
#define ALTIF_FLASH 1
|
||||||
|
|
||||||
unsigned int g_unique_id[4];
|
unsigned int g_unique_id[4];
|
||||||
|
/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */
|
||||||
|
static bool watchdog_configured = false;
|
||||||
|
|
||||||
|
/* There is not enough space in the 16 KiB DFU bootloader to include led.h functions */
|
||||||
|
#ifdef PINS_LEDS
|
||||||
|
/** LED pin configurations */
|
||||||
|
static const Pin pinsLeds[] = { PINS_LEDS } ;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* Callbacks
|
* Callbacks
|
||||||
@@ -21,46 +49,85 @@ unsigned int g_unique_id[4];
|
|||||||
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
|
#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
|
||||||
#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
|
#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
|
||||||
|
|
||||||
/* incoming call-back: Host has transfered 'len' bytes (stored at
|
/* incoming call-back: Host has transferred 'len' bytes (stored at
|
||||||
* 'data'), which we shall write to 'offset' into the partition
|
* 'data'), which we shall write to 'offset' into the partition
|
||||||
* associated with 'altif'. Guaranted to be les than
|
* associated with 'altif'. Guaranted to be less than
|
||||||
* BOARD_DFU_PAGE_SIZE */
|
* BOARD_DFU_PAGE_SIZE */
|
||||||
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
|
int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
|
||||||
uint8_t *data, unsigned int len)
|
uint8_t *data, unsigned int len)
|
||||||
{
|
{
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
|
unsigned int i;
|
||||||
int rc;
|
int rc;
|
||||||
|
/* address of the last allocated variable on the stack */
|
||||||
|
uint32_t stack_addr = (uint32_t)&rc;
|
||||||
|
/* kick the dog to have enough time to flash */
|
||||||
|
if (watchdog_configured) {
|
||||||
|
WDT_Restart(WDT);
|
||||||
|
}
|
||||||
|
|
||||||
printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
|
#if TRACE_LEVEL >= TRACE_LEVEL_INFO
|
||||||
|
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
|
||||||
|
PIO_Clear(&pinsLeds[LED_NUM_RED]);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (altif) {
|
switch (altif) {
|
||||||
case ALTIF_RAM:
|
case ALTIF_RAM:
|
||||||
addr = RAM_ADDR(offset);
|
addr = RAM_ADDR(offset);
|
||||||
if (addr > IRAM_ADDR + IRAM_SIZE) {
|
if (addr < IRAM_ADDR || addr + len >= IRAM_ADDR + IRAM_SIZE || addr + len >= stack_addr) {
|
||||||
g_dfu->state = DFU_STATE_dfuERROR;
|
g_dfu->state = DFU_STATE_dfuERROR;
|
||||||
g_dfu->status = DFU_STATUS_errADDRESS;
|
g_dfu->status = DFU_STATUS_errADDRESS;
|
||||||
return DFU_RET_STALL;
|
rc = DFU_RET_STALL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
memcpy((void *)addr, data, len);
|
memcpy((void *)addr, data, len);
|
||||||
return DFU_RET_ZLP;
|
rc = DFU_RET_ZLP;
|
||||||
|
break;
|
||||||
case ALTIF_FLASH:
|
case ALTIF_FLASH:
|
||||||
addr = FLASH_ADDR(offset);
|
addr = FLASH_ADDR(offset);
|
||||||
if (addr > IFLASH_ADDR + IFLASH_SIZE) {
|
if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) {
|
||||||
g_dfu->state = DFU_STATE_dfuERROR;
|
g_dfu->state = DFU_STATE_dfuERROR;
|
||||||
g_dfu->status = DFU_STATUS_errADDRESS;
|
g_dfu->status = DFU_STATUS_errADDRESS;
|
||||||
return DFU_RET_STALL;
|
rc = DFU_RET_STALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rc = FLASHD_Unlock(addr, addr + len, 0, 0);
|
||||||
|
if (rc != 0) {
|
||||||
|
TRACE_ERROR("DFU download flash unlock failed\n\r");
|
||||||
|
rc = DFU_RET_STALL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
rc = FLASHD_Write(addr, data, len);
|
rc = FLASHD_Write(addr, data, len);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
/* FIXME: set error codes */
|
TRACE_ERROR("DFU download flash erase failed\n\r");
|
||||||
return DFU_RET_STALL;
|
rc = DFU_RET_STALL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return DFU_RET_ZLP;
|
for (i = 0; i < len; i++) {
|
||||||
|
if (((uint8_t*)addr)[i]!=data[i]) {
|
||||||
|
TRACE_ERROR("DFU download flash data written not correct\n\r");
|
||||||
|
rc = DFU_RET_STALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = DFU_RET_ZLP;
|
||||||
|
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);
|
||||||
return DFU_RET_STALL;
|
rc = DFU_RET_STALL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PINS_LEDS
|
||||||
|
PIO_Set(&pinsLeds[LED_NUM_RED]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* incoming call-back: Host has requested to read back 'req_len' bytes
|
/* incoming call-back: Host has requested to read back 'req_len' bytes
|
||||||
@@ -105,31 +172,10 @@ int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
|
|||||||
return req_len;
|
return req_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_has_loopback_jumper(void)
|
/* can be overridden by board specific code, e.g. by pushbutton */
|
||||||
|
WEAK int board_override_enter_dfu(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
|
||||||
const Pin uart_loopback_pins[] = {
|
|
||||||
{PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT},
|
|
||||||
{PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Configure UART pins as I/O */
|
|
||||||
PIO_Configure(uart_loopback_pins, PIO_LISTSIZE(uart_loopback_pins));
|
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
|
||||||
/* Set TxD high; abort if RxD doesn't go high either */
|
|
||||||
PIO_Set(&uart_loopback_pins[1]);
|
|
||||||
if (!PIO_Get(&uart_loopback_pins[0]))
|
|
||||||
return 0;
|
return 0;
|
||||||
/* Set TxD low, abort if RxD doesn't go low either */
|
|
||||||
PIO_Clear(&uart_loopback_pins[1]);
|
|
||||||
if (PIO_Get(&uart_loopback_pins[0]))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* if we reached here, RxD always follows TxD and thus a
|
|
||||||
* loopback jumper has been placed on RxD/TxD, and we will boot
|
|
||||||
* into DFU unconditionally */
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* using this function we can determine if we should enter DFU mode
|
/* using this function we can determine if we should enter DFU mode
|
||||||
@@ -137,22 +183,30 @@ static int uart_has_loopback_jumper(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 (uart_has_loopback_jumper())
|
if (board_override_enter_dfu()) {
|
||||||
return 1;
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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) ||
|
if ((app_part[0] < IRAM_ADDR) || ((uint8_t *)app_part[0] > IRAM_END)) {
|
||||||
((uint8_t *)app_part[0] > IRAM_END))
|
return 3;
|
||||||
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 1;
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -180,15 +234,17 @@ extern int main(void)
|
|||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
|
uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
|
||||||
|
|
||||||
#if 0
|
/* Enable watchdog for 2000ms, with no window */
|
||||||
led_init();
|
|
||||||
led_blink(LED_GREEN, BLINK_3O_30F);
|
|
||||||
led_blink(LED_RED, BLINK_3O_30F);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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(500) << 16) | WDT_GetPeriod(500));
|
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
|
||||||
|
watchdog_configured = true;
|
||||||
|
|
||||||
|
#ifdef PINS_LEDS
|
||||||
|
/* Configure LED */
|
||||||
|
PIO_Configure(pinsLeds, sizeof(pinsLeds));
|
||||||
|
PIO_Set(&pinsLeds[LED_NUM_RED]);
|
||||||
|
PIO_Clear(&pinsLeds[LED_NUM_GREEN]);
|
||||||
|
#endif
|
||||||
|
|
||||||
PIO_InitializeInterrupts(0);
|
PIO_InitializeInterrupts(0);
|
||||||
|
|
||||||
@@ -196,7 +252,8 @@ extern int main(void)
|
|||||||
|
|
||||||
printf("\n\r\n\r"
|
printf("\n\r\n\r"
|
||||||
"=============================================================================\n\r"
|
"=============================================================================\n\r"
|
||||||
"DFU bootloader %s for board %s (C) 2010-2017 by Harald Welte\n\r"
|
"DFU bootloader %s for board %s\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);
|
||||||
|
|
||||||
@@ -204,7 +261,36 @@ 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%x\n\r", reset_cause);
|
TRACE_INFO("Reset Cause: 0x%lx\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)
|
||||||
@@ -213,6 +299,19 @@ extern int main(void)
|
|||||||
board_main_top();
|
board_main_top();
|
||||||
|
|
||||||
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 */
|
||||||
|
#ifdef PIN_USB_PULLUP
|
||||||
|
const Pin usb_dp_pullup = PIN_USB_PULLUP;
|
||||||
|
PIO_Configure(&usb_dp_pullup, 1);
|
||||||
|
PIO_Set(&usb_dp_pullup);
|
||||||
|
#endif
|
||||||
|
USBD_HAL_Suspend();
|
||||||
|
mdelay(20);
|
||||||
|
#ifdef PIN_USB_PULLUP
|
||||||
|
PIO_Clear(&usb_dp_pullup);
|
||||||
|
#endif
|
||||||
|
USBD_HAL_Activate();
|
||||||
|
|
||||||
USBDFU_Initialize(&dfu_descriptors);
|
USBDFU_Initialize(&dfu_descriptors);
|
||||||
|
|
||||||
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
|
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
|
||||||
@@ -229,7 +328,9 @@ extern int main(void)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize the flash to be able to write it, using the IAP ROM code */
|
||||||
FLASHD_Initialize(BOARD_MCK, 1);
|
FLASHD_Initialize(BOARD_MCK, 1);
|
||||||
|
|
||||||
TRACE_INFO("entering main loop...\n\r");
|
TRACE_INFO("entering main loop...\n\r");
|
||||||
while (1) {
|
while (1) {
|
||||||
WDT_Restart(WDT);
|
WDT_Restart(WDT);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
sysmocom - s.f.m.c. GmbH
|
sysmocom - s.f.m.c. GmbH
|
||||||
SIMtrace 2 compatible device
|
SIMtrace 2 compatible device
|
||||||
DFU (Device Firmare Upgrade)
|
DFU (Device Firmware Upgrade)
|
||||||
RAM
|
RAM
|
||||||
Flash (Application Partition)
|
Flash (Application Partition)
|
||||||
|
|||||||
3
firmware/apps/trace/Makefile
Normal file
3
firmware/apps/trace/Makefile
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
C_FILES += $(C_LIBUSB_RT)
|
||||||
|
|
||||||
|
C_FILES += iso7816_4.c iso7816_fidi.c simtrace_iso7816.c sniffer.c usb.c
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
/* SIMtrace 2 firmware sniffer application
|
||||||
|
*
|
||||||
|
* (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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Headers
|
||||||
|
*------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "simtrace.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "osmocom/core/timer.h"
|
||||||
|
|
||||||
|
unsigned int g_unique_id[4];
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Internal variables
|
||||||
|
*------------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
/* static initialization, called whether or not the usb config is active */
|
||||||
|
void (*configure) (void);
|
||||||
|
/* initialization function after the config was selected */
|
||||||
|
void (*init) (void);
|
||||||
|
/* de-initialization before selecting new config */
|
||||||
|
void (*exit) (void);
|
||||||
|
/* main loop content for given configuration */
|
||||||
|
void (*run) (void);
|
||||||
|
/* Interrupt handler for USART0 */
|
||||||
|
void (*usart0_irq) (void);
|
||||||
|
/* Interrupt handler for USART1 */
|
||||||
|
void (*usart1_irq) (void);
|
||||||
|
} conf_func;
|
||||||
|
|
||||||
|
static const conf_func config_func_ptrs[] = {
|
||||||
|
/* array slot 0 is empty, usb configs start at 1 */
|
||||||
|
#ifdef HAVE_SNIFFER
|
||||||
|
[CFG_NUM_SNIFF] = {
|
||||||
|
.configure = Sniffer_configure,
|
||||||
|
.init = Sniffer_init,
|
||||||
|
.exit = Sniffer_exit,
|
||||||
|
.run = Sniffer_run,
|
||||||
|
.usart0_irq = Sniffer_usart0_irq,
|
||||||
|
.usart1_irq = Sniffer_usart1_irq,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CCID
|
||||||
|
[CFG_NUM_CCID] = {
|
||||||
|
.configure = CCID_configure,
|
||||||
|
.init = CCID_init,
|
||||||
|
.exit = CCID_exit,
|
||||||
|
.run = CCID_run,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CARDEM
|
||||||
|
[CFG_NUM_PHONE] = {
|
||||||
|
.configure = mode_cardemu_configure,
|
||||||
|
.init = mode_cardemu_init,
|
||||||
|
.exit = mode_cardemu_exit,
|
||||||
|
.run = mode_cardemu_run,
|
||||||
|
.usart0_irq = mode_cardemu_usart0_irq,
|
||||||
|
.usart1_irq = mode_cardemu_usart1_irq,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_MITM
|
||||||
|
[CFG_NUM_MITM] = {
|
||||||
|
.configure = MITM_configure,
|
||||||
|
.init = MITM_init,
|
||||||
|
.exit = MITM_exit,
|
||||||
|
.run = MITM_run,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Internal variables
|
||||||
|
*------------------------------------------------------------------------------*/
|
||||||
|
#if defined(HAVE_SNIFFER)
|
||||||
|
static volatile enum confNum simtrace_config = CFG_NUM_SNIFF;
|
||||||
|
#elif defined(HAVE_CARDEM)
|
||||||
|
static volatile enum confNum simtrace_config = CFG_NUM_PHONE;
|
||||||
|
#elif defined(HAVE_CCID)
|
||||||
|
static volatile enum confNum simtrace_config = CFG_NUM_CCID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Callbacks
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
|
||||||
|
{
|
||||||
|
TRACE_INFO_WP("cfgChanged%d ", cfgnum);
|
||||||
|
simtrace_config = cfgnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART1_IrqHandler(void)
|
||||||
|
{
|
||||||
|
if (config_func_ptrs[simtrace_config].usart1_irq)
|
||||||
|
config_func_ptrs[simtrace_config].usart1_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART0_IrqHandler(void)
|
||||||
|
{
|
||||||
|
if (config_func_ptrs[simtrace_config].usart0_irq)
|
||||||
|
config_func_ptrs[simtrace_config].usart0_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Main
|
||||||
|
*------------------------------------------------------------------------------*/
|
||||||
|
#define MAX_USB_ITER BOARD_MCK/72 // This should be around a second
|
||||||
|
extern int main(void)
|
||||||
|
{
|
||||||
|
uint8_t isUsbConnected = 0;
|
||||||
|
enum confNum last_simtrace_config = simtrace_config;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
/* Configure LED output
|
||||||
|
* red on = power
|
||||||
|
* red blink = error
|
||||||
|
* green on = running
|
||||||
|
* green blink = activity
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
EEFC_ReadUniqueID(g_unique_id);
|
||||||
|
|
||||||
|
printf("\n\r\n\r"
|
||||||
|
"=============================================================================\n\r"
|
||||||
|
"SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r"
|
||||||
|
"=============================================================================\n\r");
|
||||||
|
|
||||||
|
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",
|
||||||
|
g_unique_id[0], g_unique_id[1],
|
||||||
|
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("USB configuration used: %d\n\r", simtrace_config);
|
||||||
|
|
||||||
|
board_main_top();
|
||||||
|
|
||||||
|
TRACE_INFO("USB init...\n\r");
|
||||||
|
SIMtrace_USB_Initialize();
|
||||||
|
|
||||||
|
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
|
||||||
|
WDT_Restart(WDT);
|
||||||
|
check_exec_dbg_cmd();
|
||||||
|
#if 0
|
||||||
|
if (i >= MAX_USB_ITER * 3) {
|
||||||
|
TRACE_ERROR("Resetting board (USB could "
|
||||||
|
"not be configured)\n\r");
|
||||||
|
USBD_Disconnect();
|
||||||
|
NVIC_SystemReset();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_INFO("calling configure of all configurations...\n\r");
|
||||||
|
for (i = 1; i < ARRAY_SIZE(config_func_ptrs); i++) {
|
||||||
|
if (config_func_ptrs[i].configure)
|
||||||
|
config_func_ptrs[i].configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_INFO("calling init of config %u...\n\r", simtrace_config);
|
||||||
|
config_func_ptrs[simtrace_config].init();
|
||||||
|
last_simtrace_config = simtrace_config;
|
||||||
|
|
||||||
|
TRACE_INFO("entering main loop...\n\r");
|
||||||
|
while (1) {
|
||||||
|
WDT_Restart(WDT);
|
||||||
|
#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
|
||||||
|
const char rotor[] = { '-', '\\', '|', '/' };
|
||||||
|
putchar('\b');
|
||||||
|
putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
|
||||||
|
#endif
|
||||||
|
check_exec_dbg_cmd();
|
||||||
|
osmo_timers_prepare();
|
||||||
|
osmo_timers_update();
|
||||||
|
|
||||||
|
if (USBD_GetState() < USBD_STATE_CONFIGURED) {
|
||||||
|
|
||||||
|
if (isUsbConnected) {
|
||||||
|
isUsbConnected = 0;
|
||||||
|
}
|
||||||
|
} else if (isUsbConnected == 0) {
|
||||||
|
TRACE_INFO("USB is now configured\n\r");
|
||||||
|
|
||||||
|
isUsbConnected = 1;
|
||||||
|
}
|
||||||
|
if (last_simtrace_config != simtrace_config) {
|
||||||
|
TRACE_INFO("USB config chg %u -> %u\n\r",
|
||||||
|
last_simtrace_config, simtrace_config);
|
||||||
|
config_func_ptrs[last_simtrace_config].exit();
|
||||||
|
config_func_ptrs[simtrace_config].init();
|
||||||
|
last_simtrace_config = simtrace_config;
|
||||||
|
} else {
|
||||||
|
config_func_ptrs[simtrace_config].run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
10
firmware/apps/trace/usb_strings.txt
Normal file
10
firmware/apps/trace/usb_strings.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
sysmocom - s.f.m.c. GmbH
|
||||||
|
SIMtrace 2 compatible device
|
||||||
|
SIMtrace Sniffer
|
||||||
|
SIMtrace CCID
|
||||||
|
SIMtrace Phone
|
||||||
|
SIMtrace MITM
|
||||||
|
CardEmulator Modem 1
|
||||||
|
CardEmulator Modem 2
|
||||||
|
CardEmulator Modem 3
|
||||||
|
CardEmulator Modem 4
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
C_FILES += $(C_LIBUSB_RT)
|
C_FILES += $(C_LIBUSB_RT)
|
||||||
|
|
||||||
C_FILES += card_emu.c ccid.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
|
C_FILES += card_emu.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
|
||||||
|
|||||||
@@ -1,4 +1,21 @@
|
|||||||
// FIXME: Copyright license here
|
/* SIMtrace 2 firmware card emulation, CCID, and sniffer application
|
||||||
|
*
|
||||||
|
* (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
|
||||||
*------------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------------*/
|
||||||
@@ -7,7 +24,7 @@
|
|||||||
#include "simtrace.h"
|
#include "simtrace.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "req_ctx.h"
|
#include "req_ctx.h"
|
||||||
#include "osmocom/core/timer.h"
|
#include <osmocom/core/timer.h>
|
||||||
|
|
||||||
unsigned int g_unique_id[4];
|
unsigned int g_unique_id[4];
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* 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.
|
||||||
*
|
*
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
|
#define printf printf_sync
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* Exported functions
|
* Exported functions
|
||||||
|
|||||||
@@ -47,6 +47,8 @@
|
|||||||
#include "USBD.h"
|
#include "USBD.h"
|
||||||
#include "USBD_HAL.h"
|
#include "USBD_HAL.h"
|
||||||
|
|
||||||
|
extern void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
* Definitions
|
* Definitions
|
||||||
*---------------------------------------------------------------------------*/
|
*---------------------------------------------------------------------------*/
|
||||||
@@ -144,7 +146,11 @@ void USBD_RequestHandler(uint8_t bEndpoint,
|
|||||||
bEndpoint);
|
bEndpoint);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
#if defined(BOARD_USB_DFU) && !defined(APPLICATION_dfu)
|
||||||
|
USBDFU_Runtime_RequestHandler(pRequest);
|
||||||
|
#else
|
||||||
USBDCallbacks_RequestReceived(pRequest);
|
USBDCallbacks_RequestReceived(pRequest);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* ATMEL Microcontroller Software Support
|
* ATMEL Microcontroller Software Support
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
* Copyright (c) 2008, Atmel Corporation
|
* Copyright (c) 2008, Atmel Corporation
|
||||||
|
* Copyright (c) 2018, Kevin Redon <kredon@sysmocom.de>
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -250,7 +251,7 @@ static void GetDescriptor(
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case USBGenericDescriptor_DEVICE:
|
case USBGenericDescriptor_DEVICE:
|
||||||
TRACE_INFO_WP("Dev ");
|
TRACE_DEBUG_WP("Dev ");
|
||||||
|
|
||||||
/* Adjust length and send descriptor */
|
/* Adjust length and send descriptor */
|
||||||
|
|
||||||
@@ -262,7 +263,7 @@ static void GetDescriptor(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericDescriptor_CONFIGURATION:
|
case USBGenericDescriptor_CONFIGURATION:
|
||||||
TRACE_INFO_WP("Cfg ");
|
TRACE_DEBUG_WP("Cfg ");
|
||||||
|
|
||||||
/* Adjust length and send descriptor */
|
/* Adjust length and send descriptor */
|
||||||
|
|
||||||
@@ -279,7 +280,7 @@ static void GetDescriptor(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericDescriptor_DEVICEQUALIFIER:
|
case USBGenericDescriptor_DEVICEQUALIFIER:
|
||||||
TRACE_INFO_WP("Qua ");
|
TRACE_DEBUG_WP("Qua ");
|
||||||
|
|
||||||
/* Check if descriptor exists */
|
/* Check if descriptor exists */
|
||||||
|
|
||||||
@@ -300,7 +301,7 @@ static void GetDescriptor(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
|
case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
|
||||||
TRACE_INFO_WP("OSC ");
|
TRACE_DEBUG_WP("OSC ");
|
||||||
|
|
||||||
/* Check if descriptor exists */
|
/* Check if descriptor exists */
|
||||||
|
|
||||||
@@ -326,13 +327,18 @@ static void GetDescriptor(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericDescriptor_STRING:
|
case USBGenericDescriptor_STRING:
|
||||||
TRACE_INFO_WP("Str%d ", indexRDesc);
|
TRACE_DEBUG_WP("Str%d ", indexRDesc);
|
||||||
|
|
||||||
/* Check if descriptor exists */
|
/* Check if descriptor exists */
|
||||||
|
|
||||||
if (indexRDesc >= numStrings) {
|
if (indexRDesc >= numStrings) {
|
||||||
|
/* Sometimes descriptor string 0xee is requested.
|
||||||
USBD_Stall(0);
|
* 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.
|
||||||
|
*/
|
||||||
|
//USBD_Stall(0);
|
||||||
|
USBD_Write(0, NULL, 0, 0, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
@@ -498,13 +504,13 @@ void USBDDriver_RequestHandler(
|
|||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
|
|
||||||
TRACE_INFO_WP("Std ");
|
TRACE_DEBUG_WP("Std ");
|
||||||
|
|
||||||
/* Check request code */
|
/* Check request code */
|
||||||
switch (USBGenericRequest_GetRequest(pRequest)) {
|
switch (USBGenericRequest_GetRequest(pRequest)) {
|
||||||
|
|
||||||
case USBGenericRequest_GETDESCRIPTOR:
|
case USBGenericRequest_GETDESCRIPTOR:
|
||||||
TRACE_INFO_WP("gDesc ");
|
TRACE_DEBUG_WP("gDesc ");
|
||||||
|
|
||||||
/* Send the requested descriptor */
|
/* Send the requested descriptor */
|
||||||
type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
|
type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
|
||||||
@@ -514,7 +520,7 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_SETADDRESS:
|
case USBGenericRequest_SETADDRESS:
|
||||||
TRACE_INFO_WP("sAddr ");
|
TRACE_DEBUG_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);
|
||||||
@@ -522,7 +528,7 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_SETCONFIGURATION:
|
case USBGenericRequest_SETCONFIGURATION:
|
||||||
TRACE_INFO_WP("sCfg ");
|
TRACE_DEBUG_WP("sCfg ");
|
||||||
|
|
||||||
/* Set the requested configuration */
|
/* Set the requested configuration */
|
||||||
cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
|
cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
|
||||||
@@ -530,27 +536,27 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_GETCONFIGURATION:
|
case USBGenericRequest_GETCONFIGURATION:
|
||||||
TRACE_INFO_WP("gCfg ");
|
TRACE_DEBUG_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_INFO_WP("gSta ");
|
TRACE_DEBUG_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_INFO_WP("Dev ");
|
TRACE_DEBUG_WP("Dev ");
|
||||||
|
|
||||||
/* Send the device status */
|
/* Send the device status */
|
||||||
GetDeviceStatus(pDriver);
|
GetDeviceStatus(pDriver);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_ENDPOINT:
|
case USBGenericRequest_ENDPOINT:
|
||||||
TRACE_INFO_WP("Ept ");
|
TRACE_DEBUG_WP("Ept ");
|
||||||
|
|
||||||
/* Send the endpoint status */
|
/* Send the endpoint status */
|
||||||
eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
|
eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
|
||||||
@@ -566,13 +572,13 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_CLEARFEATURE:
|
case USBGenericRequest_CLEARFEATURE:
|
||||||
TRACE_INFO_WP("cFeat ");
|
TRACE_DEBUG_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_INFO_WP("Hlt ");
|
TRACE_DEBUG_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));
|
||||||
@@ -580,7 +586,7 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBFeatureRequest_DEVICEREMOTEWAKEUP:
|
case USBFeatureRequest_DEVICEREMOTEWAKEUP:
|
||||||
TRACE_INFO_WP("RmWU ");
|
TRACE_DEBUG_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;
|
||||||
@@ -596,13 +602,13 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_SETFEATURE:
|
case USBGenericRequest_SETFEATURE:
|
||||||
TRACE_INFO_WP("sFeat ");
|
TRACE_DEBUG_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_INFO_WP("RmWU ");
|
TRACE_DEBUG_WP("RmWU ");
|
||||||
|
|
||||||
/* Enable remote wake-up and send a ZLP */
|
/* Enable remote wake-up and send a ZLP */
|
||||||
pDriver->isRemoteWakeUpEnabled = 1;
|
pDriver->isRemoteWakeUpEnabled = 1;
|
||||||
@@ -610,25 +616,25 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBFeatureRequest_ENDPOINTHALT:
|
case USBFeatureRequest_ENDPOINTHALT:
|
||||||
TRACE_INFO_WP("Halt ");
|
TRACE_DEBUG_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_INFO_WP("OTG_B_HNP_ENABLE ");
|
TRACE_DEBUG_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_INFO_WP("OTG_A_HNP_SUPPORT ");
|
TRACE_DEBUG_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_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
|
TRACE_DEBUG_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);
|
||||||
@@ -643,7 +649,7 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_SETINTERFACE:
|
case USBGenericRequest_SETINTERFACE:
|
||||||
TRACE_INFO_WP("sInterface ");
|
TRACE_DEBUG_WP("sInterface ");
|
||||||
|
|
||||||
infnum = USBInterfaceRequest_GetInterface(pRequest);
|
infnum = USBInterfaceRequest_GetInterface(pRequest);
|
||||||
setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
|
setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
|
||||||
@@ -651,7 +657,7 @@ void USBDDriver_RequestHandler(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case USBGenericRequest_GETINTERFACE:
|
case USBGenericRequest_GETINTERFACE:
|
||||||
TRACE_INFO_WP("gInterface ");
|
TRACE_DEBUG_WP("gInterface ");
|
||||||
|
|
||||||
infnum = USBInterfaceRequest_GetInterface(pRequest);
|
infnum = USBInterfaceRequest_GetInterface(pRequest);
|
||||||
GetInterface(pDriver, infnum);
|
GetInterface(pDriver, infnum);
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ extern const USBDDriverDescriptors dfu_descriptors;
|
|||||||
|
|
||||||
/* no DFU bootloader is being used */
|
/* no DFU bootloader is being used */
|
||||||
#define DFURT_NUM_IF 0
|
#define DFURT_NUM_IF 0
|
||||||
#define DFURT_IF_DESCRIPTOR_STRUCT(a, b)
|
#define DFURT_IF_DESCRIPTOR_STRUCT
|
||||||
#define DFURT_IF_DESCRIPTOR
|
#define DFURT_IF_DESCRIPTOR(a, b)
|
||||||
|
|
||||||
#endif /* BOARD_USB_DFU */
|
#endif /* BOARD_USB_DFU */
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ static const USBDeviceDescriptor fsDevice = {
|
|||||||
.bDeviceClass = 0,
|
.bDeviceClass = 0,
|
||||||
.bDeviceSubClass = 0,
|
.bDeviceSubClass = 0,
|
||||||
.bDeviceProtocol = 0,
|
.bDeviceProtocol = 0,
|
||||||
.bMaxPacketSize0 = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
|
.bMaxPacketSize0 = USBEndpointDescriptor_MAXCTRLSIZE_FS,
|
||||||
.idVendor = BOARD_USB_VENDOR_ID,
|
.idVendor = BOARD_USB_VENDOR_ID,
|
||||||
.idProduct = BOARD_DFU_USB_PRODUCT_ID,
|
.idProduct = BOARD_DFU_USB_PRODUCT_ID,
|
||||||
.bcdDevice = BOARD_USB_RELEASE,
|
.bcdDevice = BOARD_USB_RELEASE,
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ void USBDFU_DFU_RequestHandler(const USBGenericRequest *request)
|
|||||||
uint8_t req = USBGenericRequest_GetRequest(request);
|
uint8_t req = USBGenericRequest_GetRequest(request);
|
||||||
uint16_t len = USBGenericRequest_GetLength(request);
|
uint16_t len = USBGenericRequest_GetLength(request);
|
||||||
uint16_t val = USBGenericRequest_GetValue(request);
|
uint16_t val = USBGenericRequest_GetValue(request);
|
||||||
int rc, ret;
|
int rc, ret = DFU_RET_NOTHING;
|
||||||
|
|
||||||
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
|
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
|
||||||
USBGenericRequest_GetType(request),
|
USBGenericRequest_GetType(request),
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
|
|||||||
uint8_t req = USBGenericRequest_GetRequest(request);
|
uint8_t req = USBGenericRequest_GetRequest(request);
|
||||||
uint16_t len = USBGenericRequest_GetLength(request);
|
uint16_t len = USBGenericRequest_GetLength(request);
|
||||||
uint16_t val = USBGenericRequest_GetValue(request);
|
uint16_t val = USBGenericRequest_GetValue(request);
|
||||||
int rc, ret;
|
int rc, ret = DFU_RET_NOTHING;
|
||||||
|
|
||||||
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
|
TRACE_DEBUG("type=0x%x, recipient=0x%x val=0x%x len=%u\n\r",
|
||||||
USBGenericRequest_GetType(request),
|
USBGenericRequest_GetType(request),
|
||||||
@@ -141,7 +141,7 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
|
|||||||
if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS ||
|
if (USBGenericRequest_GetType(request) != USBGenericRequest_CLASS ||
|
||||||
USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) {
|
USBGenericRequest_GetRecipient(request) != USBGenericRequest_INTERFACE) {
|
||||||
TRACE_DEBUG("std_ho_usbd ");
|
TRACE_DEBUG("std_ho_usbd ");
|
||||||
USBDDriver_RequestHandler(usbdDriver, request);
|
USBDCallbacks_RequestReceived(request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,9 +216,3 @@ void DFURT_SwitchToDFU(void)
|
|||||||
* ResetVector of the bootloader */
|
* ResetVector of the bootloader */
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
|
|
||||||
{
|
|
||||||
/* FIXME: integration with CCID control point reqeusts */
|
|
||||||
USBDFU_Runtime_RequestHandler(request);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* 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_
|
||||||
|
|
||||||
@@ -37,10 +56,8 @@
|
|||||||
/** Core definition */
|
/** Core definition */
|
||||||
#define cortexm3
|
#define cortexm3
|
||||||
|
|
||||||
#define BOARD_MCK 48000000
|
|
||||||
|
|
||||||
#define PIO_LED_RED PIO_PA17
|
#define PIO_LED_RED PIO_PA17
|
||||||
#define PIO_LED_GREEN PIO_PA17
|
#define PIO_LED_GREEN PIO_PA18
|
||||||
|
|
||||||
#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
|
#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 PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
|
||||||
@@ -63,12 +80,16 @@
|
|||||||
#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 baudrate always using 115200. */
|
/** Console baud rate in bps */
|
||||||
#define CONSOLE_BAUDRATE 115200
|
#define CONSOLE_BAUDRATE 921600
|
||||||
/** Usart Hw interface used by the console (UART0). */
|
/** UART peripheral used by the console (UART0). */
|
||||||
#define CONSOLE_USART UART0
|
#define CONSOLE_UART UART0
|
||||||
/** Usart Hw ID used by the console (UART0). */
|
/** UART peripheral ID used by the console (UART0). */
|
||||||
#define CONSOLE_ID ID_UART0
|
#define CONSOLE_ID ID_UART0
|
||||||
|
/** UART ISR used by the console (UART0). */
|
||||||
|
#define CONSOLE_ISR UART0_IrqHandler
|
||||||
|
/** UART IRQ used by the console (UART0). */
|
||||||
|
#define CONSOLE_IRQ UART0_IRQn
|
||||||
/** Pins description corresponding to Rxd,Txd, (UART pins) */
|
/** Pins description corresponding to Rxd,Txd, (UART pins) */
|
||||||
#define CONSOLE_PINS {PINS_UART}
|
#define CONSOLE_PINS {PINS_UART}
|
||||||
|
|
||||||
@@ -77,39 +98,25 @@
|
|||||||
#define BOARD_ISO7816_BASE_USART USART0
|
#define BOARD_ISO7816_BASE_USART USART0
|
||||||
#define BOARD_ISO7816_ID_USART ID_USART0
|
#define BOARD_ISO7816_ID_USART ID_USART0
|
||||||
|
|
||||||
|
/* USART peripherals for a phone and SIM card setup */
|
||||||
|
/* USART peripheral connected to the SIM card */
|
||||||
#define USART_SIM USART0
|
#define USART_SIM USART0
|
||||||
|
/* ID of USART peripheral connected to the SIM card */
|
||||||
#define ID_USART_SIM ID_USART0
|
#define ID_USART_SIM ID_USART0
|
||||||
|
/* Interrupt request ID of USART peripheral connected to the SIM card */
|
||||||
|
#define IRQ_USART_SIM USART0_IRQn
|
||||||
|
/* USART peripheral connected to the phone */
|
||||||
#define USART_PHONE USART1
|
#define USART_PHONE USART1
|
||||||
|
/* ID of USART peripheral connected to the phone */
|
||||||
#define ID_USART_PHONE ID_USART1
|
#define ID_USART_PHONE ID_USART1
|
||||||
|
/* Interrupt request ID of USART peripheral connected to the phone */
|
||||||
|
#define IRQ_USART_PHONE USART1_IRQn
|
||||||
|
|
||||||
#define SIM_PWEN PIO_PA5
|
#define SIM_PWEN PIO_PA5
|
||||||
#define VCC_FWD PIO_PA26
|
#define VCC_FWD PIO_PA26
|
||||||
|
|
||||||
|
|
||||||
//** USB **/
|
|
||||||
// USB pull-up control pin definition (PA16).
|
|
||||||
// Default: 1 (USB Pullup deactivated)
|
|
||||||
#define PIN_USB_PULLUP {1 << 16, PIOA, ID_PIOA, PIO_OUTPUT_1, 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_NUMENDPOINTS 8
|
|
||||||
|
|
||||||
// FIXME: in all other cases return 0?
|
|
||||||
#define BOARD_USB_ENDPOINTS_MAXPACKETSIZE(i) (((i == 4) || (i == 5))? 512 : 64)
|
|
||||||
#define BOARD_USB_ENDPOINTS_BANKS(i) (((i == 0) || (i == 3)) ? 1 : 2)
|
|
||||||
|
|
||||||
#define USB_VENDOR_OPENMOKO 0x1d50
|
|
||||||
#define USB_PRODUCT_OWHW_SAM3_DFU 0x4001 /* was 0x4000 */
|
|
||||||
#define USB_PRODUCT_OWHW_SAM3 0x4001
|
|
||||||
#define USB_PRODUCT_QMOD_HUB 0x4002
|
|
||||||
#define USB_PRODUCT_QMOD_SAM3_DFU 0x4004 /* was 0x4003 */
|
|
||||||
#define USB_PRODUCT_QMOD_SAM3 0x4004
|
|
||||||
#define USB_PRODUCT_SIMTRACE2_DFU 0x60e3 /* was 0x60e2 */
|
|
||||||
#define USB_PRODUCT_SIMTRACE2 0x60e3
|
|
||||||
|
|
||||||
#define BOARD_USB_DFU
|
#define BOARD_USB_DFU
|
||||||
#define BOARD_DFU_BOOT_SIZE (16 * 1024)
|
#define BOARD_DFU_BOOT_SIZE (16 * 1024)
|
||||||
@@ -119,4 +126,5 @@
|
|||||||
|
|
||||||
extern void board_exec_dbg_cmd(int ch);
|
extern void board_exec_dbg_cmd(int ch);
|
||||||
extern void board_main_top(void);
|
extern void board_main_top(void);
|
||||||
|
extern int board_override_enter_dfu(void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
/* 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);
|
int get_board_version_adc(void);
|
||||||
|
uint32_t adc2uv(uint16_t adc);
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
|
/* 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 {
|
||||||
@@ -13,9 +27,11 @@ enum led_pattern {
|
|||||||
BLINK_3O_30F = 3,
|
BLINK_3O_30F = 3,
|
||||||
BLINK_3O_1F_3O_30F = 4,
|
BLINK_3O_1F_3O_30F = 4,
|
||||||
BLINK_3O_1F_3O_1F_3O_30F= 5,
|
BLINK_3O_1F_3O_1F_3O_30F= 5,
|
||||||
BLINK_200O_F = 6,
|
BLINK_2O_F = 6,
|
||||||
BLINK_600O_F = 7,
|
BLINK_200O_F = 7,
|
||||||
BLINK_CUSTOM = 8,
|
BLINK_600O_F = 8,
|
||||||
|
BLINK_CUSTOM = 9,
|
||||||
|
BLINK_2F_O,
|
||||||
_NUM_LED_BLINK
|
_NUM_LED_BLINK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
|
/* 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
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,26 @@
|
|||||||
|
/* 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
|
||||||
|
|
||||||
|
/** switch card lines to use physical or emulated card
|
||||||
|
* @param[in] nr card interface number (i.e. slot)
|
||||||
|
* @param[in] physical which physical interface to switch to (e.g. 0: physical, 1: virtual)
|
||||||
|
* @return 0 on success, negative else
|
||||||
|
*/
|
||||||
int sim_switch_use_physical(unsigned int nr, int physical);
|
int sim_switch_use_physical(unsigned int nr, int physical);
|
||||||
|
/** initialise card switching capabilities
|
||||||
|
* @return number of switchable card interfaces
|
||||||
|
*/
|
||||||
int sim_switch_init(void);
|
int sim_switch_init(void);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* 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.
|
||||||
*
|
*
|
||||||
@@ -26,19 +27,17 @@
|
|||||||
* 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 ) ;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
* 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) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -132,8 +134,12 @@ 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);
|
||||||
SCB->VTOR = ((unsigned int)(pSrc)) | (0x0 << 7);
|
/* set vector table to application vector table (store at the beginning of the application) */
|
||||||
appReset = pSrc[1];
|
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];
|
||||||
|
|
||||||
g_dfu->state = DFU_STATE_appIDLE;
|
g_dfu->state = DFU_STATE_appIDLE;
|
||||||
|
|
||||||
@@ -154,10 +160,9 @@ void ResetException( void )
|
|||||||
|
|
||||||
|
|
||||||
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
|
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
|
||||||
/* we are before the text segment has been relocated, so g_dfu is
|
if (!USBDFU_OverrideEnterDFU()) {
|
||||||
* not initialized yet */
|
UART_Exit();
|
||||||
g_dfu = &_g_dfu;
|
__disable_irq();
|
||||||
if ((g_dfu->magic != USB_DFU_MAGIC) && !USBDFU_OverrideEnterDFU()) {
|
|
||||||
BootIntoApp();
|
BootIntoApp();
|
||||||
/* Infinite loop */
|
/* Infinite loop */
|
||||||
while ( 1 ) ;
|
while ( 1 ) ;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* 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.
|
||||||
*
|
*
|
||||||
@@ -46,39 +47,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)
|
||||||
|
|
||||||
#if (BOARD_MCK == 48000000)
|
/** configure PLL to generate main clock based on main oscillator frequency */
|
||||||
#if (BOARD_MAINOSC == 18432000)
|
#if (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 48000000)
|
||||||
/* Clock settings at 48MHz for 18 MHz crystal */
|
|
||||||
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
|
|
||||||
| CKGR_PLLAR_MULA(13-1) \
|
|
||||||
| CKGR_PLLAR_PLLACOUNT(0x1) \
|
|
||||||
| CKGR_PLLAR_DIVA(5))
|
|
||||||
#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(8-1) \
|
| CKGR_PLLAR_MULA(8-1) \
|
||||||
| CKGR_PLLAR_PLLACOUNT(0x1) \
|
| CKGR_PLLAR_PLLACOUNT(0x1) \
|
||||||
| CKGR_PLLAR_DIVA(2))
|
| CKGR_PLLAR_DIVA(2))
|
||||||
#else
|
#elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 58000000)
|
||||||
#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 \
|
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
|
||||||
| CKGR_PLLAR_MULA(7-1) \
|
| CKGR_PLLAR_MULA(29-1) \
|
||||||
| CKGR_PLLAR_PLLACOUNT(0x1) \
|
| CKGR_PLLAR_PLLACOUNT(0x1) \
|
||||||
| CKGR_PLLAR_DIVA(2))
|
| CKGR_PLLAR_DIVA(6))
|
||||||
#elif (BOARD_MAINOSC == 12000000)
|
#elif (BOARD_MAINOSC == 12000000) && (BOARD_MCK == 60000000)
|
||||||
/* QMod has 12 MHz clock, so multply by 10 / div by 2: 60 MHz */
|
|
||||||
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
|
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
|
||||||
| CKGR_PLLAR_MULA(10-1) \
|
| CKGR_PLLAR_MULA(10-1) \
|
||||||
| CKGR_PLLAR_PLLACOUNT(0x1) \
|
| CKGR_PLLAR_PLLACOUNT(0x1) \
|
||||||
| CKGR_PLLAR_DIVA(2))
|
| CKGR_PLLAR_DIVA(2))
|
||||||
#error "Please define PLLA config for your MAINOSC frequency"
|
#elif (BOARD_MAINOSC == 18432000) && (BOARD_MCK == 47923200)
|
||||||
#endif /* MAINOSC */
|
#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 "No PLL settings for current BOARD_MCK."
|
#error "Please define PLLA config for your BOARD_MCK/MAINOSC frequency"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (BOARD_MAINOSC == 12000000)
|
#if (BOARD_MAINOSC == 12000000)
|
||||||
|
|||||||
@@ -1,9 +1,22 @@
|
|||||||
|
/* 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"
|
||||||
|
|
||||||
/* FIXME: share this with mode_cardemu.c */
|
|
||||||
#define UV_PER_LSB ((3300 * 1000) / 4096)
|
#define UV_PER_LSB ((3300 * 1000) / 4096)
|
||||||
static 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;
|
||||||
return uv;
|
return uv;
|
||||||
@@ -73,7 +86,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 => %u uV\r\n", sample, uv);
|
TRACE_INFO("VERSION_DET ADC=%u => %lu uV\r\n", sample, uv);
|
||||||
|
|
||||||
/* FIXME: convert to board version based on thresholds */
|
/* FIXME: convert to board version based on thresholds */
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* 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>
|
||||||
@@ -16,9 +35,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_Set(&pinsLeds[led]);
|
|
||||||
else
|
|
||||||
PIO_Clear(&pinsLeds[led]);
|
PIO_Clear(&pinsLeds[led]);
|
||||||
|
else
|
||||||
|
PIO_Set(&pinsLeds[led]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LED blinking code */
|
/* LED blinking code */
|
||||||
@@ -27,7 +46,7 @@ static void led_set(enum led led, int on)
|
|||||||
struct blink_state {
|
struct blink_state {
|
||||||
/* duration of the state in ms */
|
/* duration of the state in ms */
|
||||||
uint16_t duration;
|
uint16_t duration;
|
||||||
/* bringhtness of LED during the state */
|
/* brightness of LED during the state */
|
||||||
uint8_t on;
|
uint8_t on;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
@@ -54,13 +73,23 @@ 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[] = {
|
||||||
|
{ 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 {
|
||||||
@@ -94,6 +123,10 @@ static const struct blink_pattern patterns[] = {
|
|||||||
.states = bs_3on_1off_3on_1off_3on_30off,
|
.states = bs_3on_1off_3on_1off_3on_30off,
|
||||||
.size = ARRAY_SIZE(bs_3on_1off_3on_1off_3on_30off),
|
.size = ARRAY_SIZE(bs_3on_1off_3on_1off_3on_30off),
|
||||||
},
|
},
|
||||||
|
[BLINK_2O_F] = {
|
||||||
|
.states = bs_2on_off,
|
||||||
|
.size = ARRAY_SIZE(bs_2on_off),
|
||||||
|
},
|
||||||
[BLINK_200O_F] = {
|
[BLINK_200O_F] = {
|
||||||
.states = bs_200on_off,
|
.states = bs_200on_off,
|
||||||
.size = ARRAY_SIZE(bs_200on_off),
|
.size = ARRAY_SIZE(bs_200on_off),
|
||||||
@@ -102,6 +135,11 @@ 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 {
|
||||||
@@ -158,16 +196,16 @@ static void blink_tmr_cb(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct led_state led_state[] = {
|
static struct led_state led_state[] = {
|
||||||
[LED_GREEN] = {
|
|
||||||
.led = LED_GREEN,
|
|
||||||
.timer.cb = blink_tmr_cb,
|
|
||||||
.timer.data = &led_state[LED_GREEN],
|
|
||||||
},
|
|
||||||
[LED_RED] = {
|
[LED_RED] = {
|
||||||
.led = LED_RED,
|
.led = LED_RED,
|
||||||
.timer.cb = blink_tmr_cb,
|
.timer.cb = blink_tmr_cb,
|
||||||
.timer.data = &led_state[LED_RED],
|
.timer.data = &led_state[LED_RED],
|
||||||
},
|
},
|
||||||
|
[LED_GREEN] = {
|
||||||
|
.led = LED_GREEN,
|
||||||
|
.timer.cb = blink_tmr_cb,
|
||||||
|
.timer.data = &led_state[LED_GREEN],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
#endif /* PINS_LEDS */
|
#endif /* PINS_LEDS */
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
|
/* 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;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* 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,6 +44,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "ringbuffer.h"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* Definitions
|
* Definitions
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
@@ -52,7 +55,9 @@
|
|||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/** Is Console Initialized. */
|
/** Is Console Initialized. */
|
||||||
static uint8_t _ucIsConsoleInitialized=0 ;
|
static uint8_t _ucIsConsoleInitialized=0;
|
||||||
|
/** Ring buffer to queue data to be sent */
|
||||||
|
static ringbuf uart_tx_buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Configures an USART peripheral with the specified parameters.
|
* \brief Configures an USART peripheral with the specified parameters.
|
||||||
@@ -63,7 +68,7 @@ static uint8_t _ucIsConsoleInitialized=0 ;
|
|||||||
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_USART;
|
Uart *pUart = CONSOLE_UART;
|
||||||
|
|
||||||
/* Configure PIO */
|
/* Configure PIO */
|
||||||
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
|
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
|
||||||
@@ -80,38 +85,104 @@ extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
|
|||||||
|
|
||||||
/* 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 */
|
||||||
|
rbuf_reset(&uart_tx_buffer);
|
||||||
|
|
||||||
|
/* Enable TX interrupts */
|
||||||
|
pUart->UART_IER = UART_IER_TXRDY;
|
||||||
|
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 */
|
||||||
_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 */
|
||||||
|
void CONSOLE_ISR(void)
|
||||||
|
{
|
||||||
|
Uart *uart = CONSOLE_UART;
|
||||||
|
if (uart->UART_SR & UART_SR_TXRDY) {
|
||||||
|
if (!rbuf_is_empty(&uart_tx_buffer)) {
|
||||||
|
uart->UART_THR = rbuf_read(&uart_tx_buffer);
|
||||||
|
} else {
|
||||||
|
uart->UART_IDR = UART_IER_TXRDY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Outputs a character on the UART line.
|
* \brief Outputs a character on the UART line.
|
||||||
*
|
*
|
||||||
* \note This function is synchronous (i.e. uses polling).
|
* \note This function is asynchronous (i.e. uses a buffer and interrupt to complete the transfer).
|
||||||
* \param c Character to send.
|
* \param c Character to send.
|
||||||
*/
|
*/
|
||||||
extern void UART_PutChar( uint8_t c )
|
void UART_PutChar( uint8_t uc )
|
||||||
{
|
{
|
||||||
Uart *pUart=CONSOLE_USART ;
|
Uart *pUart = CONSOLE_UART ;
|
||||||
|
|
||||||
|
/* Initialize console is not already done */
|
||||||
if ( !_ucIsConsoleInitialized )
|
if ( !_ucIsConsoleInitialized )
|
||||||
{
|
{
|
||||||
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
|
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the transmitter to be ready */
|
if (!rbuf_is_full(&uart_tx_buffer)) {
|
||||||
while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ;
|
rbuf_write(&uart_tx_buffer, uc);
|
||||||
|
if (!(pUart->UART_IMR & UART_IMR_TXRDY)) {
|
||||||
|
pUart->UART_IER = UART_IER_TXRDY;
|
||||||
|
CONSOLE_ISR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Send character */
|
/**
|
||||||
pUart->UART_THR=c ;
|
* \brief Outputs a character on the UART line.
|
||||||
|
*
|
||||||
|
* \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) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,14 +193,15 @@ extern void UART_PutChar( uint8_t c )
|
|||||||
*/
|
*/
|
||||||
extern uint32_t UART_GetChar( void )
|
extern uint32_t UART_GetChar( void )
|
||||||
{
|
{
|
||||||
Uart *pUart=CONSOLE_USART ;
|
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);
|
||||||
|
|
||||||
return pUart->UART_RHR ;
|
return pUart->UART_RHR ;
|
||||||
}
|
}
|
||||||
@@ -141,7 +213,7 @@ extern uint32_t UART_GetChar( void )
|
|||||||
*/
|
*/
|
||||||
extern uint32_t UART_IsRxReady( void )
|
extern uint32_t UART_IsRxReady( void )
|
||||||
{
|
{
|
||||||
Uart *pUart=CONSOLE_USART ;
|
Uart *pUart = CONSOLE_UART;
|
||||||
|
|
||||||
if ( !_ucIsConsoleInitialized )
|
if ( !_ucIsConsoleInitialized )
|
||||||
{
|
{
|
||||||
@@ -281,6 +353,7 @@ extern uint32_t UART_GetInteger( uint32_t* pdwValue )
|
|||||||
return 0 ;
|
return 0 ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
WDT_Restart(WDT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,35 @@
|
|||||||
|
/* 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"
|
||||||
|
|
||||||
/** Name of the board */
|
/** Name of the board */
|
||||||
#define BOARD_NAME "OWHW"
|
#define BOARD_NAME "OWHW"
|
||||||
/** 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
|
||||||
|
|
||||||
/* 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}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/* 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>
|
||||||
|
* (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
|
* 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 General Public License as published by
|
||||||
@@ -13,16 +15,41 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "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)
|
||||||
@@ -36,5 +63,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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
/* 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 "sim_switch.h"
|
#include "sim_switch.h"
|
||||||
|
|
||||||
#ifdef PIN_SIM_SWITCH1
|
#ifdef PIN_SIM_SWITCH1
|
||||||
@@ -16,6 +33,7 @@ static int initialized = 0;
|
|||||||
int sim_switch_use_physical(unsigned int nr, int physical)
|
int sim_switch_use_physical(unsigned int nr, int physical)
|
||||||
{
|
{
|
||||||
const Pin *pin;
|
const Pin *pin;
|
||||||
|
enum led led;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");
|
TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");
|
||||||
@@ -29,11 +47,13 @@ int sim_switch_use_physical(unsigned int nr, int physical)
|
|||||||
#ifdef PIN_SIM_SWITCH1
|
#ifdef PIN_SIM_SWITCH1
|
||||||
case 0:
|
case 0:
|
||||||
pin = &pin_conn_usim1;
|
pin = &pin_conn_usim1;
|
||||||
|
led = LED_USIM1;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef PIN_SIM_SWITCH2
|
#ifdef PIN_SIM_SWITCH2
|
||||||
case 1:
|
case 1:
|
||||||
pin = &pin_conn_usim2;
|
pin = &pin_conn_usim2;
|
||||||
|
led = LED_USIM2;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
@@ -44,9 +64,11 @@ int sim_switch_use_physical(unsigned int nr, int physical)
|
|||||||
if (physical) {
|
if (physical) {
|
||||||
TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
|
TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
|
||||||
PIO_Clear(pin);
|
PIO_Clear(pin);
|
||||||
|
led_blink(led, BLINK_ALWAYS_ON);
|
||||||
} else {
|
} else {
|
||||||
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
|
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
|
||||||
PIO_Set(pin);
|
PIO_Set(pin);
|
||||||
|
led_blink(led, BLINK_ALWAYS_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -63,5 +85,6 @@ int sim_switch_init(void)
|
|||||||
PIO_Configure(&pin_conn_usim2, 1);
|
PIO_Configure(&pin_conn_usim2, 1);
|
||||||
num_switch++;
|
num_switch++;
|
||||||
#endif
|
#endif
|
||||||
|
initialized = 1;
|
||||||
return num_switch;
|
return num_switch;
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,37 @@
|
|||||||
|
/* 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"
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
/* 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}
|
||||||
@@ -70,4 +95,7 @@
|
|||||||
#define CARDEMU_SECOND_UART
|
#define CARDEMU_SECOND_UART
|
||||||
#define DETECT_VCC_BY_ADC
|
#define DETECT_VCC_BY_ADC
|
||||||
|
|
||||||
|
/** sysmoQMOD only supports card emulation */
|
||||||
|
#ifdef APPLICATION_cardem
|
||||||
#define HAVE_CARDEM
|
#define HAVE_CARDEM
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
/* 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);
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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);
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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);
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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);
|
||||||
|
|||||||
@@ -1,15 +1,32 @@
|
|||||||
/* Quad-modem speciic application code */
|
/* sysmocom quad-modem sysmoQMOD application code
|
||||||
/* (C) 2016-2016 by Harald Welte <laforge@gnumonks.org> */
|
*
|
||||||
|
* (C) 2016-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
|
||||||
|
*/
|
||||||
#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"
|
||||||
#include "boardver_adc.h"
|
#include "boardver_adc.h"
|
||||||
#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"
|
||||||
|
|
||||||
static const Pin pin_hubpwr_override = PIN_PRTPWR_OVERRIDE;
|
static const Pin pin_hubpwr_override = PIN_PRTPWR_OVERRIDE;
|
||||||
@@ -55,8 +72,6 @@ const unsigned char __eeprom_bin[256] = {
|
|||||||
#include "i2c.h"
|
#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 */
|
||||||
@@ -64,22 +79,25 @@ 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 < 256; i++) {
|
for (i = 0; i < ARRAY_SIZE(__eeprom_bin); i++) {
|
||||||
int rc = eeprom_write_byte(0x50, i, __eeprom_bin[i]);
|
int rc = eeprom_write_byte(0x50, i, __eeprom_bin[i]);
|
||||||
/* if the result was negative, repeat that write */
|
if (rc < 0) {
|
||||||
if (rc < 0)
|
TRACE_ERROR("Writing EEPROM failed at byte %u: 0x%02x\n\r",
|
||||||
i--;
|
i, __eeprom_bin[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 < 256; i++) {
|
for (i = 0; i < ARRAY_SIZE(__eeprom_bin); i++) {
|
||||||
int byte = eeprom_read_byte(0x50, i);
|
int byte = eeprom_read_byte(0x50, i);
|
||||||
TRACE_INFO("0x%02x: %02x\n\r", i, byte);
|
TRACE_DEBUG("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 */
|
||||||
@@ -87,6 +105,29 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -99,6 +140,9 @@ static void board_exec_dbg_cmd_st12only(int ch)
|
|||||||
case 'E':
|
case 'E':
|
||||||
write_hub_eeprom();
|
write_hub_eeprom();
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
erase_hub_eeprom();
|
||||||
|
break;
|
||||||
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);
|
||||||
@@ -123,13 +167,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%02x to EEPROM offset 0x%02x\n\r", val, addr);
|
printf("Writing value 0x%02lx to EEPROM offset 0x%02lx\n\r", val, addr);
|
||||||
eeprom_write_byte(0x50, addr, val);
|
eeprom_write_byte(0x50, addr, val);
|
||||||
break;
|
break;
|
||||||
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%02x] = 0x%02x\n\r", addr, eeprom_read_byte(0x50, addr));
|
printf("EEPROM[0x%02lx] = 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);
|
||||||
@@ -144,8 +188,13 @@ void board_exec_dbg_cmd(int 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");
|
||||||
@@ -166,6 +215,22 @@ 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);
|
||||||
@@ -249,3 +314,51 @@ void board_main_top(void)
|
|||||||
card_present_init();
|
card_present_init();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uart_has_loopback_jumper(void)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
const Pin uart_loopback_pins[] = {
|
||||||
|
{PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT},
|
||||||
|
{PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Configure UART pins as I/O */
|
||||||
|
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++) {
|
||||||
|
/* Set TxD high; abort if RxD doesn't go high either */
|
||||||
|
PIO_Set(&uart_loopback_pins[1]);
|
||||||
|
if (!PIO_Get(&uart_loopback_pins[0])) {
|
||||||
|
has_loopback_jumper = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Set TxD low, abort if RxD doesn't go low either */
|
||||||
|
PIO_Clear(&uart_loopback_pins[1]);
|
||||||
|
if (PIO_Get(&uart_loopback_pins[0])) {
|
||||||
|
has_loopback_jumper = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put pins back to UART mode */
|
||||||
|
const Pin uart_pins[] = {PINS_UART};
|
||||||
|
PIO_Configure(uart_pins, PIO_LISTSIZE(uart_pins));
|
||||||
|
|
||||||
|
return has_loopback_jumper;
|
||||||
|
}
|
||||||
|
|
||||||
|
int board_override_enter_dfu(void)
|
||||||
|
{
|
||||||
|
/* If the loopback jumper is set, we enter DFU mode */
|
||||||
|
if (uart_has_loopback_jumper())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
/* 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"
|
||||||
@@ -17,9 +35,9 @@ int is_card_present(int port)
|
|||||||
const Pin *pin;
|
const Pin *pin;
|
||||||
int present;
|
int present;
|
||||||
|
|
||||||
if (port < 1 || port > NUM_CARDPRES)
|
if (port < 0 || port >= NUM_CARDPRES)
|
||||||
return -1;
|
return -1;
|
||||||
pin = &pin_cardpres[port-1];
|
pin = &pin_cardpres[port];
|
||||||
|
|
||||||
/* Card present signals are low-active, as we have a switch
|
/* Card present signals are low-active, as we have a switch
|
||||||
* against GND and an internal-pull-up in the SAM3 */
|
* against GND and an internal-pull-up in the SAM3 */
|
||||||
@@ -32,12 +50,12 @@ static void cardpres_tmr_cb(void *data)
|
|||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 1; i <= ARRAY_SIZE(pin_cardpres); i++) {
|
for (i = 0; i < ARRAY_SIZE(pin_cardpres); i++) {
|
||||||
int state = is_card_present(i);
|
int state = is_card_present(i);
|
||||||
if (state != last_state[i-1]) {
|
if (state != last_state[i]) {
|
||||||
TRACE_INFO("Card Detect %d Status %d -> %d\r\n", i, last_state[i], state);
|
TRACE_INFO("%u: Card Detect Status %d -> %d\r\n", i, last_state[i], state);
|
||||||
/* FIXME: report to USB host */
|
/* FIXME: report to USB host */
|
||||||
last_state[i-1] = state;
|
last_state[i] = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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>
|
||||||
|
|
||||||
@@ -169,6 +185,8 @@ 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();
|
||||||
|
|||||||
90
firmware/libboard/qmod/source/sim_switch.c
Normal file
90
firmware/libboard/qmod/source/sim_switch.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/* 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 "trace.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "sim_switch.h"
|
||||||
|
|
||||||
|
#ifdef PIN_SIM_SWITCH1
|
||||||
|
static const Pin pin_conn_usim1 = {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
|
||||||
|
#endif
|
||||||
|
#ifdef PIN_SIM_SWITCH2
|
||||||
|
static const Pin pin_conn_usim2 = {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int initialized = 0;
|
||||||
|
|
||||||
|
int sim_switch_use_physical(unsigned int nr, int physical)
|
||||||
|
{
|
||||||
|
const Pin *pin;
|
||||||
|
enum led led;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");
|
||||||
|
sim_switch_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_INFO("Modem %d: %s SIM\n\r", nr,
|
||||||
|
physical ? "physical" : "virtual");
|
||||||
|
|
||||||
|
switch (nr) {
|
||||||
|
#ifdef PIN_SIM_SWITCH1
|
||||||
|
case 0:
|
||||||
|
pin = &pin_conn_usim1;
|
||||||
|
led = LED_USIM1;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef PIN_SIM_SWITCH2
|
||||||
|
case 1:
|
||||||
|
pin = &pin_conn_usim2;
|
||||||
|
led = LED_USIM2;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
TRACE_ERROR("Invalid SIM%u\n\r", nr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (physical) {
|
||||||
|
TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
|
||||||
|
PIO_Clear(pin);
|
||||||
|
led_blink(led, BLINK_ALWAYS_ON);
|
||||||
|
} else {
|
||||||
|
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
|
||||||
|
PIO_Set(pin);
|
||||||
|
led_blink(led, BLINK_ALWAYS_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sim_switch_init(void)
|
||||||
|
{
|
||||||
|
int num_switch = 0;
|
||||||
|
#ifdef PIN_SIM_SWITCH1
|
||||||
|
PIO_Configure(&pin_conn_usim1, 1);
|
||||||
|
num_switch++;
|
||||||
|
#endif
|
||||||
|
#ifdef PIN_SIM_SWITCH2
|
||||||
|
PIO_Configure(&pin_conn_usim2, 1);
|
||||||
|
num_switch++;
|
||||||
|
#endif
|
||||||
|
initialized = 1;
|
||||||
|
return num_switch;
|
||||||
|
}
|
||||||
@@ -1,11 +1,24 @@
|
|||||||
/* 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
|
||||||
*
|
*
|
||||||
* Depending on the board this is running on, it might be possible
|
* 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
|
||||||
|
*/
|
||||||
|
/* 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"
|
||||||
|
|
||||||
@@ -14,9 +27,9 @@ static const Pin pin_wwan1 = PIN_WWAN1;
|
|||||||
|
|
||||||
static void wwan1_irqhandler(const Pin *pPin)
|
static void wwan1_irqhandler(const Pin *pPin)
|
||||||
{
|
{
|
||||||
int active = wwan_led_active(1);
|
int active = wwan_led_active(0);
|
||||||
|
|
||||||
TRACE_INFO("WWAN1 LED %u\r\n", active);
|
TRACE_INFO("0: WWAN LED %u\r\n", active);
|
||||||
|
|
||||||
/* TODO: notify host via USB */
|
/* TODO: notify host via USB */
|
||||||
}
|
}
|
||||||
@@ -27,8 +40,8 @@ static const Pin pin_wwan2 = PIN_WWAN2;
|
|||||||
|
|
||||||
static void wwan2_irqhandler(const Pin *pPin)
|
static void wwan2_irqhandler(const Pin *pPin)
|
||||||
{
|
{
|
||||||
int active = wwan_led_active(2);
|
int active = wwan_led_active(1);
|
||||||
TRACE_INFO("WWAN2 LED %u\r\n", active);
|
TRACE_INFO("1: WWAN LED %u\r\n", active);
|
||||||
|
|
||||||
/* TODO: notify host via USB */
|
/* TODO: notify host via USB */
|
||||||
}
|
}
|
||||||
@@ -42,12 +55,12 @@ int wwan_led_active(int wwan)
|
|||||||
|
|
||||||
switch (wwan) {
|
switch (wwan) {
|
||||||
#ifdef PIN_WWAN1
|
#ifdef PIN_WWAN1
|
||||||
case 1:
|
case 0:
|
||||||
pin = &pin_wwan1;
|
pin = &pin_wwan1;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef PIN_WWAN2
|
#ifdef PIN_WWAN2
|
||||||
case 2:
|
case 1:
|
||||||
pin = &pin_wwan2;
|
pin = &pin_wwan2;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,29 +1,45 @@
|
|||||||
/* Code to control the PERST lines of attached modems
|
/* Code to control the PERST lines of attached modems
|
||||||
*
|
*
|
||||||
* Depending on the board this is running on, it might be possible
|
* 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
|
||||||
|
*/
|
||||||
|
/* 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"
|
||||||
#include "osmocom/core/timer.h"
|
#include <osmocom/core/timer.h>
|
||||||
|
|
||||||
struct wwan_perst {
|
struct wwan_perst {
|
||||||
|
uint8_t idx;
|
||||||
const Pin pin;
|
const Pin pin;
|
||||||
struct osmo_timer_list timer;
|
struct osmo_timer_list timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef PIN_PERST1
|
#ifdef PIN_PERST1
|
||||||
static struct wwan_perst perst1 = {
|
static struct wwan_perst perst1 = {
|
||||||
|
.idx = 0,
|
||||||
.pin = PIN_PERST1,
|
.pin = PIN_PERST1,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PIN_PERST2
|
#ifdef PIN_PERST2
|
||||||
static struct wwan_perst perst2 = {
|
static struct wwan_perst perst2 = {
|
||||||
|
.idx = 1,
|
||||||
.pin = PIN_PERST2,
|
.pin = PIN_PERST2,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -34,7 +50,7 @@ static void perst_tmr_cb(void *data)
|
|||||||
{
|
{
|
||||||
struct wwan_perst *perst = data;
|
struct wwan_perst *perst = data;
|
||||||
/* release the (low-active) reset */
|
/* release the (low-active) reset */
|
||||||
TRACE_INFO("De-asserting modem reset\r\n");
|
TRACE_INFO("%u: De-asserting modem reset\r\n", perst->idx);
|
||||||
PIO_Clear(&perst->pin);
|
PIO_Clear(&perst->pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,5 +122,6 @@ int wwan_perst_init(void)
|
|||||||
perst2.timer.data = (void *) &perst2;
|
perst2.timer.data = (void *) &perst2;
|
||||||
num_perst++;
|
num_perst++;
|
||||||
#endif
|
#endif
|
||||||
|
initialized = 1;
|
||||||
return num_perst;
|
return num_perst;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +1,163 @@
|
|||||||
|
/* 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"
|
||||||
|
|
||||||
/** Name of the board */
|
/* Name of the board */
|
||||||
#define BOARD_NAME "SAM3S-SIMTRACE"
|
#define BOARD_NAME "SAM3S-SIMTRACE"
|
||||||
/** Board definition */
|
/* Board definition */
|
||||||
#define simtrace
|
#define simtrace
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
|
||||||
/** Phone (SIM card emulator)/CCID Reader/MITM configuration **/
|
/** Pin configuration **/
|
||||||
/* Normally the communication lines between phone and SIM card are disconnected */
|
/* Button to force bootloader start (shorted to ground when pressed */
|
||||||
// Disconnect SIM card I/O, VPP line from the phone lines
|
#define PIN_BOOTLOADER_SW {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
|
||||||
// FIXME: Per default pins are input, therefore high-impedance, therefore they don not activate the bus switch, right?
|
/* 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_IT_EDGE | PIO_DEGLITCH }
|
||||||
|
/* 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 }
|
||||||
|
/* Phone I/O data signal input/output (I/O_PHONE in schematic) */
|
||||||
|
#define PIN_USIM1_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_USIM1_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}
|
#define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
|
||||||
// Disconnect SIM card RST, CLK line from the phone lines
|
/* 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}
|
#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
|
#define PINS_BUS_DEFAULT PIN_SC_SW_DEFAULT, PIN_IO_SW_DEFAULT
|
||||||
|
|
||||||
/** Sniffer configuration **/
|
/** Sniffer configuration **/
|
||||||
// Connect VPP, CLK and RST lines from smartcard to the phone
|
/* 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}
|
#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}
|
#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
|
#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
|
||||||
|
|
||||||
#define PINS_SIM_SNIFF_SIM PIN_PHONE_IO, PIN_PHONE_CLK
|
/** CCID configuration */
|
||||||
|
/* Card RST reset signal input (active low; RST_SIM in schematic) */
|
||||||
#define SIM_PWEN_PIN {PIO_PA5, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
|
|
||||||
|
|
||||||
#define PWR_PINS \
|
|
||||||
/* Enable power converter 4.5-6V to 3.3V; low: off */ \
|
|
||||||
{SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}, \
|
|
||||||
/* Enable second power converter: VCC_PHONE to VCC_SIM; high: on */ \
|
|
||||||
{VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
|
|
||||||
|
|
||||||
#define SW_SIM PIO_PA8
|
|
||||||
#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
|
|
||||||
//#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOB, ID_PIOB, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_IT_EDGE}
|
|
||||||
|
|
||||||
/// PIN used for resetting the smartcard
|
|
||||||
// FIXME: Card is resetted with pin set to 0 --> PIO_OUTPUT_1 as default is right?
|
|
||||||
#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
|
#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
|
||||||
|
/* ISO7816-communication related pins */
|
||||||
/// Pins used for connect the smartcard
|
|
||||||
#define PIN_SIM_IO_INPUT {PIO_PA1, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
|
|
||||||
#define PIN_SIM_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
|
|
||||||
#define PIN_SIM_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
|
|
||||||
#define PIN_SIM_CLK_INPUT {PIO_PA4, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
|
|
||||||
//#define PINS_ISO7816 PIN_USART1_TXD, PIN_USART1_SCK, PIN_ISO7816_RSTMC
|
|
||||||
#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2
|
#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2
|
||||||
|
|
||||||
#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT
|
/** card emulation configuration */
|
||||||
|
/* Disable power converter 4.5-6V to 3.3V (active high) */
|
||||||
|
#define PIN_SIM_PWEN_CARDEMU {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
|
||||||
|
/* Disable power switch to forward VCC_PHONE to VCC_SIM (active high) */
|
||||||
|
#define PIN_VCC_FWD_CARDEMU {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
|
||||||
|
/* Disable power to SIM */
|
||||||
|
#define PINS_PWR_CARDEMU PIN_SIM_PWEN_CARDEMU, PIN_VCC_FWD_CARDEMU
|
||||||
|
|
||||||
#define VCC_PHONE {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
|
/** External SPI flash interface **/
|
||||||
#define PIN_ISO7816_RST_PHONE {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_RISE_EDGE | PIO_DEGLITCH }
|
/* SPI MISO pin definition */
|
||||||
#define PIN_PHONE_IO_INPUT {PIO_PA21, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
|
#define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
|
||||||
#define PIN_PHONE_IO {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
|
/* SPI MOSI pin definition */
|
||||||
#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT} // External Clock Input on PA28
|
#define PIN_SPI_MOSI {PIO_PA13A_MOSI, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
|
||||||
//#define PIN_PHONE_CLK {PIO_PA23A_SCK1, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT} // External Clock Input on PA28
|
/* SPI SCK pin definition */
|
||||||
#define PIN_PHONE_CLK_INPUT {PIO_PA29, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
|
#define PIN_SPI_SCK {PIO_PA14A_SPCK, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
|
||||||
#define PINS_ISO7816_PHONE PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, VCC_PHONE, PIN_PHONE_IO_INPUT, PIN_ISO7816_RST_PHONE
|
/* SPI pins definition. Contains MISO, MOSI & SCK */
|
||||||
//, VCC_PHONE
|
#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}
|
||||||
|
|
||||||
//** SPI interface **/
|
/** USB definitions */
|
||||||
/// SPI MISO pin definition (PA12).
|
/* OpenMoko SIMtrace 2 USB vendor ID */
|
||||||
#define PIN_SPI_MISO {1 << 12, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
|
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
|
||||||
/// SPI MOSI pin definition (PA13).
|
/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */
|
||||||
#define PIN_SPI_MOSI {1 << 13, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
|
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2
|
||||||
/// SPI SPCK pin definition (PA14).
|
/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */
|
||||||
#define PIN_SPI_SPCK {1 << 14, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
|
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU
|
||||||
/// SPI pins definition. Contains MISO, MOSI & SPCK (PA12, PA13 & PA14).
|
/* USB release number (bcdDevice, shown as 0.00) */
|
||||||
#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SPCK
|
#define BOARD_USB_RELEASE 0x000
|
||||||
/// SPI chip select 0 pin definition (PA11).
|
/* Indicate SIMtrace is bus power in USB attributes */
|
||||||
#define PIN_SPI_NPCS0 {1 << 11, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
|
|
||||||
|
|
||||||
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
|
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
|
||||||
|
|
||||||
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
|
/** Supported modes */
|
||||||
#define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2
|
/* SIMtrace board supports sniffer mode */
|
||||||
#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU
|
#ifdef APPLICATION_trace
|
||||||
#define BOARD_USB_RELEASE 0x000
|
|
||||||
|
|
||||||
#define HAVE_SNIFFER
|
#define HAVE_SNIFFER
|
||||||
#define HAVE_CCID
|
#endif
|
||||||
|
/* SIMtrace board supports CCID mode */
|
||||||
|
#ifdef APPLICATION_ccid
|
||||||
|
//#define HAVE_CCID
|
||||||
|
#endif
|
||||||
|
/* SIMtrace board supports card emulation mode */
|
||||||
|
#ifdef APPLICATION_cardem
|
||||||
#define HAVE_CARDEM
|
#define HAVE_CARDEM
|
||||||
#define HAVE_MITM
|
#endif
|
||||||
|
/* SIMtrace board supports man-in-the-middle mode */
|
||||||
|
#ifdef APPLICATION_mitm
|
||||||
|
//#define HAVE_MITM
|
||||||
|
#endif
|
||||||
|
|||||||
68
firmware/libboard/simtrace/source/board_simtrace.c
Normal file
68
firmware/libboard/simtrace/source/board_simtrace.c
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/* 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"
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
63
firmware/libboard/simtrace/source/sim_switch.c
Normal file
63
firmware/libboard/simtrace/source/sim_switch.c
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/* Code to switch between local (physical) and remote (emulated) SIM
|
||||||
|
*
|
||||||
|
* (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
|
||||||
|
*/
|
||||||
|
#include "board.h"
|
||||||
|
#include "trace.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "sim_switch.h"
|
||||||
|
|
||||||
|
#ifdef PIN_SIM_SWITCH1
|
||||||
|
static const Pin pin_conn_usim1 = {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
|
||||||
|
#endif
|
||||||
|
#ifdef PIN_SIM_SWITCH2
|
||||||
|
static const Pin pin_conn_usim2 = {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int initialized = 0;
|
||||||
|
|
||||||
|
int sim_switch_use_physical(unsigned int nr, int physical)
|
||||||
|
{
|
||||||
|
const Pin pin_sc = PIN_SC_SW_DEFAULT; // pin to control bus switch for VCC/RST/CLK signals
|
||||||
|
const Pin pin_io = PIN_IO_SW_DEFAULT; // pin to control bus switch for I/O signal
|
||||||
|
|
||||||
|
if (nr > 0) {
|
||||||
|
TRACE_ERROR("SIM interface for Modem %d can't be switched\r\n", nr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_INFO("Modem %u: %s SIM\n\r", nr, physical ? "physical" : "virtual");
|
||||||
|
|
||||||
|
if (physical) {
|
||||||
|
TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
|
||||||
|
PIO_Set(&pin_sc);
|
||||||
|
PIO_Set(&pin_io);
|
||||||
|
} else {
|
||||||
|
TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
|
||||||
|
PIO_Clear(&pin_sc);
|
||||||
|
PIO_Clear(&pin_io);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sim_switch_init(void)
|
||||||
|
{
|
||||||
|
// the bus switch is already initialised
|
||||||
|
return 1; // SIMtrace hardware has only one switchable interface
|
||||||
|
}
|
||||||
@@ -1,3 +1,22 @@
|
|||||||
|
/* 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,10 +48,42 @@ struct llist_head *card_emu_get_uart_tx_queue(struct card_handle *ch);
|
|||||||
void card_emu_have_new_uart_tx(struct card_handle *ch);
|
void card_emu_have_new_uart_tx(struct card_handle *ch);
|
||||||
void card_emu_report_status(struct card_handle *ch);
|
void card_emu_report_status(struct card_handle *ch);
|
||||||
|
|
||||||
|
/*! call when the waiting time has half-expired
|
||||||
|
* param[in] ch card for which the waiting time half expired
|
||||||
|
*/
|
||||||
|
void card_emu_wt_halfed(struct card_handle *ch);
|
||||||
|
/*! call when the waiting time has expired
|
||||||
|
* param[in] ch card for which the waiting time expired
|
||||||
|
*/
|
||||||
|
void card_emu_wt_expired(struct card_handle *ch);
|
||||||
|
|
||||||
#define ENABLE_TX 0x01
|
#define ENABLE_TX 0x01
|
||||||
#define ENABLE_RX 0x02
|
#define ENABLE_RX 0x02
|
||||||
|
|
||||||
int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi);
|
// the following functions are callbacks implement in mode_cardemu.c
|
||||||
|
|
||||||
|
/*! update F and D on USART peripheral
|
||||||
|
* @param[in] usart USART peripheral to configure
|
||||||
|
* @param[in] f clock rate conversion integer F value
|
||||||
|
* @param[in] d baud rate adjustment factor D value
|
||||||
|
* @note this should happen after reset and protocol select (through PPS or implicit)
|
||||||
|
*/
|
||||||
|
void card_emu_uart_update_fd(uint8_t uart_chan, uint16_t f, uint8_t d);
|
||||||
|
/*! update WT on USART peripheral
|
||||||
|
* @param[in] usart USART peripheral to configure
|
||||||
|
* @param[in] wt inactivity Waiting Time before card_emu_wt_expired is called (0 to disable)
|
||||||
|
*/
|
||||||
|
void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt);
|
||||||
|
/*! reset waiting timeout count down on USART peripheral
|
||||||
|
* @param[in] usart USART peripheral to configure
|
||||||
|
*/
|
||||||
|
void card_emu_uart_reset_wt(uint8_t uart_chan);
|
||||||
|
/*! set I/O line high
|
||||||
|
* @param[in] usart USART peripheral to configure
|
||||||
|
* @param[in] set if I/O line should be set high (true), or cleared low (false)
|
||||||
|
*/
|
||||||
|
void card_emu_uart_io_set(uint8_t uart_chan, bool set);
|
||||||
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);
|
||||||
|
|||||||
98
firmware/libcommon/include/iso7816_3.h
Normal file
98
firmware/libcommon/include/iso7816_3.h
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
/* this library provides utilities to handle the ISO-7816 part 3 communication aspects (e.g. related to F and D) */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/** default clock rate conversion integer Fd
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 8.1
|
||||||
|
*/
|
||||||
|
#define ISO7816_3_DEFAULT_FD 372
|
||||||
|
/** default baud rate adjustment factor Dd
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 8.1
|
||||||
|
*/
|
||||||
|
#define ISO7816_3_DEFAULT_DD 1
|
||||||
|
/** default clock rate conversion integer Fi
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 8.3
|
||||||
|
* @note non-default value is optionally specified in TA1
|
||||||
|
*/
|
||||||
|
#define ISO7816_3_DEFAULT_FI 372
|
||||||
|
/** default baud rate adjustment factor Di
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 8.3
|
||||||
|
* @note non-default value is optionally specified in TA1
|
||||||
|
*/
|
||||||
|
#define ISO7816_3_DEFAULT_DI 1
|
||||||
|
/** default maximum clock frequency, in Hz
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 8.3
|
||||||
|
* @note non-default value is optionally specified in TA1
|
||||||
|
*/
|
||||||
|
#define ISO7816_3_DEFAULT_FMAX 5000000UL
|
||||||
|
/** default Waiting Integer (WI) value for T=0
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 10.2
|
||||||
|
* @note non-default value is optionally specified in TC2
|
||||||
|
*/
|
||||||
|
#define ISO7816_3_DEFAULT_WI 10
|
||||||
|
/** default Waiting Time (WT) value, in ETU
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 8.1
|
||||||
|
* @note depends on Fi, Di, and WI if protocol T=0 is selected
|
||||||
|
*/
|
||||||
|
#define ISO7816_3_DEFAULT_WT 9600
|
||||||
|
|
||||||
|
/** Table encoding the clock rate conversion integer Fi
|
||||||
|
* @note Fi is indicated in TA1, but the same table is used for F and Fn during PPS
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) table 7
|
||||||
|
*/
|
||||||
|
extern const uint16_t iso7816_3_fi_table[];
|
||||||
|
|
||||||
|
/** Table encoding the maximum clock frequency f_max in Hz
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) table 7
|
||||||
|
* @note f_max is indicated in TA1, but the same table is used for F and Fn during PPS
|
||||||
|
*/
|
||||||
|
extern const uint32_t iso7816_3_fmax_table[];
|
||||||
|
|
||||||
|
/** Table encoding the baud rate adjust integer Di
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) table 8
|
||||||
|
* @note Di is indicated in TA1, but the same table is used for D and Dn during PPS
|
||||||
|
*/
|
||||||
|
extern const uint8_t iso7816_3_di_table[];
|
||||||
|
|
||||||
|
/* verify if the clock rate conversion integer F value is valid
|
||||||
|
* @param[in] f F value to be validated
|
||||||
|
* @return if F value is valid
|
||||||
|
* @note only values in ISO/IEC 7816-3:2006(E) table 7 are valid
|
||||||
|
*/
|
||||||
|
bool iso7816_3_valid_f(uint16_t f);
|
||||||
|
/* verify if the baud rate adjustment factor D value is valid
|
||||||
|
* @param[in] d D value to be validated
|
||||||
|
* @return if D value is valid
|
||||||
|
* @note only values in ISO/IEC 7816-3:2006(E) table 8 are valid
|
||||||
|
*/
|
||||||
|
bool iso7816_3_valid_d(uint8_t d);
|
||||||
|
/** calculate Waiting Time (WT)
|
||||||
|
* @param[in] wi Waiting Integer
|
||||||
|
* @param[in] fi clock rate conversion integer Fi value
|
||||||
|
* @param[in] di baud rate adjustment factor Di value
|
||||||
|
* @param[in] f clock rate conversion integer F value
|
||||||
|
* @param[in] d baud rate adjustment factor D value
|
||||||
|
* @return Waiting Time WT, in ETU, or < 0 on error (see code for return codes)
|
||||||
|
* @note this should happen after reset and T=0 protocol select (through PPS or implicit)
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 8.1 and 10.2
|
||||||
|
*/
|
||||||
|
int32_t iso7816_3_calculate_wt(uint8_t wi, uint16_t fi, uint8_t di, uint16_t f, uint8_t d);
|
||||||
@@ -1,6 +1,30 @@
|
|||||||
|
/* 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>
|
||||||
|
|
||||||
|
/* Table 7 of ISO 7816-3:2006 */
|
||||||
|
extern const uint16_t fi_table[];
|
||||||
|
|
||||||
|
/* Table 8 from ISO 7816-3:2006 */
|
||||||
|
extern const uint8_t di_table[];
|
||||||
|
|
||||||
/* compute the F/D ratio based on Fi and Di values */
|
/* compute the F/D ratio based on Fi and Di values */
|
||||||
int compute_fidi_ratio(uint8_t fi, uint8_t di);
|
int compute_fidi_ratio(uint8_t fi, uint8_t di);
|
||||||
|
|||||||
@@ -1,19 +1,42 @@
|
|||||||
|
/* 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>
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
static inline void llist_add_irqsafe(struct llist_head *_new,
|
static inline void llist_add_irqsafe(struct llist_head *_new,
|
||||||
struct llist_head *head)
|
struct llist_head *head)
|
||||||
{
|
{
|
||||||
__disable_irq();
|
unsigned long x;
|
||||||
|
|
||||||
|
local_irq_save(x);
|
||||||
llist_add(_new, head);
|
llist_add(_new, head);
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void llist_add_tail_irqsafe(struct llist_head *_new,
|
static inline void llist_add_tail_irqsafe(struct llist_head *_new,
|
||||||
struct llist_head *head)
|
struct llist_head *head)
|
||||||
{
|
{
|
||||||
__disable_irq();
|
unsigned long x;
|
||||||
|
|
||||||
|
local_irq_save(x);
|
||||||
llist_add_tail(_new, head);
|
llist_add_tail(_new, head);
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
}
|
}
|
||||||
@@ -21,15 +44,16 @@ static inline void llist_add_tail_irqsafe(struct llist_head *_new,
|
|||||||
static inline struct llist_head *llist_head_dequeue_irqsafe(struct llist_head *head)
|
static inline struct llist_head *llist_head_dequeue_irqsafe(struct llist_head *head)
|
||||||
{
|
{
|
||||||
struct llist_head *lh;
|
struct llist_head *lh;
|
||||||
|
unsigned long x;
|
||||||
|
|
||||||
__disable_irq();
|
local_irq_save(x);
|
||||||
if (llist_empty(head)) {
|
if (llist_empty(head)) {
|
||||||
lh = NULL;
|
lh = NULL;
|
||||||
} else {
|
} else {
|
||||||
lh = head->next;
|
lh = head->next;
|
||||||
llist_del(lh);
|
llist_del(lh);
|
||||||
}
|
}
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
|
|
||||||
return lh;
|
return lh;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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
|
||||||
|
|
||||||
@@ -5,7 +21,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define RING_BUFLEN 128
|
#define RING_BUFLEN 512
|
||||||
|
|
||||||
typedef struct ringbuf {
|
typedef struct ringbuf {
|
||||||
uint8_t buf[RING_BUFLEN];
|
uint8_t buf[RING_BUFLEN];
|
||||||
@@ -16,7 +32,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);
|
||||||
void rbuf_write(volatile ringbuf * rb, uint8_t item);
|
int rbuf_write(volatile ringbuf * rb, uint8_t item);
|
||||||
bool rbuf_is_empty(volatile ringbuf * rb);
|
bool rbuf_is_empty(volatile ringbuf * rb);
|
||||||
bool rbuf_is_full(volatile ringbuf * rb);
|
bool rbuf_is_full(volatile ringbuf * rb);
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,30 @@
|
|||||||
|
/* SIMtrace 2 mode definitions
|
||||||
|
*
|
||||||
|
* (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
|
||||||
|
*/
|
||||||
#ifndef SIMTRACE_H
|
#ifndef SIMTRACE_H
|
||||||
#define SIMTRACE_H
|
#define SIMTRACE_H
|
||||||
|
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
#include <usb/device/dfu/dfu.h>
|
||||||
/* Endpoint numbers */
|
|
||||||
#define DATAOUT 1
|
|
||||||
#define DATAIN 2
|
|
||||||
#define INT 3
|
|
||||||
|
|
||||||
#define BUFLEN 512
|
#define BUFLEN 512
|
||||||
|
|
||||||
#define PHONE_DATAOUT 4
|
|
||||||
#define PHONE_DATAIN 5
|
|
||||||
#define PHONE_INT 6
|
|
||||||
|
|
||||||
#define CARDEM_USIM2_DATAOUT DATAOUT
|
|
||||||
#define CARDEM_USIM2_DATAIN DATAIN
|
|
||||||
#define CARDEM_USIM2_INT INT
|
|
||||||
|
|
||||||
#define CLK_MASTER true
|
#define CLK_MASTER true
|
||||||
#define CLK_SLAVE false
|
#define CLK_SLAVE false
|
||||||
|
|
||||||
@@ -71,12 +77,16 @@ typedef struct {
|
|||||||
USBEndpointDescriptor bulkIn;
|
USBEndpointDescriptor bulkIn;
|
||||||
/// Interrupt OUT endpoint descriptor
|
/// Interrupt OUT endpoint descriptor
|
||||||
USBEndpointDescriptor interruptIn;
|
USBEndpointDescriptor interruptIn;
|
||||||
|
DFURT_IF_DESCRIPTOR_STRUCT
|
||||||
} __attribute__ ((packed)) CCIDDriverConfigurationDescriptors;
|
} __attribute__ ((packed)) CCIDDriverConfigurationDescriptors;
|
||||||
|
|
||||||
extern const USBConfigurationDescriptor *configurationDescriptorsArr[];
|
extern const USBConfigurationDescriptor *configurationDescriptorsArr[];
|
||||||
|
|
||||||
int check_data_from_phone();
|
/*! Update USART baud rate to Fi/Di ratio
|
||||||
void update_fidi(uint8_t fidi);
|
* @param[io] usart USART peripheral base address
|
||||||
|
* @param[in] fidi FiDi value as provided in TA interface byte
|
||||||
|
*/
|
||||||
|
void update_fidi(Usart_info *usart, uint8_t fidi);
|
||||||
|
|
||||||
void ISR_PhoneRST( const Pin *pPin);
|
void ISR_PhoneRST( const Pin *pPin);
|
||||||
|
|
||||||
@@ -106,6 +116,9 @@ extern void CCID_run( void );
|
|||||||
extern void mode_cardemu_run(void);
|
extern void mode_cardemu_run(void);
|
||||||
extern void MITM_run( void );
|
extern void MITM_run( void );
|
||||||
|
|
||||||
|
/* IRQ functions */
|
||||||
|
extern void Sniffer_usart0_irq(void);
|
||||||
|
extern void Sniffer_usart1_irq(void);
|
||||||
extern void mode_cardemu_usart0_irq(void);
|
extern void mode_cardemu_usart0_irq(void);
|
||||||
extern void mode_cardemu_usart1_irq(void);
|
extern void mode_cardemu_usart1_irq(void);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
#pragma once
|
/* SIMtrace2 USB protocol
|
||||||
|
*
|
||||||
#include <stdint.h>
|
* (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>
|
||||||
/* SIMtrace2 USB protocol */
|
|
||||||
|
|
||||||
/* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
|
|
||||||
*
|
*
|
||||||
* 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 General Public License as published by
|
||||||
@@ -18,9 +15,12 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* COMMON HEADER
|
* COMMON HEADER
|
||||||
@@ -30,10 +30,10 @@ enum simtrace_msg_class {
|
|||||||
SIMTRACE_MSGC_GENERIC = 0,
|
SIMTRACE_MSGC_GENERIC = 0,
|
||||||
/* Card Emulation / Forwarding */
|
/* Card Emulation / Forwarding */
|
||||||
SIMTRACE_MSGC_CARDEM,
|
SIMTRACE_MSGC_CARDEM,
|
||||||
/* Modem Control (if modem is attached next to device */
|
/* Modem Control (if modem is attached next to device) */
|
||||||
SIMTRACE_MSGC_MODEM,
|
SIMTRACE_MSGC_MODEM,
|
||||||
/* SIM protocol tracing */
|
/* Reader/phone-car/SIM communication sniff */
|
||||||
SIMTRACE_MSGC_TRACE,
|
SIMTRACE_MSGC_SNIFF,
|
||||||
|
|
||||||
/* first vendor-specific request */
|
/* first vendor-specific request */
|
||||||
_SIMTRACE_MGSC_VENDOR_FIRST = 127,
|
_SIMTRACE_MGSC_VENDOR_FIRST = 127,
|
||||||
@@ -74,10 +74,18 @@ enum simtrace_msg_type_modem {
|
|||||||
SIMTRACE_MSGT_BD_MODEM_STATUS,
|
SIMTRACE_MSGT_BD_MODEM_STATUS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SIMTRACE_MSGC_TRACE */
|
/* SIMTRACE_MSGC_SNIFF */
|
||||||
enum simtrace_msg_type_trace {
|
enum simtrace_msg_type_sniff {
|
||||||
/* FIXME */
|
/* Status change (card inserted, reset, ...) */
|
||||||
_dummy,
|
SIMTRACE_MSGT_SNIFF_CHANGE = 0,
|
||||||
|
/* Fi/Di baudrate change */
|
||||||
|
SIMTRACE_MSGT_SNIFF_FIDI,
|
||||||
|
/* ATR data */
|
||||||
|
SIMTRACE_MSGT_SNIFF_ATR,
|
||||||
|
/* PPS (request or response) data */
|
||||||
|
SIMTRACE_MSGT_SNIFF_PPS,
|
||||||
|
/* TPDU data */
|
||||||
|
SIMTRACE_MSGT_SNIFF_TPDU,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* common message header */
|
/* common message header */
|
||||||
@@ -92,7 +100,7 @@ struct simtrace_msg_hdr {
|
|||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CARD EMULATOR / FORWARDER
|
* Capabilities
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
/* generic capabilities */
|
/* generic capabilities */
|
||||||
@@ -107,7 +115,7 @@ enum simtrace_capability_generic {
|
|||||||
SIMTRACE_CAP_LED_1,
|
SIMTRACE_CAP_LED_1,
|
||||||
/* Has LED2 */
|
/* Has LED2 */
|
||||||
SIMTRACE_CAP_LED_2,
|
SIMTRACE_CAP_LED_2,
|
||||||
/* Has Single-Pole Dual-Throw (local/remote SIM */
|
/* Has Single-Pole Dual-Throw (local/remote SIM) */
|
||||||
SIMTRACE_CAP_SPDT,
|
SIMTRACE_CAP_SPDT,
|
||||||
/* Has Bus-Switch (trace / MITM) */
|
/* Has Bus-Switch (trace / MITM) */
|
||||||
SIMTRACE_CAP_BUS_SWITCH,
|
SIMTRACE_CAP_BUS_SWITCH,
|
||||||
@@ -127,7 +135,7 @@ enum simtrace_capability_generic {
|
|||||||
SIMTRACE_CAP_ASSERT_MODEM_RST,
|
SIMTRACE_CAP_ASSERT_MODEM_RST,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vendor-specific capabilities of sysmoocm devices */
|
/* vendor-specific capabilities of sysmocom devices */
|
||||||
enum simtrace_capability_vendor {
|
enum simtrace_capability_vendor {
|
||||||
/* Can erase a peer SAM3 controller */
|
/* Can erase a peer SAM3 controller */
|
||||||
SIMTRACE_CAP_SYSMO_QMOD_ERASE_PEER,
|
SIMTRACE_CAP_SYSMO_QMOD_ERASE_PEER,
|
||||||
@@ -137,7 +145,6 @@ enum simtrace_capability_vendor {
|
|||||||
SIMTRACE_CAP_SYSMO_QMOD_RESET_HUB,
|
SIMTRACE_CAP_SYSMO_QMOD_RESET_HUB,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* SIMTRACE_CMD_BD_BOARD_INFO */
|
/* SIMTRACE_CMD_BD_BOARD_INFO */
|
||||||
struct simtrace_board_info {
|
struct simtrace_board_info {
|
||||||
struct {
|
struct {
|
||||||
@@ -221,11 +228,10 @@ struct cardemu_usb_msg_status {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
/* phone-applied target voltage in mV */
|
/* phone-applied target voltage in mV */
|
||||||
uint16_t voltage_mv;
|
uint16_t voltage_mv;
|
||||||
/* Fi/Di related information */
|
uint8_t f; /*!< index of F and f_max values as encoded in ISO/IEC 7816-3:2006(E) Table 7 */
|
||||||
uint8_t fi;
|
uint8_t d; /*!< index of D value as encoded in ISO/IEC 7816-3:2006(E) Table 8 */
|
||||||
uint8_t di;
|
uint8_t wi; /*!< Waiting Integer as defined in ISO/IEC 7816-3:2006(E) Section 10.2 */
|
||||||
uint8_t wi;
|
uint32_t wt; /*!< Waiting Time in ETU as defined in ISO/IEC 7816-3:2006(E) Section 8.1 */
|
||||||
uint32_t waiting_time;
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/* CEMU_USB_MSGT_DO_PTS */
|
/* CEMU_USB_MSGT_DO_PTS */
|
||||||
@@ -253,7 +259,7 @@ struct cardemu_usb_msg_error {
|
|||||||
|
|
||||||
/* SIMTRACE_MSGT_DT_MODEM_RESET */
|
/* SIMTRACE_MSGT_DT_MODEM_RESET */
|
||||||
struct st_modem_reset {
|
struct st_modem_reset {
|
||||||
/* 0: de-assert reset, 1: assert reset, 2: poulse reset */
|
/* 0: de-assert reset, 1: assert reset, 2: pulse reset */
|
||||||
uint8_t asserted;
|
uint8_t asserted;
|
||||||
/* if above is '2', duration of pulse in ms */
|
/* if above is '2', duration of pulse in ms */
|
||||||
uint16_t pulse_duration_msec;
|
uint16_t pulse_duration_msec;
|
||||||
@@ -276,3 +282,40 @@ struct st_modem_status {
|
|||||||
/* bit-field of changed status bits */
|
/* bit-field of changed status bits */
|
||||||
uint8_t changed_mask;
|
uint8_t changed_mask;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* SNIFF
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
/* SIMTRACE_MSGT_SNIFF_CHANGE flags */
|
||||||
|
#define SNIFF_CHANGE_FLAG_CARD_INSERT (1<<0)
|
||||||
|
#define SNIFF_CHANGE_FLAG_CARD_EJECT (1<<1)
|
||||||
|
#define SNIFF_CHANGE_FLAG_RESET_ASSERT (1<<2)
|
||||||
|
#define SNIFF_CHANGE_FLAG_RESET_DEASSERT (1<<3)
|
||||||
|
#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 */
|
||||||
|
struct sniff_change {
|
||||||
|
/* SIMTRACE_MSGT_SNIFF_CHANGE flags */
|
||||||
|
uint32_t flags;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* SIMTRACE_MSGT_SNIFF_FIDI */
|
||||||
|
struct sniff_fidi {
|
||||||
|
/* Fi/Di values as encoded in TA1 */
|
||||||
|
uint8_t fidi;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* SIMTRACE_MSGT_SNIFF_ATR, SIMTRACE_MSGT_SNIFF_PPS, SIMTRACE_MSGT_SNIFF_TPDU */
|
||||||
|
struct sniff_data {
|
||||||
|
/* data flags */
|
||||||
|
uint32_t flags;
|
||||||
|
/* data length */
|
||||||
|
uint16_t length;
|
||||||
|
/* data */
|
||||||
|
uint8_t data[0];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|||||||
67
firmware/libcommon/include/simtrace_usb.h
Normal file
67
firmware/libcommon/include/simtrace_usb.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/* SIMtrace 2 USB definitions
|
||||||
|
*
|
||||||
|
* (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
|
||||||
|
*/
|
||||||
|
/* SIMtrace USB IDs */
|
||||||
|
#define USB_VENDOR_OPENMOKO 0x1d50
|
||||||
|
#define USB_PRODUCT_OWHW_SAM3_DFU 0x4001 /* was 0x4000 */
|
||||||
|
#define USB_PRODUCT_OWHW_SAM3 0x4001
|
||||||
|
#define USB_PRODUCT_QMOD_HUB 0x4002
|
||||||
|
#define USB_PRODUCT_QMOD_SAM3_DFU 0x4004 /* was 0x4003 */
|
||||||
|
#define USB_PRODUCT_QMOD_SAM3 0x4004
|
||||||
|
#define USB_PRODUCT_SIMTRACE2_DFU 0x60e3 /* was 0x60e2 */
|
||||||
|
#define USB_PRODUCT_SIMTRACE2 0x60e3
|
||||||
|
|
||||||
|
/* USB proprietary class */
|
||||||
|
#define USB_CLASS_PROPRIETARY 0xff
|
||||||
|
|
||||||
|
/* SIMtrace USB sub-classes */
|
||||||
|
/*! Sniffer USB sub-class */
|
||||||
|
#define SIMTRACE_SNIFFER_USB_SUBCLASS 1
|
||||||
|
/*! Card-emulation USB sub-class */
|
||||||
|
#define SIMTRACE_CARDEM_USB_SUBCLASS 2
|
||||||
|
|
||||||
|
/* Generic USB endpoint numbers */
|
||||||
|
/*! Card-side USB data out (host to device) endpoint number */
|
||||||
|
#define SIMTRACE_USB_EP_CARD_DATAOUT 1
|
||||||
|
/*! Card-side USB data in (device to host) endpoint number */
|
||||||
|
#define SIMTRACE_USB_EP_CARD_DATAIN 2
|
||||||
|
/*! Card-side USB interrupt endpoint number */
|
||||||
|
#define SIMTRACE_USB_EP_CARD_INT 3
|
||||||
|
/*! Phone-side USB data out (host to device) endpoint number */
|
||||||
|
#define SIMTRACE_USB_EP_PHONE_DATAOUT 4
|
||||||
|
/*! Phone-side USB data in (device to host) endpoint number */
|
||||||
|
#define SIMTRACE_USB_EP_PHONE_DATAIN 5
|
||||||
|
/*! Phone-side USB interrupt endpoint number */
|
||||||
|
#define SIMTRACE_USB_EP_PHONE_INT 6
|
||||||
|
|
||||||
|
/* Card-emulation USB endpoint numbers */
|
||||||
|
/*! USIM1 USB data out (host to device) endpoint number */
|
||||||
|
#define SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT 4
|
||||||
|
/*! USIM1 USB data in (device to host) endpoint number */
|
||||||
|
#define SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN 5
|
||||||
|
/*! USIM1 USB interrupt endpoint number */
|
||||||
|
#define SIMTRACE_CARDEM_USB_EP_USIM1_INT 6
|
||||||
|
/*! USIM2 USB data out (host to device) endpoint number */
|
||||||
|
#define SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT 1
|
||||||
|
/*! USIM2 USB data in (device to host) endpoint number */
|
||||||
|
#define SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN 2
|
||||||
|
/*! USIM2 USB interrupt endpoint number */
|
||||||
|
#define SIMTRACE_CARDEM_USB_EP_USIM2_INT 3
|
||||||
|
|
||||||
|
/*! Maximum number of endpoints */
|
||||||
|
#define BOARD_USB_NUMENDPOINTS 6
|
||||||
@@ -1,3 +1,31 @@
|
|||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* 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>
|
||||||
@@ -24,9 +52,14 @@ 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);
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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>
|
||||||
|
|||||||
@@ -1,7 +1,23 @@
|
|||||||
|
/* 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>
|
||||||
#include "osmocom/core/msgb.h"
|
#include <osmocom/core/msgb.h>
|
||||||
|
|
||||||
/* buffered USB endpoint (with queue of msgb) */
|
/* buffered USB endpoint (with queue of msgb) */
|
||||||
struct usb_buffered_ep {
|
struct usb_buffered_ep {
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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]))
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/* 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>
|
||||||
|
* (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
|
* 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 General Public License as published by
|
||||||
@@ -13,12 +15,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define TRACE_LEVEL 6
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -28,14 +26,12 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "iso7816_fidi.h"
|
#include "iso7816_3.h"
|
||||||
#include "tc_etu.h"
|
|
||||||
#include "card_emu.h"
|
#include "card_emu.h"
|
||||||
#include "simtrace_prot.h"
|
#include "simtrace_prot.h"
|
||||||
#include "usb_buf.h"
|
#include "usb_buf.h"
|
||||||
#include "osmocom/core/linuxlist.h"
|
#include <osmocom/core/linuxlist.h>
|
||||||
#include "osmocom/core/msgb.h"
|
#include <osmocom/core/msgb.h>
|
||||||
|
|
||||||
|
|
||||||
#define NUM_SLOTS 2
|
#define NUM_SLOTS 2
|
||||||
|
|
||||||
@@ -56,6 +52,46 @@ 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,
|
||||||
@@ -72,6 +108,7 @@ 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
|
||||||
@@ -87,10 +124,50 @@ 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, /* waiitng for more data from reader */
|
TPDU_S_WAIT_RX, /* waiting 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
|
||||||
@@ -98,7 +175,7 @@ enum tpdu_state {
|
|||||||
#define _P3 4
|
#define _P3 4
|
||||||
|
|
||||||
struct card_handle {
|
struct card_handle {
|
||||||
uint32_t num;
|
unsigned int num;
|
||||||
|
|
||||||
enum iso7816_3_card_state state;
|
enum iso7816_3_card_state state;
|
||||||
|
|
||||||
@@ -107,18 +184,53 @@ struct card_handle {
|
|||||||
uint8_t in_reset; /* 1 = RST low, 0 = RST high */
|
uint8_t in_reset; /* 1 = RST low, 0 = RST high */
|
||||||
uint8_t clocked; /* 1 = active, 0 = inactive */
|
uint8_t clocked; /* 1 = active, 0 = inactive */
|
||||||
|
|
||||||
/* timing parameters, from PTS */
|
|
||||||
uint8_t fi;
|
|
||||||
uint8_t di;
|
|
||||||
uint8_t wi;
|
|
||||||
|
|
||||||
uint8_t tc_chan; /* TC channel number */
|
uint8_t tc_chan; /* TC channel number */
|
||||||
uint8_t uart_chan; /* UART channel */
|
uint8_t uart_chan; /* UART channel */
|
||||||
|
|
||||||
uint8_t in_ep; /* USB IN EP */
|
uint8_t in_ep; /* USB IN EP */
|
||||||
uint8_t irq_ep; /* USB IN EP */
|
uint8_t irq_ep; /* USB IN EP */
|
||||||
|
|
||||||
uint32_t waiting_time; /* in clocks */
|
/*! clock rate conversion integer F
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 7.1
|
||||||
|
* @note this represents the current value used
|
||||||
|
*/
|
||||||
|
uint16_t f;
|
||||||
|
/*! baud rate adjustment factor D
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 7.1
|
||||||
|
* @note this represents the current value used
|
||||||
|
*/
|
||||||
|
uint8_t d;
|
||||||
|
/*! clock frequency in Hz
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) section 7.1
|
||||||
|
* @note the USART peripheral in slave mode does not provide the current value. we could measure it but this is not really useful. instead we remember the maximum possible value corresponding to the selected F value
|
||||||
|
*/
|
||||||
|
uint32_t f_cur;
|
||||||
|
/*! clock rate conversion integer Fi
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) Table 7
|
||||||
|
* @note this represents the maximum value supported by the card, and can be indicated in TA1
|
||||||
|
* @note this value can be set in TA1
|
||||||
|
*/
|
||||||
|
uint16_t fi;
|
||||||
|
/*! baud rate adjustment factor Di
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) Table 8
|
||||||
|
* @note this represents the maximum value supported by the card, and can be indicated in TA1
|
||||||
|
*/
|
||||||
|
uint8_t di;
|
||||||
|
/*! clock frequency, in Hz
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) Table 7
|
||||||
|
* @note this represents the maximum value supported by the card, and can be indicated in TA1
|
||||||
|
*/
|
||||||
|
uint32_t f_max;
|
||||||
|
/*! Waiting Integer
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) Section 10.2
|
||||||
|
* @note this value can be set in TA2
|
||||||
|
*/
|
||||||
|
uint8_t wi;
|
||||||
|
/*! Waiting Time, in ETU
|
||||||
|
* @implements ISO/IEC 7816-3:2006(E) Section 8.1
|
||||||
|
* @note this depends on Fi, Di, and WI if T=0 is used
|
||||||
|
*/
|
||||||
|
uint32_t wt;
|
||||||
|
|
||||||
/* ATR state machine */
|
/* ATR state machine */
|
||||||
struct {
|
struct {
|
||||||
@@ -192,7 +304,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 bufffer */
|
/* Update cardemu_usb_msg_rx_data length + submit buffer */
|
||||||
static void flush_rx_buffer(struct card_handle *ch)
|
static void flush_rx_buffer(struct card_handle *ch)
|
||||||
{
|
{
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
@@ -205,14 +317,17 @@ static void flush_rx_buffer(struct card_handle *ch)
|
|||||||
|
|
||||||
ch->uart_rx_msg = NULL;
|
ch->uart_rx_msg = NULL;
|
||||||
|
|
||||||
/* store length of data payload fild in header */
|
/* store length of data payload field 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/responsei into a contiguous
|
/* convert a non-contiguous PTS request/response 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)
|
||||||
{
|
{
|
||||||
@@ -263,23 +378,6 @@ static void flush_pts(struct card_handle *ch)
|
|||||||
usb_buf_upd_len_and_submit(msg);
|
usb_buf_upd_len_and_submit(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emu_update_fidi(struct card_handle *ch)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = compute_fidi_ratio(ch->fi, ch->di);
|
|
||||||
if (rc > 0 && rc < 0x400) {
|
|
||||||
TRACE_INFO("%u: computed Fi(%u) Di(%u) ratio: %d\r\n",
|
|
||||||
ch->num, ch->fi, ch->di, rc);
|
|
||||||
/* make sure UART uses new F/D ratio */
|
|
||||||
card_emu_uart_update_fidi(ch->uart_chan, rc);
|
|
||||||
/* notify ETU timer about this */
|
|
||||||
tc_etu_set_etu(ch->tc_chan, rc);
|
|
||||||
} else
|
|
||||||
TRACE_INFO("%u: computed FiDi ration %d unsupported\r\n",
|
|
||||||
ch->num, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the ISO 7816-3 TPDU receiver state */
|
/* Update the ISO 7816-3 TPDU receiver state */
|
||||||
static void card_set_state(struct card_handle *ch,
|
static void card_set_state(struct card_handle *ch,
|
||||||
enum iso7816_3_card_state new_state)
|
enum iso7816_3_card_state new_state)
|
||||||
@@ -287,44 +385,59 @@ 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 %u -> %u\r\n", ch->num,
|
TRACE_DEBUG("%u: 7816 card state %s -> %s\r\n", ch->num,
|
||||||
ch->state, new_state);
|
get_value_string(iso7816_3_card_state_names, ch->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) {
|
||||||
case ISO_S_WAIT_POWER:
|
case ISO_S_WAIT_POWER:
|
||||||
case ISO_S_WAIT_CLK:
|
case ISO_S_WAIT_CLK:
|
||||||
case ISO_S_WAIT_RST:
|
case ISO_S_WAIT_RST:
|
||||||
/* disable Rx and Tx of UART */
|
card_emu_uart_enable(ch->uart_chan, 0); // disable Rx and Tx of UART
|
||||||
card_emu_uart_enable(ch->uart_chan, 0);
|
card_emu_uart_update_wt(ch->uart_chan, 0); // disable timeout
|
||||||
|
if (ISO_S_WAIT_POWER == new_state) {
|
||||||
|
card_emu_uart_io_set(ch->uart_chan, false); // pull I/O line low
|
||||||
|
} else {
|
||||||
|
card_emu_uart_io_set(ch->uart_chan, true); // pull I/O line high
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ISO_S_WAIT_ATR:
|
case ISO_S_WAIT_ATR:
|
||||||
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
|
// reset the ETU-related values
|
||||||
/* Reset to initial Fi / Di ratio */
|
ch->f = ISO7816_3_DEFAULT_FD;
|
||||||
ch->fi = 1;
|
ch->d = ISO7816_3_DEFAULT_DD;
|
||||||
ch->di = 1;
|
card_emu_uart_update_fd(ch->uart_chan, ch->f, ch->d); // set baud rate
|
||||||
emu_update_fidi(ch);
|
|
||||||
/* initialize todefault WI, this will be overwritten if we
|
// reset values optionally specified in the ATR
|
||||||
* receive TC2, and it will be programmed into hardware after
|
ch->fi = ISO7816_3_DEFAULT_FI;
|
||||||
* ATR is finished */
|
ch->di = ISO7816_3_DEFAULT_DI;
|
||||||
ch->wi = ISO7816_3_DEFAULT_WI;
|
ch->wi = ISO7816_3_DEFAULT_WI;
|
||||||
/* update waiting time to initial waiting time */
|
int32_t wt = iso7816_3_calculate_wt(ch->wi, ch->fi, ch->di, ch->f, ch->d); // get default waiting time
|
||||||
ch->waiting_time = ISO7816_3_INIT_WTIME;
|
if (wt <= 0) {
|
||||||
tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
|
TRACE_FATAL("%u: invalid WT %ld\r\n", ch->num, wt);
|
||||||
|
}
|
||||||
|
ch->wt = wt;
|
||||||
|
card_emu_uart_enable(ch->uart_chan, ENABLE_TX); // enable TX to be able to use the timeout
|
||||||
|
/* the ATR should only be sent 400 to 40k clock cycles after the RESET.
|
||||||
|
* we use the tc_etu mechanism to wait this time.
|
||||||
|
* since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.
|
||||||
|
*/
|
||||||
|
card_emu_uart_update_wt(ch->uart_chan, 2);
|
||||||
|
break;
|
||||||
|
case ISO_S_IN_ATR:
|
||||||
|
// FIXME disable timeout while sending ATR
|
||||||
/* Set ATR sub-state to initial state */
|
/* Set ATR sub-state to initial state */
|
||||||
ch->atr.idx = 0;
|
ch->atr.idx = 0;
|
||||||
//set_atr_state(ch, ATR_S_WAIT_TS);
|
/* enable USART transmission to reader */
|
||||||
/* 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);
|
||||||
break;
|
/* trigger USART TX IRQ to sent first ATR byte TS */
|
||||||
|
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 */
|
||||||
@@ -332,12 +445,77 @@ 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 */
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* FIXME update waiting time in case of card is specific mode */
|
||||||
|
/* 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 ATR sub-state */
|
/* Update the PTS 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",
|
||||||
@@ -388,9 +566,12 @@ from_pts3:
|
|||||||
return PTS_S_WAIT_REQ_PCK | is_resp;
|
return PTS_S_WAIT_REQ_PCK | is_resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! process incoming PTS byte
|
||||||
static int
|
* @param[in] ch card handle on which the byte has been received
|
||||||
process_byte_pts(struct card_handle *ch, uint8_t byte)
|
* @param[in] byte received PTS byte
|
||||||
|
* @return new iso7816_3_card_state or -1 at the end of PTS request
|
||||||
|
*/
|
||||||
|
static int process_byte_pts(struct card_handle *ch, uint8_t byte)
|
||||||
{
|
{
|
||||||
switch (ch->pts.state) {
|
switch (ch->pts.state) {
|
||||||
case PTS_S_WAIT_REQ_PTSS:
|
case PTS_S_WAIT_REQ_PTSS:
|
||||||
@@ -417,7 +598,7 @@ process_byte_pts(struct card_handle *ch, uint8_t byte)
|
|||||||
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
|
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
|
||||||
return ISO_S_WAIT_TPDU;
|
return ISO_S_WAIT_TPDU;
|
||||||
}
|
}
|
||||||
/* FIXME: check if proposal matches capabilities in ATR */
|
/* FIXME check if proposal matches capabilities in TA1 */
|
||||||
memcpy(ch->pts.resp, ch->pts.req, sizeof(ch->pts.resp));
|
memcpy(ch->pts.resp, ch->pts.req, sizeof(ch->pts.resp));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -456,11 +637,17 @@ static int tx_byte_pts(struct card_handle *ch)
|
|||||||
break;
|
break;
|
||||||
case PTS_S_WAIT_RESP_PTS1:
|
case PTS_S_WAIT_RESP_PTS1:
|
||||||
byte = ch->pts.resp[_PTS1];
|
byte = ch->pts.resp[_PTS1];
|
||||||
/* This must be TA1 */
|
// TODO the value should have been validated when receiving the request
|
||||||
ch->fi = byte >> 4;
|
ch->f = iso7816_3_fi_table[byte >> 4]; // save selected Fn
|
||||||
ch->di = byte & 0xf;
|
if (0 == ch->f) {
|
||||||
TRACE_DEBUG("%u: found Fi=%u Di=%u\r\n", ch->num,
|
TRACE_ERROR("%u: invalid F index in PPS response: %u\r\n", ch->num, byte >> 4);
|
||||||
ch->fi, ch->di);
|
// TODO become unresponsive to signal error condition
|
||||||
|
}
|
||||||
|
ch->d = iso7816_3_di_table[byte & 0xf]; // save selected Dn
|
||||||
|
if (0 == ch->d) {
|
||||||
|
TRACE_ERROR("%u: invalid D index in PPS response: %u\r\n", ch->num, byte & 0xf);
|
||||||
|
// TODO become unresponsive to signal error condition
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PTS_S_WAIT_RESP_PTS2:
|
case PTS_S_WAIT_RESP_PTS2:
|
||||||
byte = ch->pts.resp[_PTS2];
|
byte = ch->pts.resp[_PTS2];
|
||||||
@@ -485,8 +672,15 @@ static int tx_byte_pts(struct card_handle *ch)
|
|||||||
switch (ch->pts.state) {
|
switch (ch->pts.state) {
|
||||||
case PTS_S_WAIT_RESP_PCK:
|
case PTS_S_WAIT_RESP_PCK:
|
||||||
card_emu_uart_wait_tx_idle(ch->uart_chan);
|
card_emu_uart_wait_tx_idle(ch->uart_chan);
|
||||||
/* update baud rate generator with Fi/Di */
|
card_emu_uart_update_fd(ch->uart_chan, ch->f, ch->d); // set selected baud rate
|
||||||
emu_update_fidi(ch);
|
int32_t wt = iso7816_3_calculate_wt(ch->wi, ch->fi, ch->di, ch->f, ch->d); // get new waiting time
|
||||||
|
if (wt <= 0) {
|
||||||
|
TRACE_ERROR("%u: invalid WT calculated: %ld\r\n", ch->num, wt);
|
||||||
|
// TODO become unresponsive to signal error condition
|
||||||
|
} else {
|
||||||
|
ch->wt = wt;
|
||||||
|
}
|
||||||
|
// FIXME disable WT
|
||||||
/* Wait for the next TPDU */
|
/* Wait for the next TPDU */
|
||||||
card_set_state(ch, ISO_S_WAIT_TPDU);
|
card_set_state(ch, ISO_S_WAIT_TPDU);
|
||||||
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
|
set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
|
||||||
@@ -557,22 +751,31 @@ 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;
|
||||||
|
if (ISO_S_IN_TPDU != ch->state && ISO_S_WAIT_TPDU != ch->state) {
|
||||||
|
TRACE_ERROR("%u: setting TPDU state in %s state\r\n", ch->num,
|
||||||
|
get_value_string(iso7816_3_card_state_names, ch->state));
|
||||||
|
}
|
||||||
|
|
||||||
TRACE_DEBUG("%u: 7816 TPDU state %u -> %u\r\n", ch->num,
|
TRACE_DEBUG("%u: 7816 TPDU state %s -> %s\r\n", ch->num,
|
||||||
ch->tpdu.state, new_ts);
|
get_value_string(tpdu_state_names, ch->tpdu.state),
|
||||||
|
get_value_string(tpdu_state_names, new_ts));
|
||||||
ch->tpdu.state = new_ts;
|
ch->tpdu.state = new_ts;
|
||||||
|
|
||||||
switch (new_ts) {
|
switch (new_ts) {
|
||||||
case TPDU_S_WAIT_CLA:
|
case TPDU_S_WAIT_CLA: // we will be waiting for the next incoming TDPU
|
||||||
case TPDU_S_WAIT_RX:
|
card_emu_uart_enable(ch->uart_chan, ENABLE_RX); // switch back to receiving mode
|
||||||
card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
|
card_emu_uart_update_wt(ch->uart_chan, 0); // disable waiting time since we don't expect any data
|
||||||
|
break;
|
||||||
|
case TPDU_S_WAIT_INS: // the reader started sending the TPDU header
|
||||||
|
card_emu_uart_update_wt(ch->uart_chan, ch->wt); // start waiting for the rest of the header/body
|
||||||
|
break;
|
||||||
|
case TPDU_S_WAIT_RX: // the reader should send us the TPDU body data
|
||||||
|
card_emu_uart_enable(ch->uart_chan, ENABLE_RX); // switch to receive mode to receive the body
|
||||||
|
card_emu_uart_update_wt(ch->uart_chan, ch->wt); // start waiting for the rest body
|
||||||
break;
|
break;
|
||||||
case TPDU_S_WAIT_PB:
|
case TPDU_S_WAIT_PB:
|
||||||
/* we just completed the TPDU header from reader to card
|
card_emu_uart_enable(ch->uart_chan, ENABLE_TX); // header is completely received, now we need to transmit the procedure byte
|
||||||
* and now need to disable the receiver, enable the
|
card_emu_uart_update_wt(ch->uart_chan, ch->wt); // prepare to extend the waiting time once half of it is reached
|
||||||
* transmitter and transmit the procedure byte */
|
|
||||||
card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -718,7 +921,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 transmittd */
|
/* this must happen _after_ the byte has been transmitted */
|
||||||
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
|
||||||
@@ -765,14 +968,6 @@ 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);
|
||||||
@@ -786,6 +981,10 @@ 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:
|
||||||
@@ -800,17 +999,7 @@ 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:
|
||||||
if (ch->atr.idx < ch->atr.len) {
|
rc = tx_byte_atr(ch);
|
||||||
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);
|
||||||
@@ -865,11 +1054,11 @@ void card_emu_report_status(struct card_handle *ch)
|
|||||||
sts->flags |= CEMU_STATUS_F_CLK_ACTIVE;
|
sts->flags |= CEMU_STATUS_F_CLK_ACTIVE;
|
||||||
if (ch->in_reset)
|
if (ch->in_reset)
|
||||||
sts->flags |= CEMU_STATUS_F_RESET_ACTIVE;
|
sts->flags |= CEMU_STATUS_F_RESET_ACTIVE;
|
||||||
/* FIXME: voltage + card insert */
|
/* FIXME set voltage and card insert values */
|
||||||
sts->fi = ch->fi;
|
sts->f = ch->f;
|
||||||
sts->di = ch->di;
|
sts->d = ch->d;
|
||||||
sts->wi = ch->wi;
|
sts->wi = ch->wi;
|
||||||
sts->waiting_time = ch->waiting_time;
|
sts->wt = ch->wt;
|
||||||
|
|
||||||
usb_buf_upd_len_and_submit(msg);
|
usb_buf_upd_len_and_submit(msg);
|
||||||
}
|
}
|
||||||
@@ -881,7 +1070,6 @@ void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
|
|||||||
case CARD_IO_VCC:
|
case CARD_IO_VCC:
|
||||||
if (active == 0 && ch->vcc_active == 1) {
|
if (active == 0 && ch->vcc_active == 1) {
|
||||||
TRACE_INFO("%u: VCC deactivated\r\n", ch->num);
|
TRACE_INFO("%u: VCC deactivated\r\n", ch->num);
|
||||||
tc_etu_disable(ch->tc_chan);
|
|
||||||
card_set_state(ch, ISO_S_WAIT_POWER);
|
card_set_state(ch, ISO_S_WAIT_POWER);
|
||||||
} else if (active == 1 && ch->vcc_active == 0) {
|
} else if (active == 1 && ch->vcc_active == 0) {
|
||||||
TRACE_INFO("%u: VCC activated\r\n", ch->num);
|
TRACE_INFO("%u: VCC activated\r\n", ch->num);
|
||||||
@@ -902,19 +1090,18 @@ void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
|
|||||||
case CARD_IO_RST:
|
case CARD_IO_RST:
|
||||||
if (active == 0 && ch->in_reset) {
|
if (active == 0 && ch->in_reset) {
|
||||||
TRACE_INFO("%u: RST released\r\n", ch->num);
|
TRACE_INFO("%u: RST released\r\n", ch->num);
|
||||||
if (ch->vcc_active && ch->clocked) {
|
if (ch->vcc_active && ch->clocked && ISO_S_WAIT_RST == ch->state) {
|
||||||
/* enable the TC/ETU counter once reset has been released */
|
/* prepare to send the ATR */
|
||||||
tc_etu_enable(ch->tc_chan);
|
|
||||||
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);
|
||||||
tc_etu_disable(ch->tc_chan);
|
card_set_state(ch, ISO_S_WAIT_RST);
|
||||||
}
|
}
|
||||||
ch->in_reset = active;
|
ch->in_reset = active;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -924,46 +1111,61 @@ int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len)
|
|||||||
if (len > sizeof(ch->atr.atr))
|
if (len > sizeof(ch->atr.atr))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* ignore new ATR for now since we PPS has not been tested
|
||||||
memcpy(ch->atr.atr, atr, len);
|
memcpy(ch->atr.atr, atr, len);
|
||||||
ch->atr.len = len;
|
ch->atr.len = len;
|
||||||
ch->atr.idx = 0;
|
ch->atr.idx = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
/* FIXME: race condition with trasmitting ATR to reader? */
|
#if TRACE_LEVEL >= TRACE_LEVEL_INFO
|
||||||
|
uint8_t i;
|
||||||
|
TRACE_INFO("%u: ATR set: ", ch->num);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
TRACE_INFO_WP("%02x ", atr[i]);
|
||||||
|
}
|
||||||
|
TRACE_INFO_WP("\n\r");
|
||||||
|
TRACE_INFO("%u: ATR set currently ignored\n\r", ch->num);
|
||||||
|
#endif
|
||||||
|
/* FIXME: race condition with transmitting ATR to reader? */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hardware driver informs us that one (more) ETU has expired */
|
void card_emu_wt_halfed(struct card_handle *ch)
|
||||||
void tc_etu_wtime_half_expired(void *handle)
|
|
||||||
{
|
{
|
||||||
struct card_handle *ch = handle;
|
|
||||||
/* transmit NULL procedure byte well before waiting time expires */
|
|
||||||
switch (ch->state) {
|
switch (ch->state) {
|
||||||
case ISO_S_IN_TPDU:
|
case ISO_S_IN_TPDU:
|
||||||
switch (ch->tpdu.state) {
|
switch (ch->tpdu.state) {
|
||||||
case TPDU_S_WAIT_PB:
|
|
||||||
case TPDU_S_WAIT_TX:
|
case TPDU_S_WAIT_TX:
|
||||||
|
case TPDU_S_WAIT_PB:
|
||||||
putchar('N');
|
putchar('N');
|
||||||
card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL);
|
card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL); // we are waiting for data from the user. send a procedure byte to ask the reader to wait more time
|
||||||
|
card_emu_uart_reset_wt(ch->uart_chan); // reset WT
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hardware driver informs us that one (more) ETU has expired */
|
void card_emu_wt_expired(struct card_handle *ch)
|
||||||
void tc_etu_wtime_expired(void *handle)
|
|
||||||
{
|
{
|
||||||
struct card_handle *ch = handle;
|
switch (ch->state) {
|
||||||
|
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:
|
||||||
|
// TODO become unresponsive
|
||||||
TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
|
TRACE_ERROR("%u: wtime_exp\r\n", ch->num);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shortest ATR found in smartcard_list.txt */
|
/* shortest ATR possible (uses default speed and no options) */
|
||||||
static const uint8_t default_atr[] = { 0x3B, 0x02, 0x14, 0x50 };
|
static const uint8_t default_atr[] = { 0x3B, 0x00 };
|
||||||
|
|
||||||
static struct card_handle card_handles[NUM_SLOTS];
|
static struct card_handle card_handles[NUM_SLOTS];
|
||||||
|
|
||||||
@@ -981,7 +1183,7 @@ 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 */
|
/* initialize the card_handle with reasonable 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;
|
||||||
@@ -990,13 +1192,13 @@ struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uar
|
|||||||
ch->in_reset = 1;
|
ch->in_reset = 1;
|
||||||
ch->clocked = 0;
|
ch->clocked = 0;
|
||||||
|
|
||||||
ch->fi = 0;
|
ch->fi = ISO7816_3_DEFAULT_FI;
|
||||||
ch->di = 1;
|
ch->di = ISO7816_3_DEFAULT_DI;
|
||||||
ch->wi = ISO7816_3_DEFAULT_WI;
|
ch->wi = ISO7816_3_DEFAULT_WI;
|
||||||
|
ch->wt = ISO7816_3_DEFAULT_WT;;
|
||||||
|
|
||||||
ch->tc_chan = tc_chan;
|
ch->tc_chan = tc_chan;
|
||||||
ch->uart_chan = uart_chan;
|
ch->uart_chan = uart_chan;
|
||||||
ch->waiting_time = ISO7816_3_INIT_WTIME;
|
|
||||||
|
|
||||||
ch->atr.idx = 0;
|
ch->atr.idx = 0;
|
||||||
ch->atr.len = sizeof(default_atr);
|
ch->atr.len = sizeof(default_atr);
|
||||||
@@ -1005,7 +1207,5 @@ struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uar
|
|||||||
ch->pts.state = PTS_S_WAIT_REQ_PTSS;
|
ch->pts.state = PTS_S_WAIT_REQ_PTSS;
|
||||||
ch->tpdu.state = TPDU_S_WAIT_CLA;
|
ch->tpdu.state = TPDU_S_WAIT_CLA;
|
||||||
|
|
||||||
tc_etu_init(ch->tc_chan, ch);
|
|
||||||
|
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,8 +83,6 @@
|
|||||||
/// Driver structure for an CCID device
|
/// Driver structure for an CCID device
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
/// Standard USB device driver instance
|
|
||||||
USBDDriver usbdDriver;
|
|
||||||
/// CCID message
|
/// CCID message
|
||||||
S_ccid_bulk_in_header sCcidMessage;
|
S_ccid_bulk_in_header sCcidMessage;
|
||||||
/// CCID command
|
/// CCID command
|
||||||
@@ -849,7 +847,6 @@ static void CCIDCommandDispatcher( void *pArg, uint8_t status, uint32_t transfer
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/// SETUP request handler for a CCID device
|
/// SETUP request handler for a CCID device
|
||||||
/// \param pRequest Pointer to a USBGenericRequest instance
|
/// \param pRequest Pointer to a USBGenericRequest instance
|
||||||
@@ -890,7 +887,7 @@ static void CCID_RequestHandler(const USBGenericRequest *pRequest)
|
|||||||
else if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_STANDARD) {
|
else if (USBGenericRequest_GetType(pRequest) == USBGenericRequest_STANDARD) {
|
||||||
|
|
||||||
// Forward request to the standard handler
|
// Forward request to the standard handler
|
||||||
USBDDriver_RequestHandler(&(ccidDriver.usbdDriver), pRequest);
|
USBDDriver_RequestHandler(USBD_GetDriver(), pRequest);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
@@ -916,7 +913,6 @@ void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
|
|||||||
CCID_RequestHandler(request);
|
CCID_RequestHandler(request);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,3 +1,19 @@
|
|||||||
|
/* 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"
|
||||||
|
|
||||||
@@ -10,6 +26,19 @@ 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')
|
||||||
UART_PutChar(*s++);
|
fputc(*s++, stream);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,26 @@
|
|||||||
|
/* 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"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "osmocom/core/linuxlist.h"
|
#include <osmocom/core/linuxlist.h>
|
||||||
#include "osmocom/core/msgb.h"
|
#include <osmocom/core/msgb.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@@ -16,12 +33,13 @@ static void usb_write_cb(uint8_t *arg, uint8_t status, uint32_t transferred,
|
|||||||
{
|
{
|
||||||
struct msgb *msg = (struct msgb *) arg;
|
struct msgb *msg = (struct msgb *) arg;
|
||||||
struct usb_buffered_ep *bep = msg->dst;
|
struct usb_buffered_ep *bep = msg->dst;
|
||||||
|
unsigned long x;
|
||||||
|
|
||||||
TRACE_DEBUG("%s (EP=0x%02x)\r\n", __func__, bep->ep);
|
TRACE_DEBUG("%s (EP=0x%02x)\r\n", __func__, bep->ep);
|
||||||
|
|
||||||
__disable_irq();
|
local_irq_save(x);
|
||||||
bep->in_progress--;
|
bep->in_progress--;
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
TRACE_DEBUG("%u: in_progress=%d\n", bep->ep, bep->in_progress);
|
TRACE_DEBUG("%u: in_progress=%d\n", bep->ep, bep->in_progress);
|
||||||
|
|
||||||
if (status != USBD_STATUS_SUCCESS)
|
if (status != USBD_STATUS_SUCCESS)
|
||||||
@@ -34,6 +52,7 @@ int usb_refill_to_host(uint8_t ep)
|
|||||||
{
|
{
|
||||||
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
|
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
|
unsigned long x;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -43,14 +62,14 @@ int usb_refill_to_host(uint8_t ep)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__disable_irq();
|
local_irq_save(x);
|
||||||
if (bep->in_progress) {
|
if (bep->in_progress) {
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (llist_empty(&bep->queue)) {
|
if (llist_empty(&bep->queue)) {
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +77,7 @@ int usb_refill_to_host(uint8_t ep)
|
|||||||
|
|
||||||
msg = msgb_dequeue(&bep->queue);
|
msg = msgb_dequeue(&bep->queue);
|
||||||
|
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
|
|
||||||
TRACE_DEBUG("%s (EP=0x%02x), in_progress=%d\r\n", __func__, ep, bep->in_progress);
|
TRACE_DEBUG("%s (EP=0x%02x), in_progress=%d\r\n", __func__, ep, bep->in_progress);
|
||||||
|
|
||||||
@@ -70,9 +89,9 @@ int usb_refill_to_host(uint8_t ep)
|
|||||||
TRACE_ERROR("%s error %x\n", __func__, rc);
|
TRACE_ERROR("%s error %x\n", __func__, rc);
|
||||||
/* re-insert to head of queue */
|
/* re-insert to head of queue */
|
||||||
llist_add_irqsafe(&msg->list, &bep->queue);
|
llist_add_irqsafe(&msg->list, &bep->queue);
|
||||||
__disable_irq();
|
local_irq_save(x);
|
||||||
bep->in_progress--;
|
bep->in_progress--;
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
TRACE_DEBUG("%02x: in_progress=%d\n", bep->ep, bep->in_progress);
|
TRACE_DEBUG("%02x: in_progress=%d\n", bep->ep, bep->in_progress);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -105,6 +124,7 @@ int usb_refill_from_host(uint8_t ep)
|
|||||||
{
|
{
|
||||||
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
|
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
|
unsigned long x;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -130,7 +150,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 %s\n", __func__, rc);
|
TRACE_ERROR("%s error %d\n", __func__, rc);
|
||||||
usb_buf_free(msg);
|
usb_buf_free(msg);
|
||||||
bep->in_progress = 0;
|
bep->in_progress = 0;
|
||||||
}
|
}
|
||||||
@@ -142,16 +162,17 @@ int usb_drain_queue(uint8_t ep)
|
|||||||
{
|
{
|
||||||
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
|
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
|
||||||
struct msgb *msg;
|
struct msgb *msg;
|
||||||
|
unsigned long x;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* wait until no transfers are in progress anymore and block
|
/* wait until no transfers are in progress anymore and block
|
||||||
* further interrupts */
|
* further interrupts */
|
||||||
while (1) {
|
while (1) {
|
||||||
__disable_irq();
|
local_irq_save(x);
|
||||||
if (!bep->in_progress) {
|
if (!bep->in_progress) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
/* retry */
|
/* retry */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +183,7 @@ int usb_drain_queue(uint8_t ep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* re-enable interrupts and return number of free'd msgbs */
|
/* re-enable interrupts and return number of free'd msgbs */
|
||||||
__enable_irq();
|
local_irq_restore(x);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
123
firmware/libcommon/source/iso7816_3.c
Normal file
123
firmware/libcommon/source/iso7816_3.c
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "iso7816_3.h"
|
||||||
|
|
||||||
|
const uint16_t iso7816_3_fi_table[16] = {
|
||||||
|
372, 372, 558, 744, 1116, 1488, 1860, 0,
|
||||||
|
0, 512, 768, 1024, 1536, 2048, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32_t iso7816_3_fmax_table[16] = {
|
||||||
|
4000000, 5000000, 6000000, 8000000, 12000000, 16000000, 20000000, 0,
|
||||||
|
0, 5000000, 7500000, 10000000, 15000000, 20000000, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t iso7816_3_di_table[16] = {
|
||||||
|
0, 1, 2, 4, 8, 16, 32, 64,
|
||||||
|
12, 20, 0, 0, 0, 0, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* all values are based on the Elementary Time Unit (ETU), defined in ISO/IEC 7816-3 section 7.1
|
||||||
|
* this is the time required to transmit a bit, and is calculated as follows: 1 ETU = (F / D) x (1 / f) where:
|
||||||
|
* - F is the clock rate conversion integer
|
||||||
|
* - D is the baud rate adjustment factor
|
||||||
|
* - f is the clock frequency
|
||||||
|
* the possible F, f(max), and D values are defined in ISO/IEC 7816-3 table 7 and 8
|
||||||
|
* - the initial value for F (after reset) is Fd = 372
|
||||||
|
* - the initial value for D (after reset) is Dd = 1
|
||||||
|
* - the initial maximum frequency f(max) is 5 MHz
|
||||||
|
* the card must measure the ETU based on the clock signal provided by the reader
|
||||||
|
* one ETU (e.g. 1 bit) takes F/D clock cycles, which the card must count
|
||||||
|
*
|
||||||
|
* the card can indicate an alternative set of supported values Fi (with corresponding f(max)) and Di for higher baud rate in TA1 in the ATR (see ISO/IEC 7816-3 section 8.3)
|
||||||
|
* these values are selected according to ISO/IEC 7816-3 section 6.3.1:
|
||||||
|
* - card in specific mode: they are enforced if TA2 is present (the reader can deactivate the card if it does not support these values)
|
||||||
|
* - card in negotiable mode:
|
||||||
|
* -- they can be selected by the reader using the Protocol and Parameters Selection (PPS) procedure
|
||||||
|
* -- the first offered protocol and default values are used when no PPS is started
|
||||||
|
*
|
||||||
|
* PPS is done with Fd and Dd (see ISO/IEC 7816-3 section 9)
|
||||||
|
* the reader can propose any F and D values between from Fd to Fi, and from Dd to Di (Fi and Di are indicated in TA1)
|
||||||
|
* the in PPS agreed values F and D are called Fn and Dn and are applied after a successful exchange, corresponding to PPS1_Response bit 5
|
||||||
|
*
|
||||||
|
* the F and D values must be provided to the SAM3S USART peripheral (after reset and PPS)
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool iso7816_3_valid_f(uint16_t f)
|
||||||
|
{
|
||||||
|
if (0 == f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t i = 0;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(iso7816_3_fi_table) && iso7816_3_fi_table[i] != f; i++);
|
||||||
|
return (i < ARRAY_SIZE(iso7816_3_fi_table) && iso7816_3_fi_table[i] == f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iso7816_3_valid_d(uint8_t d)
|
||||||
|
{
|
||||||
|
if (0 == d) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t i = 0;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(iso7816_3_di_table) && iso7816_3_di_table[i] != d; i++);
|
||||||
|
return (i < ARRAY_SIZE(iso7816_3_di_table) && iso7816_3_di_table[i] == d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the ETU is not only used to define the baud rate, but also the Waiting Time (WT) (see ISO/IEC 7816-3 section 8.1)
|
||||||
|
* when exceeding WT without card response, the reader flags the card as unresponsive, and resets it
|
||||||
|
* this can be used by the card to indicate errors or unsupported operations
|
||||||
|
* if the card requires more time to respond, it shall send a procedure byte to restart WT
|
||||||
|
* WT is calculated as follows (for T=0, see ISO/IEC 7816-3 section 10.2): WT = WI x 960 x (Fi / f(max)) where
|
||||||
|
* - WI is encoded in TC2 in the ATR (10 if absent)
|
||||||
|
* - WI does not depend on D/Di (used for the ETU)
|
||||||
|
* - after reset WT is 9600 ETU
|
||||||
|
* - WI (e.g. the new WT) is applied when T=0 is used (after 6.3.1), even if Fi is not Fn (this WT extension is important to know for the reader so to have the right timeout)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32_t iso7816_3_calculate_wt(uint8_t wi, uint16_t fi, uint8_t di, uint16_t f, uint8_t d)
|
||||||
|
{
|
||||||
|
// sanity checks
|
||||||
|
if (0 == wi) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!iso7816_3_valid_f(fi)) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (!iso7816_3_valid_d(di)) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (!iso7816_3_valid_f(f)) {
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (!iso7816_3_valid_d(d)) {
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
if (f > fi) {
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
if (d > di) {
|
||||||
|
return -7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wi * 960UL * (fi/f) * (di/d); // calculate timeout value in ETU
|
||||||
|
}
|
||||||
@@ -90,6 +90,7 @@ uint32_t ISO7816_GetChar( uint8_t *pCharToReceive, Usart_info *usart)
|
|||||||
|
|
||||||
/* 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);
|
||||||
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 );
|
||||||
@@ -139,8 +140,8 @@ uint32_t ISO7816_SendChar( uint8_t CharToSend, Usart_info *usart )
|
|||||||
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: %x ", us_base->US_CSR);
|
printf("s: %lx ", us_base->US_CSR);
|
||||||
printf("s: %x\r\n", us_base->US_RHR & 0xFF);
|
printf("s: %lx\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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/* 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
|
* 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 General Public License as published by
|
||||||
@@ -13,10 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
@@ -24,13 +23,13 @@
|
|||||||
#include "iso7816_fidi.h"
|
#include "iso7816_fidi.h"
|
||||||
|
|
||||||
/* Table 7 of ISO 7816-3:2006 */
|
/* Table 7 of ISO 7816-3:2006 */
|
||||||
static const uint16_t fi_table[] = {
|
const uint16_t fi_table[] = {
|
||||||
372, 372, 558, 744, 1116, 1488, 1860, 0,
|
372, 372, 558, 744, 1116, 1488, 1860, 0,
|
||||||
0, 512, 768, 1024, 1536, 2048, 0, 0
|
0, 512, 768, 1024, 1536, 2048, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Table 8 from ISO 7816-3:2006 */
|
/* Table 8 from ISO 7816-3:2006 */
|
||||||
static const uint8_t di_table[] = {
|
const uint8_t di_table[] = {
|
||||||
0, 1, 2, 4, 8, 16, 32, 64,
|
0, 1, 2, 4, 8, 16, 32, 64,
|
||||||
12, 20, 2, 4, 8, 16, 32, 64,
|
12, 20, 2, 4, 8, 16, 32, 64,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,35 @@
|
|||||||
//#define TRACE_LEVEL 6
|
/* card emulation mode
|
||||||
|
*
|
||||||
|
* (C) 2015-2017 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
#include "boardver_adc.h"
|
||||||
#include "simtrace.h"
|
#include "simtrace.h"
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "card_emu.h"
|
#include "card_emu.h"
|
||||||
#include "iso7816_fidi.h"
|
#include "iso7816_3.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "osmocom/core/linuxlist.h"
|
#include <osmocom/core/linuxlist.h>
|
||||||
#include "osmocom/core/msgb.h"
|
#include <osmocom/core/msgb.h>
|
||||||
#include "llist_irqsafe.h"
|
#include "llist_irqsafe.h"
|
||||||
#include "usb_buf.h"
|
#include "usb_buf.h"
|
||||||
|
#include "simtrace_usb.h"
|
||||||
#include "simtrace_prot.h"
|
#include "simtrace_prot.h"
|
||||||
#include "wwan_perst.h"
|
|
||||||
#include "sim_switch.h"
|
#include "sim_switch.h"
|
||||||
|
|
||||||
#define TRACE_ENTRY() TRACE_DEBUG("%s entering\r\n", __func__)
|
#define TRACE_ENTRY() TRACE_DEBUG("%s entering\r\n", __func__)
|
||||||
@@ -32,15 +50,19 @@ static const Pin pin_usim2_vcc = PIN_USIM2_VCC;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct cardem_inst {
|
struct cardem_inst {
|
||||||
uint32_t num;
|
unsigned int 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;
|
||||||
|
uint32_t wt; /*!< receiver waiting time to trigger timeout (0 to deactivate it) */
|
||||||
|
uint32_t wt_remaining; /*!< remaining waiting time */
|
||||||
|
bool wt_halfed; /*!< if at least half of the waiting time passed */
|
||||||
struct Usart_info usart_info;
|
struct Usart_info usart_info;
|
||||||
int usb_pending_old;
|
int usb_pending_old;
|
||||||
uint8_t ep_out;
|
uint8_t ep_out;
|
||||||
uint8_t ep_in;
|
uint8_t ep_in;
|
||||||
uint8_t ep_int;
|
uint8_t ep_int;
|
||||||
|
const Pin pin_io;
|
||||||
const Pin pin_insert;
|
const Pin pin_insert;
|
||||||
uint32_t vcc_uv;
|
uint32_t vcc_uv;
|
||||||
uint32_t vcc_uv_last;
|
uint32_t vcc_uv_last;
|
||||||
@@ -54,9 +76,10 @@ struct cardem_inst cardem_inst[] = {
|
|||||||
.id = ID_USART1,
|
.id = ID_USART1,
|
||||||
.state = USART_RCV
|
.state = USART_RCV
|
||||||
},
|
},
|
||||||
.ep_out = PHONE_DATAOUT,
|
.ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT,
|
||||||
.ep_in = PHONE_DATAIN,
|
.ep_in = SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,
|
||||||
.ep_int = PHONE_INT,
|
.ep_int = SIMTRACE_CARDEM_USB_EP_USIM1_INT,
|
||||||
|
.pin_io = PIN_USIM1_IO,
|
||||||
#ifdef PIN_SET_USIM1_PRES
|
#ifdef PIN_SET_USIM1_PRES
|
||||||
.pin_insert = PIN_SET_USIM1_PRES,
|
.pin_insert = PIN_SET_USIM1_PRES,
|
||||||
#endif
|
#endif
|
||||||
@@ -69,9 +92,10 @@ struct cardem_inst cardem_inst[] = {
|
|||||||
.id = ID_USART0,
|
.id = ID_USART0,
|
||||||
.state = USART_RCV
|
.state = USART_RCV
|
||||||
},
|
},
|
||||||
.ep_out = CARDEM_USIM2_DATAOUT,
|
.ep_out = SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT,
|
||||||
.ep_in = CARDEM_USIM2_DATAIN,
|
.ep_in = SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,
|
||||||
.ep_int = CARDEM_USIM2_INT,
|
.ep_int = SIMTRACE_CARDEM_USB_EP_USIM2_INT,
|
||||||
|
.pin_io = PIN_USIM2_IO,
|
||||||
#ifdef PIN_SET_USIM2_PRES
|
#ifdef PIN_SET_USIM2_PRES
|
||||||
.pin_insert = PIN_SET_USIM2_PRES,
|
.pin_insert = PIN_SET_USIM2_PRES,
|
||||||
#endif
|
#endif
|
||||||
@@ -81,15 +105,11 @@ 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)
|
||||||
{
|
{
|
||||||
switch (uart_chan) {
|
if (uart_chan < ARRAY_SIZE(cardem_inst)) {
|
||||||
case 0:
|
return cardem_inst[uart_chan].usart_info.base;
|
||||||
return USART1;
|
} else {
|
||||||
#ifdef CARDEMU_SECOND_UART
|
|
||||||
case 1:
|
|
||||||
return USART0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@@ -103,7 +123,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: %x \r\n", usart->US_CSR);
|
TRACE_ERROR("s: %lx \r\n", usart->US_CSR);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -126,7 +146,7 @@ void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
|
|||||||
* receiver enabled during transmit */
|
* receiver enabled during transmit */
|
||||||
USART_SetReceiverEnabled(usart, 1);
|
USART_SetReceiverEnabled(usart, 1);
|
||||||
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
|
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
|
||||||
USART_EnableIt(usart, US_IER_TXRDY);
|
USART_EnableIt(usart, US_IER_TXRDY | US_IER_TIMEOUT);
|
||||||
USART_SetTransmitterEnabled(usart, 1);
|
USART_SetTransmitterEnabled(usart, 1);
|
||||||
break;
|
break;
|
||||||
case ENABLE_RX:
|
case ENABLE_RX:
|
||||||
@@ -136,7 +156,7 @@ void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
|
|||||||
USART_SetTransmitterEnabled(usart, 1);
|
USART_SetTransmitterEnabled(usart, 1);
|
||||||
wait_tx_idle(usart);
|
wait_tx_idle(usart);
|
||||||
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
|
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
|
||||||
USART_EnableIt(usart, US_IER_RXRDY);
|
USART_EnableIt(usart, US_IER_RXRDY | US_IER_TIMEOUT);
|
||||||
USART_SetReceiverEnabled(usart, 1);
|
USART_SetReceiverEnabled(usart, 1);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
@@ -160,7 +180,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: %x %02X\r\n",
|
TRACE_ERROR("%u: s: %lx %02lX\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;
|
||||||
@@ -174,56 +194,171 @@ int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: integrate this with actual irq handler */
|
/* FIXME: integrate this with actual irq handler */
|
||||||
static void usart_irq_rx(uint8_t inst_num)
|
static void usart_irq_rx(uint8_t inst_num)
|
||||||
{
|
{
|
||||||
|
if (inst_num >= ARRAY_SIZE(cardem_inst)) {
|
||||||
|
TRACE_ERROR("%u: UART channel out of bounds\r\n", inst_num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Usart *usart = get_usart_by_chan(inst_num);
|
Usart *usart = get_usart_by_chan(inst_num);
|
||||||
struct cardem_inst *ci = &cardem_inst[inst_num];
|
struct cardem_inst *ci = &cardem_inst[inst_num];
|
||||||
uint32_t csr;
|
uint32_t csr;
|
||||||
uint8_t byte = 0;
|
uint8_t byte = 0;
|
||||||
|
|
||||||
csr = usart->US_CSR & usart->US_IMR;
|
csr = usart->US_CSR & usart->US_IMR; // save state/flags before they get changed
|
||||||
|
|
||||||
if (csr & US_CSR_RXRDY) {
|
if (csr & US_CSR_RXRDY) { // bytes has been received
|
||||||
byte = (usart->US_RHR) & 0xFF;
|
byte = (usart->US_RHR) & 0xFF; // ready out byte
|
||||||
rbuf_write(&ci->rb, byte);
|
if (rbuf_write(&ci->rb, byte) < 0) // store byte in buffer
|
||||||
|
TRACE_ERROR("rbuf overrun\r\n"); // error if could not store in buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csr & US_CSR_TXRDY) {
|
if (csr & US_CSR_TXRDY) { // ready to transmit the next byte
|
||||||
if (card_emu_tx_byte(ci->ch) == 0)
|
if (card_emu_tx_byte(ci->ch) == 0) // transmit next byte, and check if a byte is being transmitted
|
||||||
USART_DisableIt(usart, US_IER_TXRDY);
|
USART_DisableIt(usart, US_IER_TXRDY); // stop the TX ready signal if not byte has been transmitted
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|
|
if (csr & (US_CSR_OVRE | US_CSR_FRAME | US_CSR_PARE | US_CSR_NACK | (1 << 10))) { // error flag set
|
||||||
US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) {
|
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; // reset UART state to clear flag
|
||||||
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
|
TRACE_ERROR("%u USART error on 0x%x status: 0x%lx\n", ci->num, byte, csr); // warn user about error
|
||||||
TRACE_ERROR("%u e 0x%x st: 0x%x\n", ci->num, byte, csr);
|
}
|
||||||
|
|
||||||
|
// handle timeout
|
||||||
|
if (csr & US_CSR_TIMEOUT) { // RX has been inactive for some time
|
||||||
|
if (ci->wt_remaining <= (usart->US_RTOR & 0xffff)) { // waiting time has passed
|
||||||
|
ci->wt_remaining = 0; // timeout reached (will stop the timer)
|
||||||
|
} else {
|
||||||
|
ci->wt_remaining -= (usart->US_RTOR & 0xffff); // be sure to subtract the actual timeout since the new might not have been set and reloaded yet
|
||||||
|
}
|
||||||
|
if (0 == ci->wt_remaining) {
|
||||||
|
card_emu_wt_expired(ci->ch); // let the state know WT has expired
|
||||||
|
} else if (ci->wt_remaining <= ci->wt / 2 && !ci->wt_halfed) {
|
||||||
|
ci->wt_halfed = true;
|
||||||
|
card_emu_wt_halfed(ci->ch); // let the state know WT has half expired
|
||||||
|
}
|
||||||
|
if (ci->wt_remaining > 0xffff) { // value exceeds the USART TO range
|
||||||
|
usart->US_RTOR = 0xffff; // use the MAX
|
||||||
|
} else {
|
||||||
|
usart->US_RTOR = ci->wt_remaining;
|
||||||
|
}
|
||||||
|
usart->US_CR |= US_CR_STTTO; // clear timeout flag (and stop timeout until next character is received)
|
||||||
|
usart->US_CR |= US_CR_RETTO; // restart the counter (it wt is 0, the timeout is not started)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! ISR called for USART0 */
|
||||||
void mode_cardemu_usart0_irq(void)
|
void mode_cardemu_usart0_irq(void)
|
||||||
{
|
{
|
||||||
/* USART0 == Instance 1 == USIM 2 */
|
/* USART0 == Instance 1 == USIM 2 */
|
||||||
usart_irq_rx(1);
|
usart_irq_rx(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! ISR called for USART1 */
|
||||||
void mode_cardemu_usart1_irq(void)
|
void mode_cardemu_usart1_irq(void)
|
||||||
{
|
{
|
||||||
/* USART1 == Instance 0 == USIM 1 */
|
/* USART1 == Instance 0 == USIM 1 */
|
||||||
usart_irq_rx(0);
|
usart_irq_rx(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call-back from card_emu.c to change UART baud rate */
|
// call-back from card_emu.c to change UART baud rate
|
||||||
int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
Usart *usart = get_usart_by_chan(uart_chan);
|
|
||||||
|
|
||||||
usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX;
|
void card_emu_uart_update_fd(uint8_t uart_chan, uint16_t f, uint8_t d)
|
||||||
usart->US_FIDI = fidi & 0x3ff;
|
{
|
||||||
usart->US_CR |= US_CR_RXEN | US_CR_STTTO;
|
Usart *usart = get_usart_by_chan(uart_chan); // get the USART based on the card handle
|
||||||
return 0;
|
if (NULL == usart) {
|
||||||
|
TRACE_ERROR("%u: USART not found by chan\r\n", uart_chan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!iso7816_3_valid_f(f)) {
|
||||||
|
TRACE_ERROR("%u: invalid F: %u\r\n", uart_chan, f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!iso7816_3_valid_d(d)) {
|
||||||
|
TRACE_ERROR("%u: invalid D: %u\r\n", uart_chan, d);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ratio = f / d;
|
||||||
|
if (ratio > 0 && ratio < 2048) {
|
||||||
|
/* make sure USART uses new F/D ratio */
|
||||||
|
usart->US_CR |= US_CR_RXDIS | US_CR_RSTRX; // disable USART before changing baud rate
|
||||||
|
usart->US_FIDI = (ratio & 0x7ff); // change baud rate (ratio)
|
||||||
|
usart->US_CR |= US_CR_RXEN | US_CR_STTTO; // re-enable USART (and stop timeout)
|
||||||
|
TRACE_INFO("%u: USART F/D set to %u/%u\r\n", uart_chan, f, d);
|
||||||
|
} else {
|
||||||
|
TRACE_ERROR("%u: USART could not set F/D to %u/%u\r\n", uart_chan, f, d);
|
||||||
|
// TODO become unresponsive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)
|
||||||
|
{
|
||||||
|
if (uart_chan >= ARRAY_SIZE(cardem_inst)) {
|
||||||
|
TRACE_ERROR("%u: UART channel out of bounds\r\n", uart_chan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct cardem_inst *ci = &cardem_inst[uart_chan];
|
||||||
|
Usart *usart = get_usart_by_chan(uart_chan); // get the USART based on the card handle
|
||||||
|
if (NULL == usart) {
|
||||||
|
TRACE_ERROR("%u: USART not found by chan\r\n", uart_chan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ci->wt = wt; // save value
|
||||||
|
card_emu_uart_reset_wt(uart_chan); // reset and start timer
|
||||||
|
TRACE_INFO("%u: USART WT set to %lu ETU\r\n", uart_chan, wt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void card_emu_uart_reset_wt(uint8_t uart_chan)
|
||||||
|
{
|
||||||
|
if (uart_chan >= ARRAY_SIZE(cardem_inst)) {
|
||||||
|
TRACE_ERROR("%u: UART channel out of bounds\r\n", uart_chan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct cardem_inst *ci = &cardem_inst[uart_chan];
|
||||||
|
Usart *usart = get_usart_by_chan(uart_chan); // get the USART based on the card handle
|
||||||
|
if (NULL == usart) {
|
||||||
|
TRACE_ERROR("%u: USART not found by chan\r\n", uart_chan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ci->wt_remaining = ci->wt; // reload WT value
|
||||||
|
ci->wt_halfed = false; // reset half expired
|
||||||
|
if (ci->wt_remaining > 0xffff) { // value exceeds the USART TO range
|
||||||
|
usart->US_RTOR = 0xffff; // use the MAX
|
||||||
|
} else {
|
||||||
|
usart->US_RTOR = ci->wt_remaining;
|
||||||
|
}
|
||||||
|
usart->US_CR |= US_CR_RETTO; // restart the counter (if wt is 0, the timeout is not started)
|
||||||
|
}
|
||||||
|
|
||||||
|
void card_emu_uart_io_set(uint8_t uart_chan, bool set)
|
||||||
|
{
|
||||||
|
if (uart_chan >= ARRAY_SIZE(cardem_inst)) {
|
||||||
|
TRACE_ERROR("%u: UART channel out of bounds\r\n", uart_chan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct cardem_inst *ci = &cardem_inst[uart_chan];
|
||||||
|
if (set) {
|
||||||
|
PIO_Set(&ci->pin_io);
|
||||||
|
} else {
|
||||||
|
PIO_Clear(&ci->pin_io);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@@ -279,7 +414,6 @@ static int card_vcc_adc_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define UV_PER_LSB ((3300 * 1000) / 4096)
|
|
||||||
#define VCC_UV_THRESH_1V8 1500000
|
#define VCC_UV_THRESH_1V8 1500000
|
||||||
#define VCC_UV_THRESH_3V 2800000
|
#define VCC_UV_THRESH_3V 2800000
|
||||||
|
|
||||||
@@ -299,12 +433,6 @@ static void process_vcc_adc(struct cardem_inst *ci)
|
|||||||
ci->vcc_uv_last = ci->vcc_uv;
|
ci->vcc_uv_last = ci->vcc_uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t adc2uv(uint16_t adc)
|
|
||||||
{
|
|
||||||
uint32_t uv = (uint32_t) adc * UV_PER_LSB;
|
|
||||||
return uv;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADC_IrqHandler(void)
|
void ADC_IrqHandler(void)
|
||||||
{
|
{
|
||||||
#ifdef CARDEMU_SECOND_UART
|
#ifdef CARDEMU_SECOND_UART
|
||||||
@@ -330,7 +458,7 @@ void ADC_IrqHandler(void)
|
|||||||
#endif /* DETECT_VCC_BY_ADC */
|
#endif /* DETECT_VCC_BY_ADC */
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Core USB / mainloop integration
|
* Core USB / main loop integration
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
static void usim1_rst_irqhandler(const Pin *pPin)
|
static void usim1_rst_irqhandler(const Pin *pPin)
|
||||||
@@ -344,7 +472,7 @@ static void usim1_vcc_irqhandler(const Pin *pPin)
|
|||||||
{
|
{
|
||||||
int active = PIO_Get(&pin_usim1_vcc) ? 1 : 0;
|
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 readers enable clock after providing power and before releasing reset, but we should check it */
|
||||||
card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_CLK, active);
|
card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_CLK, active);
|
||||||
}
|
}
|
||||||
#endif /* !DETECT_VCC_BY_ADC */
|
#endif /* !DETECT_VCC_BY_ADC */
|
||||||
@@ -361,7 +489,7 @@ static void usim2_vcc_irqhandler(const Pin *pPin)
|
|||||||
{
|
{
|
||||||
int active = PIO_Get(&pin_usim2_vcc) ? 1 : 0;
|
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 readers enable clock after providing power and before releasing reset, but we should check it */
|
||||||
card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_CLK, active);
|
card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_CLK, active);
|
||||||
}
|
}
|
||||||
#endif /* !DETECT_VCC_BY_ADC */
|
#endif /* !DETECT_VCC_BY_ADC */
|
||||||
@@ -380,31 +508,47 @@ void mode_cardemu_init(void)
|
|||||||
|
|
||||||
TRACE_ENTRY();
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
#ifdef PINS_PWR_CARDEMU
|
||||||
|
// enable power on required peripherals, else disable
|
||||||
|
Pin pins_pwr_cardemu[] = { PINS_PWR_CARDEMU };
|
||||||
|
PIO_Configure(pins_pwr_cardemu, PIO_LISTSIZE(pins_pwr_cardemu));
|
||||||
|
#endif /* PINS_PWR_CARDEMU */
|
||||||
#ifdef PINS_CARDSIM
|
#ifdef PINS_CARDSIM
|
||||||
PIO_Configure(pins_cardsim, PIO_LISTSIZE(pins_cardsim));
|
PIO_Configure(pins_cardsim, PIO_LISTSIZE(pins_cardsim));
|
||||||
#endif
|
#endif
|
||||||
|
// ADC channel 6 and 7 are used to measure VCC (else they are grounded)
|
||||||
|
ADC->ADC_CHER |= ADC_CHER_CH6 | ADC_CHER_CH7; // enable the ADC channels to put them in high impedance (else they leak current)
|
||||||
#ifdef DETECT_VCC_BY_ADC
|
#ifdef DETECT_VCC_BY_ADC
|
||||||
card_vcc_adc_init();
|
card_vcc_adc_init(); // configure the ADC to measure VCC
|
||||||
#endif /* DETECT_VCC_BY_ADC */
|
#endif /* DETECT_VCC_BY_ADC */
|
||||||
|
// TODO pull SIMtrace board SIM lines low, else they can leak current back to VCC
|
||||||
|
|
||||||
INIT_LLIST_HEAD(&cardem_inst[0].usb_out_queue);
|
INIT_LLIST_HEAD(&cardem_inst[0].usb_out_queue);
|
||||||
rbuf_reset(&cardem_inst[0].rb);
|
rbuf_reset(&cardem_inst[0].rb);
|
||||||
PIO_Configure(pins_usim1, PIO_LISTSIZE(pins_usim1));
|
PIO_Configure(pins_usim1, PIO_LISTSIZE(pins_usim1));
|
||||||
ISO7816_Init(&cardem_inst[0].usart_info, CLK_SLAVE);
|
ISO7816_Init(&cardem_inst[0].usart_info, CLK_SLAVE); // configure USART as ISO-7816 slave (e.g. card)
|
||||||
NVIC_EnableIRQ(USART1_IRQn);
|
cardem_inst[0].usart_info.base->US_RTOR = 0; // don't use receive timeout timer for now
|
||||||
PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler);
|
USART_EnableIt(cardem_inst[0].usart_info.base, US_IER_RXRDY | US_IER_TIMEOUT); // enable interrupts to indicate when data has been received or timeout occurred
|
||||||
PIO_EnableIt(&pin_usim1_rst);
|
NVIC_EnableIRQ(USART1_IRQn); // enable interrupt requests for the USART peripheral
|
||||||
|
PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler); // register ISR to handle reset signal change
|
||||||
|
PIO_EnableIt(&pin_usim1_rst); // enable interrupt for reset pin change
|
||||||
#ifndef DETECT_VCC_BY_ADC
|
#ifndef DETECT_VCC_BY_ADC
|
||||||
PIO_ConfigureIt(&pin_usim1_vcc, usim1_vcc_irqhandler);
|
PIO_ConfigureIt(&pin_usim1_vcc, usim1_vcc_irqhandler); // register ISR to handle VCC signal change
|
||||||
PIO_EnableIt(&pin_usim1_vcc);
|
PIO_EnableIt(&pin_usim1_vcc); // enable interrupt for VCC pin change
|
||||||
#endif /* DETECT_VCC_BY_ADC */
|
#endif /* DETECT_VCC_BY_ADC */
|
||||||
cardem_inst[0].ch = card_emu_init(0, 2, 0, PHONE_DATAIN, PHONE_INT);
|
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);
|
||||||
|
#ifndef DETECT_VCC_BY_ADC
|
||||||
|
usim1_vcc_irqhandler(NULL); // check VCC/CLK state
|
||||||
|
#endif
|
||||||
|
usim1_rst_irqhandler(NULL); // force RST state
|
||||||
|
|
||||||
#ifdef CARDEMU_SECOND_UART
|
#ifdef CARDEMU_SECOND_UART
|
||||||
INIT_LLIST_HEAD(&cardem_inst[1].usb_out_queue);
|
INIT_LLIST_HEAD(&cardem_inst[1].usb_out_queue);
|
||||||
rbuf_reset(&cardem_inst[1].rb);
|
rbuf_reset(&cardem_inst[1].rb);
|
||||||
PIO_Configure(pins_usim2, PIO_LISTSIZE(pins_usim2));
|
PIO_Configure(pins_usim2, PIO_LISTSIZE(pins_usim2));
|
||||||
ISO7816_Init(&cardem_inst[1].usart_info, CLK_SLAVE);
|
ISO7816_Init(&cardem_inst[1].usart_info, CLK_SLAVE);
|
||||||
|
// TODO enable timeout
|
||||||
NVIC_EnableIRQ(USART0_IRQn);
|
NVIC_EnableIRQ(USART0_IRQn);
|
||||||
PIO_ConfigureIt(&pin_usim2_rst, usim2_rst_irqhandler);
|
PIO_ConfigureIt(&pin_usim2_rst, usim2_rst_irqhandler);
|
||||||
PIO_EnableIt(&pin_usim2_rst);
|
PIO_EnableIt(&pin_usim2_rst);
|
||||||
@@ -412,8 +556,11 @@ 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, CARDEM_USIM2_DATAIN, CARDEM_USIM2_INT);
|
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);
|
||||||
|
// TODO check rst and vcc
|
||||||
#endif /* CARDEMU_SECOND_UART */
|
#endif /* CARDEMU_SECOND_UART */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called if config is deactivated */
|
/* called if config is deactivated */
|
||||||
@@ -478,6 +625,11 @@ static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci
|
|||||||
break;
|
break;
|
||||||
case SIMTRACE_MSGT_DT_CEMU_CARDINSERT:
|
case SIMTRACE_MSGT_DT_CEMU_CARDINSERT:
|
||||||
cardins = (struct cardemu_usb_msg_cardinsert *) msg->l2h;
|
cardins = (struct cardemu_usb_msg_cardinsert *) msg->l2h;
|
||||||
|
if (!ci->pin_insert.pio) {
|
||||||
|
TRACE_INFO("%u: skipping unsupported card_insert to %s\r\n",
|
||||||
|
ci->num, cardins->card_insert ? "INSERTED" : "REMOVED");
|
||||||
|
break;
|
||||||
|
}
|
||||||
TRACE_INFO("%u: set card_insert to %s\r\n", ci->num,
|
TRACE_INFO("%u: set card_insert to %s\r\n", ci->num,
|
||||||
cardins->card_insert ? "INSERTED" : "REMOVED");
|
cardins->card_insert ? "INSERTED" : "REMOVED");
|
||||||
if (cardins->card_insert)
|
if (cardins->card_insert)
|
||||||
@@ -498,6 +650,10 @@ static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PINS_PERST
|
||||||
|
#include "wwan_perst.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static int usb_command_modem_reset(struct msgb *msg, struct cardem_inst *ci)
|
static int usb_command_modem_reset(struct msgb *msg, struct cardem_inst *ci)
|
||||||
{
|
{
|
||||||
struct st_modem_reset *mr = (struct st_modem_reset *) msg->l2h;
|
struct st_modem_reset *mr = (struct st_modem_reset *) msg->l2h;
|
||||||
@@ -506,6 +662,7 @@ static int usb_command_modem_reset(struct msgb *msg, struct cardem_inst *ci)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
switch (mr->asserted) {
|
switch (mr->asserted) {
|
||||||
|
#ifdef PINS_PERST
|
||||||
case 0:
|
case 0:
|
||||||
wwan_perst_set(ci->num, 0);
|
wwan_perst_set(ci->num, 0);
|
||||||
break;
|
break;
|
||||||
@@ -515,6 +672,7 @@ static int usb_command_modem_reset(struct msgb *msg, struct cardem_inst *ci)
|
|||||||
case 2:
|
case 2:
|
||||||
wwan_perst_do_reset_pulse(ci->num, mr->pulse_duration_msec);
|
wwan_perst_do_reset_pulse(ci->num, mr->pulse_duration_msec);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -568,6 +726,7 @@ 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:
|
||||||
@@ -579,7 +738,6 @@ 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:
|
||||||
|
|||||||
@@ -27,14 +27,15 @@
|
|||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "simtrace.h"
|
||||||
|
|
||||||
#ifdef HAVE_CCID
|
#ifdef HAVE_CCID
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* Headers
|
* Headers
|
||||||
*------------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "board.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
@@ -125,6 +126,7 @@ static void ConfigureCardDetection(void)
|
|||||||
*-----------------------------------------------------------------------------*/
|
*-----------------------------------------------------------------------------*/
|
||||||
extern CCIDDriverConfigurationDescriptors configurationDescriptorCCID;
|
extern CCIDDriverConfigurationDescriptors configurationDescriptorCCID;
|
||||||
|
|
||||||
|
/* Called during USB enumeration after device is enumerated by host */
|
||||||
void CCID_configure(void)
|
void CCID_configure(void)
|
||||||
{
|
{
|
||||||
CCIDDriver_Initialize();
|
CCIDDriver_Initialize();
|
||||||
@@ -132,6 +134,7 @@ void CCID_configure(void)
|
|||||||
PIO_ConfigureIt(&pinSmartCard, ISR_PioSmartCard);
|
PIO_ConfigureIt(&pinSmartCard, ISR_PioSmartCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* called when *different* configuration is set by host */
|
||||||
void CCID_exit(void)
|
void CCID_exit(void)
|
||||||
{
|
{
|
||||||
PIO_DisableIt(&pinSmartCard);
|
PIO_DisableIt(&pinSmartCard);
|
||||||
@@ -139,6 +142,7 @@ void CCID_exit(void)
|
|||||||
USART_SetReceiverEnabled(usart_info.base, 0);
|
USART_SetReceiverEnabled(usart_info.base, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* called when *CCID* configuration is set by host */
|
||||||
void CCID_init(void)
|
void CCID_init(void)
|
||||||
{
|
{
|
||||||
uint8_t pAtr[MAX_ATR_SIZE];
|
uint8_t pAtr[MAX_ATR_SIZE];
|
||||||
@@ -178,6 +182,7 @@ void CCID_init(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* main (idle/busy) loop of this USB configuration */
|
||||||
void CCID_run(void)
|
void CCID_run(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* ATMEL Microcontroller Software Support
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
* Copyright (c) 2009, 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.
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
|
||||||
* Headers
|
|
||||||
*------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "board.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
|
||||||
* Internal definitions
|
|
||||||
*------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/** Maximum ucSize in bytes of the smartcard answer to a command.*/
|
|
||||||
#define MAX_ANSWER_SIZE 10
|
|
||||||
|
|
||||||
/** Maximum ATR ucSize in bytes.*/
|
|
||||||
#define MAX_ATR_SIZE 55
|
|
||||||
|
|
||||||
/** USB states */
|
|
||||||
/// Use for power management
|
|
||||||
#define STATE_IDLE 0
|
|
||||||
/// The USB device is in suspend state
|
|
||||||
#define STATE_SUSPEND 4
|
|
||||||
/// The USB device is in resume state
|
|
||||||
#define STATE_RESUME 5
|
|
||||||
|
|
||||||
extern volatile uint8_t timeout_occured;
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
|
||||||
* Internal variables
|
|
||||||
*------------------------------------------------------------------------------*/
|
|
||||||
/** USB state: suspend, resume, idle */
|
|
||||||
unsigned char USBState = STATE_IDLE;
|
|
||||||
|
|
||||||
/** ISO7816 pins */
|
|
||||||
static const Pin pinsISO7816_PHONE[] = { PINS_ISO7816_PHONE };
|
|
||||||
|
|
||||||
/** Bus switch pins */
|
|
||||||
|
|
||||||
#if DEBUG_PHONE_SNIFF
|
|
||||||
#warning "Debug phone sniff via logic analyzer is enabled"
|
|
||||||
// Logic analyzer probes are easier to attach to the SIM card slot
|
|
||||||
static const Pin pins_bus[] = { PINS_BUS_SNIFF };
|
|
||||||
#else
|
|
||||||
static const Pin pins_bus[] = { PINS_BUS_DEFAULT };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** ISO7816 RST pin */
|
|
||||||
static uint8_t sim_inserted = 0;
|
|
||||||
|
|
||||||
static const Pin pPwr[] = {
|
|
||||||
/* Enable power converter 4.5-6V to 3.3V; low: off */
|
|
||||||
{SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT},
|
|
||||||
|
|
||||||
/* Enable second power converter: VCC_PHONE to VCC_SIM; high: off */
|
|
||||||
{VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
|
|
||||||
};
|
|
||||||
|
|
||||||
const Pin pinPhoneRST = PIN_ISO7816_RST_PHONE;
|
|
||||||
|
|
||||||
static struct Usart_info usart_info = {
|
|
||||||
.base = USART_PHONE,
|
|
||||||
.id = ID_USART_PHONE,
|
|
||||||
.state = USART_RCV,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ===================================================*/
|
|
||||||
/* Taken from iso7816_4.c */
|
|
||||||
/* ===================================================*/
|
|
||||||
/** Flip flop for send and receive char */
|
|
||||||
#define USART_SEND 0
|
|
||||||
#define USART_RCV 1
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
|
||||||
* Internal variables
|
|
||||||
*-----------------------------------------------------------------------------*/
|
|
||||||
static uint8_t host_to_sim_buf[BUFLEN];
|
|
||||||
static bool change_fidi = false;
|
|
||||||
|
|
||||||
static void receive_from_host(void);
|
|
||||||
static void sendResponse_to_phone(uint8_t * pArg, uint8_t status,
|
|
||||||
uint32_t transferred, uint32_t remaining)
|
|
||||||
{
|
|
||||||
if (status != USBD_STATUS_SUCCESS) {
|
|
||||||
TRACE_ERROR("USB err status: %d (%s)\n", __FUNCTION__, status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TRACE_DEBUG("sendResp, stat: %X, trnsf: %x, rem: %x\n\r", status,
|
|
||||||
transferred, remaining);
|
|
||||||
TRACE_DEBUG("Resp: %x %x %x .. %x\n", host_to_sim_buf[0],
|
|
||||||
host_to_sim_buf[1], host_to_sim_buf[2],
|
|
||||||
host_to_sim_buf[transferred - 1]);
|
|
||||||
|
|
||||||
USART_SetReceiverEnabled(USART_PHONE, 0);
|
|
||||||
USART_SetTransmitterEnabled(USART_PHONE, 1);
|
|
||||||
uint32_t i = 0;
|
|
||||||
if (host_to_sim_buf[0] == 0xff) {
|
|
||||||
printf("Change FIDI detected\n");
|
|
||||||
// PTS command, change FIDI after command
|
|
||||||
i = 2;
|
|
||||||
change_fidi = true;
|
|
||||||
}
|
|
||||||
for (; i < transferred; i++) {
|
|
||||||
ISO7816_SendChar(host_to_sim_buf[i], &usart_info);
|
|
||||||
}
|
|
||||||
USART_SetTransmitterEnabled(USART_PHONE, 0);
|
|
||||||
USART_SetReceiverEnabled(USART_PHONE, 1);
|
|
||||||
|
|
||||||
if (change_fidi == true) {
|
|
||||||
printf("Change FIDI: %x\n", host_to_sim_buf[2]);
|
|
||||||
update_fidi(host_to_sim_buf[2]);
|
|
||||||
change_fidi = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
receive_from_host();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void receive_from_host()
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if ((ret = USBD_Read(PHONE_DATAOUT, &host_to_sim_buf,
|
|
||||||
sizeof(host_to_sim_buf),
|
|
||||||
(TransferCallback) &sendResponse_to_phone,
|
|
||||||
0)) == USBD_STATUS_SUCCESS) {
|
|
||||||
} else {
|
|
||||||
TRACE_ERROR("USB Err: %X\n", ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Phone_configure(void)
|
|
||||||
{
|
|
||||||
PIO_ConfigureIt(&pinPhoneRST, ISR_PhoneRST);
|
|
||||||
NVIC_EnableIRQ(PIOA_IRQn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Phone_exit(void)
|
|
||||||
{
|
|
||||||
PIO_DisableIt(&pinPhoneRST);
|
|
||||||
NVIC_DisableIRQ(USART1_IRQn);
|
|
||||||
USART_DisableIt(USART_PHONE, US_IER_RXRDY);
|
|
||||||
USART_SetTransmitterEnabled(USART_PHONE, 0);
|
|
||||||
USART_SetReceiverEnabled(USART_PHONE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Phone_init(void)
|
|
||||||
{
|
|
||||||
PIO_Configure(pinsISO7816_PHONE, PIO_LISTSIZE(pinsISO7816_PHONE));
|
|
||||||
PIO_Configure(pins_bus, PIO_LISTSIZE(pins_bus));
|
|
||||||
|
|
||||||
PIO_Configure(&pinPhoneRST, 1);
|
|
||||||
|
|
||||||
PIO_EnableIt(&pinPhoneRST);
|
|
||||||
ISO7816_Init(&usart_info, CLK_SLAVE);
|
|
||||||
|
|
||||||
USART_SetTransmitterEnabled(USART_PHONE, 0);
|
|
||||||
USART_SetReceiverEnabled(USART_PHONE, 1);
|
|
||||||
|
|
||||||
USART_EnableIt(USART_PHONE, US_IER_RXRDY);
|
|
||||||
NVIC_EnableIRQ(USART1_IRQn);
|
|
||||||
|
|
||||||
receive_from_host();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Phone_run(void)
|
|
||||||
{
|
|
||||||
check_data_from_phone();
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,25 @@
|
|||||||
|
/* 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"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "osmocom/core/utils.h"
|
#include "utils.h"
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
|
||||||
#define NUM_RCTX_SMALL 10
|
#define NUM_RCTX_SMALL 10
|
||||||
#define RCTX_SIZE_SMALL 348
|
#define RCTX_SIZE_SMALL 348
|
||||||
@@ -13,8 +30,11 @@ static uint8_t msgb_inuse[NUM_RCTX_SMALL];
|
|||||||
void *_talloc_zero(const void *ctx, size_t size, const char *name)
|
void *_talloc_zero(const void *ctx, size_t size, const char *name)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned long x;
|
||||||
|
|
||||||
|
local_irq_save(x);
|
||||||
if (size > RCTX_SIZE_SMALL) {
|
if (size > RCTX_SIZE_SMALL) {
|
||||||
|
local_irq_restore(x);
|
||||||
TRACE_ERROR("%s() request too large(%d > %d)\r\n", __func__, size, RCTX_SIZE_SMALL);
|
TRACE_ERROR("%s() request too large(%d > %d)\r\n", __func__, size, RCTX_SIZE_SMALL);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -24,9 +44,11 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name)
|
|||||||
uint8_t *out = msgb_data[i];
|
uint8_t *out = msgb_data[i];
|
||||||
msgb_inuse[i] = 1;
|
msgb_inuse[i] = 1;
|
||||||
memset(out, 0, size);
|
memset(out, 0, size);
|
||||||
|
local_irq_restore(x);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
local_irq_restore(x);
|
||||||
TRACE_ERROR("%s() out of memory!\r\n", __func__);
|
TRACE_ERROR("%s() out of memory!\r\n", __func__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -34,17 +56,22 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name)
|
|||||||
int _talloc_free(void *ptr, const char *location)
|
int _talloc_free(void *ptr, const char *location)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned long x;
|
||||||
|
|
||||||
|
local_irq_save(x);
|
||||||
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 \r\n", __func__, location);
|
TRACE_ERROR("%s: double_free by %s\r\n", __func__, location);
|
||||||
} else {
|
} else {
|
||||||
msgb_inuse[i] = 0;
|
msgb_inuse[i] = 0;
|
||||||
}
|
}
|
||||||
|
local_irq_restore(x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_irq_restore(x);
|
||||||
TRACE_ERROR("%s: invalid pointer %p from %s\r\n", __func__, ptr, location);
|
TRACE_ERROR("%s: invalid pointer %p from %s\r\n", __func__, ptr, location);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,27 @@
|
|||||||
|
/* 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;
|
||||||
@@ -52,7 +72,7 @@ bool rbuf_is_full(volatile ringbuf * rb)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rbuf_write(volatile volatile ringbuf * rb, uint8_t item)
|
int rbuf_write(volatile ringbuf * rb, uint8_t item)
|
||||||
{
|
{
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
|
|
||||||
@@ -61,9 +81,10 @@ void rbuf_write(volatile 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);
|
||||||
TRACE_ERROR("Ringbuffer full, losing bytes!");
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "simtrace.h"
|
#include "simtrace.h"
|
||||||
|
#include "simtrace_usb.h"
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "iso7816_fidi.h"
|
#include "iso7816_fidi.h"
|
||||||
|
|
||||||
@@ -57,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!! %x\n\r", pinPhoneRST.pio->PIO_ISR);
|
printf("+++ Int!! %lx\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 ");
|
||||||
@@ -67,7 +68,7 @@ void ISR_PhoneRST(const Pin * pPin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((ret =
|
if ((ret =
|
||||||
USBD_Write(PHONE_INT, "R", 1,
|
USBD_Write(SIMTRACE_USB_EP_PHONE_INT, "R", 1,
|
||||||
(TransferCallback) & Callback_PhoneRST_ISR,
|
(TransferCallback) & Callback_PhoneRST_ISR,
|
||||||
0)) != USBD_STATUS_SUCCESS) {
|
0)) != USBD_STATUS_SUCCESS) {
|
||||||
TRACE_ERROR("USB err status: %d (%s)\n", ret, __FUNCTION__);
|
TRACE_ERROR("USB err status: %d (%s)\n", ret, __FUNCTION__);
|
||||||
@@ -79,7 +80,7 @@ void ISR_PhoneRST(const Pin * pPin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* char_stat is zero if no error occured.
|
* char_stat is zero if no error occurred.
|
||||||
* 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)
|
||||||
@@ -109,27 +110,34 @@ 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 occured */
|
} /* else: error occurred */
|
||||||
|
|
||||||
char_stat = stat;
|
char_stat = stat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIDI update functions */
|
/* FIDI update functions */
|
||||||
void update_fidi(uint8_t fidi)
|
void update_fidi(Usart_info *usart, uint8_t fidi)
|
||||||
{
|
{
|
||||||
int rc;
|
if (NULL==usart) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t fi = fidi >> 4;
|
uint8_t fi = fidi >> 4;
|
||||||
uint8_t di = fidi & 0xf;
|
uint8_t di = fidi & 0xf;
|
||||||
|
int ratio = compute_fidi_ratio(fi, di);
|
||||||
|
|
||||||
rc = compute_fidi_ratio(fi, di);
|
if (ratio > 0 && ratio < 0x8000) {
|
||||||
if (rc > 0 && rc < 0x400) {
|
/* make sure USART uses new F/D ratio */
|
||||||
TRACE_INFO("computed Fi(%u) Di(%u) ratio: %d", fi, di, rc);
|
usart->base->US_CR |= US_CR_RXDIS | US_CR_RSTRX;
|
||||||
/* make sure UART uses new F/D ratio */
|
/* disable write protection */
|
||||||
USART_PHONE->US_CR |= US_CR_RXDIS | US_CR_RSTRX;
|
if (usart->base->US_WPMR) {
|
||||||
USART_PHONE->US_FIDI = rc & 0x3ff;
|
usart->base->US_WPMR = US_WPMR_WPKEY(0x555341);
|
||||||
USART_PHONE->US_CR |= US_CR_RXEN | US_CR_STTTO;
|
}
|
||||||
} else
|
usart->base->US_FIDI = (ratio & 0x7ff);
|
||||||
TRACE_INFO("computed FiDi ratio %d unsupported", rc);
|
usart->base->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);
|
||||||
|
} else {
|
||||||
|
//TRACE_WARNING("computed Fi/Di ratio %d unsupported\n\r", ratio); /* don't print since this is function is also called by ISRs */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
|||||||
* ATMEL Microcontroller Software Support
|
* ATMEL Microcontroller Software Support
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
* Copyright (c) 2008, Atmel Corporation
|
* Copyright (c) 2008, Atmel Corporation
|
||||||
|
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -61,8 +62,10 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
FILE* const stdin = NULL;
|
FILE* const stdin = NULL;
|
||||||
FILE* const stdout = NULL;
|
/* If we use NULL here, we get compiler warnings of calling stdio functions with
|
||||||
FILE* const stderr = NULL;
|
* NULL values. Our fputs() implementation ignores the value of those pointers anyway */
|
||||||
|
FILE* const stdout = (FILE *) 0x1;
|
||||||
|
FILE* const stderr = (FILE *) 0x2;
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -347,7 +350,10 @@ signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse type
|
// Parse type
|
||||||
|
do {
|
||||||
|
num = 0;
|
||||||
switch (*pFormat) {
|
switch (*pFormat) {
|
||||||
|
case 'l': num = -1; break; // ignore long qualifier since int == long (and long long is not supported)
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
|
case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
|
||||||
case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
|
case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
|
||||||
@@ -358,8 +364,8 @@ signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
|
|||||||
default:
|
default:
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFormat++;
|
pFormat++;
|
||||||
|
} while (num < 0);
|
||||||
pStr += num;
|
pStr += num;
|
||||||
size += num;
|
size += num;
|
||||||
}
|
}
|
||||||
@@ -423,18 +429,54 @@ signed int vsprintf(char *pString, const char *pFormat, va_list ap)
|
|||||||
signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
|
signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
|
||||||
{
|
{
|
||||||
char pStr[MAX_STRING_SIZE];
|
char pStr[MAX_STRING_SIZE];
|
||||||
char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";
|
|
||||||
|
|
||||||
// Write formatted string in buffer
|
// Write formatted string in buffer
|
||||||
if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
|
int rc = vsprintf(pStr, pFormat, ap);
|
||||||
|
if (rc < 0) {
|
||||||
fputs(pError, stderr);
|
fputs("format string error in ", stderr);
|
||||||
|
fputs(pFormat, stderr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (rc >= MAX_STRING_SIZE) {
|
||||||
|
fputs("stdio.c: increase MAX_STRING_SIZE\n\r", stderr);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display string
|
// Display string
|
||||||
return fputs(pStr, pStream);
|
return fputs(pStr, pStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Outputs a formatted string on the given stream. Format arguments are given
|
||||||
|
/// in a va_list instance.
|
||||||
|
/// \note This function is synchronous (i.e. blocks until the print completes)
|
||||||
|
/// \param pStream Output stream.
|
||||||
|
/// \param pFormat Format string
|
||||||
|
/// \param ap Argument list.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
|
||||||
|
signed int vfprintf_sync(FILE *pStream, const char *pFormat, va_list ap)
|
||||||
|
{
|
||||||
|
char pStr[MAX_STRING_SIZE];
|
||||||
|
|
||||||
|
// Write formatted string in buffer
|
||||||
|
int rc = vsprintf(pStr, pFormat, ap);
|
||||||
|
if (rc < 0) {
|
||||||
|
fputs_sync("format string error in ", stderr);
|
||||||
|
fputs_sync(pFormat, stderr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (rc >= MAX_STRING_SIZE) {
|
||||||
|
fputs_sync("stdio.c: increase MAX_STRING_SIZE\n\r", stderr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display string
|
||||||
|
return fputs_sync(pStr, pStream);
|
||||||
|
}
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/// Outputs a formatted string on the DBGU stream. Format arguments are given
|
/// Outputs a formatted string on the DBGU stream. Format arguments are given
|
||||||
/// in a va_list instance.
|
/// in a va_list instance.
|
||||||
@@ -446,6 +488,18 @@ signed int vprintf(const char *pFormat, va_list ap)
|
|||||||
return vfprintf(stdout, pFormat, ap);
|
return vfprintf(stdout, pFormat, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Outputs a formatted string on the DBGU stream. Format arguments are given
|
||||||
|
/// in a va_list instance.
|
||||||
|
/// \note This function is synchronous (i.e. blocks until the print completes)
|
||||||
|
/// \param pFormat Format string
|
||||||
|
/// \param ap Argument list.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int vprintf_sync(const char *pFormat, va_list ap)
|
||||||
|
{
|
||||||
|
return vfprintf_sync(stdout, pFormat, ap);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/// Outputs a formatted string on the given stream, using a variable number of
|
/// Outputs a formatted string on the given stream, using a variable number of
|
||||||
/// arguments.
|
/// arguments.
|
||||||
@@ -483,6 +537,25 @@ signed int printf(const char *pFormat, ...)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Outputs a formatted string on the DBGU stream, using a variable number of
|
||||||
|
/// arguments.
|
||||||
|
/// \note This function is synchronous (i.e. blocks until the print completes)
|
||||||
|
/// \param pFormat Format string.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int printf_sync(const char *pFormat, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
signed int result;
|
||||||
|
|
||||||
|
// Forward call to vprintf
|
||||||
|
va_start(ap, pFormat);
|
||||||
|
result = vprintf_sync(pFormat, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
/// Writes a formatted string inside another string.
|
/// Writes a formatted string inside another string.
|
||||||
/// \param pStr Storage string.
|
/// \param pStr Storage string.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* SIMtrace TC (Timer / Clock) code for ETU tracking */
|
/* SIMtrace TC (Timer / Clock) code for ETU tracking
|
||||||
|
*
|
||||||
/* (C) 2006-2016 by Harald Welte <hwelte@hmw-consulting.de>
|
* (C) 2006-2016 by Harald Welte <laforge@gnumonks.org>
|
||||||
*
|
*
|
||||||
* 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 General Public License as published by
|
||||||
@@ -14,10 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* 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.
|
||||||
*
|
*
|
||||||
@@ -33,15 +34,14 @@
|
|||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "simtrace.h"
|
#include "simtrace.h"
|
||||||
|
#include "simtrace_usb.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "USBD_HAL.h"
|
||||||
|
|
||||||
#include <cciddriverdescriptors.h>
|
#include <cciddriverdescriptors.h>
|
||||||
#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>
|
||||||
|
|
||||||
#define SIMTRACE_SUBCLASS_SNIFFER 1
|
|
||||||
#define SIMTRACE_SUBCLASS_CARDEM 2
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
* USB String descriptors
|
* USB String descriptors
|
||||||
*------------------------------------------------------------------------------*/
|
*------------------------------------------------------------------------------*/
|
||||||
@@ -94,8 +94,8 @@ static const SIMTraceDriverConfigurationDescriptorSniffer
|
|||||||
.bInterfaceNumber = 0,
|
.bInterfaceNumber = 0,
|
||||||
.bAlternateSetting = 0,
|
.bAlternateSetting = 0,
|
||||||
.bNumEndpoints = 3,
|
.bNumEndpoints = 3,
|
||||||
.bInterfaceClass = 0xff,
|
.bInterfaceClass = USB_CLASS_PROPRIETARY,
|
||||||
.bInterfaceSubClass = SIMTRACE_SUBCLASS_SNIFFER,
|
.bInterfaceSubClass = SIMTRACE_SNIFFER_USB_SUBCLASS,
|
||||||
.bInterfaceProtocol = 0,
|
.bInterfaceProtocol = 0,
|
||||||
.iInterface = SNIFFER_CONF_STR,
|
.iInterface = SNIFFER_CONF_STR,
|
||||||
},
|
},
|
||||||
@@ -105,11 +105,9 @@ static const SIMTraceDriverConfigurationDescriptorSniffer
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_OUT,
|
USBEndpointDescriptor_OUT,
|
||||||
PHONE_DATAOUT),
|
SIMTRACE_USB_EP_CARD_DATAOUT),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
PHONE_DATAOUT),
|
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0,
|
.bInterval = 0,
|
||||||
},
|
},
|
||||||
/* Bulk-IN endpoint descriptor */
|
/* Bulk-IN endpoint descriptor */
|
||||||
@@ -118,11 +116,9 @@ static const SIMTraceDriverConfigurationDescriptorSniffer
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
PHONE_DATAIN),
|
SIMTRACE_USB_EP_CARD_DATAIN),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
PHONE_DATAIN),
|
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0,
|
.bInterval = 0,
|
||||||
},
|
},
|
||||||
// Notification endpoint descriptor
|
// Notification endpoint descriptor
|
||||||
@@ -131,11 +127,9 @@ static const SIMTraceDriverConfigurationDescriptorSniffer
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
PHONE_INT),
|
SIMTRACE_USB_EP_CARD_INT),
|
||||||
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
|
||||||
PHONE_INT),
|
|
||||||
USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
|
|
||||||
.bInterval = 0x10,
|
.bInterval = 0x10,
|
||||||
},
|
},
|
||||||
DFURT_IF_DESCRIPTOR(1, 0),
|
DFURT_IF_DESCRIPTOR(1, 0),
|
||||||
@@ -205,9 +199,7 @@ static const CCIDDriverConfigurationDescriptors configurationDescriptorCCID = {
|
|||||||
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
|
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
|
||||||
CCID_EPT_DATA_OUT),
|
CCID_EPT_DATA_OUT),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
CCID_EPT_DATA_OUT),
|
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0x00,
|
.bInterval = 0x00,
|
||||||
},
|
},
|
||||||
// Bulk-IN endpoint descriptor
|
// Bulk-IN endpoint descriptor
|
||||||
@@ -218,9 +210,7 @@ static const CCIDDriverConfigurationDescriptors configurationDescriptorCCID = {
|
|||||||
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
||||||
CCID_EPT_DATA_IN),
|
CCID_EPT_DATA_IN),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS),
|
||||||
CCID_EPT_DATA_IN),
|
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0x00,
|
.bInterval = 0x00,
|
||||||
},
|
},
|
||||||
// Notification endpoint descriptor
|
// Notification endpoint descriptor
|
||||||
@@ -231,9 +221,7 @@ static const CCIDDriverConfigurationDescriptors configurationDescriptorCCID = {
|
|||||||
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
||||||
CCID_EPT_NOTIFICATION),
|
CCID_EPT_NOTIFICATION),
|
||||||
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
|
||||||
CCID_EPT_NOTIFICATION),
|
|
||||||
USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
|
|
||||||
.bInterval = 0x10,
|
.bInterval = 0x10,
|
||||||
},
|
},
|
||||||
DFURT_IF_DESCRIPTOR(1, 0),
|
DFURT_IF_DESCRIPTOR(1, 0),
|
||||||
@@ -268,7 +256,7 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
#ifdef CARDEMU_SECOND_UART
|
#ifdef CARDEMU_SECOND_UART
|
||||||
.bNumInterfaces = 2+DFURT_NUM_IF,
|
.bNumInterfaces = 2+DFURT_NUM_IF,
|
||||||
#else
|
#else
|
||||||
.bNumInterefaces = 1+DFURT_NUM_IF,
|
.bNumInterfaces = 1+DFURT_NUM_IF,
|
||||||
#endif
|
#endif
|
||||||
.bConfigurationValue = CFG_NUM_PHONE,
|
.bConfigurationValue = CFG_NUM_PHONE,
|
||||||
.iConfiguration = PHONE_CONF_STR,
|
.iConfiguration = PHONE_CONF_STR,
|
||||||
@@ -282,8 +270,8 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bInterfaceNumber = 0,
|
.bInterfaceNumber = 0,
|
||||||
.bAlternateSetting = 0,
|
.bAlternateSetting = 0,
|
||||||
.bNumEndpoints = 3,
|
.bNumEndpoints = 3,
|
||||||
.bInterfaceClass = 0xff,
|
.bInterfaceClass = USB_CLASS_PROPRIETARY,
|
||||||
.bInterfaceSubClass = SIMTRACE_SUBCLASS_CARDEM,
|
.bInterfaceSubClass = SIMTRACE_CARDEM_USB_SUBCLASS,
|
||||||
.bInterfaceProtocol = 0,
|
.bInterfaceProtocol = 0,
|
||||||
.iInterface = CARDEM_USIM1_INTF_STR,
|
.iInterface = CARDEM_USIM1_INTF_STR,
|
||||||
},
|
},
|
||||||
@@ -293,10 +281,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_OUT,
|
USBEndpointDescriptor_OUT,
|
||||||
PHONE_DATAOUT),
|
SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(PHONE_DATAOUT),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
||||||
},
|
},
|
||||||
/* Bulk-IN endpoint descriptor */
|
/* Bulk-IN endpoint descriptor */
|
||||||
@@ -305,10 +292,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
PHONE_DATAIN),
|
SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(PHONE_DATAIN),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
||||||
},
|
},
|
||||||
/* Notification endpoint descriptor */
|
/* Notification endpoint descriptor */
|
||||||
@@ -317,10 +303,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
PHONE_INT),
|
SIMTRACE_CARDEM_USB_EP_USIM1_INT),
|
||||||
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(PHONE_INT),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
|
|
||||||
.bInterval = 0x10
|
.bInterval = 0x10
|
||||||
},
|
},
|
||||||
#ifdef CARDEMU_SECOND_UART
|
#ifdef CARDEMU_SECOND_UART
|
||||||
@@ -331,8 +316,8 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bInterfaceNumber = 1,
|
.bInterfaceNumber = 1,
|
||||||
.bAlternateSetting = 0,
|
.bAlternateSetting = 0,
|
||||||
.bNumEndpoints = 3,
|
.bNumEndpoints = 3,
|
||||||
.bInterfaceClass = 0xff,
|
.bInterfaceClass = USB_CLASS_PROPRIETARY,
|
||||||
.bInterfaceSubClass = SIMTRACE_SUBCLASS_CARDEM,
|
.bInterfaceSubClass = SIMTRACE_CARDEM_USB_SUBCLASS,
|
||||||
.bInterfaceProtocol = 0,
|
.bInterfaceProtocol = 0,
|
||||||
.iInterface = CARDEM_USIM2_INTF_STR,
|
.iInterface = CARDEM_USIM2_INTF_STR,
|
||||||
},
|
},
|
||||||
@@ -342,10 +327,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_OUT,
|
USBEndpointDescriptor_OUT,
|
||||||
CARDEM_USIM2_DATAOUT),
|
SIMTRACE_CARDEM_USB_EP_USIM2_DATAOUT),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CARDEM_USIM2_DATAOUT),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
@@ -355,10 +339,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
CARDEM_USIM2_DATAIN),
|
SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CARDEM_USIM2_DATAIN),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
.bInterval = 0 /* Must be 0 for full-speed bulk endpoints */
|
||||||
},
|
},
|
||||||
/* Notification endpoint descriptor */
|
/* Notification endpoint descriptor */
|
||||||
@@ -367,10 +350,9 @@ static const SIMTraceDriverConfigurationDescriptorPhone
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
CARDEM_USIM2_INT),
|
SIMTRACE_CARDEM_USB_EP_USIM2_INT),
|
||||||
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(CARDEM_USIM2_INT),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
|
|
||||||
.bInterval = 0x10,
|
.bInterval = 0x10,
|
||||||
},
|
},
|
||||||
DFURT_IF_DESCRIPTOR(2, 0),
|
DFURT_IF_DESCRIPTOR(2, 0),
|
||||||
@@ -466,9 +448,7 @@ static const SIMTraceDriverConfigurationDescriptorMITM
|
|||||||
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
|
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_OUT,
|
||||||
CCID_EPT_DATA_OUT),
|
CCID_EPT_DATA_OUT),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
CCID_EPT_DATA_OUT),
|
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0x00,
|
.bInterval = 0x00,
|
||||||
},
|
},
|
||||||
// Bulk-IN endpoint descriptor
|
// Bulk-IN endpoint descriptor
|
||||||
@@ -479,9 +459,7 @@ static const SIMTraceDriverConfigurationDescriptorMITM
|
|||||||
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
||||||
CCID_EPT_DATA_IN),
|
CCID_EPT_DATA_IN),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
CCID_EPT_DATA_IN),
|
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0x00,
|
.bInterval = 0x00,
|
||||||
},
|
},
|
||||||
// Notification endpoint descriptor
|
// Notification endpoint descriptor
|
||||||
@@ -492,9 +470,7 @@ static const SIMTraceDriverConfigurationDescriptorMITM
|
|||||||
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_ADDRESS(USBEndpointDescriptor_IN,
|
||||||
CCID_EPT_NOTIFICATION),
|
CCID_EPT_NOTIFICATION),
|
||||||
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(
|
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
|
||||||
CCID_EPT_NOTIFICATION),
|
|
||||||
USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
|
|
||||||
.bInterval = 0x10,
|
.bInterval = 0x10,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -506,7 +482,7 @@ static const SIMTraceDriverConfigurationDescriptorMITM
|
|||||||
.bAlternateSetting = 0,
|
.bAlternateSetting = 0,
|
||||||
.bNumEndpoints = 3,
|
.bNumEndpoints = 3,
|
||||||
.bInterfaceClass = 0xff,
|
.bInterfaceClass = 0xff,
|
||||||
.bInterfaceSubClass = SIMTRAC_SUBCLASS_CARDEM,
|
.bInterfaceSubClass = SIMTRACE_SUBCLASS_CARDEM,
|
||||||
.bInterfaceProtocol = 0,
|
.bInterfaceProtocol = 0,
|
||||||
.iInterface = PHONE_CONF_STR,
|
.iInterface = PHONE_CONF_STR,
|
||||||
},
|
},
|
||||||
@@ -516,10 +492,9 @@ static const SIMTraceDriverConfigurationDescriptorMITM
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_OUT,
|
USBEndpointDescriptor_OUT,
|
||||||
PHONE_DATAOUT),
|
SIMTRACE_USB_EP_PHONE_DATAOUT),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(PHONE_DATAOUT),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0, /* Must be 0 for full-speed bulk endpoints */
|
.bInterval = 0, /* Must be 0 for full-speed bulk endpoints */
|
||||||
},
|
},
|
||||||
/* Bulk-IN endpoint descriptor */
|
/* Bulk-IN endpoint descriptor */
|
||||||
@@ -528,10 +503,9 @@ static const SIMTraceDriverConfigurationDescriptorMITM
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
PHONE_DATAIN),
|
SIMTRACE_USB_EP_PHONE_DATAIN),
|
||||||
.bmAttributes = USBEndpointDescriptor_BULK,
|
.bmAttributes = USBEndpointDescriptor_BULK,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(PHONE_DATAIN),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXBULKSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXBULKSIZE_FS),
|
|
||||||
.bInterval = 0, /* Must be 0 for full-speed bulk endpoints */
|
.bInterval = 0, /* Must be 0 for full-speed bulk endpoints */
|
||||||
},
|
},
|
||||||
/* Notification endpoint descriptor */
|
/* Notification endpoint descriptor */
|
||||||
@@ -540,10 +514,9 @@ static const SIMTraceDriverConfigurationDescriptorMITM
|
|||||||
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
.bDescriptorType = USBGenericDescriptor_ENDPOINT,
|
||||||
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
.bEndpointAddress = USBEndpointDescriptor_ADDRESS(
|
||||||
USBEndpointDescriptor_IN,
|
USBEndpointDescriptor_IN,
|
||||||
PHONE_INT),
|
SIMTRACE_USB_EP_PHONE_INT),
|
||||||
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
|
||||||
.wMaxPacketSize = MIN(BOARD_USB_ENDPOINTS_MAXPACKETSIZE(PHONE_INT),
|
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
|
||||||
USBEndpointDescriptor_MAXINTERRUPTSIZE_FS),
|
|
||||||
.bInterval = 0x10
|
.bInterval = 0x10
|
||||||
},
|
},
|
||||||
DFURT_IF_DESCRIPTOR(2, 0),
|
DFURT_IF_DESCRIPTOR(2, 0),
|
||||||
@@ -573,7 +546,7 @@ const USBDeviceDescriptor deviceDescriptor = {
|
|||||||
.bDeviceClass = 0,
|
.bDeviceClass = 0,
|
||||||
.bDeviceSubClass = 0,
|
.bDeviceSubClass = 0,
|
||||||
.bDeviceProtocol = 0,
|
.bDeviceProtocol = 0,
|
||||||
.bMaxPacketSize0 = BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
|
.bMaxPacketSize0 = 64,
|
||||||
.idVendor = BOARD_USB_VENDOR_ID,
|
.idVendor = BOARD_USB_VENDOR_ID,
|
||||||
.idProduct = BOARD_USB_PRODUCT_ID,
|
.idProduct = BOARD_USB_PRODUCT_ID,
|
||||||
.bcdDevice = 2, /* Release number */
|
.bcdDevice = 2, /* Release number */
|
||||||
@@ -603,11 +576,23 @@ static const USBDDriverDescriptors driverDescriptors = {
|
|||||||
|
|
||||||
void SIMtrace_USB_Initialize(void)
|
void SIMtrace_USB_Initialize(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
|
||||||
|
#ifdef PIN_USB_PULLUP
|
||||||
|
const Pin usb_dp_pullup = PIN_USB_PULLUP;
|
||||||
|
PIO_Configure(&usb_dp_pullup, 1);
|
||||||
|
PIO_Set(&usb_dp_pullup);
|
||||||
|
#endif
|
||||||
|
USBD_HAL_Suspend();
|
||||||
|
mdelay(20);
|
||||||
|
#ifdef PIN_USB_PULLUP
|
||||||
|
PIO_Clear(&usb_dp_pullup);
|
||||||
|
#endif
|
||||||
|
USBD_HAL_Activate();
|
||||||
|
|
||||||
// Get std USB driver
|
// Get std USB driver
|
||||||
USBDDriver *pUsbd = USBD_GetDriver();
|
USBDDriver *pUsbd = USBD_GetDriver();
|
||||||
|
|
||||||
TRACE_DEBUG(".");
|
|
||||||
|
|
||||||
// Initialize standard USB driver
|
// Initialize standard USB driver
|
||||||
USBDDriver_Initialize(pUsbd, &driverDescriptors, 0); // Multiple interface settings not supported
|
USBDDriver_Initialize(pUsbd, &driverDescriptors, 0); // Multiple interface settings not supported
|
||||||
USBD_Init();
|
USBD_Init();
|
||||||
|
|||||||
@@ -1,9 +1,26 @@
|
|||||||
|
/* 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
|
||||||
|
*/
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "usb_buf.h"
|
#include "usb_buf.h"
|
||||||
|
#include "simtrace_usb.h"
|
||||||
|
|
||||||
#include "osmocom/core/linuxlist.h"
|
#include <osmocom/core/linuxlist.h>
|
||||||
#include "osmocom/core/msgb.h"
|
#include <osmocom/core/msgb.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define USB_ALLOC_SIZE 280
|
#define USB_ALLOC_SIZE 280
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ struct timezone;
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "osmocom/core/linuxlist.h"
|
#include <osmocom/core/linuxlist.h>
|
||||||
#include "osmocom/core/linuxrbtree.h"
|
#include <osmocom/core/linuxrbtree.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timer management:
|
* Timer management:
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const char *get_value_string_or_null(const struct value_string *vs,
|
|||||||
int get_string_value(const struct value_string *vs, const char *str);
|
int get_string_value(const struct value_string *vs, const char *str);
|
||||||
|
|
||||||
char osmo_bcd2char(uint8_t bcd);
|
char osmo_bcd2char(uint8_t bcd);
|
||||||
/* only works for numbers in ascci */
|
/* only works for numbers in ASCII */
|
||||||
uint8_t osmo_char2bcd(char c);
|
uint8_t osmo_char2bcd(char c);
|
||||||
|
|
||||||
int osmo_hexparse(const char *str, uint8_t *b, int max_len);
|
int osmo_hexparse(const char *str, uint8_t *b, int max_len);
|
||||||
@@ -60,7 +60,7 @@ do { \
|
|||||||
rem -= ret; \
|
rem -= ret; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/*! Helper macro to terminate when an assertion failes
|
/*! Helper macro to terminate when an assertion fails
|
||||||
* \param[in] exp Predicate to verify
|
* \param[in] exp Predicate to verify
|
||||||
* This function will generate a backtrace and terminate the program if
|
* This function will generate a backtrace and terminate the program if
|
||||||
* the predicate evaluates to false (0).
|
* the predicate evaluates to false (0).
|
||||||
@@ -75,7 +75,7 @@ do { \
|
|||||||
/*! duplicate a string using talloc and release its prior content (if any)
|
/*! duplicate a string using talloc and release its prior content (if any)
|
||||||
* \param[in] ctx Talloc context to use for allocation
|
* \param[in] ctx Talloc context to use for allocation
|
||||||
* \param[out] dst pointer to string, will be updated with ptr to new string
|
* \param[out] dst pointer to string, will be updated with ptr to new string
|
||||||
* \param[in] newstr String that will be copieed to newly allocated string */
|
* \param[in] newstr String that will be copied to newly allocated string */
|
||||||
static inline void osmo_talloc_replace_string(void *ctx, char **dst, const char *newstr)
|
static inline void osmo_talloc_replace_string(void *ctx, char **dst, const char *newstr)
|
||||||
{
|
{
|
||||||
if (*dst)
|
if (*dst)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ static osmo_panic_handler_t osmo_panic_handler = (void*)0;
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
__attribute__ ((format (printf, 1, 0)))
|
||||||
static void osmo_panic_default(const char *fmt, va_list args)
|
static void osmo_panic_default(const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
vfprintf(stderr, fmt, args);
|
vfprintf(stderr, fmt, args);
|
||||||
@@ -73,6 +74,7 @@ static void osmo_panic_default(const char *fmt, va_list args)
|
|||||||
* The default function on most systems will generate a backtrace and
|
* The default function on most systems will generate a backtrace and
|
||||||
* then abort() the process.
|
* then abort() the process.
|
||||||
*/
|
*/
|
||||||
|
__attribute__ ((format (printf, 1, 0)))
|
||||||
void osmo_panic(const char *fmt, ...)
|
void osmo_panic(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|||||||
@@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "osmocom/core/linuxlist.h"
|
#include <osmocom/core/linuxlist.h>
|
||||||
#include "osmocom/core/timer.h"
|
#include <osmocom/core/timer.h>
|
||||||
|
|
||||||
/* These store the amount of time that we wait until next timer expires. */
|
/* These store the amount of time that we wait until next timer expires. */
|
||||||
static struct osmo_timeval nearest;
|
static struct osmo_timeval nearest;
|
||||||
|
|||||||
632
firmware/libosmocore/source/utils.c
Normal file
632
firmware/libosmocore/source/utils.c
Normal file
@@ -0,0 +1,632 @@
|
|||||||
|
/*
|
||||||
|
* (C) 2011 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
* (C) 2011 by Sylvain Munaut <tnt@246tNt.com>
|
||||||
|
* (C) 2014 by Nils O. Selåsdal <noselasd@fiane.dyndns.org>
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
|
*
|
||||||
|
* 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 <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/core/bit64gen.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*! \addtogroup utils
|
||||||
|
* @{
|
||||||
|
* various utility routines
|
||||||
|
*
|
||||||
|
* \file utils.c */
|
||||||
|
|
||||||
|
static char namebuf[255];
|
||||||
|
|
||||||
|
/*! get human-readable string for given value
|
||||||
|
* \param[in] vs Array of value_string tuples
|
||||||
|
* \param[in] val Value to be converted
|
||||||
|
* \returns pointer to human-readable string
|
||||||
|
*
|
||||||
|
* If val is found in vs, the array's string entry is returned. Otherwise, an
|
||||||
|
* "unknown" string containing the actual value is composed in a static buffer
|
||||||
|
* that is reused across invocations.
|
||||||
|
*/
|
||||||
|
const char *get_value_string(const struct value_string *vs, uint32_t val)
|
||||||
|
{
|
||||||
|
const char *str = get_value_string_or_null(vs, val);
|
||||||
|
if (str)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
snprintf(namebuf, sizeof(namebuf), "unknown 0x%"PRIx32, val);
|
||||||
|
namebuf[sizeof(namebuf) - 1] = '\0';
|
||||||
|
return namebuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! get human-readable string or NULL for given value
|
||||||
|
* \param[in] vs Array of value_string tuples
|
||||||
|
* \param[in] val Value to be converted
|
||||||
|
* \returns pointer to human-readable string or NULL if val is not found
|
||||||
|
*/
|
||||||
|
const char *get_value_string_or_null(const struct value_string *vs,
|
||||||
|
uint32_t val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0;; i++) {
|
||||||
|
if (vs[i].value == 0 && vs[i].str == NULL)
|
||||||
|
break;
|
||||||
|
if (vs[i].value == val)
|
||||||
|
return vs[i].str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! get numeric value for given human-readable string
|
||||||
|
* \param[in] vs Array of value_string tuples
|
||||||
|
* \param[in] str human-readable string
|
||||||
|
* \returns numeric value (>0) or negative numer in case of error
|
||||||
|
*/
|
||||||
|
int get_string_value(const struct value_string *vs, const char *str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0;; i++) {
|
||||||
|
if (vs[i].value == 0 && vs[i].str == NULL)
|
||||||
|
break;
|
||||||
|
if (!strcasecmp(vs[i].str, str))
|
||||||
|
return vs[i].value;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Convert BCD-encoded digit into printable character
|
||||||
|
* \param[in] bcd A single BCD-encoded digit
|
||||||
|
* \returns single printable character
|
||||||
|
*/
|
||||||
|
char osmo_bcd2char(uint8_t bcd)
|
||||||
|
{
|
||||||
|
if (bcd < 0xa)
|
||||||
|
return '0' + bcd;
|
||||||
|
else
|
||||||
|
return 'A' + (bcd - 0xa);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Convert number in ASCII to BCD value
|
||||||
|
* \param[in] c ASCII character
|
||||||
|
* \returns BCD encoded value of character
|
||||||
|
*/
|
||||||
|
uint8_t osmo_char2bcd(char c)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - 0x30;
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
return 0xa + (c - 'A');
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
return 0xa + (c - 'a');
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Parse a string containing hexadecimal digits
|
||||||
|
* \param[in] str string containing ASCII encoded hexadecimal digits
|
||||||
|
* \param[out] b output buffer
|
||||||
|
* \param[in] max_len maximum space in output buffer
|
||||||
|
* \returns number of parsed octets, or -1 on error
|
||||||
|
*/
|
||||||
|
int osmo_hexparse(const char *str, uint8_t *b, int max_len)
|
||||||
|
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
uint8_t v;
|
||||||
|
const char *strpos;
|
||||||
|
unsigned int nibblepos = 0;
|
||||||
|
|
||||||
|
memset(b, 0x00, max_len);
|
||||||
|
|
||||||
|
for (strpos = str; (c = *strpos); strpos++) {
|
||||||
|
/* skip whitespace */
|
||||||
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If the buffer is too small, error out */
|
||||||
|
if (nibblepos >= (max_len << 1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
v = c - '0';
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
v = 10 + (c - 'a');
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
v = 10 + (c - 'A');
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
b[nibblepos >> 1] |= v << (nibblepos & 1 ? 0 : 4);
|
||||||
|
nibblepos ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In case of uneven amount of digits, the last byte is not complete
|
||||||
|
* and that's an error. */
|
||||||
|
if (nibblepos & 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return nibblepos >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char hexd_buff[4096];
|
||||||
|
static const char hex_chars[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
static char *_osmo_hexdump(const unsigned char *buf, int len, const char *delim)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *cur = hexd_buff;
|
||||||
|
|
||||||
|
hexd_buff[0] = 0;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
const char *delimp = delim;
|
||||||
|
int len_remain = sizeof(hexd_buff) - (cur - hexd_buff);
|
||||||
|
if (len_remain < 3)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*cur++ = hex_chars[buf[i] >> 4];
|
||||||
|
*cur++ = hex_chars[buf[i] & 0xf];
|
||||||
|
|
||||||
|
while (len_remain > 1 && *delimp) {
|
||||||
|
*cur++ = *delimp++;
|
||||||
|
len_remain--;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cur = 0;
|
||||||
|
}
|
||||||
|
hexd_buff[sizeof(hexd_buff)-1] = 0;
|
||||||
|
return hexd_buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Convert a sequence of unpacked bits to ASCII string
|
||||||
|
* \param[in] bits A sequence of unpacked bits
|
||||||
|
* \param[in] len Length of bits
|
||||||
|
*/
|
||||||
|
char *osmo_ubit_dump(const uint8_t *bits, unsigned int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (len > sizeof(hexd_buff)-1)
|
||||||
|
len = sizeof(hexd_buff)-1;
|
||||||
|
memset(hexd_buff, 0, sizeof(hexd_buff));
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
char outch;
|
||||||
|
switch (bits[i]) {
|
||||||
|
case 0:
|
||||||
|
outch = '0';
|
||||||
|
break;
|
||||||
|
case 0xff:
|
||||||
|
outch = '?';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
outch = '1';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
outch = 'E';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hexd_buff[i] = outch;
|
||||||
|
}
|
||||||
|
hexd_buff[sizeof(hexd_buff)-1] = 0;
|
||||||
|
return hexd_buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Convert binary sequence to hexadecimal ASCII string
|
||||||
|
* \param[in] buf pointer to sequence of bytes
|
||||||
|
* \param[in] len length of buf in number of bytes
|
||||||
|
* \returns pointer to zero-terminated string
|
||||||
|
*
|
||||||
|
* This function will print a sequence of bytes as hexadecimal numbers,
|
||||||
|
* adding one space character between each byte (e.g. "1a ef d9")
|
||||||
|
*
|
||||||
|
* The maximum size of the output buffer is 4096 bytes, i.e. the maximum
|
||||||
|
* number of input bytes that can be printed in one call is 1365!
|
||||||
|
*/
|
||||||
|
char *osmo_hexdump(const unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
return _osmo_hexdump(buf, len, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Convert binary sequence to hexadecimal ASCII string
|
||||||
|
* \param[in] buf pointer to sequence of bytes
|
||||||
|
* \param[in] len length of buf in number of bytes
|
||||||
|
* \returns pointer to zero-terminated string
|
||||||
|
*
|
||||||
|
* This function will print a sequence of bytes as hexadecimal numbers,
|
||||||
|
* without any space character between each byte (e.g. "1aefd9")
|
||||||
|
*
|
||||||
|
* The maximum size of the output buffer is 4096 bytes, i.e. the maximum
|
||||||
|
* number of input bytes that can be printed in one call is 2048!
|
||||||
|
*/
|
||||||
|
char *osmo_hexdump_nospc(const unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
return _osmo_hexdump(buf, len, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compat with previous typo to preserve abi */
|
||||||
|
char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
|
||||||
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
|
;
|
||||||
|
#else
|
||||||
|
__attribute__((weak, alias("osmo_hexdump_nospc")));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
/*! Convert an entire string to lower case
|
||||||
|
* \param[out] out output string, caller-allocated
|
||||||
|
* \param[in] in input string
|
||||||
|
*/
|
||||||
|
void osmo_str2lower(char *out, const char *in)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < strlen(in); i++)
|
||||||
|
out[i] = tolower((const unsigned char)in[i]);
|
||||||
|
out[strlen(in)] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Convert an entire string to upper case
|
||||||
|
* \param[out] out output string, caller-allocated
|
||||||
|
* \param[in] in input string
|
||||||
|
*/
|
||||||
|
void osmo_str2upper(char *out, const char *in)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < strlen(in); i++)
|
||||||
|
out[i] = toupper((const unsigned char)in[i]);
|
||||||
|
out[strlen(in)] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Wishful thinking to generate a constant time compare
|
||||||
|
* \param[in] exp Expected data
|
||||||
|
* \param[in] rel Comparison value
|
||||||
|
* \param[in] count Number of bytes to compare
|
||||||
|
* \returns 1 in case \a exp equals \a rel; zero otherwise
|
||||||
|
*
|
||||||
|
* Compare count bytes of exp to rel. Return 0 if they are identical, 1
|
||||||
|
* otherwise. Do not return a mismatch on the first mismatching byte,
|
||||||
|
* but always compare all bytes, regardless. The idea is that the amount of
|
||||||
|
* matching bytes cannot be inferred from the time the comparison took. */
|
||||||
|
int osmo_constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count)
|
||||||
|
{
|
||||||
|
int x = 0, i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
x |= exp[i] ^ rel[i];
|
||||||
|
|
||||||
|
/* if x is zero, all data was identical */
|
||||||
|
return x? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Generic retrieval of 1..8 bytes as big-endian uint64_t
|
||||||
|
* \param[in] data Input data as byte-array
|
||||||
|
* \param[in] data_len Length of \a data in octets
|
||||||
|
* \returns uint64_t of \a data interpreted as big-endian
|
||||||
|
*
|
||||||
|
* This is like osmo_load64be_ext, except that if data_len is less than
|
||||||
|
* sizeof(uint64_t), the data is interpreted as the least significant bytes
|
||||||
|
* (osmo_load64be_ext loads them as the most significant bytes into the
|
||||||
|
* returned uint64_t). In this way, any integer size up to 64 bits can be
|
||||||
|
* decoded conveniently by using sizeof(), without the need to call specific
|
||||||
|
* numbered functions (osmo_load16, 32, ...). */
|
||||||
|
uint64_t osmo_decode_big_endian(const uint8_t *data, size_t data_len)
|
||||||
|
{
|
||||||
|
uint64_t value = 0;
|
||||||
|
|
||||||
|
while (data_len > 0) {
|
||||||
|
value = (value << 8) + *data;
|
||||||
|
data += 1;
|
||||||
|
data_len -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Generic big-endian encoding of big endian number up to 64bit
|
||||||
|
* \param[in] value unsigned integer value to be stored
|
||||||
|
* \param[in] data_len number of octets
|
||||||
|
* \returns static buffer containing big-endian stored value
|
||||||
|
*
|
||||||
|
* This is like osmo_store64be_ext, except that this returns a static buffer of
|
||||||
|
* the result (for convenience, but not threadsafe). If data_len is less than
|
||||||
|
* sizeof(uint64_t), only the least significant bytes of value are encoded. */
|
||||||
|
uint8_t *osmo_encode_big_endian(uint64_t value, size_t data_len)
|
||||||
|
{
|
||||||
|
static uint8_t buf[sizeof(uint64_t)];
|
||||||
|
OSMO_ASSERT(data_len <= ARRAY_SIZE(buf));
|
||||||
|
osmo_store64be_ext(value, buf, data_len);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Copy a C-string into a sized buffer
|
||||||
|
* \param[in] src source string
|
||||||
|
* \param[out] dst destination string
|
||||||
|
* \param[in] siz size of the \a dst buffer
|
||||||
|
* \returns length of \a src
|
||||||
|
*
|
||||||
|
* Copy at most \a siz bytes from \a src to \a dst, ensuring that the result is
|
||||||
|
* NUL terminated. The NUL character is included in \a siz, i.e. passing the
|
||||||
|
* actual sizeof(*dst) is correct.
|
||||||
|
*/
|
||||||
|
size_t osmo_strlcpy(char *dst, const char *src, size_t siz)
|
||||||
|
{
|
||||||
|
size_t ret = src ? strlen(src) : 0;
|
||||||
|
|
||||||
|
if (siz) {
|
||||||
|
size_t len = (ret >= siz) ? siz - 1 : ret;
|
||||||
|
if (src)
|
||||||
|
memcpy(dst, src, len);
|
||||||
|
dst[len] = '\0';
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Validate that a given string is a hex string within given size limits.
|
||||||
|
* Note that each hex digit amounts to a nibble, so if checking for a hex
|
||||||
|
* string to result in N bytes, pass amount of digits as 2*N.
|
||||||
|
* \param str A nul-terminated string to validate, or NULL.
|
||||||
|
* \param min_digits least permitted amount of digits.
|
||||||
|
* \param max_digits most permitted amount of digits.
|
||||||
|
* \param require_even if true, require an even amount of digits.
|
||||||
|
* \returns true when the hex_str contains only hexadecimal digits (no
|
||||||
|
* whitespace) and matches the requested length; also true
|
||||||
|
* when min_digits <= 0 and str is NULL.
|
||||||
|
*/
|
||||||
|
bool osmo_is_hexstr(const char *str, int min_digits, int max_digits,
|
||||||
|
bool require_even)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
/* Use unsigned char * to avoid a compiler warning of
|
||||||
|
* "error: array subscript has type 'char' [-Werror=char-subscripts]" */
|
||||||
|
const unsigned char *pos = (const unsigned char*)str;
|
||||||
|
if (!pos)
|
||||||
|
return min_digits < 1;
|
||||||
|
for (len = 0; *pos && len < max_digits; len++, pos++)
|
||||||
|
if (!isxdigit(*pos))
|
||||||
|
return false;
|
||||||
|
if (len < min_digits)
|
||||||
|
return false;
|
||||||
|
/* With not too many digits, we should have reached *str == nul */
|
||||||
|
if (*pos)
|
||||||
|
return false;
|
||||||
|
if (require_even && (len & 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Determine if a given identifier is valid, i.e. doesn't contain illegal chars
|
||||||
|
* \param[in] str String to validate
|
||||||
|
* \param[in] sep_chars Permitted separation characters between identifiers.
|
||||||
|
* \returns true in case \a str contains only valid identifiers and sep_chars, false otherwise
|
||||||
|
*/
|
||||||
|
bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars)
|
||||||
|
{
|
||||||
|
/* characters that are illegal in names */
|
||||||
|
static const char illegal_chars[] = "., {}[]()<>|~\\^`'\"?=;/+*&%$#!";
|
||||||
|
unsigned int i;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* an empty string is not a valid identifier */
|
||||||
|
if (!str || (len = strlen(str)) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (sep_chars && strchr(sep_chars, str[i]))
|
||||||
|
continue;
|
||||||
|
/* check for 7-bit ASCII */
|
||||||
|
if (str[i] & 0x80)
|
||||||
|
return false;
|
||||||
|
if (!isprint((int)str[i]))
|
||||||
|
return false;
|
||||||
|
/* check for some explicit reserved control characters */
|
||||||
|
if (strchr(illegal_chars, str[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Determine if a given identifier is valid, i.e. doesn't contain illegal chars
|
||||||
|
* \param[in] str String to validate
|
||||||
|
* \returns true in case \a str contains valid identifier, false otherwise
|
||||||
|
*/
|
||||||
|
bool osmo_identifier_valid(const char *str)
|
||||||
|
{
|
||||||
|
return osmo_separated_identifiers_valid(str, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Return the string with all non-printable characters escaped.
|
||||||
|
* \param[in] str A string that may contain any characters.
|
||||||
|
* \param[in] len Pass -1 to print until nul char, or >= 0 to force a length.
|
||||||
|
* \param[inout] buf string buffer to write escaped characters to.
|
||||||
|
* \param[in] bufsize size of \a buf.
|
||||||
|
* \returns buf containing an escaped representation, possibly truncated, or str itself.
|
||||||
|
*/
|
||||||
|
const char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
int in_pos = 0;
|
||||||
|
int next_unprintable = 0;
|
||||||
|
int out_pos = 0;
|
||||||
|
char *out = buf;
|
||||||
|
/* -1 to leave space for a final \0 */
|
||||||
|
int out_len = bufsize-1;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return "(null)";
|
||||||
|
|
||||||
|
if (in_len < 0)
|
||||||
|
in_len = strlen(str);
|
||||||
|
|
||||||
|
while (in_pos < in_len) {
|
||||||
|
for (next_unprintable = in_pos;
|
||||||
|
next_unprintable < in_len && isprint((int)str[next_unprintable])
|
||||||
|
&& str[next_unprintable] != '"'
|
||||||
|
&& str[next_unprintable] != '\\';
|
||||||
|
next_unprintable++);
|
||||||
|
|
||||||
|
if (next_unprintable == in_len
|
||||||
|
&& in_pos == 0)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
while (in_pos < next_unprintable && out_pos < out_len)
|
||||||
|
out[out_pos++] = str[in_pos++];
|
||||||
|
|
||||||
|
if (out_pos == out_len || in_pos == in_len)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
switch (str[next_unprintable]) {
|
||||||
|
#define BACKSLASH_CASE(c, repr) \
|
||||||
|
case c: \
|
||||||
|
if (out_pos > out_len-2) \
|
||||||
|
goto done; \
|
||||||
|
out[out_pos++] = '\\'; \
|
||||||
|
out[out_pos++] = repr; \
|
||||||
|
break
|
||||||
|
|
||||||
|
BACKSLASH_CASE('\n', 'n');
|
||||||
|
BACKSLASH_CASE('\r', 'r');
|
||||||
|
BACKSLASH_CASE('\t', 't');
|
||||||
|
BACKSLASH_CASE('\0', '0');
|
||||||
|
BACKSLASH_CASE('\a', 'a');
|
||||||
|
BACKSLASH_CASE('\b', 'b');
|
||||||
|
BACKSLASH_CASE('\v', 'v');
|
||||||
|
BACKSLASH_CASE('\f', 'f');
|
||||||
|
BACKSLASH_CASE('\\', '\\');
|
||||||
|
BACKSLASH_CASE('"', '"');
|
||||||
|
#undef BACKSLASH_CASE
|
||||||
|
|
||||||
|
default:
|
||||||
|
out_pos += snprintf(&out[out_pos], out_len - out_pos, "\\%u", (unsigned char)str[in_pos]);
|
||||||
|
if (out_pos > out_len) {
|
||||||
|
out_pos = out_len;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in_pos ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
out[out_pos] = '\0';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Return the string with all non-printable characters escaped.
|
||||||
|
* Call osmo_escape_str_buf() with a static buffer.
|
||||||
|
* \param[in] str A string that may contain any characters.
|
||||||
|
* \param[in] len Pass -1 to print until nul char, or >= 0 to force a length.
|
||||||
|
* \returns buf containing an escaped representation, possibly truncated, or str itself.
|
||||||
|
*/
|
||||||
|
const char *osmo_escape_str(const char *str, int in_len)
|
||||||
|
{
|
||||||
|
return osmo_escape_str_buf(str, in_len, namebuf, sizeof(namebuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Like osmo_escape_str(), but returns double-quotes around a string, or "NULL" for a NULL string.
|
||||||
|
* This allows passing any char* value and get its C representation as string.
|
||||||
|
* \param[in] str A string that may contain any characters.
|
||||||
|
* \param[in] len Pass -1 to print until nul char, or >= 0 to force a length.
|
||||||
|
* \returns buf containing an escaped representation, possibly truncated, or str itself.
|
||||||
|
*/
|
||||||
|
const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
const char *res;
|
||||||
|
int l;
|
||||||
|
if (!str)
|
||||||
|
return "NULL";
|
||||||
|
if (bufsize < 3)
|
||||||
|
return "<buf-too-small>";
|
||||||
|
buf[0] = '"';
|
||||||
|
res = osmo_escape_str_buf(str, in_len, buf + 1, bufsize - 2);
|
||||||
|
/* if osmo_escape_str_buf() returned the str itself, we need to copy it to buf to be able to
|
||||||
|
* quote it. */
|
||||||
|
if (res == str) {
|
||||||
|
/* max_len = bufsize - two quotes - nul term */
|
||||||
|
int max_len = bufsize - 2 - 1;
|
||||||
|
if (in_len >= 0)
|
||||||
|
max_len = OSMO_MIN(in_len, max_len);
|
||||||
|
/* It is not allowed to pass unterminated strings into osmo_strlcpy() :/ */
|
||||||
|
strncpy(buf + 1, str, max_len);
|
||||||
|
buf[1 + max_len] = '\0';
|
||||||
|
}
|
||||||
|
l = strlen(buf);
|
||||||
|
buf[l] = '"';
|
||||||
|
buf[l+1] = '\0'; /* both osmo_escape_str_buf() and max_len above ensure room for '\0' */
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *osmo_quote_str(const char *str, int in_len)
|
||||||
|
{
|
||||||
|
return osmo_quote_str_buf(str, in_len, namebuf, sizeof(namebuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! perform an integer square root operation on unsigned 32bit integer.
|
||||||
|
* This implementation is taken from "Hacker's Delight" Figure 11-1 "Integer square root, Newton's
|
||||||
|
* method", which can also be found at http://www.hackersdelight.org/hdcodetxt/isqrt.c.txt */
|
||||||
|
uint32_t osmo_isqrt32(uint32_t x)
|
||||||
|
{
|
||||||
|
uint32_t x1;
|
||||||
|
int s, g0, g1;
|
||||||
|
|
||||||
|
if (x <= 1)
|
||||||
|
return x;
|
||||||
|
|
||||||
|
s = 1;
|
||||||
|
x1 = x - 1;
|
||||||
|
if (x1 > 0xffff) {
|
||||||
|
s = s + 8;
|
||||||
|
x1 = x1 >> 16;
|
||||||
|
}
|
||||||
|
if (x1 > 0xff) {
|
||||||
|
s = s + 4;
|
||||||
|
x1 = x1 >> 8;
|
||||||
|
}
|
||||||
|
if (x1 > 0xf) {
|
||||||
|
s = s + 2;
|
||||||
|
x1 = x1 >> 4;
|
||||||
|
}
|
||||||
|
if (x1 > 0x3) {
|
||||||
|
s = s + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g0 = 1 << s; /* g0 = 2**s */
|
||||||
|
g1 = (g0 + (x >> s)) >> 1; /* g1 = (g0 + x/g0)/2 */
|
||||||
|
|
||||||
|
/* converges after four to five divisions for arguments up to 16,785,407 */
|
||||||
|
while (g1 < g0) {
|
||||||
|
g0 = g1;
|
||||||
|
g1 = (g0 + (x/g0)) >> 1;
|
||||||
|
}
|
||||||
|
return g0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! @} */
|
||||||
@@ -1,5 +1,17 @@
|
|||||||
CFLAGS=-g -Wall -I../src_simtrace -I../libcommon/include -I.
|
LIBOSMOCORE_CFLAGS=`pkg-config --cflags libosmocore`
|
||||||
LDFLAGS=-losmocore
|
LIBOSMOCORE_LIBS=`pkg-config --libs libosmocore`
|
||||||
|
|
||||||
|
CFLAGS=-g -Wall $(LIBOSMOCORE_CFLAGS) \
|
||||||
|
-I../src_simtrace \
|
||||||
|
-I../atmel_softpack_libraries/libchip_sam3s \
|
||||||
|
-I../atmel_softpack_libraries/libchip_sam3s/cmsis \
|
||||||
|
-I../atmel_softpack_libraries/libchip_sam3s/include \
|
||||||
|
-I../atmel_softpack_libraries/usb/include \
|
||||||
|
-I../libcommon/include \
|
||||||
|
-I../libboard/common/include \
|
||||||
|
-I../libboard/simtrace/include \
|
||||||
|
-I.
|
||||||
|
LDFLAGS=$(LIBOSMOCORE_LIBS)
|
||||||
|
|
||||||
VPATH=../src_simtrace ../libcommon/source
|
VPATH=../src_simtrace ../libcommon/source
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
|
|||||||
printf("uart_enable(uart_chan=%u, %s)\n", uart_chan, rts);
|
printf("uart_enable(uart_chan=%u, %s)\n", uart_chan, rts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void card_emu_uart_interrupt(uint8_t uart_chan)
|
||||||
|
{
|
||||||
|
printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
|
||||||
|
}
|
||||||
|
|
||||||
void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
|
void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
|
||||||
{
|
{
|
||||||
printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
|
printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
|
||||||
@@ -120,6 +125,8 @@ static void io_start_card(struct card_handle *ch)
|
|||||||
|
|
||||||
/* release from reset and verify th ATR */
|
/* release from reset and verify th ATR */
|
||||||
card_emu_io_statechg(ch, CARD_IO_RST, 0);
|
card_emu_io_statechg(ch, CARD_IO_RST, 0);
|
||||||
|
/* simulate waiting time before ATR expired */
|
||||||
|
tc_etu_wtime_expired(ch);
|
||||||
verify_atr(ch);
|
verify_atr(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
LDFLAGS=`pkg-config --libs libusb-1.0 libosmocore` -losmocore
|
LDFLAGS+=`pkg-config --libs libusb-1.0 libosmocore` -pthread
|
||||||
CFLAGS=-Wall -g
|
CFLAGS=-Wall -g
|
||||||
|
|
||||||
all: simtrace2-remsim simtrace2-remsim-usb2udp simtrace2-list
|
APPS=simtrace2-remsim simtrace2-remsim-usb2udp simtrace2-list simtrace2-sniff
|
||||||
|
|
||||||
|
all: $(APPS)
|
||||||
|
|
||||||
simtrace2-remsim: simtrace2-remsim.o apdu_dispatch.o simtrace2-discovery.o libusb_util.o
|
simtrace2-remsim: simtrace2-remsim.o apdu_dispatch.o simtrace2-discovery.o libusb_util.o
|
||||||
$(CC) -o $@ $^ $(LDFLAGS) -losmosim
|
$(CC) -o $@ $^ $(LDFLAGS) `pkg-config --libs libosmosim libpcsclite`
|
||||||
|
|
||||||
simtrace2-remsim-usb2udp: usb2udp.o simtrace2-discovery.o
|
simtrace2-remsim-usb2udp: usb2udp.o simtrace2-discovery.o
|
||||||
$(CC) -o $@ $^ $(LDFLAGS)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
@@ -12,8 +14,15 @@ simtrace2-remsim-usb2udp: usb2udp.o simtrace2-discovery.o
|
|||||||
simtrace2-list: simtrace2_usb.o libusb_util.o
|
simtrace2-list: simtrace2_usb.o libusb_util.o
|
||||||
$(CC) -o $@ $^ $(LDFLAGS)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
simtrace2-sniff: simtrace2-sniff.o simtrace2-discovery.o libusb_util.o
|
||||||
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) $(CFLAGS) `pkg-config --cflags libusb-1.0 libosmocore` -o $@ -c $^
|
$(CC) $(CFLAGS) `pkg-config --cflags libusb-1.0 libosmocore` -o $@ -c $^
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f simtrace2-remsim simtrace2-remsim-usb2udp simtrace2-list *.o
|
@rm -f *.o $(APPS)
|
||||||
|
|
||||||
|
install: $(APPS)
|
||||||
|
mkdir -p $(DESTDIR)/usr/bin
|
||||||
|
cp $(APPS) $(DESTDIR)/usr/bin/
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
*
|
*
|
||||||
* (C) 2016 by Harald Welte <hwelte@hmw-consulting.de>
|
* (C) 2016 by Harald Welte <hwelte@hmw-consulting.de>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or
|
||||||
* it under the terms of the GNU General Public License version 2
|
* modify it under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation
|
* 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
|
||||||
@@ -13,9 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
/* apdu_dispatch - State machine to determine Rx/Tx phases of APDU
|
||||||
|
*
|
||||||
|
* (C) 2016 by Harald Welte <hwelte@hmw-consulting.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
/* libisb utilities
|
||||||
|
*
|
||||||
|
* (C) 2010-2016 by Harald Welte <hwelte@hmw-consulting.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -130,18 +148,18 @@ int dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class, i
|
|||||||
for (k = 0; k < intf->num_altsetting; k++) {
|
for (k = 0; k < intf->num_altsetting; k++) {
|
||||||
const struct libusb_interface_descriptor *if_desc;
|
const struct libusb_interface_descriptor *if_desc;
|
||||||
if_desc = &intf->altsetting[k];
|
if_desc = &intf->altsetting[k];
|
||||||
if (class > 0 && if_desc->bInterfaceClass != class)
|
if (class >= 0 && if_desc->bInterfaceClass != class)
|
||||||
continue;
|
continue;
|
||||||
if (sub_class > 0 && if_desc->bInterfaceSubClass != sub_class)
|
if (sub_class >= 0 && if_desc->bInterfaceSubClass != sub_class)
|
||||||
continue;
|
continue;
|
||||||
if (protocol > 0 && if_desc->bInterfaceProtocol != protocol)
|
if (protocol >= 0 && if_desc->bInterfaceProtocol != protocol)
|
||||||
continue;
|
continue;
|
||||||
/* MATCH! */
|
/* MATCH! */
|
||||||
out[out_idx].usb_dev = dev;
|
out[out_idx].usb_dev = dev;
|
||||||
out[out_idx].vendor = dev_desc.idVendor;
|
out[out_idx].vendor = dev_desc.idVendor;
|
||||||
out[out_idx].product = dev_desc.idProduct;
|
out[out_idx].product = dev_desc.idProduct;
|
||||||
out[out_idx].addr = addr;
|
out[out_idx].addr = addr;
|
||||||
strncpy(out[out_idx].path, path, sizeof(out[out_idx].path));
|
strncpy(out[out_idx].path, path, sizeof(out[out_idx].path)-1);
|
||||||
out[out_idx].path[sizeof(out[out_idx].path)-1] = '\0';
|
out[out_idx].path[sizeof(out[out_idx].path)-1] = '\0';
|
||||||
out[out_idx].configuration = conf_desc->bConfigurationValue;
|
out[out_idx].configuration = conf_desc->bConfigurationValue;
|
||||||
out[out_idx].interface = if_desc->bInterfaceNumber;
|
out[out_idx].interface = if_desc->bInterfaceNumber;
|
||||||
@@ -197,7 +215,7 @@ int usb_match_interfaces(libusb_context *ctx, const struct dev_id *dev_ids,
|
|||||||
dev_desc.idVendor, dev_desc.idProduct, addr);
|
dev_desc.idVendor, dev_desc.idProduct, addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = dev_find_matching_interfaces(*dev, 255, 2, -1, out_cur, out_len_remain);
|
rc = dev_find_matching_interfaces(*dev, class, sub_class, protocol, out_cur, out_len_remain);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
continue;
|
continue;
|
||||||
out_cur += rc;
|
out_cur += rc;
|
||||||
@@ -232,34 +250,39 @@ libusb_device_handle *usb_open_claim_interface(libusb_context *ctx,
|
|||||||
(strlen(ifm->path) && !strcmp(path, ifm->path))) {
|
(strlen(ifm->path) && !strcmp(path, ifm->path))) {
|
||||||
rc = libusb_open(*dev, &usb_devh);
|
rc = libusb_open(*dev, &usb_devh);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("Cannot open device");
|
fprintf(stderr, "Cannot open device: %s\n", libusb_error_name(rc));
|
||||||
|
usb_devh = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = libusb_get_configuration(usb_devh, &config);
|
rc = libusb_get_configuration(usb_devh, &config);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("Cannot get current configuration");
|
fprintf(stderr, "Cannot get current configuration: %s\n", libusb_error_name(rc));
|
||||||
libusb_close(usb_devh);
|
libusb_close(usb_devh);
|
||||||
|
usb_devh = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (config != ifm->configuration) {
|
if (config != ifm->configuration) {
|
||||||
rc = libusb_set_configuration(usb_devh, ifm->configuration);
|
rc = libusb_set_configuration(usb_devh, ifm->configuration);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("Cannot set configuration");
|
fprintf(stderr, "Cannot set configuration: %s\n", libusb_error_name(rc));
|
||||||
libusb_close(usb_devh);
|
libusb_close(usb_devh);
|
||||||
|
usb_devh = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc = libusb_claim_interface(usb_devh, ifm->interface);
|
rc = libusb_claim_interface(usb_devh, ifm->interface);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("Cannot claim interface");
|
fprintf(stderr, "Cannot claim interface: %s\n", libusb_error_name(rc));
|
||||||
libusb_close(usb_devh);
|
libusb_close(usb_devh);
|
||||||
|
usb_devh = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = libusb_set_interface_alt_setting(usb_devh, ifm->interface, ifm->altsetting);
|
rc = libusb_set_interface_alt_setting(usb_devh, ifm->interface, ifm->altsetting);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("Cannot set interface altsetting");
|
fprintf(stderr, "Cannot set interface altsetting: %s\n", libusb_error_name(rc));
|
||||||
libusb_release_interface(usb_devh, ifm->interface);
|
libusb_release_interface(usb_devh, ifm->interface);
|
||||||
libusb_close(usb_devh);
|
libusb_close(usb_devh);
|
||||||
|
usb_devh = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user