└── sniff-pn53x.sh
/sniff-pn53x.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #######################################################################
4 | # Linux USB sniffer with PN53x basic parsing
5 | # Copyright (C) 2010, Yobibe
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 | #######################################################################
20 |
21 | # Warning! usbmon is truncating long data packets,
22 | # e.g. with PN533 we get only the first 24 bytes after D4/D5
23 |
24 | # Usages:
25 |
26 | # (default): decode data, e.g.:
27 | # d4 02 -> GetFirmwareVersion
28 | # d5 03 32 01 04 07
29 |
30 | # --nodecode: don't try to interpret data, e.g.:
31 | # d402
32 | # d50332010407
33 |
34 | # --internal: reader-dependent frames, e.g.:
35 | # with ACR122U: (output colorized to highlight Tama content)
36 | # -> ff00480000
37 | # <- 41435231323255313032
38 | # -> ff00000002d402
39 | # <- 6108
40 | # -> ffc0000008
41 | # <- d503320104079000
42 | # with PN533: (output colorized to highlight Tama content)
43 | # -> 0000ff00ff00
44 | # -> 0000ff02fed4022a00
45 | # <- 0000ff00ff00
46 | # <- 0000ff06fad50333020707e500
47 |
48 | # --rawusb: as from usbmon
49 | # with PN533:
50 | # ffff88000ca45480 3985505915 S Ci:7:045:0 s 80 06 0300 0000 00ff 255 <
51 | # ffff88000ca45480 3985508248 C Ci:7:045:0 0 4 = 04030904
52 | # ffff88000ca45480 3985508282 S Ci:7:045:0 s 80 06 0301 0409 00ff 255 <
53 | # ffff88000ca45480 3985511235 C Ci:7:045:0 0 20 = 14035300 43004d00 20004d00 69006300 72006f00
54 | # ffff88000ca45480 3985511295 S Ci:7:045:0 s 80 06 0300 0000 00ff 255 <
55 | # ffff88000ca45480 3985513250 C Ci:7:045:0 0 4 = 04030904
56 | # ffff88000ca45480 3985513301 S Ci:7:045:0 s 80 06 0302 0409 00ff 255 <
57 | # ffff88000ca45480 3985516428 C Ci:7:045:0 0 30 = 1e035300 43004c00 33003700 31003100 2d004e00 46004300 26005200 5700
58 | # ffff88000ca45cc0 3985516625 S Co:7:045:0 s 00 09 0001 0000 0000 0
59 | # ffff88000ca45cc0 3985518230 C Co:7:045:0 0 0
60 | # ffff88000ca45cc0 3985518297 S Bo:7:045:4 -115 6 = 0000ff00 ff00
61 | # ffff88000ca45cc0 3985519229 C Bo:7:045:4 0 6 >
62 | # ffff88000ca45cc0 3985519263 S Bo:7:045:4 -115 9 = 0000ff02 fed4022a 00
63 | # ffff88000ca45cc0 3985520253 C Bo:7:045:4 0 9 >
64 | # ffff880010d31240 3985520300 S Bi:7:045:4 -115 256 <
65 | # ffff880010d31240 3985521251 C Bi:7:045:4 0 6 = 0000ff00 ff00
66 | # ffff880010d31240 3985521284 S Bi:7:045:4 -115 256 <
67 | # ffff880010d31240 3985522430 C Bi:7:045:4 0 13 = 0000ff06 fad50333 020707e5 00
68 |
69 | if [ "$1" == "--bus" ]; then
70 | shift
71 | USBBUS=$1
72 | shift
73 | fi
74 |
75 | # I try to detect devices in the following order:
76 | DEVICES="pn53x_usb touchatag"
77 |
78 | # Find right bus
79 | for DEVICE in $DEVICES
80 | do
81 | if [ "$DEVICE" == "touchatag" ]
82 | then
83 | # USB identifier string
84 | DEVID="(072f:90cc|072f:2200)"
85 | elif [ "$DEVICE" == "pn53x_usb" ]
86 | then
87 | # USB identifier string PN531/PN533
88 | DEVID="(054c:0193|04cc:0531|04cc:2533|04e6:5591|1fd3:0608|054c:02e1)"
89 | fi
90 | if [ "$USBBUS" != "" ]
91 | then
92 | USBBUS=$(lsusb|egrep "$DEVID"|cut -d ' ' -f2|sed 's/^0\+//'|grep -m 1 "$USBBUS")
93 | else
94 | USBBUS=$(lsusb|egrep -m 1 "$DEVID"|cut -d ' ' -f2|sed 's/^0\+//')
95 | fi
96 | if [ "$USBBUS" != "" ]
97 | then
98 | echo "Found $DEVICE on bus $USBBUS" >&2
99 | break
100 | fi
101 | done
102 | if [ "$USBBUS" == "" ]
103 | then
104 | echo "Could not find any reader, sorry"
105 | exit 1
106 | fi
107 |
108 | # Prepare kernel interface for USBMON
109 | ls /sys/kernel/debug| grep -q . || sudo mount -t debugfs none_debugs /sys/kernel/debug
110 | lsmod | grep -q usbmon || sudo modprobe usbmon
111 |
112 | FILTER1=true
113 | DECODE=true
114 | OUTPUT=--only-matching
115 |
116 | case "$1" in
117 | "--nodecode")
118 | DECODE=false
119 | ;;
120 | "--internal")
121 | DECODE=false
122 | OUTPUT=--color
123 | ;;
124 | "--rawusb")
125 | FILTER1=false
126 | DECODE=false
127 | OUTPUT=--color
128 | ;;
129 | esac
130 |
131 | if [ "$DEVICE" == "touchatag" ]
132 | then
133 | function filter1 {
134 | # APDUs in bulk transfers
135 | grep --line-buffered "B[io]:.*= ........ ........ ........" | sed -u 's/ //g;s/.*Bi.*=..................../<- /;s/.*Bo.*=..................../-> /'|\
136 | grep -C999 --line-buffered $OUTPUT -P '((?<=-> ff000000..).*|(?<=<- ).*(?=9000))'
137 | }
138 | elif [ "$DEVICE" == "pn53x_usb" ]
139 | then
140 | function filter1 {
141 | # PN53x USB frames
142 | grep --line-buffered "B[io]:.*= ........" | sed -u 's/ //g;s/.*Bi.*=/<- /;s/.*Bo.*=/-> /' |\
143 | grep -C999 --line-buffered $OUTPUT -P '(?<=.. 0000ff(?!ffff)....)(..).*(?=....)|(?<=.. 0000ffffff......)(..).*(?=....)'
144 | }
145 | fi
146 |
147 | function get_usb_data {
148 | if [ ! -e "/sys/kernel/debug/usb/usbmon/${USBBUS}u" ]
149 | then
150 | echo "Error device $DEVICE not found" >&2
151 | exit 1
152 | fi
153 | sudo cat /sys/kernel/debug/usb/usbmon/${USBBUS}u
154 | }
155 |
156 | function decode_pn53x {
157 | sed -u 's/^[<>-][<>-] //;s/\([0-9a-f]\{2\}\)/\1 /g'|awk '
158 | function showline(col2) {
159 | if (done) return
160 | col1=$0
161 | col1width=40
162 | printf col1;
163 | for (i=length(); i Diagnose") }
170 | /^d4 02/ { showline("-> GetFirmwareVersion") }
171 | /^d4 04/ { showline("-> GetGeneralStatus") }
172 | /^d4 06/ { showline("-> ReadRegister 0x" $3 $4 ) }
173 | /^d4 08/ { showline("-> WriteRegister 0x" $3 $4 ) }
174 | /^d4 0c/ { showline("-> ReadGPIO") }
175 | /^d4 0e/ { showline("-> WriteGPIO") }
176 | /^d4 10/ { showline("-> SetSerialBaudRate") } # PN531 PN532
177 | /^d4 12/ { showline("-> SetParameters: 0x" $3) }
178 | /^d4 14/ { showline("-> SAMConfiguration") } # PN531 PN532
179 | /^d4 16/ { showline("-> PowerDown") } # PN531 PN532
180 | /^d4 18/ { showline("-> AlparCommandForTDA") } # PN533
181 | /^d4 32 01/ { showline("-> RFConfiguration RFfield: " $4) }
182 | /^d4 32 02/ { showline("-> RFConfiguration Timings: " $4 " " $5 " " $6) }
183 | /^d4 32 04/ { showline("-> RFConfiguration MaxRtyCOM: " 44) }
184 | /^d4 32 05/ { showline("-> RFConfiguration MaxRetries: " $4 " " $5 " " $6) }
185 | /^d4 32/ { showline("-> RFConfiguration unknown") }
186 | /^d4 32/ { showline("-> RFConfiguration") }
187 | /^d4 38/ { showline("-> InQuartetByteExchange") } # PN533
188 | /^d4 40/ { showline("-> InDataExchange") }
189 | /^d4 42/ { showline("-> InCommunicateThru") }
190 | /^d4 44/ { showline("-> InDeselect") }
191 | /^d4 46/ { showline("-> InJumpForPSL") }
192 | /^d4 48/ { showline("-> InActivateDeactivatePaypass") } # PN533
193 | /^d4 4a/ { showline("-> InListPassiveTarget") }
194 | /^d4 4e/ { showline("-> InPSL") }
195 | /^d4 50/ { showline("-> InATR") }
196 | /^d4 52/ { showline("-> InRelease") }
197 | /^d4 54/ { showline("-> InSelect") }
198 | /^d4 56/ { showline("-> InJumpForDEP") }
199 | /^d4 58/ { showline("-> RFRegulationTest") }
200 | /^d4 60/ { showline("-> InAutoPoll") } # PN532
201 | /^d4 86/ { showline("-> TgGetData") }
202 | /^d4 88/ { showline("-> TgGetInitiatorCommand") }
203 | /^d4 8a/ { showline("-> TgGetTargetStatus") }
204 | /^d4 8c/ { showline("-> TgInitAsTarget") }
205 | /^d4 8e/ { showline("-> TgSetData") }
206 | /^d4 90/ { showline("-> TgResponseToInitiator") }
207 | /^d4 92/ { showline("-> TgSetGeneralBytes") }
208 | /^d4 94/ { showline("-> TgSetMetaData") } # PN531 PN532
209 | /^d4 96/ { showline("-> TgSetDataSecure") } # PN533
210 | /^d4 98/ { showline("-> TgSetMetaData") } # PN533
211 | /^7f/ { showline("<- resp error frame") }
212 | !done
213 | '
214 | }
215 |
216 | if $DECODE
217 | then
218 | get_usb_data | filter1 | decode_pn53x
219 | elif $FILTER1
220 | then
221 | get_usb_data | filter1
222 | else
223 | get_usb_data
224 | fi
225 |
--------------------------------------------------------------------------------