I recently bought a USB reader/writer for 125kHz RFID tokens. It comes directly from china with no driver/API description, just a windows application called RFID-APP-E-N.exe or RFID_APP_EN.exe on a CD, and a PL2303 driver for the USB-to-serial convertor used by the device.
A reverse engineering of a USB capture allowed to have a good view of the serial protocol used.
Here's a python script/driver to handle the device: rfid_app.py
Serial communication protocol
Serial protocol is at 38400 bauds using 8bit, no parity, 1 stop bit. You need to install the driver for the Prolific PL2303 USB-to-serial embedded in the reader.
Capture of raw serial exchange with the device and the RFID-APP-E-N.exe tool : rfid_app_capture.txt
Request format:
AA DD | length | command code | request data | checksum |
- 2 bytes: AA DD
- 2 bytes: length L (MSB first, 10 => 00 0A)
- 2 bytes: command code
- L-3 bytes: request data
- 1 byte: checksum = XOR of last L-1 bytes (command+data)
Answer format:
AA DD | length | command code | status | answer data | checksum |
- 2 bytes: AA DD
- 2 bytes: length L (MSB first, 10 => 00 0A)
- 2 bytes: command code copied from the request
- 1 byte: status (00 => OK; 01 => error/no token; 02 or 03 => communication error with token)
- L-4 bytes: answer data
- 1 byte: checksum = XOR of last L-1 bytes (command+status+data)
Commands are:
name | code | request data | answer data |
model info | 01 02 | none | "ID card reader & writer" |
beep | 01 03 | (1 byte) beep length, using an arbitrary unit. 0 = forever | none |
led color | 01 04 | (1 byte) 01=red / 02=green / 00=none | none |
read tag | 01 0C | none | (5 bytes) card data |
write2 | 02 0C | (1 byte) 00=default / 01=lock (token will then be readonly!) then (5 bytes) card data |
none |
write3 | 03 0C | (1 byte) 00=default / 01=lock (token will then be readonly!) then (5 bytes) card data |
none |
It seems that write2 and write3 use to different communication protocols with RFID token, to manage two type of tokens. To write any compatible token:
- send a write2 command
- send a read command to check if write succeed
- if failed send a write3 command
- send a read command to check if write succeed
- if failed, write failed :( (readonly or not compatible token)
Command code brute force
tested ranges:
0x0000 - 0x0020 0x0100 - 0x016c 0x0200 - 0x026a 0x0300 - 0x032b 0x0400 - 0x0420 0x0500 - 0x0520 0x0600 - 0x0620 0x0700 - 0x0720 0x0800 - 0x0820 0x0900 - 0x0920 0x0A00 - 0x0A20
results using format "opcode: (status, data)":
0x0101: ('\x01', '') 0x0102: ('\x00', 'ID card reader & writer') 0x0103: ('\x00', '') 0x0104: ('\x00', '') 0x0105: ('\x00', '') => LED is switched off until next command (then red) 0x010c without token: ('\x01', '') 0x010c with token: ('\x00', '\x00\x00\x00\x13\xec') 0x0201: ('\x00', '') 0x0202: ('\x00', '') 0x0207: ('\x00', '') 0x020c: ('\x00', '') 0x0301: ('\x00', '') 0x0303: ('\x00', '') 0x0304: ('\x00', '\x07\xaa\xdd\x00\x04\x03\x04\x00') 0x030c: ('\x00', '') other: no answer from device
Hardware description
Device is using two chips:
- A Prolific PL2303 USB-to-serial chip, labeled "PL-2303HX LFC150688", accessible from a female USB mini connector.
- A chip labeled "P300 EAXI 527+" in charge of the RFID communication, connected to a 125KHz antenna, 2 leds, and a buzzer. This chip receives commands through a TTL serial line connected to the PL2303 chip.
Read/write card EM4305 / T55x7 and read card EM4001 / EM4200. However, it seems that it doesn't support the full protocols if those cards and can only managed the first 5 bytes (first 40 bits).
I did a quick implementation of the protocol in python and uploaded it here in case anyone would need it.
https://github.com/freedick/pl2303_rfid
If the data sent or received contains the byte 'AA', it should also be followed by the additional byte '00'. This is to avoid anyone thinking that it is part of the header ('AADD'). But note, the length does not change.
@sam : it seems that there's no answer on search engines for TK555. If you speak of T5557/T5567/T5577 cards, they can be read or written by this tool. I imagine that the limit of 40 first bits is related to the firmware of the tool.