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).