dd40aeaa79
With this script it is possible to test libfprint/fprintd without any hardware device. The image needs to be provides as a PNG with the alpha channel storing the print data. See the comment in the file on how the script can be used.
111 lines
3 KiB
Python
Executable file
111 lines
3 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
# This script can be used together with the virtual_imgdev to simulate an
|
|
# image based fingerprint reader.
|
|
#
|
|
# To use, set the FP_VIRTUAL_IMAGE environment variable for both the
|
|
# libfprint using program (e.g. fprintd) and this script.
|
|
#
|
|
# Usually this would work by adding it into the systemd unit file. The
|
|
# best way of doing so is to create
|
|
# /etc/systemd/system/fprintd.service.d/fprintd-test.conf
|
|
#
|
|
# [Service]
|
|
# RuntimeDirectory=fprint
|
|
# Environment=FP_VIRTUAL_IMAGE=/run/fprint/virtimg_sock
|
|
# Environment=G_MESSAGES_DEBUG=all
|
|
# ReadWritePaths=$RUNTIME_DIR
|
|
#
|
|
# After that run:
|
|
#
|
|
# systemctl daemon-reload
|
|
# systemctl restart fprintd.service
|
|
#
|
|
# You may also need to disable selinux.
|
|
#
|
|
# Then run this script with e.g.
|
|
# FP_VIRTUAL_IMAGE=/run/fprint/virtimg_sock ./sendvirtimg.py prints/whorl.png
|
|
|
|
|
|
|
|
import cairo
|
|
import sys
|
|
import os
|
|
import socket
|
|
import struct
|
|
|
|
if len(sys.argv) != 2:
|
|
sys.stderr.write('You need to pass a PNG with an alpha channel!\n')
|
|
sys.exit(1)
|
|
|
|
# Just copied from the C file, we could also use the introspection data for
|
|
# this. Also, most of them do *not* make any sense.
|
|
commands = {
|
|
'retry' : struct.pack('ii', -1, 0),
|
|
'retry-too-short' : struct.pack('ii', -1, 1),
|
|
'retry-center-finger' : struct.pack('ii', -1, 2),
|
|
'retry-remove-finger' : struct.pack('ii', -1, 3),
|
|
|
|
'error' : struct.pack('ii', -2, 0),
|
|
'error-not-supported' : struct.pack('ii', -2, 1),
|
|
'error-not-open' : struct.pack('ii', -2, 2),
|
|
'error-already-open' : struct.pack('ii', -2, 3),
|
|
'error-busy' : struct.pack('ii', -2, 4),
|
|
'error-proto' : struct.pack('ii', -2, 5),
|
|
'error-data-invalid' : struct.pack('ii', -2, 6),
|
|
'error-data-not-found' : struct.pack('ii', -2, 7),
|
|
'error-data-full' : struct.pack('ii', -2, 8),
|
|
}
|
|
|
|
|
|
if sys.argv[1] in commands:
|
|
command = commands[sys.argv[1]]
|
|
else:
|
|
png = cairo.ImageSurface.create_from_png(sys.argv[1])
|
|
|
|
# Cairo wants 4 byte aligned rows, so just add a few pixel if necessary
|
|
w = png.get_width()
|
|
h = png.get_height()
|
|
w = (w + 3) // 4 * 4
|
|
h = (h + 3) // 4 * 4
|
|
img = cairo.ImageSurface(cairo.Format.A8, w, h)
|
|
cr = cairo.Context(img)
|
|
|
|
cr.set_source_rgba(1, 1, 1, 1)
|
|
cr.paint()
|
|
|
|
cr.set_source_rgba(0, 0, 0, 0)
|
|
cr.set_operator(cairo.OPERATOR_SOURCE)
|
|
|
|
cr.set_source_surface(png)
|
|
cr.paint()
|
|
|
|
mem = img.get_data()
|
|
mem = mem.tobytes()
|
|
assert len(mem) == img.get_width() * img.get_height()
|
|
|
|
command = struct.pack('ii', img.get_width(), img.get_height())
|
|
command += mem
|
|
|
|
|
|
|
|
def write_dbg_img():
|
|
dbg_img_rgb = cairo.ImageSurface(cairo.Format.RGB24, img.get_width(), img.get_height())
|
|
dbg_cr = cairo.Context(dbg_img_rgb)
|
|
dbg_cr.set_source_rgb(0, 0, 0)
|
|
dbg_cr.paint()
|
|
dbg_cr.set_source_rgb(1, 1, 1)
|
|
dbg_cr.mask_surface(img, 0, 0)
|
|
|
|
dbg_img_rgb.write_to_png('/tmp/test.png')
|
|
|
|
#write_dbg_img()
|
|
|
|
# Send image through socket
|
|
sockaddr = os.environ['FP_VIRTUAL_IMAGE']
|
|
|
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
sock.connect(sockaddr)
|
|
|
|
sock.sendall(command)
|
|
|