└── 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 | --------------------------------------------------------------------------------