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