Homepage | Contact
Egistec ES603
Last update: 2012-12-13

Egistec ES603 fingerprint device

Outline

Introduction

All started when I bought a laptop to replace my desktop computer. My choice was the Lenovo Essential B570. It comes with Windows 7 Home edition so the first thing I did was to change the HDD to the SSD from my old desktop PC and to install Ubuntu. After fixing the different issues (GPT partition, 3Gb SATA link, wifi, ...), I focused on the embedded fingerprint device.

'lsusb' command gives this:

Bus 002 Device 003: ID 1c7a:0603 LighTuning Technology Inc.
LighTuning was bought by Egistec few years ago but both does not provide linux support of the device. On linux, libfprint seems the most advanced framework for fingerprint. My search about Egistec ended to the driver from Alexey for the SS801U device. However, the device embedded in my laptop is a ES603 and after testing, I concluded my device was not compatible.

I could wait someone to implement the driver but since I had no experience about this, I decided to put hands under the hood. Here the plan:

  1. Use the Windows support to monitor USB traffic between the fingerprint device and the host
  2. Create a simple linux application to communicate with a USB device
  3. Understand part of the traces and of the protocol and implement it into the testing application
  4. Iterate previous step until the protocol is reversed to capture a fingerprint
  5. Add support to libfprint

Once booted on Windows, let's try to gather informations! A quick search on Egistec website to find the ES603 characteristics (it could help to understand the protocol):

Two files compose the Windows driver:

Egistec BioExcess software permits to exploit this driver on Windows.

Analysis

In order to understand the protocol, we need to capture the USB communication on Windows 7. I used different softwares but two are quite good. USBlyzer has a trial version for 33 days however data frame size is also limited. USBSnoop is free but it is not easy to install and to make it work properly. All the captured traces will be used to reverse engineer how to communicate with the device. To understand properly the protocol, we need a lot of traces from device activation and deactivation, from no finger, from one finger, from many fingers, ...

The device uses endpoint 0x02 to send a request (from host to device) and endpoint 0x81 to receive (from device to host).

The first thing you figure out is the fixed header of usb frames (5 bytes).

The rest is much more difficult to understand. Since I have no experience about fingerprint device, I read briefly sources of other drivers in the libfprint package.

Sensor's registers
In this following tables, this is all registers used in the driver. However I was not able to determine purposes of all registers.

Register numberRegister purposeRegister values
0x02Mode controlSleep:0x30 Contact:0x31 Sensor:0x33 FlyEstimation:0x34
0x03Contact register/capacitance?(value >> 4) & 0x1 = 1 if finger contact otherwise
0x04?
0x10MVS FRMBUF control
0x1A?
0x20?def: 0x00
0x21Small gaindef: 0x23
0x22Normal gaindef: 0x21
0x23Large gaindef: 0x20
0x24?def: 0x14
0x25?def: 0x6A
0x26VRB again?def: 0x00
0x27VRT again?def: 0x00
0x28?def: 0x00
0x29?def: 0xC0
0x2A?def: 0x50
0x2B?def: 0x50
0x2C?def: 0x4D
0x2D?def: 0x03
0x2E?def: 0x06
0x2F?def: 0x06
0x30?def: 0x10
0x31?def: 0x02
0x32?def: 0x14
0x33?def: 0x34
0x34?def: 0x01
0x35?def: 0x08
0x36?def: 0x03
0x37?def: 0x21
0x41Encryption byte1def: 0x12
0x42Encryption byte2def: 0x34
0x43Encryption byte3def: 0x56
0x44Encryption byte4def: 0x78
0x45Encryption byte5def: 0x90
0x46Encryption byte6def: 0xAB
0x47Encryption byte7def: 0xCD
0x48Encryption byte8def: 0xEF
0x50required for contact detection?init: 0x0F valid: value | 0x80 / 0x8F
0x51?valid: value & 0xF7 / 0x30
0x59?valid: 0x18
0x5A?valid: 0x08
0x5B?valid: 0x00/0x10
0x70Sensor model byte0 (version?, firmware?)def: 0x4A
0x71Sensor model byte1def: 0x44
0x72Sensor model byte2def: 0x49
0x73Sensor model byte3def: 0x31
0x93?
0x94?
0xE0Sensor Gaininit: 0x04, GAIN_SMALL_INIT: 0x23 (default gain)
0xE1For brightness and contrastMaximum value for VRT: 0x3F
0xE2For brightness and contrastMaximum value for VRB: 0x3A
0xE3Used for contact detectionMaximum value for DTVRT: 0x3A
0xE5VCO Control0x13 (IDLE?), 0x14 (REALTIME)
0xE6DC OffsetMinimum value for DCoffset: 0x00 Maximum value for DCoffset: 0x35
0xF0?init:0x00 close:0x01
0xF2?init:0x00 close:0x4E

Reading sensor registers
Request:

CMD_READ_REG NN XX ...
CMD_READ_REG is 0x01. NN is the number of registers to read. XX are the registers number.
Answer:
CMD_OK XX ...
CMD_OK is 0x01. XX are register values.

Writing sensor registers
Request:

