mincrmatt12 / elan-spi-fingerprint

prototype linux driver for elantech spi-based fingerprint sensors
38 stars 4 forks source link

Asus Expertbook B9400CEA #2

Closed DupiDachs closed 3 years ago

DupiDachs commented 3 years ago

First of all: Thanks a lot for all the work you have put into this!

I am currently trying to get your prototype running on an ASUS Expertbook B9400. This device has a somewhat different sensor, but is also based on SPI ELAN device.

Hence, I set up 04F3:3134 as VID:PID and the ACPI ID ELAN70A1. Then I built the prototype and ran it:

sudo ./prototype udev Prototype starting... Compiled with HKEY values : TP_VID 4f3; TP_PID 3134; ACPI_ID ELAN70A1 Got SPI entry /sys/devices/pci0000:00/0000:00:1e.2/pxa2xx-spi.4/spi_master/spi0/spi-ELAN70A1:00/spidev/spidev0.0 Found ACPI id! Got HID entry /sys/devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-2/i2c-ASUE140A:00/0018:04F3:3134.0001/hidraw/hidraw0 Found TP ID! Got SPI = /dev/spidev0.0 and HID = /dev/hidraw0, opening. Beginning initialization SPIStatus = 0x01 Result of ioctl for reset 5 SPIStatus after reset = 0x01

  • Register 00 = 00
  • Register 01 = 00
  • Register 02 = 4f
  • Register 03 = 00
  • Register 04 = 4f
  • Register 05 = a0
  • Register 06 = 00
  • Register 07 = 00
  • Register 08 = 00
  • Register 09 = 04
  • Register 0a = 73
  • Register 0b = 01
  • Register 0c = 08
  • Register 0d = 00
  • Register 0e = 00
  • Register 0f = 13
  • Register 10 = 38
  • Register 11 = 01
  • Register 12 = 00
  • Register 13 = 00
  • Register 14 = 00
  • Register 15 = 04
  • Register 16 = 00
  • Register 17 = 64
  • Register 18 = 01
  • Register 19 = f4
  • Register 1a = 00
  • Register 1b = 00
  • Register 1c = 00
  • Register 1d = 00
  • Register 1e = 00
  • Register 1f = 00
  • Register 20 = 00
  • Register 21 = 00
  • Register 22 = 04
  • Register 23 = 00
  • Register 24 = 00
  • Register 25 = 00
  • Register 26 = 00
  • Register 27 = 00
  • Register 28 = 00
  • Register 29 = 02
  • Register 2a = 07
  • Register 2b = e0
  • Register 2c = 00
  • Register 2d = 00
  • Register 2e = d0
  • Register 2f = 40
  • Register 30 = 01
  • Register 31 = 38
  • Register 32 = 00
  • Register 33 = 00
  • Register 34 = 00
  • Register 35 = 1f
  • Register 36 = ff
  • Register 37 = 00
  • Register 38 = 00
  • Register 39 = 00
  • Register 3a = 00
  • Register 3b = 24
  • Register 3c = ff
  • Register 3d = ff
  • Register 3e = ff
  • Register 3f = f8 Reading raw dimensions Got 80x80 sensor After hardcoded lookup: (80 x 80) Version = 39 Speicherzugriffsfehler

Speicherzugriffsfehler is German for memory access error. Any ideas on how I might get this working? Maybe I need to somehow follow what you have done in Windows for your ELAN reader chasing logs. Is there any help on how to get me started?

DupiDachs commented 3 years ago

OK. Already got a step further and simply hardcoded sensIcVersion = 1; to the code.

It is now running and returns somehow sensible values:

So I guess there is still something off with the register that sets the gain. I'll take a look ...

mincrmatt12 commented 3 years ago

OK so I opened up the build of the driver for your laptop and it seems to be a newer sensor than what the version I originally reversed supported, and I think it's using a different calibration sequence. I'm still reading through it but I might have some new initialization/calibration stuff pushed soon.

I would ask for windows driver logs but the new drivers don't use OutputDebugString so you can't use something simple like sysinternals debugview to view them, and I'm not sure how to view UMDF 2 TraceMessage outputs. In theory you can do it with windbg, like how msdn explains it here but I don't have any experience with that, although if you manage to get anything going that route (something containing logs with "FpDeviceInitialize" in them) they'd be useful for understanding the driver.

DupiDachs commented 3 years ago

Thanks for the hint. I'll give that link of yours a try once I have some time again - possibly this weekend. :)

