From 6d4b498dae482a3373ff74ffbf90eb1a0170e048 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 13 Jan 2021 14:45:07 +0100 Subject: [PATCH 01/27] tests: Mark umockdev-test.py executable This makes it easier to execute it for out-of-tree tests. --- tests/umockdev-test.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tests/umockdev-test.py diff --git a/tests/umockdev-test.py b/tests/umockdev-test.py old mode 100644 new mode 100755 From 17a8bacfaffe70f6358ee89fac2e9ee5b73bfdeb Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 18 Jan 2021 14:37:53 +0100 Subject: [PATCH 02/27] usb-transfer: Remove incorrect statement from documentation The string was still written without having the _full function in mind. --- libfprint/fpi-usb-transfer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libfprint/fpi-usb-transfer.c b/libfprint/fpi-usb-transfer.c index fe491685..784aa59d 100644 --- a/libfprint/fpi-usb-transfer.c +++ b/libfprint/fpi-usb-transfer.c @@ -187,7 +187,7 @@ fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer, * fpi_usb_transfer_fill_bulk_full: * @transfer: The #FpiUsbTransfer * @endpoint: The endpoint to send the transfer to - * @buffer: The data to send. A buffer will be created and managed for you if you pass NULL. + * @buffer: The data to send. * @length: The size of @buffer * @free_func: (destroy buffer): Destroy notify for @buffer * @@ -275,7 +275,7 @@ fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer, * fpi_usb_transfer_fill_interrupt_full: * @transfer: The #FpiUsbTransfer * @endpoint: The endpoint to send the transfer to - * @buffer: The data to send. A buffer will be created and managed for you if you pass NULL. + * @buffer: The data to send. * @length: The size of @buffer * @free_func: (destroy buffer): Destroy notify for @buffer * From 349fbeb834c7b938e91e90d7329e2b502ea47124 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 18 Jan 2021 16:25:25 +0100 Subject: [PATCH 03/27] drivers: Disable reindent and disable uncrustify for large headers There are static data and take a long time to process. Also, the VFS301 fragments were really badly indented, fix that. --- libfprint/drivers/aes1660.h | 2 + libfprint/drivers/aes2660.h | 2 + libfprint/drivers/upektc.h | 2 + libfprint/drivers/vfs301_proto_fragments.h | 384 +++++++++++---------- libfprint/drivers/vfs5011_proto.h | 2 + 5 files changed, 201 insertions(+), 191 deletions(-) diff --git a/libfprint/drivers/aes1660.h b/libfprint/drivers/aes1660.h index 18e4e0c9..452582d1 100644 --- a/libfprint/drivers/aes1660.h +++ b/libfprint/drivers/aes1660.h @@ -22,6 +22,8 @@ #define AES1660_FRAME_SIZE 0x244 +/* *INDENT-OFF* */ + /* First init sequence, 0x07 cmd returns following before INIT1: * { 0x07, 0x05, 0x00, 0x8f, 0x16, 0x25, 0x01, 0x00 } */ diff --git a/libfprint/drivers/aes2660.h b/libfprint/drivers/aes2660.h index 5427c80a..485b5809 100644 --- a/libfprint/drivers/aes2660.h +++ b/libfprint/drivers/aes2660.h @@ -21,6 +21,8 @@ #define AES2660_FRAME_SIZE 0x354 +/* *INDENT-OFF* */ + /* First init sequence, 0x07 cmd returns following before INIT1: * { 0x07, 0x05, 0x00, 0x91, 0x26, 0x21, 0x00, 0x00 } */ diff --git a/libfprint/drivers/upektc.h b/libfprint/drivers/upektc.h index a1f9a231..58c4a0cc 100644 --- a/libfprint/drivers/upektc.h +++ b/libfprint/drivers/upektc.h @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* *INDENT-OFF* */ + #pragma once #define UPEKTC_CMD_LEN 0x40 diff --git a/libfprint/drivers/vfs301_proto_fragments.h b/libfprint/drivers/vfs301_proto_fragments.h index 6decbc79..9691bc8f 100644 --- a/libfprint/drivers/vfs301_proto_fragments.h +++ b/libfprint/drivers/vfs301_proto_fragments.h @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/* *INDENT-OFF* */ + /* There are many similar blocks in the data below, also the data are * self-similar (looks like some config blocks? pokes like in vfs101?) */ @@ -1621,56 +1623,56 @@ static const unsigned char vfs301_24[] = { /* 119 B */ #define vfs301_02D0_ALIGNED_BLOB \ PACKET ("0200", "8005", \ "FF830720" "5F820720" "FF830720" \ - "5F820720" "FF830720" "5F820720" "FF830720" \ - "5F820720" "FF830720" "5F820720" "FF8B0720" \ - "608A0720" "FF930720" "61920720" "FF9B0720" \ - "629A0720" "FFA30720" "63A20720" "FFAB0720" \ - "64AA0720" "FFB30720" "65B20720" "FFBB0720" \ - "66BA0720" "FFC30720" "67C20720" "FFCB0720" \ - "68CA0720" "FFD30720" "69D20720" "FFDB0720" \ - "6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \ - "6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \ - "6EFA0720" "FF850720" "6F840720" "FF8D0720" \ - "708C0720" "FF950720" "71940720" "FF9D0720" \ - "729C0720" "FFA50720" "73A40720" "FFAD0720" \ - "74AC0720" "FFB50720" "75B40720" "FFBD0720" \ - "76BC0720" "FFC50720" "77C40720" "FFCD0720" \ - "78CC0720" "FFD50720" "79D40720" "FFDD0720" \ - "7ADC0720" "FFE50720" "7BE40720" "FFED0720" \ - "7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \ - "7EFC0720" "FF870720" "7F860720" "FF8F0720" \ - "808E0720" "FF970720" "81960720" "FF9F0720" \ - "829E0720" "FFA70720" "83A60720" "FFAF0720" \ - "84AE0720" "FFB70720" "85B60720" "FFBF0720" \ - "86BE0720" "FFC70720" "87C60720" "FFCF0720" \ - "88CE0720" "FFD70720" "89D60720" "FFDF0720" \ - "8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \ - "8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \ - "8EFE0720" \ - "FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \ - "FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \ - "FFDF0720" "8ADE0720" "FFD70720" "89D60720" \ - "FFCF0720" "88CE0720" "FFC70720" "87C60720" \ - "FFBF0720" "86BE0720" "FFB70720" "85B60720" \ - "FFAF0720" "84AE0720" "FFA70720" "83A60720" \ - "FF9F0720" "829E0720" "FF970720" "81960720" \ - "FF8F0720" "808E0720" "FF870720" "7F860720" \ - "FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \ - "FFED0720" "7CEC0720" "FFE50720" "7BE40720" \ - "FFDD0720" "7ADC0720" "FFD50720" "79D40720" \ - "FFCD0720" "78CC0720" "FFC50720" "77C40720" \ - "FFBD0720" "76BC0720" "FFB50720" "75B40720" \ - "FFAD0720" "74AC0720" "FFA50720" "73A40720" \ - "FF9D0720" "729C0720" "FF950720" "71940720" \ - "FF8D0720" "708C0720" "FF850720" "6F840720" \ - "FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \ - "FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \ - "FFDB0720" "6ADA0720" "FFD30720" "69D20720" \ - "FFCB0720" "68CA0720" "FFC30720" "67C20720" \ - "FFBB0720" "66BA0720" "FFB30720" "65B20720" \ - "FFAB0720" "64AA0720" "FFA30720" "63A20720" \ - "FF9B0720" "629A0720" "FF930720" "61920720" \ - "FF8B0720" "608A0720" "FF830720" "5F820720" \ + "5F820720" "FF830720" "5F820720" "FF830720" \ + "5F820720" "FF830720" "5F820720" "FF8B0720" \ + "608A0720" "FF930720" "61920720" "FF9B0720" \ + "629A0720" "FFA30720" "63A20720" "FFAB0720" \ + "64AA0720" "FFB30720" "65B20720" "FFBB0720" \ + "66BA0720" "FFC30720" "67C20720" "FFCB0720" \ + "68CA0720" "FFD30720" "69D20720" "FFDB0720" \ + "6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \ + "6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \ + "6EFA0720" "FF850720" "6F840720" "FF8D0720" \ + "708C0720" "FF950720" "71940720" "FF9D0720" \ + "729C0720" "FFA50720" "73A40720" "FFAD0720" \ + "74AC0720" "FFB50720" "75B40720" "FFBD0720" \ + "76BC0720" "FFC50720" "77C40720" "FFCD0720" \ + "78CC0720" "FFD50720" "79D40720" "FFDD0720" \ + "7ADC0720" "FFE50720" "7BE40720" "FFED0720" \ + "7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \ + "7EFC0720" "FF870720" "7F860720" "FF8F0720" \ + "808E0720" "FF970720" "81960720" "FF9F0720" \ + "829E0720" "FFA70720" "83A60720" "FFAF0720" \ + "84AE0720" "FFB70720" "85B60720" "FFBF0720" \ + "86BE0720" "FFC70720" "87C60720" "FFCF0720" \ + "88CE0720" "FFD70720" "89D60720" "FFDF0720" \ + "8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \ + "8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \ + "8EFE0720" \ + "FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \ + "FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \ + "FFDF0720" "8ADE0720" "FFD70720" "89D60720" \ + "FFCF0720" "88CE0720" "FFC70720" "87C60720" \ + "FFBF0720" "86BE0720" "FFB70720" "85B60720" \ + "FFAF0720" "84AE0720" "FFA70720" "83A60720" \ + "FF9F0720" "829E0720" "FF970720" "81960720" \ + "FF8F0720" "808E0720" "FF870720" "7F860720" \ + "FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \ + "FFED0720" "7CEC0720" "FFE50720" "7BE40720" \ + "FFDD0720" "7ADC0720" "FFD50720" "79D40720" \ + "FFCD0720" "78CC0720" "FFC50720" "77C40720" \ + "FFBD0720" "76BC0720" "FFB50720" "75B40720" \ + "FFAD0720" "74AC0720" "FFA50720" "73A40720" \ + "FF9D0720" "729C0720" "FF950720" "71940720" \ + "FF8D0720" "708C0720" "FF850720" "6F840720" \ + "FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \ + "FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \ + "FFDB0720" "6ADA0720" "FFD30720" "69D20720" \ + "FFCB0720" "68CA0720" "FFC30720" "67C20720" \ + "FFBB0720" "66BA0720" "FFB30720" "65B20720" \ + "FFAB0720" "64AA0720" "FFA30720" "63A20720" \ + "FF9B0720" "629A0720" "FF930720" "61920720" \ + "FF8B0720" "608A0720" "FF830720" "5F820720" \ Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () \ @@ -1871,49 +1873,49 @@ const char *vfs301_0220_01[] = { "A46C0420" "A46C0400" "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" "83688420" "83688420" - "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" "83688420" "83688420" + "83688420" "83688420" Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () @@ -2268,55 +2270,55 @@ const char *vfs301_02D0_04[] = { * any troubles. */ PACKET ("0200", "8005", "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" - "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" + "FFF30720" "80F20720" "FFF30720" "80F20720" Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () @@ -2437,55 +2439,55 @@ const char *vfs301_02D0_05[] = { * any troubles. */ PACKET ("0200", "8005", "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" - "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" + "FFF34720" "80F24720" "FFF34720" "80F24720" Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () Z8 () diff --git a/libfprint/drivers/vfs5011_proto.h b/libfprint/drivers/vfs5011_proto.h index 5b2f8f41..e49cd800 100644 --- a/libfprint/drivers/vfs5011_proto.h +++ b/libfprint/drivers/vfs5011_proto.h @@ -1,5 +1,7 @@ #pragma once +/* *INDENT-OFF* */ + #define VFS5011_LINE_SIZE 240 #define VFS5011_IMAGE_WIDTH 160 From 944e0d03837daa71c9db64b457d0239aa75596bd Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 13:29:17 +0100 Subject: [PATCH 04/27] udev-rules: Print warning if an ID is supported --- libfprint/fprint-list-udev-rules.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libfprint/fprint-list-udev-rules.c b/libfprint/fprint-list-udev-rules.c index d6c884cb..5f80fe19 100644 --- a/libfprint/fprint-list-udev-rules.c +++ b/libfprint/fprint-list-udev-rules.c @@ -110,6 +110,7 @@ static const FpIdEntry blacklist_id_table[] = { static const FpDeviceClass whitelist = { .type = FP_DEVICE_TYPE_USB, .id_table = whitelist_id_table, + .id = "whitelist", .full_name = "Hardcoded whitelist" }; @@ -138,13 +139,15 @@ print_driver (const FpDeviceClass *cls) key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid); - if (g_hash_table_lookup (printed, key) != NULL) + if (cls == &whitelist && g_hash_table_lookup (printed, key) != NULL) { + g_warning ("%s implemented by driver %s", + key, (const char *) g_hash_table_lookup (printed, key)); g_free (key); continue; } - g_hash_table_insert (printed, key, GINT_TO_POINTER (1)); + g_hash_table_insert (printed, key, (void *) cls->id); if (num_printed == 0) g_print ("# %s\n", cls->full_name); From 80dbc9c0cb0825c89cdd07c5d4ceda5055cc2d8a Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 13:37:51 +0100 Subject: [PATCH 05/27] udev-rules: Remove supported synaptics devices --- libfprint/fprint-list-udev-rules.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libfprint/fprint-list-udev-rules.c b/libfprint/fprint-list-udev-rules.c index 5f80fe19..e574cac7 100644 --- a/libfprint/fprint-list-udev-rules.c +++ b/libfprint/fprint-list-udev-rules.c @@ -45,12 +45,9 @@ static const FpIdEntry whitelist_id_table[] = { { .vid = 0x06cb, .pid = 0x00b7 }, { .vid = 0x06cb, .pid = 0x00bb }, { .vid = 0x06cb, .pid = 0x00be }, - { .vid = 0x06cb, .pid = 0x00c2 }, - { .vid = 0x06cb, .pid = 0x00c9 }, { .vid = 0x06cb, .pid = 0x00cb }, { .vid = 0x06cb, .pid = 0x00d8 }, { .vid = 0x06cb, .pid = 0x00da }, - { .vid = 0x06cb, .pid = 0x00e7 }, { .vid = 0x0a5c, .pid = 0x5801 }, { .vid = 0x0a5c, .pid = 0x5805 }, { .vid = 0x0a5c, .pid = 0x5834 }, From 16095a21fd0a86a0ecc29ee4e67dfb0e25d78683 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 13:38:08 +0100 Subject: [PATCH 06/27] tests: Add check that no supported device is whitelisted --- tests/meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/meson.build b/tests/meson.build index 12a10959..f9603b89 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -168,6 +168,11 @@ foreach test_name: unit_tests ) endforeach +# Run udev rule generator with fatal warnings +test('udev-rules', + udev_rules, + env: envs) + gdb = find_program('gdb', required: false) if gdb.found() add_test_setup('gdb', From 55a2bb55361ae3f1b46c542167069e85e66b1e74 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:13:03 +0100 Subject: [PATCH 07/27] Generate a hwdb instead of udev rules We only use the rules/hwdb to enable auto-suspend. So, instead of shipping our own rules, we can just use the existing autosuspend rules and ship a hwdb that sets the appropriate flag. Closes: #336 --- ...nt-list-udev-rules.c => fprint-list-udev-hwdb.c} | 13 ++++++++----- libfprint/meson.build | 10 +++++----- meson.build | 6 +++--- meson_options.txt | 4 ++-- tests/meson.build | 4 ++-- 5 files changed, 20 insertions(+), 17 deletions(-) rename libfprint/{fprint-list-udev-rules.c => fprint-list-udev-hwdb.c} (93%) diff --git a/libfprint/fprint-list-udev-rules.c b/libfprint/fprint-list-udev-hwdb.c similarity index 93% rename from libfprint/fprint-list-udev-rules.c rename to libfprint/fprint-list-udev-hwdb.c index e574cac7..1553db4d 100644 --- a/libfprint/fprint-list-udev-rules.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -147,17 +147,20 @@ print_driver (const FpDeviceClass *cls) g_hash_table_insert (printed, key, (void *) cls->id); if (num_printed == 0) - g_print ("# %s\n", cls->full_name); + { + if (cls != &whitelist) + g_print ("\n# Supported by libfprint driver %s\n", cls->id); + else + g_print ("\n# Known unsupported devices\n"); + } - g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n", + g_print ("usb:v%04Xp%04X*\n", entry->vid, entry->pid); - g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{LIBFPRINT_DRIVER}=\"%s\"\n", - entry->vid, entry->pid, cls->full_name); num_printed++; } if (num_printed > 0) - g_print ("\n"); + g_print (" ID_AUTOSUSPEND=1\n"); } int diff --git a/libfprint/meson.build b/libfprint/meson.build index 4d1d30cc..e385ce83 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -295,19 +295,19 @@ libfprint_private_dep = declare_dependency( ] ) -udev_rules = executable('fprint-list-udev-rules', - 'fprint-list-udev-rules.c', +udev_hwdb = executable('fprint-list-udev-hwdb', + 'fprint-list-udev-hwdb.c', dependencies: libfprint_private_dep, link_with: libfprint_drivers, install: false) if get_option('udev_rules') custom_target('udev-rules', - output: '60-@0@-autosuspend.rules'.format(versioned_libname), + output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), capture: true, - command: [ udev_rules ], + command: [ udev_hwdb ], install: true, - install_dir: udev_rules_dir) + install_dir: udev_hwdb_dir) endif supported_devices = executable('fprint-list-supported-devices', diff --git a/meson.build b/meson.build index 139c571c..0d4822d3 100644 --- a/meson.build +++ b/meson.build @@ -175,11 +175,11 @@ drivers_type_func += '}' root_inc = include_directories('.') if get_option('udev_rules') - udev_rules_dir = get_option('udev_rules_dir') + udev_hwdb_dir = get_option('udev_hwdb_dir') - if udev_rules_dir == 'auto' + if udev_hwdb_dir == 'auto' udev_dep = dependency('udev') - udev_rules_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/rules.d' + udev_hwdb_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/hwdb.d' endif endif diff --git a/meson_options.txt b/meson_options.txt index 746efdc7..414695fd 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,8 +10,8 @@ option('udev_rules', description: 'Whether to create a udev rules file', type: 'boolean', value: true) -option('udev_rules_dir', - description: 'Installation path for udev rules', +option('udev_hwdb_dir', + description: 'Installation path for udev hwdb', type: 'string', value: 'auto') option('gtk-examples', diff --git a/tests/meson.build b/tests/meson.build index f9603b89..537a00a2 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -169,8 +169,8 @@ foreach test_name: unit_tests endforeach # Run udev rule generator with fatal warnings -test('udev-rules', - udev_rules, +test('udev-hwdb', + udev_hwdb, env: envs) gdb = find_program('gdb', required: false) From cbce56c14241c3f64a428ced4558e0b57fa8d18c Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:19:10 +0100 Subject: [PATCH 08/27] meson: Always build hwdb file We want systemd to pull our hwdb. In order to ease this, always build the hwdb file, even if it is disabled. Once systemd has merged the rules, downstream should turn off the rules in libfprint. The default in libfprint will also be changed to not build the hwdb (udev_rules option) eventually. --- libfprint/meson.build | 18 ++++++++++-------- meson.build | 2 ++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index e385ce83..3464bf37 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -301,14 +301,16 @@ udev_hwdb = executable('fprint-list-udev-hwdb', link_with: libfprint_drivers, install: false) -if get_option('udev_rules') - custom_target('udev-rules', - output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), - capture: true, - command: [ udev_hwdb ], - install: true, - install_dir: udev_hwdb_dir) -endif +# We always build this file; primarily so that systemd can pull it +# from the artefacts! +custom_target('udev-rules', + output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), + capture: true, + command: [ udev_hwdb ], + install: get_option('udev_rules'), + install_dir: udev_hwdb_dir, + build_by_default: true + ) supported_devices = executable('fprint-list-supported-devices', 'fprint-list-supported-devices.c', diff --git a/meson.build b/meson.build index 0d4822d3..cd0d83d2 100644 --- a/meson.build +++ b/meson.build @@ -181,6 +181,8 @@ if get_option('udev_rules') udev_dep = dependency('udev') udev_hwdb_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/hwdb.d' endif +else + udev_hwdb_dir = false endif if get_option('gtk-examples') From f6179d6cc4758276d7eeb825e1de8a1f36c87d2c Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:36:45 +0100 Subject: [PATCH 09/27] ci: Export hwdb into artefacts --- .gitlab-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3f0925b8..bf190b23 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,10 +49,13 @@ build: <<: *build_one_driver <<: *build # <<: *check_abi + after_script: + - cp _build/libfprint/60-autosuspend-libfprint-2.hwdb . artifacts: expose_as: "HTML Documentation" paths: - _build/doc/html/ + - 60-autosuspend-libfprint-2.hwdb expire_in: 1 week test: From 1f2d723485efb4a352a42a085e1dd17315971377 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 14:42:35 +0100 Subject: [PATCH 10/27] Drop version from libfprint hwdb As we are shipping a hwdb file now, we cannot have a collision with the old libfprint version. Also, we are going to pull these rules into systemd and they will not be installed via libfprint in the future. As such, collisions will not happen again and it makes more sense like this for systemd. --- .gitlab-ci.yml | 4 ++-- libfprint/meson.build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bf190b23..c416c2b0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,12 +50,12 @@ build: <<: *build # <<: *check_abi after_script: - - cp _build/libfprint/60-autosuspend-libfprint-2.hwdb . + - cp _build/libfprint/60-autosuspend-libfprint.hwdb . artifacts: expose_as: "HTML Documentation" paths: - _build/doc/html/ - - 60-autosuspend-libfprint-2.hwdb + - 60-autosuspend-libfprint.hwdb expire_in: 1 week test: diff --git a/libfprint/meson.build b/libfprint/meson.build index 3464bf37..abf2fb92 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -304,7 +304,7 @@ udev_hwdb = executable('fprint-list-udev-hwdb', # We always build this file; primarily so that systemd can pull it # from the artefacts! custom_target('udev-rules', - output: '60-autosuspend-@0@.hwdb'.format(versioned_libname), + output: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), capture: true, command: [ udev_hwdb ], install: get_option('udev_rules'), From 284f6f1ef812f9561c150ca28b06f91a44f7a09c Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 19 Jan 2021 15:55:56 +0100 Subject: [PATCH 11/27] ci: Add check that wiki and generator are in sync Add a new test that checks that the unsupported list is not out of date. As the wiki can be edited at any time, add this as a further optional check into the CI pipeline. --- .gitlab-ci.yml | 9 ++++++ tests/hwdb-check-unsupported.py | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100755 tests/hwdb-check-unsupported.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c416c2b0..4f56ec77 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -112,6 +112,15 @@ test_indent: - git diff - "! git status -s | grep -q ." +test_unsupported_list: + stage: check-source + except: + variables: + - $CI_PIPELINE_SOURCE == "schedule" + allow_failure: true + script: + - tests/hwdb-check-unsupported.py + flatpak: stage: flatpak extends: .flatpak diff --git a/tests/hwdb-check-unsupported.py b/tests/hwdb-check-unsupported.py new file mode 100755 index 00000000..650cd099 --- /dev/null +++ b/tests/hwdb-check-unsupported.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +import os +import sys +import urllib +import urllib.request +import re + +error = False + +try: + response = urllib.request.urlopen('https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md') +except: + print("Could not download current list of unsupported devices, skipping test.") + sys.exit(77) +data = response.read().decode('utf-8') + +devices = [] +devices_re = re.compile(r'^.*([0-9a-fA-F]{4}):([0-9a-fA-F]{4}).*$', re.MULTILINE) +for m in devices_re.finditer(data): + vid = m.group(1) + pid = m.group(2) + devices.append((vid, pid)) + +generator = open(os.path.join(os.path.dirname(__file__), '..', 'libfprint', 'fprint-list-udev-hwdb.c')).read() + +id_re = re.compile(' { .vid = 0x([a-fA-F0-9]*), .pid = 0x([a-fA-F0-9]*) }') +# Check everything is the same +started = False +for l in generator.split('\n'): + m = id_re.match(l) + if m is None: + # Stop on the first line that does not match anymore + if started: + break + continue + else: + started = True + + vid_pid = (m.group(1), m.group(2)) + try: + devices.remove(vid_pid) + except ValueError: + print("Generator has entry that is not on wiki: {}:{}".format(*vid_pid)) + error = True + +for vid_pid in devices: + print("New entry from wiki is missing: {}:{}".format(*vid_pid)) + error = True + +if error: + sys.exit(1) +else: + sys.exit(0) From 66fc93eeff14d273f06ea9ba9c7ee590e94d56cc Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 20 Jan 2021 18:02:31 +0100 Subject: [PATCH 12/27] udev-hwdb: Prevent devices from being listed twice The change to print a warning (for testing purposes) from commit 944e0d03837 (udev-rules: Print warning if an ID is supported) was incorrect because it prevented duplicated to be suppressed if a device is listed by two independent drivers. --- libfprint/fprint-list-udev-hwdb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index 1553db4d..b6870852 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -136,10 +136,11 @@ print_driver (const FpDeviceClass *cls) key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid); - if (cls == &whitelist && g_hash_table_lookup (printed, key) != NULL) + if (g_hash_table_lookup (printed, key) != NULL) { - g_warning ("%s implemented by driver %s", - key, (const char *) g_hash_table_lookup (printed, key)); + if (cls == &whitelist) + g_warning ("%s implemented by driver %s", + key, (const char *) g_hash_table_lookup (printed, key)); g_free (key); continue; } From 99c269b3fe3048d6d7050c9d460cd2ff04090df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 10 Dec 2020 20:22:54 +0100 Subject: [PATCH 13/27] meson: Do not support drivers known to fail in Big Endian archs When building in big endian architectures some device tests will fail, as per this we're pretty sure that most of the drivers are not ready to work in big-endian architectures. Since we're aware of this, better to just stop supporting those drivers instead of having each distribution to handle the problem. So, add a list of supported drivers that is filled depending the architecture type we're building on. Keep continue building those drivers since we want to at least test-build them, but do not expose them as libfprint drivers, so if a device in the system uses any of them will be ignored. At the same time, we keep track of the problem, so that we can fix the drivers. Related to #236 --- meson.build | 20 +++++++++++++++++++- tests/meson.build | 3 ++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index cd0d83d2..ec5d9a6f 100644 --- a/meson.build +++ b/meson.build @@ -89,6 +89,7 @@ cairo_dep = dependency('cairo', required: false) # Drivers drivers = get_option('drivers').split(',') virtual_drivers = [ 'virtual_image' ] + default_drivers = [ 'upektc_img', 'vfs5011', @@ -113,6 +114,13 @@ default_drivers = [ 'goodixmoc', ] +# FIXME: All the drivers should be fixed by adjusting the byte order. +# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236 +endian_independent_drivers = virtual_drivers + [ + 'aes3500', + 'synaptics', +] + all_drivers = default_drivers + virtual_drivers if drivers == [ 'all' ] @@ -150,6 +158,16 @@ foreach driver: drivers endif endforeach +supported_drivers = [] +foreach driver: drivers + if build_machine.endian() == 'little' or driver in endian_independent_drivers + supported_drivers += driver + else + warning('Driver @0@ is not supported by big endian cpu @1@. Please, fix it!'.format( + driver, build_machine.cpu())) + endif +endforeach + # Export the drivers' types to the core code drivers_type_list = [] drivers_type_func = [] @@ -162,7 +180,7 @@ drivers_type_func += '{' drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));' drivers_type_func += ' GType t;' drivers_type_func += '' -foreach driver: drivers +foreach driver: supported_drivers drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);' drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();' drivers_type_func += ' g_array_append_val (drivers, t);' diff --git a/tests/meson.build b/tests/meson.build index 537a00a2..4ebf3b70 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -70,7 +70,8 @@ if get_option('introspection') driver_envs = envs driver_envs.set('FP_DRIVERS_WHITELIST', driver_test) - if driver_test in drivers and gusb_dep.version().version_compare('>= 0.3.0') + if (driver_test in supported_drivers and + gusb_dep.version().version_compare('>= 0.3.0')) test(driver_test, find_program('umockdev-test.py'), args: join_paths(meson.current_source_dir(), driver_test), From 533180a2e639148d2e6657f7ecbfab7c0025da63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 20 Jan 2021 20:02:05 +0100 Subject: [PATCH 14/27] data: Use auto-generated but hardcoded autosuspend hwdb file This solves various problems: 1. It stays the same also if some drivers have been disabled 2. It uses a stable path for being imported by systemd 3. It is still checked for its validity by tests 4. It can be auto-generated using a simple command --- .gitlab-ci.yml | 3 - data/autosuspend.hwdb | 262 ++++++++++++++++++++++++++++++ data/meson.build | 9 + libfprint/fprint-list-udev-hwdb.c | 5 + libfprint/meson.build | 24 ++- meson.build | 12 ++ tests/meson.build | 5 +- tests/test-generated-hwdb.sh | 24 +++ 8 files changed, 332 insertions(+), 12 deletions(-) create mode 100644 data/autosuspend.hwdb create mode 100644 data/meson.build create mode 100755 tests/test-generated-hwdb.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4f56ec77..e6f736cd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,13 +49,10 @@ build: <<: *build_one_driver <<: *build # <<: *check_abi - after_script: - - cp _build/libfprint/60-autosuspend-libfprint.hwdb . artifacts: expose_as: "HTML Documentation" paths: - _build/doc/html/ - - 60-autosuspend-libfprint.hwdb expire_in: 1 week test: diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb new file mode 100644 index 00000000..f22d16a2 --- /dev/null +++ b/data/autosuspend.hwdb @@ -0,0 +1,262 @@ +# This file has been generated using fprint-list-udev-hwdb with all drivers enabled + +# Supported by libfprint driver upektc_img +usb:v147Ep2016* +usb:v147Ep2020* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs5011 +usb:v138Ap0010* +usb:v138Ap0011* +usb:v138Ap0015* +usb:v138Ap0017* +usb:v138Ap0018* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes3500 +usb:v08FFp5731* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes4000 +usb:v5501p08FF* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes1610 +usb:v08FFp1600* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes1660 +usb:v08FFp1660* +usb:v08FFp1680* +usb:v08FFp1681* +usb:v08FFp1682* +usb:v08FFp1683* +usb:v08FFp1684* +usb:v08FFp1685* +usb:v08FFp1686* +usb:v08FFp1687* +usb:v08FFp1688* +usb:v08FFp1689* +usb:v08FFp168A* +usb:v08FFp168B* +usb:v08FFp168C* +usb:v08FFp168D* +usb:v08FFp168E* +usb:v08FFp168F* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2660 +usb:v08FFp2660* +usb:v08FFp2680* +usb:v08FFp2681* +usb:v08FFp2682* +usb:v08FFp2683* +usb:v08FFp2684* +usb:v08FFp2685* +usb:v08FFp2686* +usb:v08FFp2687* +usb:v08FFp2688* +usb:v08FFp2689* +usb:v08FFp268A* +usb:v08FFp268B* +usb:v08FFp268C* +usb:v08FFp268D* +usb:v08FFp268E* +usb:v08FFp268F* +usb:v08FFp2691* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2501 +usb:v08FFp2500* +usb:v08FFp2580* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2550 +usb:v08FFp2550* +usb:v08FFp2810* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs101 +usb:v138Ap0001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs301 +usb:v138Ap0005* +usb:v138Ap0008* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs0050 +usb:v138Ap0050* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver etes603 +usb:v1C7Ap0603* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vcom5s +usb:v061Ap0110* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver synaptics +usb:v06CBp00BD* +usb:v06CBp00E9* +usb:v06CBp00DF* +usb:v06CBp00F9* +usb:v06CBp00FC* +usb:v06CBp00C2* +usb:v06CBp00C9* +usb:v06CBp00E7* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver elan +usb:v04F3p0903* +usb:v04F3p0907* +usb:v04F3p0C01* +usb:v04F3p0C02* +usb:v04F3p0C03* +usb:v04F3p0C04* +usb:v04F3p0C05* +usb:v04F3p0C06* +usb:v04F3p0C07* +usb:v04F3p0C08* +usb:v04F3p0C09* +usb:v04F3p0C0A* +usb:v04F3p0C0B* +usb:v04F3p0C0C* +usb:v04F3p0C0D* +usb:v04F3p0C0E* +usb:v04F3p0C0F* +usb:v04F3p0C10* +usb:v04F3p0C11* +usb:v04F3p0C12* +usb:v04F3p0C13* +usb:v04F3p0C14* +usb:v04F3p0C15* +usb:v04F3p0C16* +usb:v04F3p0C17* +usb:v04F3p0C18* +usb:v04F3p0C19* +usb:v04F3p0C1A* +usb:v04F3p0C1B* +usb:v04F3p0C1C* +usb:v04F3p0C1D* +usb:v04F3p0C1E* +usb:v04F3p0C1F* +usb:v04F3p0C20* +usb:v04F3p0C21* +usb:v04F3p0C22* +usb:v04F3p0C23* +usb:v04F3p0C24* +usb:v04F3p0C25* +usb:v04F3p0C26* +usb:v04F3p0C27* +usb:v04F3p0C28* +usb:v04F3p0C29* +usb:v04F3p0C2A* +usb:v04F3p0C2B* +usb:v04F3p0C2C* +usb:v04F3p0C2D* +usb:v04F3p0C2E* +usb:v04F3p0C2F* +usb:v04F3p0C30* +usb:v04F3p0C31* +usb:v04F3p0C32* +usb:v04F3p0C33* +usb:v04F3p0C42* +usb:v04F3p0C4D* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver uru4000 +usb:v045Ep00BC* +usb:v045Ep00BD* +usb:v045Ep00CA* +usb:v05BAp0007* +usb:v05BAp0008* +usb:v05BAp000A* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upektc +usb:v0483p2015* +usb:v147Ep3001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upeksonly +usb:v147Ep1000* +usb:v147Ep1001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver goodixmoc +usb:v27C6p5840* +usb:v27C6p6496* +usb:v27C6p60A2* +usb:v27C6p63AC* +usb:v27C6p639C* + ID_AUTOSUSPEND=1 + +# Known unsupported devices +usb:v04F3p036B* +usb:v04F3p0C00* +usb:v04F3p0C4B* +usb:v04F3p0C4C* +usb:v04F3p0C4F* +usb:v04F3p0C57* +usb:v04F3p2706* +usb:v06CBp0081* +usb:v06CBp0088* +usb:v06CBp008A* +usb:v06CBp009A* +usb:v06CBp009B* +usb:v06CBp00A2* +usb:v06CBp00B7* +usb:v06CBp00BB* +usb:v06CBp00BE* +usb:v06CBp00CB* +usb:v06CBp00D8* +usb:v06CBp00DA* +usb:v0A5Cp5801* +usb:v0A5Cp5805* +usb:v0A5Cp5834* +usb:v0A5Cp5843* +usb:v10A5p0007* +usb:v1188p9545* +usb:v138Ap0007* +usb:v138Ap003A* +usb:v138Ap003C* +usb:v138Ap003D* +usb:v138Ap003F* +usb:v138Ap0090* +usb:v138Ap0091* +usb:v138Ap0092* +usb:v138Ap0094* +usb:v138Ap0097* +usb:v138Ap009D* +usb:v138Ap00AB* +usb:v147Ep1002* +usb:v1491p0088* +usb:v16D1p1027* +usb:v1C7Ap0300* +usb:v1C7Ap0570* +usb:v1C7Ap0575* +usb:v27C6p5042* +usb:v27C6p5110* +usb:v27C6p5117* +usb:v27C6p5201* +usb:v27C6p521D* +usb:v27C6p5301* +usb:v27C6p530C* +usb:v27C6p532D* +usb:v27C6p533C* +usb:v27C6p5381* +usb:v27C6p5385* +usb:v27C6p538C* +usb:v27C6p538D* +usb:v27C6p5395* +usb:v27C6p5584* +usb:v27C6p55A2* +usb:v27C6p55A4* +usb:v27C6p55B4* +usb:v27C6p5740* +usb:v2808p9338* +usb:v298Dp2033* +usb:v3538p0930* + ID_AUTOSUSPEND=1 diff --git a/data/meson.build b/data/meson.build new file mode 100644 index 00000000..975c1c3f --- /dev/null +++ b/data/meson.build @@ -0,0 +1,9 @@ +if get_option('udev_rules') + # This file has to be updated using + # ninja -C libfprint/sync-udev-hwdb + + install_data('autosuspend.hwdb', + rename: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), + install_dir: udev_hwdb_dir, + ) +endif diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index b6870852..630be0f7 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -168,8 +168,13 @@ int main (int argc, char **argv) { g_autoptr(GArray) drivers = fpi_get_driver_types (); + g_autofree char *program_name = NULL; guint i; + program_name = g_path_get_basename (argv[0]); + g_print ("# This file has been generated using %s with all drivers enabled\n", + program_name); + printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (i = 0; i < drivers->len; i++) diff --git a/libfprint/meson.build b/libfprint/meson.build index abf2fb92..110c4582 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -301,16 +301,24 @@ udev_hwdb = executable('fprint-list-udev-hwdb', link_with: libfprint_drivers, install: false) -# We always build this file; primarily so that systemd can pull it -# from the artefacts! -custom_target('udev-rules', - output: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), +udev_hwdb_generator = custom_target('udev-hwdb', + output: 'autosuspend.hwdb', + depend_files: drivers_sources, capture: true, command: [ udev_hwdb ], - install: get_option('udev_rules'), - install_dir: udev_hwdb_dir, - build_by_default: true - ) + install: false, +) + +custom_target('sync-udev-hwdb', + depends: udev_hwdb_generator, + output: 'sync-udev-hwdb', + install: false, + command: [ + 'cp', '-v', + udev_hwdb_generator.full_path(), + meson.source_root() / 'data' + ] +) supported_devices = executable('fprint-list-supported-devices', 'fprint-list-supported-devices.c', diff --git a/meson.build b/meson.build index ec5d9a6f..8dc852aa 100644 --- a/meson.build +++ b/meson.build @@ -135,6 +135,18 @@ if drivers.length() == 0 or drivers[0] == '' error('Cannot build libfprint without drivers, please specify a valid value for the drivers option') endif +if drivers == all_drivers or drivers == default_drivers + default_drivers_are_enabled = true +else + default_drivers_are_enabled = true + foreach driver: default_drivers + if driver not in drivers + default_drivers_are_enabled = false + break + endif + endforeach +endif + nss_dep = dependency('', required: false) imaging_dep = dependency('', required: false) libfprint_conf.set10('HAVE_PIXMAN', false) diff --git a/tests/meson.build b/tests/meson.build index 4ebf3b70..8e24980b 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -5,6 +5,7 @@ envs.set('G_MESSAGES_DEBUG', 'all') # Setup paths envs.set('MESON_SOURCE_ROOT', meson.source_root()) +envs.set('MESON_BUILD_ROOT', meson.build_root()) envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint')) # Set FP_DEVICE_EMULATION so that drivers can adapt (e.g. to use fixed @@ -170,8 +171,10 @@ foreach test_name: unit_tests endforeach # Run udev rule generator with fatal warnings +envs.set('UDEV_HWDB', udev_hwdb.full_path()) +envs.set('UDEV_HWDB_CHECK_CONTENTS', default_drivers_are_enabled ? '1' : '0') test('udev-hwdb', - udev_hwdb, + find_program('test-generated-hwdb.sh'), env: envs) gdb = find_program('gdb', required: false) diff --git a/tests/test-generated-hwdb.sh b/tests/test-generated-hwdb.sh new file mode 100755 index 00000000..34209cb5 --- /dev/null +++ b/tests/test-generated-hwdb.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -e + +[ -x "$UDEV_HWDB" ] || exit 1 + +if [ "$UDEV_HWDB_CHECK_CONTENTS" == 1 ]; then + generated_rules=$(mktemp "${TMPDIR:-/tmp}/libfprint-XXXXXX.hwdb") +else + generated_rules=/dev/null +fi + +$UDEV_HWDB > "$generated_rules" + +if [ "$UDEV_HWDB_CHECK_CONTENTS" != 1 ]; then + exit 77 +fi + +if ! cmp "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then + echo "E: Autosuspend file needs to be re-generated!" + echo " ninja -C $MESON_BUILD_ROOT libfprint/sync-udev-hwdb" + exit 1 +fi + +rm "$generated_rules" From 2f2da87240eb3d65ff7a0d11b29029a3d084115d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 20 Jan 2021 22:02:10 +0100 Subject: [PATCH 15/27] list-udev-hwdb: Add SPDX license to the generated file And update it... --- data/autosuspend.hwdb | 1 + libfprint/fprint-list-udev-hwdb.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb index f22d16a2..7a78068c 100644 --- a/data/autosuspend.hwdb +++ b/data/autosuspend.hwdb @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later # This file has been generated using fprint-list-udev-hwdb with all drivers enabled # Supported by libfprint driver upektc_img diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index 630be0f7..6f533fb6 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -172,6 +172,8 @@ main (int argc, char **argv) guint i; program_name = g_path_get_basename (argv[0]); + + g_print ("# SPDX-License-Identifier: LGPL-2.1-or-later\n"); g_print ("# This file has been generated using %s with all drivers enabled\n", program_name); From 5df14206d8f93ba45044daac463bc1500a2b0065 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 15:57:21 +0100 Subject: [PATCH 16/27] tests: Add support for creating other virtual readers Add support for creating more virtual readers. Co-authored-by: Bastien Nocera --- tests/test-fp-context.c | 14 +++++++------- tests/test-fp-device.c | 30 +++++++++++++++--------------- tests/test-utils.c | 38 +++++++++++++++++++++++++++++--------- tests/test-utils.h | 9 +++++++-- 4 files changed, 58 insertions(+), 33 deletions(-) diff --git a/tests/test-fp-context.c b/tests/test-fp-context.c index 156e6d47..c74548cd 100644 --- a/tests/test-fp-context.c +++ b/tests/test-fp-context.c @@ -50,7 +50,7 @@ test_context_has_virtual_device (void) GPtrArray *devices; unsigned int i; - fpt_setup_virtual_device_environment (); + fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE); context = fp_context_new (); devices = fp_context_get_devices (context); @@ -82,7 +82,7 @@ test_context_enumerates_new_devices (void) context = fp_context_new (); - fpt_setup_virtual_device_environment (); + fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE); fp_context_enumerate (context); devices = fp_context_get_devices (context); @@ -120,7 +120,7 @@ context_device_removed_cb (FpContext *ctx, FpDevice *device, FptContext *tctx) static void test_context_remove_device_closed (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); gboolean removed; tctx->user_data = NULL; @@ -162,7 +162,7 @@ close_done_cb (GObject *device, GAsyncResult *res, gpointer user_data) static void test_context_remove_device_closing (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) close_error = NULL; g_autoptr(GError) error = NULL; gboolean removed; @@ -207,7 +207,7 @@ test_context_remove_device_closing (void) static void test_context_remove_device_open (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) error = NULL; gboolean removed = FALSE; @@ -267,7 +267,7 @@ open_done_cb (GObject *device, GAsyncResult *res, gpointer user_data) static void test_context_remove_device_opening (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) close_error = NULL; gboolean open_done = FALSE; gboolean removed; @@ -327,7 +327,7 @@ enroll_done_cb (GObject *device, GAsyncResult *res, gpointer user_data) static void test_context_remove_device_active (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) error = NULL; g_autoptr(GCancellable) cancellable = NULL; g_autoptr(GError) enroll_error = NULL; diff --git a/tests/test-fp-device.c b/tests/test-fp-device.c index e3eb662e..b8f6f172 100644 --- a/tests/test-fp-device.c +++ b/tests/test-fp-device.c @@ -36,7 +36,7 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, FptContext *tctx) static void test_device_open_async (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx); @@ -59,7 +59,7 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, FptContext *tctx) static void test_device_close_async (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx); while (!tctx->user_data) @@ -76,7 +76,7 @@ static void test_device_open_sync (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, &error); g_assert_no_error (error); @@ -97,7 +97,7 @@ static void test_device_open_sync_notify (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_open_notify), tctx); fp_device_open_sync (tctx->device, NULL, &error); @@ -109,7 +109,7 @@ static void test_device_close_sync (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); fp_device_close_sync (tctx->device, NULL, &error); @@ -131,7 +131,7 @@ static void test_device_close_sync_notify (void) { g_autoptr(GError) error = NULL; - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); @@ -144,7 +144,7 @@ test_device_close_sync_notify (void) static void test_device_get_driver (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image"); @@ -153,7 +153,7 @@ test_device_get_driver (void) static void test_device_get_device_id (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0"); @@ -162,7 +162,7 @@ test_device_get_device_id (void) static void test_device_get_name (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpstr (fp_device_get_name (tctx->device), ==, @@ -172,7 +172,7 @@ test_device_get_name (void) static void test_device_get_scan_type (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE); @@ -181,7 +181,7 @@ test_device_get_scan_type (void) static void test_device_get_finger_status (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpint (fp_device_get_finger_status (tctx->device), ==, FP_FINGER_STATUS_NONE); @@ -190,7 +190,7 @@ test_device_get_finger_status (void) static void test_device_get_nr_enroll_stages (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_cmpuint (fp_device_get_nr_enroll_stages (tctx->device), ==, 5); @@ -199,7 +199,7 @@ test_device_get_nr_enroll_stages (void) static void test_device_supports_identify (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_true (fp_device_supports_identify (tctx->device)); @@ -208,7 +208,7 @@ test_device_supports_identify (void) static void test_device_supports_capture (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_true (fp_device_supports_capture (tctx->device)); @@ -217,7 +217,7 @@ test_device_supports_capture (void) static void test_device_has_storage (void) { - g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev (); + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); fp_device_open_sync (tctx->device, NULL, NULL); g_assert_false (fp_device_has_storage (tctx->device)); diff --git a/tests/test-utils.c b/tests/test-utils.c index 834a90e8..1c1be17f 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -22,16 +22,29 @@ #include "test-utils.h" +struct +{ + const char *envvar; + const char *driver_id; + const char *device_id; +} devtype_vars[FPT_NUM_VIRTUAL_DEVICE_TYPES] = { + { "FP_VIRTUAL_IMAGE", "virtual_image", "virtual_image" }, /* FPT_VIRTUAL_DEVICE_IMAGE */ +}; + +static FptVirtualDeviceType global_devtype; + void fpt_teardown_virtual_device_environment (void) { - const char *path = g_getenv ("FP_VIRTUAL_IMAGE"); + const char *path; + + path = g_getenv (devtype_vars[global_devtype].envvar); if (path) { g_autofree char *temp_dir = g_path_get_dirname (path); - g_unsetenv ("FP_VIRTUAL_IMAGE"); + g_unsetenv (devtype_vars[global_devtype].envvar); g_unlink (path); g_rmdir (temp_dir); } @@ -44,19 +57,23 @@ on_signal_event (int sig) } void -fpt_setup_virtual_device_environment (void) +fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype) { g_autoptr(GError) error = NULL; g_autofree char *temp_dir = NULL; g_autofree char *temp_path = NULL; + g_autofree char *filename = NULL; - g_assert_null (g_getenv ("FP_VIRTUAL_IMAGE")); + g_assert_null (g_getenv (devtype_vars[devtype].envvar)); temp_dir = g_dir_make_tmp ("libfprint-XXXXXX", &error); g_assert_no_error (error); - temp_path = g_build_filename (temp_dir, "virtual-image.socket", NULL); - g_setenv ("FP_VIRTUAL_IMAGE", temp_path, TRUE); + filename = g_strdup_printf ("%s.socket", devtype_vars[devtype].device_id); + temp_path = g_build_filename (temp_dir, filename, NULL); + g_setenv (devtype_vars[devtype].envvar, temp_path, TRUE); + + global_devtype = devtype; signal (SIGKILL, on_signal_event); signal (SIGABRT, on_signal_event); @@ -78,13 +95,16 @@ fpt_context_new (void) } FptContext * -fpt_context_new_with_virtual_imgdev (void) +fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype) { FptContext *tctx; GPtrArray *devices; unsigned int i; - fpt_setup_virtual_device_environment (); + g_assert_true (devtype >= FPT_VIRTUAL_DEVICE_IMAGE && + devtype < FPT_NUM_VIRTUAL_DEVICE_TYPES); + + fpt_setup_virtual_device_environment (devtype); tctx = fpt_context_new (); devices = fp_context_get_devices (tctx->fp_context); @@ -96,7 +116,7 @@ fpt_context_new_with_virtual_imgdev (void) { FpDevice *device = devices->pdata[i]; - if (g_strcmp0 (fp_device_get_driver (device), "virtual_image") == 0) + if (g_strcmp0 (fp_device_get_driver (device), devtype_vars[devtype].driver_id) == 0) { tctx->device = device; break; diff --git a/tests/test-utils.h b/tests/test-utils.h index 4bc1e699..e4e4c30e 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -19,7 +19,12 @@ #include -void fpt_setup_virtual_device_environment (void); +typedef enum { + FPT_VIRTUAL_DEVICE_IMAGE = 0, + FPT_NUM_VIRTUAL_DEVICE_TYPES +} FptVirtualDeviceType; + +void fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype); void fpt_teardown_virtual_device_environment (void); typedef struct _FptContext @@ -30,7 +35,7 @@ typedef struct _FptContext } FptContext; FptContext * fpt_context_new (void); -FptContext * fpt_context_new_with_virtual_imgdev (void); +FptContext * fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype); void fpt_context_free (FptContext *test_context); From 253750ec0864af7831c72120a8efe1263bc0393d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 15:54:12 +0100 Subject: [PATCH 17/27] virtual-device-listener: Add a device socket handler class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of repeating the same code in both the virtual-image and the virtual-device drivers, implement a class to handle the socket listening an data reading. Co-authored-by: Marco Trevisan (Treviño) --- libfprint/drivers/virtual-device-listener.c | 355 ++++++++++++++++++++ libfprint/drivers/virtual-device-private.h | 93 +++++ libfprint/drivers/virtual-image.c | 260 ++++---------- libfprint/meson.build | 3 + 4 files changed, 524 insertions(+), 187 deletions(-) create mode 100644 libfprint/drivers/virtual-device-listener.c create mode 100644 libfprint/drivers/virtual-device-private.h diff --git a/libfprint/drivers/virtual-device-listener.c b/libfprint/drivers/virtual-device-listener.c new file mode 100644 index 00000000..50fe95fa --- /dev/null +++ b/libfprint/drivers/virtual-device-listener.c @@ -0,0 +1,355 @@ +/* + * Socket utilities for "simple" device debugging + * + * Copyright (C) 2019 Benjamin Berg + * Copyright (C) 2020 Marco Trevisan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define FP_COMPONENT "virtual_device_connection" + +#include "fpi-log.h" + +#include +#include + +#include "virtual-device-private.h" + +struct _FpDeviceVirtualListener +{ + GSocketListener parent_instance; + + GSocketConnection *connection; + GCancellable *cancellable; + guint cancellable_id; + + FpDeviceVirtualListenerConnectionCb ready_cb; + gpointer ready_cb_data; + + gint socket_fd; + gint client_fd; +}; + +G_DEFINE_TYPE (FpDeviceVirtualListener, fp_device_virtual_listener, G_TYPE_SOCKET_LISTENER) + +static void start_listen (FpDeviceVirtualListener *self); + +FpDeviceVirtualListener * +fp_device_virtual_listener_new (void) +{ + return g_object_new (fp_device_virtual_listener_get_type (), NULL); +} + +static void +fp_device_virtual_listener_dispose (GObject *object) +{ + FpDeviceVirtualListener *self = FP_DEVICE_VIRTUAL_LISTENER (object); + + if (self->cancellable_id) + { + g_cancellable_disconnect (self->cancellable, self->cancellable_id); + self->cancellable_id = 0; + } + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + g_clear_object (&self->connection); + + self->ready_cb = NULL; + + G_OBJECT_CLASS (fp_device_virtual_listener_parent_class)->dispose (object); +} + +static void +fp_device_virtual_listener_class_init (FpDeviceVirtualListenerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = fp_device_virtual_listener_dispose; +} + +static void +fp_device_virtual_listener_init (FpDeviceVirtualListener *self) +{ +} + +static void +new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + g_autoptr(GError) error = NULL; + FpDeviceVirtualListener *self = user_data; + GSocketConnection *connection; + + connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object), + res, + NULL, + &error); + if (!connection) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_warning ("Error accepting a new connection: %s", error->message); + start_listen (self); + return; + } + + /* Always allow further connections. + * If we get a new one, we generally just close the old connection. */ + start_listen (self); + if (self->connection) + { + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + g_clear_object (&self->connection); + } + + self->connection = connection; + fp_dbg ("Got a new connection!"); + + self->ready_cb (self, self->ready_cb_data); +} + +static void +start_listen (FpDeviceVirtualListener *self) +{ + g_socket_listener_accept_async (G_SOCKET_LISTENER (self), + self->cancellable, + new_connection_cb, + self); +} + +static void +on_cancelled (GCancellable *cancellable, + FpDeviceVirtualListener *self) +{ + fp_device_virtual_listener_connection_close (self); + g_socket_listener_close (G_SOCKET_LISTENER (self)); + g_clear_object (&self->cancellable); + self->ready_cb = NULL; +} + +gboolean +fp_device_virtual_listener_start (FpDeviceVirtualListener *self, + const char *address, + GCancellable *cancellable, + FpDeviceVirtualListenerConnectionCb cb, + gpointer user_data, + GError **error) +{ + g_autoptr(GSocketAddress) addr = NULL; + G_DEBUG_HERE (); + + g_return_val_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE); + g_return_val_if_fail (cb != NULL, FALSE); + g_return_val_if_fail (self->ready_cb == NULL, FALSE); + + self->client_fd = -1; + + g_socket_listener_set_backlog (G_SOCKET_LISTENER (self), 1); + + /* Remove any left over socket. */ + g_unlink (address); + + addr = g_unix_socket_address_new (address); + + if (!g_socket_listener_add_address (G_SOCKET_LISTENER (self), + addr, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + NULL, + NULL, + error)) + { + g_warning ("Could not listen on unix socket: %s", (*error)->message); + return FALSE; + } + + self->ready_cb = cb; + self->ready_cb_data = user_data; + self->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + + if (self->cancellable) + self->cancellable_id = g_cancellable_connect (self->cancellable, + G_CALLBACK (on_cancelled), self, NULL); + + start_listen (self); + + return TRUE; +} + +gboolean +fp_device_virtual_listener_connection_close (FpDeviceVirtualListener *self) +{ + g_return_val_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE); + + if (!self->connection) + return FALSE; + + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + g_clear_object (&self->connection); + + return TRUE; +} + +static void +on_stream_read_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + g_autoptr(GTask) task = user_data; + FpDeviceVirtualListener *self = g_task_get_source_object (task); + gboolean all; + gboolean success; + gsize bytes; + + all = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (task), "all")); + + if (all) + { + success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error); + } + else + { + gssize sbytes; + + sbytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); + bytes = sbytes; + success = (sbytes >= 0); + } + + if (g_task_return_error_if_cancelled (task)) + return; + + /* If we are cancelled, just return immediately. */ + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)) + { + g_task_return_int (task, 0); + return; + } + + /* If this error is for an old connection (that should be closed already), + * then just give up immediately with a CLOSED error. + */ + if (self->connection && + g_io_stream_get_input_stream (G_IO_STREAM (self->connection)) != G_INPUT_STREAM (source_object)) + { + g_task_return_new_error (task, + G_IO_ERROR, + G_IO_ERROR_CLOSED, + "Error on old connection, ignoring."); + return; + } + + if (!success || bytes == 0) + { + /* We accept it if someone tries to read twice and just return that error. */ + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) + { + if (self->connection) + { + g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); + g_clear_object (&self->connection); + } + } + + if (error) + { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + else + { + // g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got empty data"); + return; + } + } + + g_task_return_int (task, bytes); +} + +void +fp_device_virtual_listener_read (FpDeviceVirtualListener *self, + gboolean all, + void *buffer, + gsize count, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + GInputStream *stream; + + g_return_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self)); + + task = g_task_new (self, self->cancellable, callback, user_data); + g_object_set_data (G_OBJECT (task), "all", GINT_TO_POINTER (all)); + + if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection))) + { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED, + "Listener not connected to any stream"); + return; + } + + stream = g_io_stream_get_input_stream (G_IO_STREAM (self->connection)); + if (all) + { + g_input_stream_read_all_async (stream, buffer, count, + G_PRIORITY_DEFAULT, + self->cancellable, + on_stream_read_cb, + g_steal_pointer (&task)); + } + else + { + g_input_stream_read_async (stream, buffer, count, + G_PRIORITY_DEFAULT, + self->cancellable, + on_stream_read_cb, + g_steal_pointer (&task)); + } +} + +gsize +fp_device_virtual_listener_read_finish (FpDeviceVirtualListener *self, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, self), 0); + + return g_task_propagate_int (G_TASK (result), error); +} + +gboolean +fp_device_virtual_listener_write_sync (FpDeviceVirtualListener *self, + const char *buffer, + gsize count, + GError **error) +{ + if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection))) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED, + "Listener not connected to any stream"); + return FALSE; + } + + return g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (self->connection)), + buffer, + count, + NULL, + self->cancellable, + error); +} diff --git a/libfprint/drivers/virtual-device-private.h b/libfprint/drivers/virtual-device-private.h new file mode 100644 index 00000000..6049d66b --- /dev/null +++ b/libfprint/drivers/virtual-device-private.h @@ -0,0 +1,93 @@ +/* + * Virtual driver for "simple" device debugging + * + * Copyright (C) 2019 Benjamin Berg + * Copyright (C) 2020 Bastien Nocera + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This is a virtual driver to debug the non-image based drivers. A small + * python script is provided to connect to it via a socket, allowing + * prints to registered programmatically. + * Using this, it is possible to test libfprint and fprintd. + */ + +#include + +#include "fpi-device.h" + +#define MAX_LINE_LEN 1024 + +G_DECLARE_FINAL_TYPE (FpDeviceVirtualListener, fp_device_virtual_listener, FP, DEVICE_VIRTUAL_LISTENER, GSocketListener) + +typedef void (*FpDeviceVirtualListenerConnectionCb) (FpDeviceVirtualListener *listener, + gpointer user_data); + +FpDeviceVirtualListener * fp_device_virtual_listener_new (void); + +gboolean fp_device_virtual_listener_start (FpDeviceVirtualListener *listener, + const char *address, + GCancellable *cancellable, + FpDeviceVirtualListenerConnectionCb cb, + gpointer user_data, + GError **error); + +gboolean fp_device_virtual_listener_connection_close (FpDeviceVirtualListener *listener); + +void fp_device_virtual_listener_read (FpDeviceVirtualListener *listener, + gboolean all, + void *buffer, + gsize count, + GAsyncReadyCallback callback, + gpointer user_data); +gsize fp_device_virtual_listener_read_finish (FpDeviceVirtualListener *listener, + GAsyncResult *result, + GError **error); + +gboolean fp_device_virtual_listener_write_sync (FpDeviceVirtualListener *self, + const char *buffer, + gsize count, + GError **error); + + +struct _FpDeviceVirtualDevice +{ + FpDevice parent; + + FpDeviceVirtualListener *listener; + GCancellable *cancellable; + + char recv_buf[MAX_LINE_LEN]; + + GPtrArray *pending_commands; + + GHashTable *prints_storage; +}; + +/* Not really final here, but we can do this to share the FpDeviceVirtualDevice + * contents without having to use a shared private struct instead. */ +G_DECLARE_FINAL_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP, DEVICE_VIRTUAL_DEVICE, FpDevice) + +struct _FpDeviceVirtualDeviceStorage +{ + FpDeviceVirtualDevice parent; +}; + +G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, FP, DEVICE_VIRTUAL_DEVICE_STORAGE, FpDeviceVirtualDevice) + + +char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error); diff --git a/libfprint/drivers/virtual-image.c b/libfprint/drivers/virtual-image.c index d4c7cc54..6b0043fe 100644 --- a/libfprint/drivers/virtual-image.c +++ b/libfprint/drivers/virtual-image.c @@ -29,36 +29,27 @@ #include "fpi-log.h" +#include "virtual-device-private.h" + #include "../fpi-image.h" #include "../fpi-image-device.h" -#include -#include -#include - struct _FpDeviceVirtualImage { - FpImageDevice parent; + FpImageDevice parent; - GSocketListener *listener; - GSocketConnection *connection; - GCancellable *listen_cancellable; - GCancellable *cancellable; + FpDeviceVirtualListener *listener; + GCancellable *cancellable; - gint socket_fd; - gint client_fd; - - gboolean automatic_finger; - FpImage *recv_img; - gint recv_img_hdr[2]; + gboolean automatic_finger; + FpImage *recv_img; + gint recv_img_hdr[2]; }; G_DECLARE_FINAL_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FPI, DEVICE_VIRTUAL_IMAGE, FpImageDevice) G_DEFINE_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FP_TYPE_IMAGE_DEVICE) -static void start_listen (FpDeviceVirtualImage *dev); -static void recv_image (FpDeviceVirtualImage *dev, - GInputStream *stream); +static void recv_image (FpDeviceVirtualImage *self); static void recv_image_img_recv_cb (GObject *source_object, @@ -66,35 +57,20 @@ recv_image_img_recv_cb (GObject *source_object, gpointer user_data) { g_autoptr(GError) error = NULL; + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object); FpDeviceVirtualImage *self; FpImageDevice *device; - gboolean success; - gsize bytes = 0; + gsize bytes; - success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error); + bytes = fp_device_virtual_listener_read_finish (listener, res, &error); - /* Can't use self if the operation was cancelled. */ - if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + if (!bytes || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED)) return; self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); device = FP_IMAGE_DEVICE (self); - /* Consider success if we received the right amount of data, otherwise - * an error must have happened. */ - if (bytes < self->recv_img->width * self->recv_img->height) - { - if (!success) - g_warning ("Error receiving image data: %s", error->message); - else - g_warning ("Error receiving image data: end of stream before all data was read"); - - self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); - return; - } - if (self->automatic_finger) fpi_image_device_report_finger_status (device, TRUE); fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img)); @@ -102,7 +78,7 @@ recv_image_img_recv_cb (GObject *source_object, fpi_image_device_report_finger_status (device, FALSE); /* And, listen for more images from the same client. */ - recv_image (self, G_INPUT_STREAM (source_object)); + recv_image (self); } static void @@ -112,37 +88,30 @@ recv_image_hdr_recv_cb (GObject *source_object, { g_autoptr(GError) error = NULL; FpDeviceVirtualImage *self; - gboolean success; + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object); gsize bytes; - success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error); + bytes = fp_device_virtual_listener_read_finish (listener, res, &error); - if (!success || bytes != sizeof (self->recv_img_hdr)) + if (error) { - if (!success) - { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || - g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)) - return; - g_warning ("Error receiving header for image data: %s", error->message); - } - else if (bytes != 0) - { - g_warning ("Received incomplete header before end of stream."); - } + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) + return; - self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); + g_warning ("Error receiving header for image data: %s", error->message); return; } + if (!bytes) + return; + self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000) { g_warning ("Image header suggests an unrealistically large image, disconnecting client."); - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); + fp_device_virtual_listener_connection_close (listener); } if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0) @@ -178,153 +147,80 @@ recv_image_hdr_recv_cb (GObject *source_object, default: /* disconnect client, it didn't play fair */ - g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); - g_clear_object (&self->connection); + fp_device_virtual_listener_connection_close (listener); } /* And, listen for more images from the same client. */ - recv_image (self, G_INPUT_STREAM (source_object)); + recv_image (self); return; } self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]); g_debug ("image data: %p", self->recv_img->data); - g_input_stream_read_all_async (G_INPUT_STREAM (source_object), - (guint8 *) self->recv_img->data, - self->recv_img->width * self->recv_img->height, - G_PRIORITY_DEFAULT, - self->cancellable, - recv_image_img_recv_cb, - self); + fp_device_virtual_listener_read (listener, + TRUE, + (guint8 *) self->recv_img->data, + self->recv_img->width * self->recv_img->height, + recv_image_img_recv_cb, + self); } static void -recv_image (FpDeviceVirtualImage *self, GInputStream *stream) +recv_image (FpDeviceVirtualImage *self) { + fp_device_virtual_listener_read (self->listener, + TRUE, + self->recv_img_hdr, + sizeof (self->recv_img_hdr), + recv_image_hdr_recv_cb, + self); +} + +static void +on_listener_connected (FpDeviceVirtualListener *listener, + gpointer user_data) +{ + FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); FpiImageDeviceState state; - g_object_get (self, "fpi-image-device-state", &state, NULL); + self->automatic_finger = TRUE; - g_debug ("Starting image receive (if active), state is: %i", state); + g_object_get (self, + "fpi-image-device-state", &state, + NULL); + /* Only read if we are in AWAIT_FINGER_* or CAPTURE states */ + if (state <= FPI_IMAGE_DEVICE_STATE_DEACTIVATING) + return; - /* Only register if the state is active. */ - if (state >= FPI_IMAGE_DEVICE_STATE_IDLE) - { - g_input_stream_read_all_async (stream, - self->recv_img_hdr, - sizeof (self->recv_img_hdr), - G_PRIORITY_DEFAULT, - self->cancellable, - recv_image_hdr_recv_cb, - self); - } -} - -static void -new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) -{ - g_autoptr(GError) error = NULL; - GSocketConnection *connection; - GInputStream *stream; - FpDeviceVirtualImage *dev = user_data; - - connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object), - res, - NULL, - &error); - if (!connection) - { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - g_warning ("Error accepting a new connection: %s", error->message); - start_listen (dev); - } - - /* Always accept further connections (but we disconnect them immediately - * if we already have a connection). */ - start_listen (dev); - - if (dev->connection) - { - /* We may not have noticed that the stream was closed, - * if the device is deactivated. - * Cancel any ongoing operation on the old connection. */ - g_cancellable_cancel (dev->cancellable); - g_clear_object (&dev->cancellable); - dev->cancellable = g_cancellable_new (); - - g_clear_object (&dev->connection); - } - - if (dev->connection) - { - g_warning ("Rejecting new connection"); - g_io_stream_close (G_IO_STREAM (connection), NULL, NULL); - g_object_unref (connection); - return; - } - - dev->connection = connection; - dev->automatic_finger = TRUE; - stream = g_io_stream_get_input_stream (G_IO_STREAM (connection)); - - fp_dbg ("Got a new connection!"); - recv_image (dev, stream); -} - -static void -start_listen (FpDeviceVirtualImage *dev) -{ - g_socket_listener_accept_async (dev->listener, - dev->listen_cancellable, - new_connection_cb, - dev); + recv_image (self); } static void dev_init (FpImageDevice *dev) { g_autoptr(GError) error = NULL; - g_autoptr(GSocketListener) listener = NULL; + g_autoptr(FpDeviceVirtualListener) listener = NULL; + g_autoptr(GCancellable) cancellable = NULL; FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); - const char *env; - g_autoptr(GSocketAddress) addr = NULL; G_DEBUG_HERE (); - self->client_fd = -1; + listener = fp_device_virtual_listener_new (); + cancellable = g_cancellable_new (); - env = fpi_device_get_virtual_env (FP_DEVICE (self)); - - listener = g_socket_listener_new (); - g_socket_listener_set_backlog (listener, 1); - - /* Remove any left over socket. */ - g_unlink (env); - - addr = g_unix_socket_address_new (env); - - if (!g_socket_listener_add_address (listener, - addr, - G_SOCKET_TYPE_STREAM, - G_SOCKET_PROTOCOL_DEFAULT, - NULL, - NULL, - &error)) + if (!fp_device_virtual_listener_start (listener, + fpi_device_get_virtual_env (FP_DEVICE (self)), + cancellable, + on_listener_connected, + self, + &error)) { - g_warning ("Could not listen on unix socket: %s", error->message); - - fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), g_steal_pointer (&error)); - + fpi_image_device_open_complete (dev, g_steal_pointer (&error)); return; } self->listener = g_steal_pointer (&listener); - self->cancellable = g_cancellable_new (); - self->listen_cancellable = g_cancellable_new (); - - start_listen (self); + self->cancellable = g_steal_pointer (&cancellable); /* Delay result to open up the possibility of testing race conditions. */ fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_open_complete, NULL, NULL); @@ -338,11 +234,8 @@ dev_deinit (FpImageDevice *dev) G_DEBUG_HERE (); g_cancellable_cancel (self->cancellable); - g_cancellable_cancel (self->listen_cancellable); g_clear_object (&self->cancellable); - g_clear_object (&self->listen_cancellable); g_clear_object (&self->listener); - g_clear_object (&self->connection); /* Delay result to open up the possibility of testing race conditions. */ fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_close_complete, NULL, NULL); @@ -353,23 +246,16 @@ dev_activate (FpImageDevice *dev) { FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); - fpi_image_device_activate_complete (dev, NULL); + /* Start reading (again). */ + recv_image (self); - if (self->connection) - recv_image (self, g_io_stream_get_input_stream (G_IO_STREAM (self->connection))); + fpi_image_device_activate_complete (dev, NULL); } static void dev_deactivate (FpImageDevice *dev) { - FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); - - g_cancellable_cancel (self->cancellable); - g_clear_object (&self->cancellable); - self->cancellable = g_cancellable_new (); - - /* XXX: Need to wait for the operation to be cancelled. */ - fpi_device_add_timeout (FP_DEVICE (dev), 10, (FpTimeoutFunc) fpi_image_device_deactivate_complete, NULL, NULL); + fpi_image_device_deactivate_complete (dev, NULL); } static void diff --git a/libfprint/meson.build b/libfprint/meson.build index 110c4582..5309391a 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -155,6 +155,9 @@ foreach driver: drivers if driver == 'virtual_image' drivers_sources += [ 'drivers/virtual-image.c' ] endif + if driver.startswith('virtual_') + drivers_sources += [ 'drivers/virtual-device-listener.c' ] + endif if driver == 'synaptics' drivers_sources += [ 'drivers/synaptics/synaptics.c', From 3f7a638eed88e24ed221bd3b08def3951a80e651 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 15:59:07 +0100 Subject: [PATCH 18/27] virtual-device: Add non-image mock devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two variants one with storage and identify support and the other without storage. It implements the following commands: * INSERT id * REMOVE id * SCAN id * ERROR error-code * LIST (returns saved print) The INSERT/REMOVE/LIST commands are only available in the storage driver. The SCAN command emulates presenting a finger. These commands can be send ahead of time, and will be queued and processed when appropriate. i.e. for INSERT/REMOVE that is immediately when possible, for SCAN/ERROR processing is delayed. The LIST command is always processed immediately. Note that only a single command can be send per socket connection and the command must be send in a single message. The socket will be closed after the command has been processed. Co-authored-by: Bastien Nocera Co-authored-by: Marco Trevisan (Treviño) --- libfprint/drivers/virtual-device-storage.c | 181 +++++++++++ libfprint/drivers/virtual-device.c | 331 +++++++++++++++++++++ libfprint/meson.build | 6 + meson.build | 6 +- tests/meson.build | 6 +- tests/test-utils.c | 2 + tests/test-utils.h | 2 + 7 files changed, 532 insertions(+), 2 deletions(-) create mode 100644 libfprint/drivers/virtual-device-storage.c create mode 100644 libfprint/drivers/virtual-device.c diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c new file mode 100644 index 00000000..aae0f33e --- /dev/null +++ b/libfprint/drivers/virtual-device-storage.c @@ -0,0 +1,181 @@ +/* + * Virtual driver for "simple" device debugging with storage + * + * Copyright (C) 2020 Bastien Nocera + * Copyright (C) 2020 Marco Trevisan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This is a virtual driver to debug the non-image based drivers. A small + * python script is provided to connect to it via a socket, allowing + * prints to registered programmatically. + * Using this, it is possible to test libfprint and fprintd. + */ + +#define FP_COMPONENT "virtual_device_storage" + +#include "virtual-device-private.h" +#include "fpi-log.h" + +G_DEFINE_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, fpi_device_virtual_device_get_type ()) + +static void +dev_identify (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + GPtrArray *prints; + GError *error = NULL; + g_autofree char *scan_id = NULL; + + fpi_device_get_identify_data (dev, &prints); + + scan_id = process_cmds (self, TRUE, &error); + + if (scan_id) + { + GVariant *data = NULL; + FpPrint *new_scan; + FpPrint *match = NULL; + guint idx; + + new_scan = fp_print_new (dev); + fpi_print_set_type (new_scan, FPI_PRINT_RAW); + if (self->prints_storage) + fpi_print_set_device_stored (new_scan, TRUE); + data = g_variant_new_string (scan_id); + g_object_set (new_scan, "fpi-data", data, NULL); + + if (g_ptr_array_find_with_equal_func (prints, + new_scan, + (GEqualFunc) fp_print_equal, + &idx)) + match = g_ptr_array_index (prints, idx); + + fpi_device_identify_report (dev, + match, + new_scan, + NULL); + } + + fpi_device_identify_complete (dev, error); +} + +struct ListData +{ + FpDevice *dev; + GPtrArray *res; +}; + +static void +dev_list_insert_print (gpointer key, + gpointer value, + gpointer user_data) +{ + struct ListData *data = user_data; + FpPrint *print = fp_print_new (data->dev); + GVariant *var = NULL; + + fpi_print_fill_from_user_id (print, key); + fpi_print_set_type (print, FPI_PRINT_RAW); + var = g_variant_new_string (key); + g_object_set (print, "fpi-data", var, NULL); + g_object_ref_sink (print); + + g_ptr_array_add (data->res, print); +} + +static void +dev_list (FpDevice *dev) +{ + g_autoptr(GPtrArray) prints_list = NULL; + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); + struct ListData data; + + process_cmds (vdev, FALSE, NULL); + + prints_list = g_ptr_array_new_full (g_hash_table_size (vdev->prints_storage), NULL); + data.dev = dev; + data.res = prints_list; + + g_hash_table_foreach (vdev->prints_storage, dev_list_insert_print, &data); + + fpi_device_list_complete (dev, g_steal_pointer (&prints_list), NULL); +} + +static void +dev_delete (FpDevice *dev) +{ + g_autoptr(GVariant) data = NULL; + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); + FpPrint *print = NULL; + const char *id = NULL; + + process_cmds (vdev, FALSE, NULL); + + fpi_device_get_delete_data (dev, &print); + + g_object_get (print, "fpi-data", &data, NULL); + if (data == NULL) + { + fpi_device_delete_complete (dev, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); + return; + } + + id = g_variant_get_string (data, NULL); + + fp_dbg ("Deleting print %s for user %s", + id, + fp_print_get_username (print)); + + if (g_hash_table_remove (vdev->prints_storage, id)) + fpi_device_delete_complete (dev, NULL); + else + fpi_device_delete_complete (dev, + fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); +} + +static void +fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self) +{ + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (self); + + vdev->prints_storage = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); +} + +static const FpIdEntry driver_ids[] = { + { .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE" }, + { .virtual_envvar = "FP_VIRTUAL_DEVICE_IDENT" }, + { .virtual_envvar = NULL } +}; + +static void +fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + + dev_class->id = FP_COMPONENT; + dev_class->full_name = "Virtual device with storage and identification for debugging"; + dev_class->id_table = driver_ids; + + dev_class->identify = dev_identify; + dev_class->list = dev_list; + dev_class->delete = dev_delete; +} diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c new file mode 100644 index 00000000..5c143b19 --- /dev/null +++ b/libfprint/drivers/virtual-device.c @@ -0,0 +1,331 @@ +/* + * Virtual driver for "simple" device debugging + * + * Copyright (C) 2019 Benjamin Berg + * Copyright (C) 2020 Bastien Nocera + * Copyright (C) 2020 Marco Trevisan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * This is a virtual driver to debug the non-image based drivers. A small + * python script is provided to connect to it via a socket, allowing + * prints to registered programmatically. + * Using this, it is possible to test libfprint and fprintd. + */ + +#define FP_COMPONENT "virtual_device" + +#include "virtual-device-private.h" +#include "fpi-log.h" + +G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE) + +#define INSERT_CMD_PREFIX "INSERT " +#define REMOVE_CMD_PREFIX "REMOVE " +#define SCAN_CMD_PREFIX "SCAN " +#define ERROR_CMD_PREFIX "ERROR " + +#define LIST_CMD "LIST" + +char * +process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError * *error) +{ + while (self->pending_commands->len > 0) + { + gchar *cmd = g_ptr_array_index (self->pending_commands, 0); + + /* These are always processed. */ + if (g_str_has_prefix (cmd, INSERT_CMD_PREFIX)) + { + g_assert (self->prints_storage); + g_hash_table_add (self->prints_storage, + g_strdup (cmd + strlen (INSERT_CMD_PREFIX))); + + g_ptr_array_remove_index (self->pending_commands, 0); + continue; + } + else if (g_str_has_prefix (cmd, REMOVE_CMD_PREFIX)) + { + g_assert (self->prints_storage); + if (!g_hash_table_remove (self->prints_storage, + cmd + strlen (REMOVE_CMD_PREFIX))) + g_warning ("ID %s was not found in storage", cmd + strlen (REMOVE_CMD_PREFIX)); + + g_ptr_array_remove_index (self->pending_commands, 0); + continue; + } + + /* If we are not scanning, then we have to stop here. */ + if (!scan) + break; + + if (g_str_has_prefix (cmd, SCAN_CMD_PREFIX)) + { + char *res = g_strdup (cmd + strlen (SCAN_CMD_PREFIX)); + + g_ptr_array_remove_index (self->pending_commands, 0); + return res; + } + else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX)) + { + g_propagate_error (error, + fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10))); + + g_ptr_array_remove_index (self->pending_commands, 0); + return NULL; + } + else + { + g_warning ("Could not process command: %s", cmd); + g_ptr_array_remove_index (self->pending_commands, 0); + } + } + + /* No commands left, throw a timeout error. */ + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands left that can be run!"); + return NULL; +} + +static void +write_key_to_listener (void *key, void *val, void *user_data) +{ + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (user_data); + + if (!fp_device_virtual_listener_write_sync (listener, key, strlen (key), NULL) || + !fp_device_virtual_listener_write_sync (listener, "\n", 1, NULL)) + g_warning ("Error writing reply to LIST command"); +} + +static void +recv_instruction_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object); + gsize bytes; + + bytes = fp_device_virtual_listener_read_finish (listener, res, &error); + fp_dbg ("Got instructions of length %ld\n", bytes); + + if (error) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + g_warning ("Error receiving instruction data: %s", error->message); + return; + } + + if (bytes > 0) + { + FpDeviceVirtualDevice *self; + g_autofree char *cmd = NULL; + + self = FP_DEVICE_VIRTUAL_DEVICE (user_data); + + cmd = g_strndup (self->recv_buf, bytes); + + if (g_str_has_prefix (cmd, LIST_CMD)) + { + if (self->prints_storage) + g_hash_table_foreach (self->prints_storage, write_key_to_listener, listener); + } + else + { + g_ptr_array_add (self->pending_commands, g_steal_pointer (&cmd)); + } + } + + fp_device_virtual_listener_connection_close (listener); +} + +static void +recv_instruction (FpDeviceVirtualDevice *self) +{ + fp_device_virtual_listener_read (self->listener, + FALSE, + self->recv_buf, + sizeof (self->recv_buf), + recv_instruction_cb, + self); +} + +static void +on_listener_connected (FpDeviceVirtualListener *listener, + gpointer user_data) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (user_data); + + recv_instruction (self); +} + +static void +dev_init (FpDevice *dev) +{ + g_autoptr(GError) error = NULL; + g_autoptr(GCancellable) cancellable = NULL; + g_autoptr(FpDeviceVirtualListener) listener = NULL; + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + + G_DEBUG_HERE (); + + listener = fp_device_virtual_listener_new (); + cancellable = g_cancellable_new (); + + if (!fp_device_virtual_listener_start (listener, + fpi_device_get_virtual_env (FP_DEVICE (self)), + cancellable, + on_listener_connected, + self, + &error)) + { + fpi_device_open_complete (dev, g_steal_pointer (&error)); + return; + } + + self->listener = g_steal_pointer (&listener); + self->cancellable = g_steal_pointer (&cancellable); + + fpi_device_open_complete (dev, NULL); +} + +static void +dev_verify (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + FpPrint *print; + GError *error = NULL; + g_autofree char *scan_id = NULL; + + fpi_device_get_verify_data (dev, &print); + + scan_id = process_cmds (self, TRUE, &error); + + if (scan_id) + { + GVariant *data = NULL; + FpPrint *new_scan; + gboolean success; + + g_debug ("Virtual device scanned print %s", scan_id); + + new_scan = fp_print_new (dev); + fpi_print_set_type (new_scan, FPI_PRINT_RAW); + if (self->prints_storage) + fpi_print_set_device_stored (new_scan, TRUE); + data = g_variant_new_string (scan_id); + g_object_set (new_scan, "fpi-data", data, NULL); + + success = fp_print_equal (print, new_scan); + + fpi_device_verify_report (dev, + success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, + new_scan, + NULL); + } + else + { + g_debug ("Virtual device scann failed with error: %s", error->message); + } + + fpi_device_verify_complete (dev, error); +} + +static void +dev_enroll (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + GError *error = NULL; + FpPrint *print = NULL; + g_autofree char *id = NULL; + + fpi_device_get_enroll_data (dev, &print); + + id = process_cmds (self, TRUE, &error); + + if (id) + { + GVariant *data; + + fpi_print_set_type (print, FPI_PRINT_RAW); + data = g_variant_new_string (id); + g_object_set (print, "fpi-data", data, NULL); + + if (self->prints_storage) + { + g_hash_table_add (self->prints_storage, g_strdup (id)); + fpi_print_set_device_stored (print, TRUE); + } + + fpi_device_enroll_complete (dev, g_object_ref (print), error); + } + else + { + fpi_device_enroll_complete (dev, NULL, error); + } +} + +static void +dev_deinit (FpDevice *dev) +{ + FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev); + + g_cancellable_cancel (self->cancellable); + g_clear_object (&self->cancellable); + g_clear_object (&self->listener); + g_clear_object (&self->listener); + + fpi_device_close_complete (dev, NULL); +} + +static void +fpi_device_virtual_device_finalize (GObject *object) +{ + G_DEBUG_HERE (); +} + +static void +fpi_device_virtual_device_init (FpDeviceVirtualDevice *self) +{ + self->pending_commands = g_ptr_array_new_with_free_func (g_free); +} + +static const FpIdEntry driver_ids[] = { + { .virtual_envvar = "FP_VIRTUAL_DEVICE", }, + { .virtual_envvar = NULL } +}; + +static void +fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass) +{ + FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = fpi_device_virtual_device_finalize; + + dev_class->id = FP_COMPONENT; + dev_class->full_name = "Virtual device for debugging"; + dev_class->type = FP_DEVICE_TYPE_VIRTUAL; + dev_class->id_table = driver_ids; + dev_class->nr_enroll_stages = 5; + + dev_class->open = dev_init; + dev_class->close = dev_deinit; + dev_class->verify = dev_verify; + dev_class->enroll = dev_enroll; +} diff --git a/libfprint/meson.build b/libfprint/meson.build index 5309391a..0090ece3 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -155,6 +155,12 @@ foreach driver: drivers if driver == 'virtual_image' drivers_sources += [ 'drivers/virtual-image.c' ] endif + if driver == 'virtual_device' + drivers_sources += [ 'drivers/virtual-device.c' ] + endif + if driver == 'virtual_device_storage' + drivers_sources += [ 'drivers/virtual-device-storage.c' ] + endif if driver.startswith('virtual_') drivers_sources += [ 'drivers/virtual-device-listener.c' ] endif diff --git a/meson.build b/meson.build index 8dc852aa..2b6fe846 100644 --- a/meson.build +++ b/meson.build @@ -88,7 +88,11 @@ cairo_dep = dependency('cairo', required: false) # Drivers drivers = get_option('drivers').split(',') -virtual_drivers = [ 'virtual_image' ] +virtual_drivers = [ + 'virtual_image', + 'virtual_device', + 'virtual_device_storage', +] default_drivers = [ 'upektc_img', diff --git a/tests/meson.build b/tests/meson.build index 8e24980b..61decd5d 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -13,7 +13,11 @@ envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint')) envs.set('FP_DEVICE_EMULATION', '1') # Set a colon-separated list of native drivers we enable in tests -envs.set('FP_DRIVERS_WHITELIST', 'virtual_image') +envs.set('FP_DRIVERS_WHITELIST', ':'.join([ + 'virtual_image', + 'virtual_device', + 'virtual_device_storage', +])) envs.set('NO_AT_BRIDGE', '1') diff --git a/tests/test-utils.c b/tests/test-utils.c index 1c1be17f..a14d1cae 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -29,6 +29,8 @@ struct const char *device_id; } devtype_vars[FPT_NUM_VIRTUAL_DEVICE_TYPES] = { { "FP_VIRTUAL_IMAGE", "virtual_image", "virtual_image" }, /* FPT_VIRTUAL_DEVICE_IMAGE */ + { "FP_VIRTUAL_DEVICE", "virtual_device", "virtual_device" }, /* FPT_VIRTUAL_DEVICE_NONIMAGE */ + { "FP_VIRTUAL_DEVICE_STORAGE", "virtual_device_storage", "virtual_device_storage" } /* FPT_VIRTUAL_DEVICE_NONIMAGE_STORAGE */ }; static FptVirtualDeviceType global_devtype; diff --git a/tests/test-utils.h b/tests/test-utils.h index e4e4c30e..7419a4c7 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -21,6 +21,8 @@ typedef enum { FPT_VIRTUAL_DEVICE_IMAGE = 0, + FPT_VIRTUAL_DEVICE_NONIMAGE, + FPT_VIRTUAL_DEVICE_NONIMAGE_STORAGE, FPT_NUM_VIRTUAL_DEVICE_TYPES } FptVirtualDeviceType; From 8ded064e65f7aca1d5910582826519409fbd28ee Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 5 Jan 2021 16:23:18 +0100 Subject: [PATCH 19/27] tests: Add test based on the new virtual devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marco Trevisan (Treviño) --- tests/meson.build | 70 +++++++----- tests/virtual-device.py | 247 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 286 insertions(+), 31 deletions(-) create mode 100644 tests/virtual-device.py diff --git a/tests/meson.build b/tests/meson.build index 61decd5d..f15bd8ad 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -33,43 +33,51 @@ drivers_tests = [ if get_option('introspection') envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint')) + virtual_devices_tests = [ + 'virtual-image', + 'virtual-device', + ] - if 'virtual_image' in drivers - python3 = find_program('python3') - unittest_inspector = find_program('unittest_inspector.py') - base_args = files('virtual-image.py') - suite = [] + unittest_inspector = find_program('unittest_inspector.py') - r = run_command(unittest_inspector, files('virtual-image.py')) - unit_tests = r.stdout().strip().split('\n') + foreach vdtest: virtual_devices_tests + driver_name = '_'.join(vdtest.split('-')) + if driver_name in drivers + python3 = find_program('python3') + base_args = files(vdtest + '.py') + suite = ['virtual-driver'] - if r.returncode() == 0 and unit_tests.length() > 0 - suite += 'virtual-image' - else - unit_tests = ['virtual-image'] - endif + r = run_command(unittest_inspector, files(vdtest + '.py')) + unit_tests = r.stdout().strip().split('\n') - foreach ut: unit_tests - ut_suite = suite - ut_args = base_args - if unit_tests.length() > 1 - ut_args += ut - ut_suite += ut.split('.')[0] + if r.returncode() == 0 and unit_tests.length() > 0 + suite += vdtest + else + unit_tests = [vdtest] endif - test(ut, - python3, - args: ut_args, - suite: ut_suite, - depends: libfprint_typelib, - env: envs, + + foreach ut: unit_tests + ut_suite = suite + ut_args = base_args + if unit_tests.length() > 1 + ut_args += ut + ut_suite += ut.split('.')[0] + endif + test(ut, + python3, + args: ut_args, + suite: ut_suite, + depends: libfprint_typelib, + env: envs, + ) + endforeach + else + test(vdtest, + find_program('sh'), + args: ['-c', 'exit 77'] ) - endforeach - else - test('virtual-image', - find_program('sh'), - args: ['-c', 'exit 77'] - ) - endif + endif + endforeach foreach driver_test: drivers_tests driver_envs = envs diff --git a/tests/virtual-device.py b/tests/virtual-device.py new file mode 100644 index 00000000..8d15bfd4 --- /dev/null +++ b/tests/virtual-device.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 + +import sys +try: + import gi + import re + import os + + from gi.repository import GLib, Gio + + import unittest + import socket + import struct + import subprocess + import shutil + import glob + import tempfile +except Exception as e: + print("Missing dependencies: %s" % str(e)) + sys.exit(77) + +FPrint = None + +# Re-run the test with the passed wrapper if set +wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER') +if wrapper: + wrap_cmd = wrapper.split(' ') + [sys.executable, os.path.abspath(__file__)] + \ + sys.argv[1:] + os.unsetenv('LIBFPRINT_TEST_WRAPPER') + sys.exit(subprocess.check_call(wrap_cmd)) + +ctx = GLib.main_context_default() + + +class Connection: + + def __init__(self, addr): + self.addr = addr + + def __enter__(self): + self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.con.connect(self.addr) + return self.con + + def __exit__(self, exc_type, exc_val, exc_tb): + self.con.close() + del self.con + +class VirtualDevice(unittest.TestCase): + + @classmethod + def setUpClass(cls): + unittest.TestCase.setUpClass() + cls.tmpdir = tempfile.mkdtemp(prefix='libfprint-') + + driver_name = cls.driver_name if hasattr(cls, 'driver_name') else None + if not driver_name: + driver_name = re.compile(r'(? Date: Thu, 21 Jan 2021 00:57:43 +0100 Subject: [PATCH 20/27] build: Ensure we process the data dir --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index 2b6fe846..0a65754e 100644 --- a/meson.build +++ b/meson.build @@ -240,6 +240,7 @@ if get_option('gtk-examples') subdir('demo') endif +subdir('data') subdir('tests') pkgconfig = import('pkgconfig') From 2f6adce2fa95d95778054ed6f1ce8615e63cc794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 01:17:02 +0100 Subject: [PATCH 21/27] data: Keep using versioned libname for hwdb file --- data/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/meson.build b/data/meson.build index 975c1c3f..99adf5d7 100644 --- a/data/meson.build +++ b/data/meson.build @@ -3,7 +3,7 @@ if get_option('udev_rules') # ninja -C libfprint/sync-udev-hwdb install_data('autosuspend.hwdb', - rename: '60-autosuspend-@0@.hwdb'.format(meson.project_name()), + rename: '60-autosuspend-@0@.hwdb'.format(versioned_libname), install_dir: udev_hwdb_dir, ) endif From 63bfaf4f608e31ae7798fe5cc8a58a1913444b3d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 21 Jan 2021 12:22:08 +0100 Subject: [PATCH 22/27] tests: Add trailing newline to busname/devname sysfs attributes libusb 1.0.24 now expects busnum/devnum to be \n terminated. Update the device descriptions accordingly. https://github.com/martinpitt/umockdev/issues/115 --- tests/aes3500/device | 16 ++++++++-------- tests/elan/device | 12 ++++++------ tests/goodixmoc/device | 8 ++++---- tests/synaptics/device | 4 ++-- tests/vfs0050/device | 4 ++-- tests/vfs301/device | 12 ++++++------ tests/vfs5011/device | 4 ++-- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/aes3500/device b/tests/aes3500/device index 4a2a9037..c662cc8f 100644 --- a/tests/aes3500/device +++ b/tests/aes3500/device @@ -35,11 +35,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0000 A: bmAttributes=80 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12011001FFFFFF08FF0831570000000100010902200001010080320904000002FFFFFF000705810240000007050202080000 A: dev=189:259 -A: devnum=4 +A: devnum=4\n A: devpath=1.1.3 L: driver=../../../../../../../../../../bus/usb/drivers/usb A: idProduct=5731 @@ -106,11 +106,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=9100 A: bmAttributes=e0 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C A: dev=189:258 -A: devnum=3 +A: devnum=3\n A: devpath=1.1 L: driver=../../../../../../../../../bus/usb/drivers/usb A: idProduct=0006 @@ -186,11 +186,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=9100 A: bmAttributes=e0 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C A: dev=189:257 -A: devnum=2 +A: devnum=2\n A: devpath=1 L: driver=../../../../../../../../bus/usb/drivers/usb A: idProduct=0006 @@ -270,11 +270,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0415 A: bmAttributes=e0 -A: busnum=3 +A: busnum=3\n A: configuration= H: descriptors=12010002090001406B1D020015040302010109021900010100E0000904000001090000000705810304000C A: dev=189:256 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/elan/device b/tests/elan/device index 7374dc24..6e1e421e 100644 --- a/tests/elan/device +++ b/tests/elan/device @@ -36,11 +36,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0140 A: bmAttributes=80 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=1201000200000008F304260C40010102000109023E0001010080320904000005FF0000000921100100012215000705810240000107050102400001070582024000010705830240000107050302400001 A: dev=189:93 -A: devnum=94 +A: devnum=94\n A: devpath=4.4 L: driver=../../../../../../bus/usb/drivers/usb A: idProduct=0c26 @@ -107,11 +107,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=5284 A: bmAttributes=e0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=1201100209000140EF17181084520102000109021900010100E0000904000001090000000705810301000C A: dev=189:82 -A: devnum=83 +A: devnum=83\n A: devpath=4 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=1018 @@ -189,11 +189,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0503 A: bmAttributes=e0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12010002090001406B1D020003050302010109021900010100E0000904000001090000000705810304000C A: dev=189:0 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/goodixmoc/device b/tests/goodixmoc/device index 627c9dc0..b008eb2b 100644 --- a/tests/goodixmoc/device +++ b/tests/goodixmoc/device @@ -37,11 +37,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0100 A: bmAttributes=a0 -A: busnum=1 +A: busnum=1\n A: configuration=UIDCBEE4D7B_XXXX_MOC_B0 H: descriptors=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000 A: dev=189:2 -A: devnum=3 +A: devnum=3\n A: devpath=8 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=60a2 @@ -125,11 +125,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0504 A: bmAttributes=e0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C A: dev=189:0 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/synaptics/device b/tests/synaptics/device index 6da3eea7..87c4bed2 100644 --- a/tests/synaptics/device +++ b/tests/synaptics/device @@ -34,11 +34,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0000 A: bmAttributes=a0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004 A: dev=189:69 -A: devnum=70 +A: devnum=70\n A: devpath=1 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=00bd diff --git a/tests/vfs0050/device b/tests/vfs0050/device index 1bea50a0..b66be4ba 100644 --- a/tests/vfs0050/device +++ b/tests/vfs0050/device @@ -38,11 +38,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0060 A: bmAttributes=a0 -A: busnum=1 +A: busnum=1\n A: configuration= H: descriptors=12011001FF10FF088A13500060000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 A: dev=189:3 -A: devnum=4 +A: devnum=4\n A: devpath=9 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=0050 diff --git a/tests/vfs301/device b/tests/vfs301/device index 635f7951..26d3b57e 100644 --- a/tests/vfs301/device +++ b/tests/vfs301/device @@ -37,11 +37,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0c90 A: bmAttributes=a0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12011001FF10FF088A130500900C0000000109022700010100A0320904000003FF000000070501024000000705810240000007058202400000 A: dev=189:132 -A: devnum=5 +A: devnum=5\n A: devpath=1.3 L: driver=../../../../../../bus/usb/drivers/usb A: idProduct=0005 @@ -120,11 +120,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0000 A: bmAttributes=e0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12010002090001408780200000000000000109021900010100E0000904000001090000000705810302000C A: dev=189:129 -A: devnum=2 +A: devnum=2\n A: devpath=1 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=0020 @@ -204,11 +204,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0504 A: bmAttributes=e0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12010002090000406B1D020004050302010109021900010100E0000904000001090000000705810304000C A: dev=189:128 -A: devnum=1 +A: devnum=1\n A: devpath=0 L: driver=../../../../bus/usb/drivers/usb A: idProduct=0002 diff --git a/tests/vfs5011/device b/tests/vfs5011/device index 4c75e596..e39a74fa 100644 --- a/tests/vfs5011/device +++ b/tests/vfs5011/device @@ -35,11 +35,11 @@ A: bNumConfigurations=1 A: bNumInterfaces= 1 A: bcdDevice=0078 A: bmAttributes=a0 -A: busnum=2 +A: busnum=2\n A: configuration= H: descriptors=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 A: dev=189:144 -A: devnum=17 +A: devnum=17\n A: devpath=6 L: driver=../../../../../bus/usb/drivers/usb A: idProduct=0017 From 170924ee4fc2143ed1569545b39d4bfb4857f378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 15:01:55 +0100 Subject: [PATCH 23/27] test-generated-hwdb: Just use diff to compare for being more informative --- tests/test-generated-hwdb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-generated-hwdb.sh b/tests/test-generated-hwdb.sh index 34209cb5..87c08bbf 100755 --- a/tests/test-generated-hwdb.sh +++ b/tests/test-generated-hwdb.sh @@ -15,7 +15,7 @@ if [ "$UDEV_HWDB_CHECK_CONTENTS" != 1 ]; then exit 77 fi -if ! cmp "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then +if ! diff -u "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then echo "E: Autosuspend file needs to be re-generated!" echo " ninja -C $MESON_BUILD_ROOT libfprint/sync-udev-hwdb" exit 1 From 57f836a0f65fcc7f69c082b71d33afcb6c6fd1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 15:26:31 +0100 Subject: [PATCH 24/27] udev-hwdb: Generate autosuspend list using a sorted list --- data/autosuspend.hwdb | 142 +++++++++++++++--------------- libfprint/fprint-list-udev-hwdb.c | 10 +++ 2 files changed, 81 insertions(+), 71 deletions(-) diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb index 7a78068c..63e40cf7 100644 --- a/data/autosuspend.hwdb +++ b/data/autosuspend.hwdb @@ -1,27 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # This file has been generated using fprint-list-udev-hwdb with all drivers enabled -# Supported by libfprint driver upektc_img -usb:v147Ep2016* -usb:v147Ep2020* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs5011 -usb:v138Ap0010* -usb:v138Ap0011* -usb:v138Ap0015* -usb:v138Ap0017* -usb:v138Ap0018* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver aes3500 -usb:v08FFp5731* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver aes4000 -usb:v5501p08FF* - ID_AUTOSUSPEND=1 - # Supported by libfprint driver aes1610 usb:v08FFp1600* ID_AUTOSUSPEND=1 @@ -46,6 +25,16 @@ usb:v08FFp168E* usb:v08FFp168F* ID_AUTOSUSPEND=1 +# Supported by libfprint driver aes2501 +usb:v08FFp2500* +usb:v08FFp2580* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver aes2550 +usb:v08FFp2550* +usb:v08FFp2810* + ID_AUTOSUSPEND=1 + # Supported by libfprint driver aes2660 usb:v08FFp2660* usb:v08FFp2680* @@ -67,46 +56,12 @@ usb:v08FFp268F* usb:v08FFp2691* ID_AUTOSUSPEND=1 -# Supported by libfprint driver aes2501 -usb:v08FFp2500* -usb:v08FFp2580* +# Supported by libfprint driver aes3500 +usb:v08FFp5731* ID_AUTOSUSPEND=1 -# Supported by libfprint driver aes2550 -usb:v08FFp2550* -usb:v08FFp2810* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs101 -usb:v138Ap0001* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs301 -usb:v138Ap0005* -usb:v138Ap0008* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vfs0050 -usb:v138Ap0050* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver etes603 -usb:v1C7Ap0603* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver vcom5s -usb:v061Ap0110* - ID_AUTOSUSPEND=1 - -# Supported by libfprint driver synaptics -usb:v06CBp00BD* -usb:v06CBp00E9* -usb:v06CBp00DF* -usb:v06CBp00F9* -usb:v06CBp00FC* -usb:v06CBp00C2* -usb:v06CBp00C9* -usb:v06CBp00E7* +# Supported by libfprint driver aes4000 +usb:v5501p08FF* ID_AUTOSUSPEND=1 # Supported by libfprint driver elan @@ -167,6 +122,44 @@ usb:v04F3p0C42* usb:v04F3p0C4D* ID_AUTOSUSPEND=1 +# Supported by libfprint driver etes603 +usb:v1C7Ap0603* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver goodixmoc +usb:v27C6p5840* +usb:v27C6p6496* +usb:v27C6p60A2* +usb:v27C6p63AC* +usb:v27C6p639C* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver synaptics +usb:v06CBp00BD* +usb:v06CBp00E9* +usb:v06CBp00DF* +usb:v06CBp00F9* +usb:v06CBp00FC* +usb:v06CBp00C2* +usb:v06CBp00C9* +usb:v06CBp00E7* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upeksonly +usb:v147Ep2016* +usb:v147Ep1000* +usb:v147Ep1001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upektc +usb:v0483p2015* +usb:v147Ep3001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver upektc_img +usb:v147Ep2020* + ID_AUTOSUSPEND=1 + # Supported by libfprint driver uru4000 usb:v045Ep00BC* usb:v045Ep00BD* @@ -176,22 +169,29 @@ usb:v05BAp0008* usb:v05BAp000A* ID_AUTOSUSPEND=1 -# Supported by libfprint driver upektc -usb:v0483p2015* -usb:v147Ep3001* +# Supported by libfprint driver vcom5s +usb:v061Ap0110* ID_AUTOSUSPEND=1 -# Supported by libfprint driver upeksonly -usb:v147Ep1000* -usb:v147Ep1001* +# Supported by libfprint driver vfs0050 +usb:v138Ap0050* ID_AUTOSUSPEND=1 -# Supported by libfprint driver goodixmoc -usb:v27C6p5840* -usb:v27C6p6496* -usb:v27C6p60A2* -usb:v27C6p63AC* -usb:v27C6p639C* +# Supported by libfprint driver vfs101 +usb:v138Ap0001* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs301 +usb:v138Ap0005* +usb:v138Ap0008* + ID_AUTOSUSPEND=1 + +# Supported by libfprint driver vfs5011 +usb:v138Ap0010* +usb:v138Ap0011* +usb:v138Ap0015* +usb:v138Ap0017* +usb:v138Ap0018* ID_AUTOSUSPEND=1 # Known unsupported devices diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c index 6f533fb6..2a78e81f 100644 --- a/libfprint/fprint-list-udev-hwdb.c +++ b/libfprint/fprint-list-udev-hwdb.c @@ -164,6 +164,15 @@ print_driver (const FpDeviceClass *cls) g_print (" ID_AUTOSUSPEND=1\n"); } +static int +driver_compare (gconstpointer p1, gconstpointer p2) +{ + g_autoptr(FpDeviceClass) cls1 = g_type_class_ref (*(GType *) p1); + g_autoptr(FpDeviceClass) cls2 = g_type_class_ref (*(GType *) p2); + + return g_strcmp0 (cls1->id, cls2->id); +} + int main (int argc, char **argv) { @@ -178,6 +187,7 @@ main (int argc, char **argv) program_name); printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_array_sort (drivers, driver_compare); for (i = 0; i < drivers->len; i++) { From 3b83157e9b9b642dfb7f6ab177ec9e601e6e6a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 21 Jan 2021 15:34:36 +0100 Subject: [PATCH 25/27] build: Skip the hwdb test if not all drivers are really enabled --- meson.build | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meson.build b/meson.build index 0a65754e..cbeab4d6 100644 --- a/meson.build +++ b/meson.build @@ -184,6 +184,10 @@ foreach driver: drivers endif endforeach +if default_drivers_are_enabled and supported_drivers != drivers + default_drivers_are_enabled = false +endif + # Export the drivers' types to the core code drivers_type_list = [] drivers_type_func = [] From e0c41c544413ade2e8577bf2c667ed405d8ace6f Mon Sep 17 00:00:00 2001 From: fengqiangguo Date: Wed, 16 Dec 2020 10:31:46 +0800 Subject: [PATCH 26/27] goodixmoc: Fix some big/little endian support issues Goodix driver is not working fine in BigEndian architectures. This commit fixes some of these issues. Related: #236 --- libfprint/drivers/goodixmoc/goodix.c | 2 +- libfprint/drivers/goodixmoc/goodix_proto.c | 85 ++++++++++++++-------- libfprint/drivers/goodixmoc/goodix_proto.h | 4 +- 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index af64d814..82913d73 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -127,7 +127,7 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer, } gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc); - if(crc32_calc != *(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)) + if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len))) { fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, diff --git a/libfprint/drivers/goodixmoc/goodix_proto.c b/libfprint/drivers/goodixmoc/goodix_proto.c index e30d23df..962fd6e7 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.c +++ b/libfprint/drivers/goodixmoc/goodix_proto.c @@ -141,8 +141,11 @@ crc32_update (gf_crc32_context *ctx, const uint8_t *message, uint32_t n_bytes) static void crc32_final (gf_crc32_context *ctx, uint8_t *md) { + uint32_t crc = 0; + ctx->crc = (REFLECT_REMAINDER (ctx->crc) ^ FINAL_XOR_VALUE); - memcpy (md, &ctx->crc, 4); + crc = GUINT32_TO_LE (ctx->crc); + memcpy (md, &crc, 4); } uint8_t @@ -184,7 +187,7 @@ init_pack_header ( pheader->cmd1 = LOBYTE (cmd); pheader->packagenum = packagenum; pheader->reserved = dump_seq++; - pheader->len = len + PACKAGE_CRC_SIZE; + pheader->len = GUINT16_TO_LE (len + PACKAGE_CRC_SIZE); pheader->crc8 = gx_proto_crc8_calc ((uint8_t *) pheader, 6); pheader->rev_crc8 = ~pheader->crc8; } @@ -224,14 +227,14 @@ gx_proto_parse_header ( { if (!buffer || !pheader) return -1; - if (buffer_len < PACKAGE_HEADER_SIZE) + if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE) return -1; memcpy (pheader, buffer, sizeof (pack_header)); - - pheader->len = GUINT16_FROM_LE ( *(uint16_t *) (buffer + 4)); + pheader->len = GUINT16_FROM_LE (pheader->len); + if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE) + return -1; pheader->len -= PACKAGE_CRC_SIZE; - return 0; } @@ -248,7 +251,7 @@ gx_proto_parse_fingerid ( if (!template || !fid_buffer) return -1; - if (fid_buffer_size < 70) + if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t)) return -1; buffer = fid_buffer; @@ -256,28 +259,30 @@ gx_proto_parse_fingerid ( if (buffer[Offset++] != 67) return -1; + fid_buffer_size--; template->type = buffer[Offset++]; + fid_buffer_size--; template->finger_index = buffer[Offset++]; + fid_buffer_size--; Offset++; - - memcpy (template->accountid, &buffer[Offset], 32); - Offset += 32; - - memcpy (template->tid, &buffer[Offset], 32); - Offset += 32; // Offset == 68 - + memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid)); + Offset += sizeof (template->accountid); + memcpy (template->tid, &buffer[Offset], sizeof (template->tid)); + Offset += sizeof (template->tid); // Offset == 68 template->payload.size = buffer[Offset++]; - memset (template->payload.data, 0, 56); + if (template->payload.size > sizeof (template->payload.data)) + return -1; + memset (template->payload.data, 0, template->payload.size); memcpy (template->payload.data, &buffer[Offset], template->payload.size); return 0; } int -gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_cmd_response_t presp) +gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_cmd_response_t presp) { - uint32_t offset = 0; + uint16_t offset = 0; uint8_t *fingerlist = NULL; if (!buffer || !presp) @@ -289,6 +294,8 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c { case RESPONSE_PACKAGE_CMD: { + if (buffer_len < sizeof (gxfp_parse_msg_t) + 1) + return -1; presp->parse_msg.ack_cmd = buffer[1]; } break; @@ -296,32 +303,46 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c case MOC_CMD0_UPDATE_CONFIG: { presp->finger_config.status = buffer[0]; - presp->finger_config.max_stored_prints = buffer[2]; + if (buffer_len >= 3) + presp->finger_config.max_stored_prints = buffer[2]; + else + /* to compatiable old version firmware */ + presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM; + } break; case MOC_CMD0_COMMITENROLLMENT: case MOC_CMD0_DELETETEMPLATE: + /* just check result */ break; case MOC_CMD0_GET_VERSION: + if (buffer_len < sizeof (gxfp_version_info_t) + 1) + return -1; memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t)); break; case MOC_CMD0_CAPTURE_DATA: if (LOBYTE (cmd) == MOC_CMD1_DEFAULT) { + if (buffer_len < sizeof (gxfp_capturedata_t) + 1) + return -1; presp->capture_data_resp.img_quality = buffer[1]; presp->capture_data_resp.img_coverage = buffer[2]; } break; case MOC_CMD0_ENROLL_INIT: + if (buffer_len < sizeof (gxfp_enroll_init_t) + 1) + return -1; if (presp->result == GX_SUCCESS) memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE); break; case MOC_CMD0_ENROLL: + if (buffer_len < sizeof (gxfp_enroll_update_t)) + return -1; presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true; presp->enroll_update.img_overlay = buffer[1]; presp->enroll_update.img_preoverlay = buffer[2]; @@ -331,7 +352,11 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true; if (presp->check_duplicate_resp.duplicate) { - uint16_t tid_size = GUINT16_FROM_LE (*(buffer + 1)); + if (buffer_len < 3) + return -1; + uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1)); + if ((buffer_len < tid_size + 3) || (buffer_len > sizeof (template_format_t)) + 3) + return -1; memcpy (&presp->check_duplicate_resp.template, buffer + 3, tid_size); } break; @@ -339,18 +364,16 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c case MOC_CMD0_GETFINGERLIST: if (presp->result != GX_SUCCESS) break; + if (buffer_len < 2) + return -1; presp->finger_list_resp.finger_num = buffer[1]; - if (presp->finger_list_resp.finger_num > FP_MAX_FINGERNUM) - { - presp->finger_list_resp.finger_num = 0; - presp->result = GX_ERROR_NO_AVAILABLE_SPACE; - break; - } fingerlist = buffer + 2; for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++) { - uint16_t fingerid_length = GUINT16_FROM_LE (*(fingerlist + offset)); + uint16_t fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset)); offset += 2; + if (buffer_len < fingerid_length + offset + 2) + return -1; if (gx_proto_parse_fingerid (fingerlist + offset, fingerid_length, &presp->finger_list_resp.finger_list[num]) != 0) @@ -372,14 +395,16 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c presp->verify.match = (buffer[0] == 0) ? true : false; if (presp->verify.match) { + if (buffer_len < sizeof (template_format_t) + 10) + return -1; offset += 1; - presp->verify.rejectdetail = GUINT16_FROM_LE (*(buffer + offset)); + presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset)); offset += 2; - score = GUINT32_FROM_LE (*(buffer + offset)); + score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset)); offset += 4; - study = GUINT16_FROM_LE (*(buffer + offset)); + study = buffer[offset]; offset += 1; - fingerid_size = GUINT16_FROM_LE (*(buffer + offset)); + fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset)); offset += 2; if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0) { diff --git a/libfprint/drivers/goodixmoc/goodix_proto.h b/libfprint/drivers/goodixmoc/goodix_proto.h index 53eea046..e98e4e44 100644 --- a/libfprint/drivers/goodixmoc/goodix_proto.h +++ b/libfprint/drivers/goodixmoc/goodix_proto.h @@ -89,7 +89,7 @@ typedef struct _gxfp_version_info uint8_t interface[GX_VERSION_LEN]; uint8_t protocol[GX_VERSION_LEN]; uint8_t flashVersion[GX_VERSION_LEN]; - uint8_t reserved[62]; + uint8_t reserved[38]; } gxfp_version_info_t, *pgxfp_version_info_t; @@ -225,7 +225,7 @@ int gx_proto_parse_header (uint8_t *buffer, int gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, - uint32_t buffer_len, + uint16_t buffer_len, pgxfp_cmd_response_t presponse); int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig); From 89890dbd1f00289ed8ae2bcff41edc993a33b457 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 21 Jan 2021 17:36:41 +0100 Subject: [PATCH 27/27] build: Explicitly mark libfprint as a shared library While meson suggests to always use 'library' this leads to some unwanted behaviors when it comes to generate pkg-config files for it, as they will include `Libs.Private` / `Required.private` fields that should not be really part of a shared library as libfprint is meant to be used. --- libfprint/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfprint/meson.build b/libfprint/meson.build index 0090ece3..66c4c747 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -267,7 +267,7 @@ libfprint_drivers = static_library('fprint-drivers', mapfile = files('libfprint.ver') vflag = '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0]) -libfprint = library(versioned_libname.split('lib')[1], +libfprint = shared_library(versioned_libname.split('lib')[1], sources: [ fp_enums, libfprint_sources,