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
write3 03 0C (1 byte) 00=default / 01=lock (token will then be readonly!)
then (5 bytes) card data

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


#10 Egor 2023-12-18 20:26
I think AA DD 00 is preambula and field "length" is 1 byte long.
If data length is greater than 15, then the XOR checksum (1 byte) is not very effective. And when the length is greater than 255 (supposing 2 bytes len), the XOR checksum is completely useless. When data length is more than 15, it is necessary to use a checksum like CRC-16 or greater degree. Device developers should know this.
#9 Aaron 2019-01-31 02:40
Can and may you provide the same code but in Java? I want to learn about implementing these kinds of stuff.
#8 freedick 2018-11-03 14:06
Thank you for the detailed specification. :-)

I did a quick implementation of the protocol in python and uploaded it here in case anyone would need it.

#7 Dan 2018-10-22 07:10
Here's an additional trap...

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.
#6 Dom 2018-06-28 00:45
Any chance you could provide a .NET version of Python script. Need to understand how to read these buffers in vb or c#
#5 Triades 2018-03-10 15:29
@mario : me too

@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.
#4 Mario 2017-12-27 18:48
Any way you can add a link to the software? I discarded the CD haha :(
#3 Sam 2017-12-01 08:26
Hi, do you have any suggestion on how to read a TK555 trasponder with this? Seller told me I can read cards but that a different antenna is needed to read the trasponder directly
#2 Triades 2016-12-17 15:06
This reader doesn't support RFID products based on the 13.56MHz frequency (Mifare, Felica, ISO 14443, NFC), nor HID Prox cards (on 125Khz frequency).
#1 Michael 2016-09-09 20:20
I think I have the same product. The menu only has EM4200 under Card, which makes me wonder if this device can handle other types of cards (i.e. Mifare Classic). If not, is it because the protocol is handled at the hardware level, or can it potentially support any type of protocol implemented at the software level as long as the frequency remains the same (125Khz) ? Thanks for any help in understanding this.