One more info: Ignoring the calibration procedure and allowing a far higher mean_value lets me proceed with taking an image. At least the process runs reliable here. I then ran the python script to get an visual output, changing the size from 96x96 to 80x80 (as indicated by my sensor) in the script. Output is pretty useless, but reproducable. :D

bla

mincrmatt12 commented 3 years ago

You might think it's useless but that confirms my basic understanding of the capture image code for this sensor is correct. Specifically unlike the other sensors which you request line-by-line, for this one it seems you have to request the entire image at once. Since the current code doesn't know that, it's requesting the entire image for each line and so you get 80 first lines (plus a bunch of junk since you also apparently have to filter 0xffs from the bytestream)

mincrmatt12 commented 3 years ago

Alright in theory you should be able to use the new code to capture an image.

DupiDachs commented 3 years ago

Thanks for the input! I did a git pull just now, rebuilt the prototype and ran another test. I found a couple of things: image

I'll try later to take a closer look. Thanks again for your efforts!

mincrmatt12 commented 3 years ago

I should have fixed the missing sensor name in 33e5c9a, but hmm that is interesting. When you hardcoded it did you also have it use the HV version of the calibration code too? What kind of output did it end up giving you?

DupiDachs commented 3 years ago

Yes. It also enters CalibrateHV. Just checked that with a simple printf in there. image

Another thing I have found. Linux lists TP_PID = 0x3134; When I am in Windows, I found the following HKLM regedit: // These values come from HKLM\System\CurrentControlSet\Control\ElanFP\OtherSetting\TP_VID,TP_PID // available PIDs: 22FE, 3028, 304D, 3059, 306F, 30B1, 30B2, 3104 You also find 3104 in there, which is the ID for which you have set up an assert. I am not using this PID, but is it actually the right one? On linux, I do not see it.

mincrmatt12 commented 3 years ago

The PID that the touchpad is reporting shows up in the path in /sys, and based on what you showed earlier you have it set correctly. Plus, the driver refers to that mode (the reason that I've specifically asserted against that specific touchpad) as "x571_special_parameter", which I assume means the X571 which is not what you have.

Based on those results though CaptureImage doesn't seem to actually be getting new (or even any valid) data at all.

DupiDachs commented 3 years ago
mincrmatt12 commented 3 years ago

I just re-read the CaptureImage method in the windows driver and it seems like I was missing a "wait for ready" bit thing; I just pushed code that does wait for it so maybe now it will actually have some valid data?

DupiDachs commented 3 years ago

That did not do it unfortunately. :/ I'll keep looking. :)

mincrmatt12 commented 3 years ago

Anything noticeably different in the output?

DupiDachs commented 3 years ago

Interestingly, the "waiting for image" part never gets printed... Did not see any difference. From time to time, I get now "EMPTY" instead of "UNKNOWN", but I guess that is just passing a different threshold by accident. image

mincrmatt12 commented 3 years ago

Maybe I'm hitting the upper limit on the size of an SPI transfer, some googling says they can only be at most 4096 bytes long by default and I'm doing what the windows driver does which is one huge 16k transfer.

I just pushed some slightly suspicious code that tries to chunk up big transfers into 2048byte segments.

DupiDachs commented 3 years ago

image I put this printf statement there and it never gets printed. Nevermind the for loop, played a bit there as well...

Trying your push now...

mincrmatt12 commented 3 years ago

Actually I just checked the spidev code directly and that push wouldn't bypass the limit (it's applied to the entire ioctl) so I made another one that just uses multiple reads. Based on the fact that it's never seeing any data it probably was never actually doing any transferring and the "image" was just junk on the stack.

DupiDachs commented 3 years ago

Crap. Gotta continue tomorrow - no more time. From what I tried just now it simply proceeds and writes out an image, but it its all zeros. I'll be back...

DupiDachs commented 3 years ago

OK! So, I do not know why the sequential read process in blocks of 0x300 fails, but I managed to get a successful reading by going back to the previous code and setting the kernel parameter spidev.bufsiz=65536! I might reduce that to a value that is actually required... I then get a very clean reading of my finger :) image Thanks again for your great work! And btw: Also the calibration is now working.

mincrmatt12 commented 3 years ago

Cool! I guess the sensor doesn't like it if you deselect it while receiving the image partway through. At some point (bit busy rn) I'll start work on adding the new routines to the libfprint driver.

DupiDachs commented 3 years ago

Just wanted to let you know that with your latest push, I could remove my manual tweaks and have it run successfully without them. I will continue taking a look at your fprint branch...