CMD_WRITE_REG NN XX YY ...
CMD_WRITE_REG is 0x02. NN is the number of registers to write. XX are the registers number. YY are the new registers values.
Answer:
CMD_OK

Capturing an image (frame)
Request:

WIDTH, 0x01, GAIN, VRT, VRB
WIDTH, 0x00, 0x00, 0x00, 0x00
it seems that the only working WIDTH is 0xC0 (192) and it the only value used in the windows driver. If the second byte is 0, registers for GAIN/VRT/VRB will be used.
Answer: Frame is 384 bytes long (depending on WIDTH). The image encoding is 4 bits per pixel raw image. So the resulting image is 192 * 4 pixels.

Capturing an image using Fly-Estimation
Image capture (aka Fly-Estimation® technology) completes fingerprint without software reconstruction.
Request:

HEIGHT0, HEIGHT1, UNK1, UNK2, UNK3
0xF4, 0x02, 0x01, 0x64, 0x00
In the windows driver, values are fixed to the above values. 1st 2nd bytes is unsigned short for height, but only on value range: 0x01 0xF4 (500), 0x02 0x00 (512), 0x02 0xF4 (756) are ok. 3rd byte : ?? but changes frame size. 4th byte : ??. 5th byte : motion sensibility?.
Answer: The sensor buffered 64000 bytes of data. The encoding used is a 4 bits raw. So the resulting image is 256*500 pixels. The command is synchronous (blocking).

Controlling LEDs on selected models (CMD 0x60)
Some models have 2 LEDs (red and blue) that can be controlled with CMD 0x60.
Request CMD 0x60: ask status of LEDs:

0x60 0x01

Answer CMD 0x60: returns OK and status of LEDs
CMD_OK 0xXX

Request CMD 0x60 write: set status of LEDs
0x60 0x02 0xXX

None: 0x00 Red: 0x10 Blue: 0x20 Red+Blue: 0x10|0x20 = 0x30 (Unknown behaviour with value 0x11, 0x21, 0x31)
Answer CMD 0x60 write:
CMD_OK 0xXX

CMD 0x20 / CMD 0x25
I was not able to determine the exact purpose of those commands.
Request CMD 0x20:

0x20

Answer CMD 0x20:
0x05 0x00 0x00

Request CMD 0x25:
0x25

Answer CMD 0x25:
CMD_OK 0x00

Tuning DCoffset register

  1. Set initial values: gain=0x23 min_dcoffset=0x00 max_dcoffset=0x35
  2. Get a frame with the current gain and use fixed vrt=0x15 vrb=0x10
  3. Use dichotomy to find at what dcoffset value the frame start to be completely black
  4. Reduce gain if cannot get a completely black frame

Tuning DTVRT register
DTVRT tuning permit to detect finger contact with the sensor.

  1. Read registers 0x50, 0x51, 0x59, 0x5A, 0x5B to reset the initial values at the end of tuning
  2. Change to sleep mode
  3. Set VCO_CONTROL to VCO_IDLE
  4. Set register 0x50 to value | 0x80
  5. Set register 0x51 to value & 0xF7
  6. Set registers 0x59 to 0x18, 0x5A to 0x08 and 0x5B to 0x00
  7. Change to contact mode
  8. Set DTVRT to MAX
  9. Read register 0x03 and if value is
  10. If (value>> 4 & 1) == 1, then we found the tuned DTVRT value (current + 5)
  11. Else Set DTVRT register to current - 5 and read register 0x03 until contact is found
  12. If DTVRT reaches 0, reduce DCoffset of 1 and restart tuning

Tuning VRT and VRB registers

  1. Initial values are vrt = 0x0A, vrb = 0x10
  2. Reduce DCoffset of 1 (reset it at the end of this tuning)
  3. Get a frame with this specific vrt/vrb and gain found in tune DCoffset
  4. Calculate the histogram of the image
  5. The image should not have more than 95% of black or white pixel (otherwise need to decrease/increase DCoffset)
  6. increase vrt/vrb until you found a balanced image

Detecting a finger
The detection of a finger can be done in different ways. The first way is to capture contiguously frames and that if the frame is black or not. But the sensor has a specific way to detect the finger contact with the E-Field (as advertised on the website). Following how to use the E-Field:

  1. Change to mode contact
  2. Set registers 0x59 to 0x18, 0x5A to 0x08, 0x5B to 0x10
  3. Read register 0x50 and set it to (value & 0x7F) | 0x80
  4. Read register 0x03 until value is (value >> 4) & 0x1 == 1 which indicates contact
  5. Add sleep of 5ms between each read and add a timeout
  6. When done, change to sleep mode

Implementation

As described before, I developped a small C application with GUI and synchronous usb communcation to figure out how the sensor works. The second step was to implement the protocol for libfprint (asynchronous usb communication) and to test it with fprint_demo. The code can be found at code.google.com/p/etes603/.

On ubuntu, you have to change rights to access the fingerprint device for non-root:

sudo chmod a+rw /dev/bus/usb/002/003
but the better way to set rights at each reboot is to add a udev rules. Create the file /etc/udev/rules.d/90-egis.rules with the following content:
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1c7a", ATTR{idProduct}=="0603", MODE="0666"

Thanks to all people who helps to test the driver.