New upstream version 1.90.7+git1

This commit is contained in:
Marco Trevisan (Treviño)
2021-01-21 19:13:37 +01:00
37 changed files with 2154 additions and 536 deletions
+9
View File
@@ -109,6 +109,15 @@ test_indent:
- git diff - git diff
- "! git status -s | grep -q ." - "! 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: flatpak:
stage: flatpak stage: flatpak
extends: .flatpak extends: .flatpak
+263
View File
@@ -0,0 +1,263 @@
# 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 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 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*
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 aes3500
usb:v08FFp5731*
ID_AUTOSUSPEND=1
# Supported by libfprint driver aes4000
usb:v5501p08FF*
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 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*
usb:v045Ep00CA*
usb:v05BAp0007*
usb:v05BAp0008*
usb:v05BAp000A*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vcom5s
usb:v061Ap0110*
ID_AUTOSUSPEND=1
# Supported by libfprint driver vfs0050
usb:v138Ap0050*
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 vfs5011
usb:v138Ap0010*
usb:v138Ap0011*
usb:v138Ap0015*
usb:v138Ap0017*
usb:v138Ap0018*
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
+9
View File
@@ -0,0 +1,9 @@
if get_option('udev_rules')
# This file has to be updated using
# ninja -C <builddir> libfprint/sync-udev-hwdb
install_data('autosuspend.hwdb',
rename: '60-autosuspend-@0@.hwdb'.format(versioned_libname),
install_dir: udev_hwdb_dir,
)
endif
+2
View File
@@ -22,6 +22,8 @@
#define AES1660_FRAME_SIZE 0x244 #define AES1660_FRAME_SIZE 0x244
/* *INDENT-OFF* */
/* First init sequence, 0x07 cmd returns following before INIT1: /* First init sequence, 0x07 cmd returns following before INIT1:
* { 0x07, 0x05, 0x00, 0x8f, 0x16, 0x25, 0x01, 0x00 } * { 0x07, 0x05, 0x00, 0x8f, 0x16, 0x25, 0x01, 0x00 }
*/ */
+2
View File
@@ -21,6 +21,8 @@
#define AES2660_FRAME_SIZE 0x354 #define AES2660_FRAME_SIZE 0x354
/* *INDENT-OFF* */
/* First init sequence, 0x07 cmd returns following before INIT1: /* First init sequence, 0x07 cmd returns following before INIT1:
* { 0x07, 0x05, 0x00, 0x91, 0x26, 0x21, 0x00, 0x00 } * { 0x07, 0x05, 0x00, 0x91, 0x26, 0x21, 0x00, 0x00 }
*/ */
+1 -1
View File
@@ -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); 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_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
+55 -30
View File
@@ -141,8 +141,11 @@ crc32_update (gf_crc32_context *ctx, const uint8_t *message, uint32_t n_bytes)
static void static void
crc32_final (gf_crc32_context *ctx, uint8_t *md) crc32_final (gf_crc32_context *ctx, uint8_t *md)
{ {
uint32_t crc = 0;
ctx->crc = (REFLECT_REMAINDER (ctx->crc) ^ FINAL_XOR_VALUE); 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 uint8_t
@@ -184,7 +187,7 @@ init_pack_header (
pheader->cmd1 = LOBYTE (cmd); pheader->cmd1 = LOBYTE (cmd);
pheader->packagenum = packagenum; pheader->packagenum = packagenum;
pheader->reserved = dump_seq++; 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->crc8 = gx_proto_crc8_calc ((uint8_t *) pheader, 6);
pheader->rev_crc8 = ~pheader->crc8; pheader->rev_crc8 = ~pheader->crc8;
} }
@@ -224,14 +227,14 @@ gx_proto_parse_header (
{ {
if (!buffer || !pheader) if (!buffer || !pheader)
return -1; return -1;
if (buffer_len < PACKAGE_HEADER_SIZE) if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE)
return -1; return -1;
memcpy (pheader, buffer, sizeof (pack_header)); memcpy (pheader, buffer, sizeof (pack_header));
pheader->len = GUINT16_FROM_LE (pheader->len);
pheader->len = GUINT16_FROM_LE ( *(uint16_t *) (buffer + 4)); if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE)
return -1;
pheader->len -= PACKAGE_CRC_SIZE; pheader->len -= PACKAGE_CRC_SIZE;
return 0; return 0;
} }
@@ -248,7 +251,7 @@ gx_proto_parse_fingerid (
if (!template || !fid_buffer) if (!template || !fid_buffer)
return -1; return -1;
if (fid_buffer_size < 70) if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t))
return -1; return -1;
buffer = fid_buffer; buffer = fid_buffer;
@@ -256,28 +259,30 @@ gx_proto_parse_fingerid (
if (buffer[Offset++] != 67) if (buffer[Offset++] != 67)
return -1; return -1;
fid_buffer_size--;
template->type = buffer[Offset++]; template->type = buffer[Offset++];
fid_buffer_size--;
template->finger_index = buffer[Offset++]; template->finger_index = buffer[Offset++];
fid_buffer_size--;
Offset++; Offset++;
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
memcpy (template->accountid, &buffer[Offset], 32); Offset += sizeof (template->accountid);
Offset += 32; memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
Offset += sizeof (template->tid); // Offset == 68
memcpy (template->tid, &buffer[Offset], 32);
Offset += 32; // Offset == 68
template->payload.size = buffer[Offset++]; 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); memcpy (template->payload.data, &buffer[Offset], template->payload.size);
return 0; return 0;
} }
int 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; uint8_t *fingerlist = NULL;
if (!buffer || !presp) 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: case RESPONSE_PACKAGE_CMD:
{ {
if (buffer_len < sizeof (gxfp_parse_msg_t) + 1)
return -1;
presp->parse_msg.ack_cmd = buffer[1]; presp->parse_msg.ack_cmd = buffer[1];
} }
break; 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: case MOC_CMD0_UPDATE_CONFIG:
{ {
presp->finger_config.status = buffer[0]; 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; break;
case MOC_CMD0_COMMITENROLLMENT: case MOC_CMD0_COMMITENROLLMENT:
case MOC_CMD0_DELETETEMPLATE: case MOC_CMD0_DELETETEMPLATE:
/* just check result */
break; break;
case MOC_CMD0_GET_VERSION: 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)); memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t));
break; break;
case MOC_CMD0_CAPTURE_DATA: case MOC_CMD0_CAPTURE_DATA:
if (LOBYTE (cmd) == MOC_CMD1_DEFAULT) 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_quality = buffer[1];
presp->capture_data_resp.img_coverage = buffer[2]; presp->capture_data_resp.img_coverage = buffer[2];
} }
break; break;
case MOC_CMD0_ENROLL_INIT: case MOC_CMD0_ENROLL_INIT:
if (buffer_len < sizeof (gxfp_enroll_init_t) + 1)
return -1;
if (presp->result == GX_SUCCESS) if (presp->result == GX_SUCCESS)
memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE); memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE);
break; break;
case MOC_CMD0_ENROLL: 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.rollback = (buffer[0] < 0x80) ? false : true;
presp->enroll_update.img_overlay = buffer[1]; presp->enroll_update.img_overlay = buffer[1];
presp->enroll_update.img_preoverlay = buffer[2]; 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; presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true;
if (presp->check_duplicate_resp.duplicate) 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); memcpy (&presp->check_duplicate_resp.template, buffer + 3, tid_size);
} }
break; 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: case MOC_CMD0_GETFINGERLIST:
if (presp->result != GX_SUCCESS) if (presp->result != GX_SUCCESS)
break; break;
if (buffer_len < 2)
return -1;
presp->finger_list_resp.finger_num = buffer[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; fingerlist = buffer + 2;
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++) 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; offset += 2;
if (buffer_len < fingerid_length + offset + 2)
return -1;
if (gx_proto_parse_fingerid (fingerlist + offset, if (gx_proto_parse_fingerid (fingerlist + offset,
fingerid_length, fingerid_length,
&presp->finger_list_resp.finger_list[num]) != 0) &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; presp->verify.match = (buffer[0] == 0) ? true : false;
if (presp->verify.match) if (presp->verify.match)
{ {
if (buffer_len < sizeof (template_format_t) + 10)
return -1;
offset += 1; offset += 1;
presp->verify.rejectdetail = GUINT16_FROM_LE (*(buffer + offset)); presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
offset += 2; offset += 2;
score = GUINT32_FROM_LE (*(buffer + offset)); score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset));
offset += 4; offset += 4;
study = GUINT16_FROM_LE (*(buffer + offset)); study = buffer[offset];
offset += 1; offset += 1;
fingerid_size = GUINT16_FROM_LE (*(buffer + offset)); fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
offset += 2; offset += 2;
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0) if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
{ {
+2 -2
View File
@@ -89,7 +89,7 @@ typedef struct _gxfp_version_info
uint8_t interface[GX_VERSION_LEN]; uint8_t interface[GX_VERSION_LEN];
uint8_t protocol[GX_VERSION_LEN]; uint8_t protocol[GX_VERSION_LEN];
uint8_t flashVersion[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; } 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, int gx_proto_parse_body (uint16_t cmd,
uint8_t *buffer, uint8_t *buffer,
uint32_t buffer_len, uint16_t buffer_len,
pgxfp_cmd_response_t presponse); pgxfp_cmd_response_t presponse);
int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig); int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig);
+2
View File
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
/* *INDENT-OFF* */
#pragma once #pragma once
#define UPEKTC_CMD_LEN 0x40 #define UPEKTC_CMD_LEN 0x40
+193 -191
View File
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 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 /* There are many similar blocks in the data below, also the data are
* self-similar (looks like some config blocks? pokes like in vfs101?) */ * 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 \ #define vfs301_02D0_ALIGNED_BLOB \
PACKET ("0200", "8005", \ PACKET ("0200", "8005", \
"FF830720" "5F820720" "FF830720" \ "FF830720" "5F820720" "FF830720" \
"5F820720" "FF830720" "5F820720" "FF830720" \ "5F820720" "FF830720" "5F820720" "FF830720" \
"5F820720" "FF830720" "5F820720" "FF8B0720" \ "5F820720" "FF830720" "5F820720" "FF8B0720" \
"608A0720" "FF930720" "61920720" "FF9B0720" \ "608A0720" "FF930720" "61920720" "FF9B0720" \
"629A0720" "FFA30720" "63A20720" "FFAB0720" \ "629A0720" "FFA30720" "63A20720" "FFAB0720" \
"64AA0720" "FFB30720" "65B20720" "FFBB0720" \ "64AA0720" "FFB30720" "65B20720" "FFBB0720" \
"66BA0720" "FFC30720" "67C20720" "FFCB0720" \ "66BA0720" "FFC30720" "67C20720" "FFCB0720" \
"68CA0720" "FFD30720" "69D20720" "FFDB0720" \ "68CA0720" "FFD30720" "69D20720" "FFDB0720" \
"6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \ "6ADA0720" "FFE30720" "6BE20720" "FFEB0720" \
"6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \ "6CEA0720" "FFF30720" "6DF20720" "FFFB0720" \
"6EFA0720" "FF850720" "6F840720" "FF8D0720" \ "6EFA0720" "FF850720" "6F840720" "FF8D0720" \
"708C0720" "FF950720" "71940720" "FF9D0720" \ "708C0720" "FF950720" "71940720" "FF9D0720" \
"729C0720" "FFA50720" "73A40720" "FFAD0720" \ "729C0720" "FFA50720" "73A40720" "FFAD0720" \
"74AC0720" "FFB50720" "75B40720" "FFBD0720" \ "74AC0720" "FFB50720" "75B40720" "FFBD0720" \
"76BC0720" "FFC50720" "77C40720" "FFCD0720" \ "76BC0720" "FFC50720" "77C40720" "FFCD0720" \
"78CC0720" "FFD50720" "79D40720" "FFDD0720" \ "78CC0720" "FFD50720" "79D40720" "FFDD0720" \
"7ADC0720" "FFE50720" "7BE40720" "FFED0720" \ "7ADC0720" "FFE50720" "7BE40720" "FFED0720" \
"7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \ "7CEC0720" "FFF50720" "7DF40720" "FFFD0720" \
"7EFC0720" "FF870720" "7F860720" "FF8F0720" \ "7EFC0720" "FF870720" "7F860720" "FF8F0720" \
"808E0720" "FF970720" "81960720" "FF9F0720" \ "808E0720" "FF970720" "81960720" "FF9F0720" \
"829E0720" "FFA70720" "83A60720" "FFAF0720" \ "829E0720" "FFA70720" "83A60720" "FFAF0720" \
"84AE0720" "FFB70720" "85B60720" "FFBF0720" \ "84AE0720" "FFB70720" "85B60720" "FFBF0720" \
"86BE0720" "FFC70720" "87C60720" "FFCF0720" \ "86BE0720" "FFC70720" "87C60720" "FFCF0720" \
"88CE0720" "FFD70720" "89D60720" "FFDF0720" \ "88CE0720" "FFD70720" "89D60720" "FFDF0720" \
"8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \ "8ADE0720" "FFE70720" "8BE60720" "FFEF0720" \
"8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \ "8CEE0720" "FFF70720" "8DF60720" "FFFF0720" \
"8EFE0720" \ "8EFE0720" \
"FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \ "FFFF0720" "8EFE0720" "FFF70720" "8DF60720" \
"FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \ "FFEF0720" "8CEE0720" "FFE70720" "8BE60720" \
"FFDF0720" "8ADE0720" "FFD70720" "89D60720" \ "FFDF0720" "8ADE0720" "FFD70720" "89D60720" \
"FFCF0720" "88CE0720" "FFC70720" "87C60720" \ "FFCF0720" "88CE0720" "FFC70720" "87C60720" \
"FFBF0720" "86BE0720" "FFB70720" "85B60720" \ "FFBF0720" "86BE0720" "FFB70720" "85B60720" \
"FFAF0720" "84AE0720" "FFA70720" "83A60720" \ "FFAF0720" "84AE0720" "FFA70720" "83A60720" \
"FF9F0720" "829E0720" "FF970720" "81960720" \ "FF9F0720" "829E0720" "FF970720" "81960720" \
"FF8F0720" "808E0720" "FF870720" "7F860720" \ "FF8F0720" "808E0720" "FF870720" "7F860720" \
"FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \ "FFFD0720" "7EFC0720" "FFF50720" "7DF40720" \
"FFED0720" "7CEC0720" "FFE50720" "7BE40720" \ "FFED0720" "7CEC0720" "FFE50720" "7BE40720" \
"FFDD0720" "7ADC0720" "FFD50720" "79D40720" \ "FFDD0720" "7ADC0720" "FFD50720" "79D40720" \
"FFCD0720" "78CC0720" "FFC50720" "77C40720" \ "FFCD0720" "78CC0720" "FFC50720" "77C40720" \
"FFBD0720" "76BC0720" "FFB50720" "75B40720" \ "FFBD0720" "76BC0720" "FFB50720" "75B40720" \
"FFAD0720" "74AC0720" "FFA50720" "73A40720" \ "FFAD0720" "74AC0720" "FFA50720" "73A40720" \
"FF9D0720" "729C0720" "FF950720" "71940720" \ "FF9D0720" "729C0720" "FF950720" "71940720" \
"FF8D0720" "708C0720" "FF850720" "6F840720" \ "FF8D0720" "708C0720" "FF850720" "6F840720" \
"FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \ "FFFB0720" "6EFA0720" "FFF30720" "6DF20720" \
"FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \ "FFEB0720" "6CEA0720" "FFE30720" "6BE20720" \
"FFDB0720" "6ADA0720" "FFD30720" "69D20720" \ "FFDB0720" "6ADA0720" "FFD30720" "69D20720" \
"FFCB0720" "68CA0720" "FFC30720" "67C20720" \ "FFCB0720" "68CA0720" "FFC30720" "67C20720" \
"FFBB0720" "66BA0720" "FFB30720" "65B20720" \ "FFBB0720" "66BA0720" "FFB30720" "65B20720" \
"FFAB0720" "64AA0720" "FFA30720" "63A20720" \ "FFAB0720" "64AA0720" "FFA30720" "63A20720" \
"FF9B0720" "629A0720" "FF930720" "61920720" \ "FF9B0720" "629A0720" "FF930720" "61920720" \
"FF8B0720" "608A0720" "FF830720" "5F820720" \ "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 () \ 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" "A46C0420"
"A46C0400" "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"
"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 () 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. */ * any troubles. */
PACKET ("0200", "8005", 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" "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 () 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. */ * any troubles. */
PACKET ("0200", "8005", 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" "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 () 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 ()
+2
View File
@@ -1,5 +1,7 @@
#pragma once #pragma once
/* *INDENT-OFF* */
#define VFS5011_LINE_SIZE 240 #define VFS5011_LINE_SIZE 240
#define VFS5011_IMAGE_WIDTH 160 #define VFS5011_IMAGE_WIDTH 160
+355
View File
@@ -0,0 +1,355 @@
/*
* Socket utilities for "simple" device debugging
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* 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 <glib/gstdio.h>
#include <gio/gunixsocketaddress.h>
#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);
}
@@ -0,0 +1,93 @@
/*
* Virtual driver for "simple" device debugging
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2020 Bastien Nocera <hadess@hadess.net>
*
* 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 <gio/gio.h>
#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);
+181
View File
@@ -0,0 +1,181 @@
/*
* Virtual driver for "simple" device debugging with storage
*
* Copyright (C) 2020 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* 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;
}
+331
View File
@@ -0,0 +1,331 @@
/*
* Virtual driver for "simple" device debugging
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2020 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* 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;
}
+73 -187
View File
@@ -29,36 +29,27 @@
#include "fpi-log.h" #include "fpi-log.h"
#include "virtual-device-private.h"
#include "../fpi-image.h" #include "../fpi-image.h"
#include "../fpi-image-device.h" #include "../fpi-image-device.h"
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <gio/gunixsocketaddress.h>
struct _FpDeviceVirtualImage struct _FpDeviceVirtualImage
{ {
FpImageDevice parent; FpImageDevice parent;
GSocketListener *listener; FpDeviceVirtualListener *listener;
GSocketConnection *connection; GCancellable *cancellable;
GCancellable *listen_cancellable;
GCancellable *cancellable;
gint socket_fd; gboolean automatic_finger;
gint client_fd; 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_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) G_DEFINE_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FP_TYPE_IMAGE_DEVICE)
static void start_listen (FpDeviceVirtualImage *dev); static void recv_image (FpDeviceVirtualImage *self);
static void recv_image (FpDeviceVirtualImage *dev,
GInputStream *stream);
static void static void
recv_image_img_recv_cb (GObject *source_object, recv_image_img_recv_cb (GObject *source_object,
@@ -66,35 +57,20 @@ recv_image_img_recv_cb (GObject *source_object,
gpointer user_data) gpointer user_data)
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object);
FpDeviceVirtualImage *self; FpDeviceVirtualImage *self;
FpImageDevice *device; FpImageDevice *device;
gboolean success; gsize bytes;
gsize bytes = 0;
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 (!bytes || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
return; return;
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self); 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) if (self->automatic_finger)
fpi_image_device_report_finger_status (device, TRUE); fpi_image_device_report_finger_status (device, TRUE);
fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img)); 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); fpi_image_device_report_finger_status (device, FALSE);
/* And, listen for more images from the same client. */ /* And, listen for more images from the same client. */
recv_image (self, G_INPUT_STREAM (source_object)); recv_image (self);
} }
static void static void
@@ -112,37 +88,30 @@ recv_image_hdr_recv_cb (GObject *source_object,
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self; FpDeviceVirtualImage *self;
gboolean success; FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object);
gsize bytes; 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_CONNECTION_CLOSED) ||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)) return;
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.");
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); g_warning ("Error receiving header for image data: %s", error->message);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
g_clear_object (&self->connection);
return; return;
} }
if (!bytes)
return;
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000) 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_warning ("Image header suggests an unrealistically large image, disconnecting client.");
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); fp_device_virtual_listener_connection_close (listener);
g_clear_object (&self->connection);
} }
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0) 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: default:
/* disconnect client, it didn't play fair */ /* disconnect client, it didn't play fair */
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); fp_device_virtual_listener_connection_close (listener);
g_clear_object (&self->connection);
} }
/* And, listen for more images from the same client. */ /* And, listen for more images from the same client. */
recv_image (self, G_INPUT_STREAM (source_object)); recv_image (self);
return; return;
} }
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]); 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_debug ("image data: %p", self->recv_img->data);
g_input_stream_read_all_async (G_INPUT_STREAM (source_object), fp_device_virtual_listener_read (listener,
(guint8 *) self->recv_img->data, TRUE,
self->recv_img->width * self->recv_img->height, (guint8 *) self->recv_img->data,
G_PRIORITY_DEFAULT, self->recv_img->width * self->recv_img->height,
self->cancellable, recv_image_img_recv_cb,
recv_image_img_recv_cb, self);
self);
} }
static void 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; 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. */ recv_image (self);
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);
} }
static void static void
dev_init (FpImageDevice *dev) dev_init (FpImageDevice *dev)
{ {
g_autoptr(GError) error = NULL; 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); FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
const char *env;
g_autoptr(GSocketAddress) addr = NULL;
G_DEBUG_HERE (); 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)); if (!fp_device_virtual_listener_start (listener,
fpi_device_get_virtual_env (FP_DEVICE (self)),
listener = g_socket_listener_new (); cancellable,
g_socket_listener_set_backlog (listener, 1); on_listener_connected,
self,
/* Remove any left over socket. */ &error))
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))
{ {
g_warning ("Could not listen on unix socket: %s", error->message); fpi_image_device_open_complete (dev, g_steal_pointer (&error));
fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), g_steal_pointer (&error));
return; return;
} }
self->listener = g_steal_pointer (&listener); self->listener = g_steal_pointer (&listener);
self->cancellable = g_cancellable_new (); self->cancellable = g_steal_pointer (&cancellable);
self->listen_cancellable = g_cancellable_new ();
start_listen (self);
/* Delay result to open up the possibility of testing race conditions. */ /* 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); 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_DEBUG_HERE ();
g_cancellable_cancel (self->cancellable); g_cancellable_cancel (self->cancellable);
g_cancellable_cancel (self->listen_cancellable);
g_clear_object (&self->cancellable); g_clear_object (&self->cancellable);
g_clear_object (&self->listen_cancellable);
g_clear_object (&self->listener); g_clear_object (&self->listener);
g_clear_object (&self->connection);
/* Delay result to open up the possibility of testing race conditions. */ /* 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); 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); FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
fpi_image_device_activate_complete (dev, NULL); /* Start reading (again). */
recv_image (self);
if (self->connection) fpi_image_device_activate_complete (dev, NULL);
recv_image (self, g_io_stream_get_input_stream (G_IO_STREAM (self->connection)));
} }
static void static void
dev_deactivate (FpImageDevice *dev) dev_deactivate (FpImageDevice *dev)
{ {
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); fpi_image_device_deactivate_complete (dev, NULL);
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);
} }
static void static void
+2 -2
View File
@@ -187,7 +187,7 @@ fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer,
* fpi_usb_transfer_fill_bulk_full: * fpi_usb_transfer_fill_bulk_full:
* @transfer: The #FpiUsbTransfer * @transfer: The #FpiUsbTransfer
* @endpoint: The endpoint to send the transfer to * @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 * @length: The size of @buffer
* @free_func: (destroy buffer): Destroy notify for @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: * fpi_usb_transfer_fill_interrupt_full:
* @transfer: The #FpiUsbTransfer * @transfer: The #FpiUsbTransfer
* @endpoint: The endpoint to send the transfer to * @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 * @length: The size of @buffer
* @free_func: (destroy buffer): Destroy notify for @buffer * @free_func: (destroy buffer): Destroy notify for @buffer
* *
@@ -45,12 +45,9 @@ static const FpIdEntry whitelist_id_table[] = {
{ .vid = 0x06cb, .pid = 0x00b7 }, { .vid = 0x06cb, .pid = 0x00b7 },
{ .vid = 0x06cb, .pid = 0x00bb }, { .vid = 0x06cb, .pid = 0x00bb },
{ .vid = 0x06cb, .pid = 0x00be }, { .vid = 0x06cb, .pid = 0x00be },
{ .vid = 0x06cb, .pid = 0x00c2 },
{ .vid = 0x06cb, .pid = 0x00c9 },
{ .vid = 0x06cb, .pid = 0x00cb }, { .vid = 0x06cb, .pid = 0x00cb },
{ .vid = 0x06cb, .pid = 0x00d8 }, { .vid = 0x06cb, .pid = 0x00d8 },
{ .vid = 0x06cb, .pid = 0x00da }, { .vid = 0x06cb, .pid = 0x00da },
{ .vid = 0x06cb, .pid = 0x00e7 },
{ .vid = 0x0a5c, .pid = 0x5801 }, { .vid = 0x0a5c, .pid = 0x5801 },
{ .vid = 0x0a5c, .pid = 0x5805 }, { .vid = 0x0a5c, .pid = 0x5805 },
{ .vid = 0x0a5c, .pid = 0x5834 }, { .vid = 0x0a5c, .pid = 0x5834 },
@@ -110,6 +107,7 @@ static const FpIdEntry blacklist_id_table[] = {
static const FpDeviceClass whitelist = { static const FpDeviceClass whitelist = {
.type = FP_DEVICE_TYPE_USB, .type = FP_DEVICE_TYPE_USB,
.id_table = whitelist_id_table, .id_table = whitelist_id_table,
.id = "whitelist",
.full_name = "Hardcoded whitelist" .full_name = "Hardcoded whitelist"
}; };
@@ -140,33 +138,56 @@ print_driver (const FpDeviceClass *cls)
if (g_hash_table_lookup (printed, key) != NULL) if (g_hash_table_lookup (printed, key) != NULL)
{ {
if (cls == &whitelist)
g_warning ("%s implemented by driver %s",
key, (const char *) g_hash_table_lookup (printed, key));
g_free (key); g_free (key);
continue; continue;
} }
g_hash_table_insert (printed, key, GINT_TO_POINTER (1)); g_hash_table_insert (printed, key, (void *) cls->id);
if (num_printed == 0) 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); 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++; num_printed++;
} }
if (num_printed > 0) if (num_printed > 0)
g_print ("\n"); 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 int
main (int argc, char **argv) main (int argc, char **argv)
{ {
g_autoptr(GArray) drivers = fpi_get_driver_types (); g_autoptr(GArray) drivers = fpi_get_driver_types ();
g_autofree char *program_name = NULL;
guint i; 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);
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); 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++) for (i = 0; i < drivers->len; i++)
{ {
+30 -11
View File
@@ -155,6 +155,15 @@ foreach driver: drivers
if driver == 'virtual_image' if driver == 'virtual_image'
drivers_sources += [ 'drivers/virtual-image.c' ] drivers_sources += [ 'drivers/virtual-image.c' ]
endif 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
if driver == 'synaptics' if driver == 'synaptics'
drivers_sources += [ drivers_sources += [
'drivers/synaptics/synaptics.c', 'drivers/synaptics/synaptics.c',
@@ -258,7 +267,7 @@ libfprint_drivers = static_library('fprint-drivers',
mapfile = files('libfprint.ver') mapfile = files('libfprint.ver')
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0]) 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: [ sources: [
fp_enums, fp_enums,
libfprint_sources, libfprint_sources,
@@ -295,20 +304,30 @@ libfprint_private_dep = declare_dependency(
] ]
) )
udev_rules = executable('fprint-list-udev-rules', udev_hwdb = executable('fprint-list-udev-hwdb',
'fprint-list-udev-rules.c', 'fprint-list-udev-hwdb.c',
dependencies: libfprint_private_dep, dependencies: libfprint_private_dep,
link_with: libfprint_drivers, link_with: libfprint_drivers,
install: false) install: false)
if get_option('udev_rules') udev_hwdb_generator = custom_target('udev-hwdb',
custom_target('udev-rules', output: 'autosuspend.hwdb',
output: '60-@0@-autosuspend.rules'.format(versioned_libname), depend_files: drivers_sources,
capture: true, capture: true,
command: [ udev_rules ], command: [ udev_hwdb ],
install: true, install: false,
install_dir: udev_rules_dir) )
endif
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', supported_devices = executable('fprint-list-supported-devices',
'fprint-list-supported-devices.c', 'fprint-list-supported-devices.c',
+46 -5
View File
@@ -88,7 +88,12 @@ cairo_dep = dependency('cairo', required: false)
# Drivers # Drivers
drivers = get_option('drivers').split(',') drivers = get_option('drivers').split(',')
virtual_drivers = [ 'virtual_image' ] virtual_drivers = [
'virtual_image',
'virtual_device',
'virtual_device_storage',
]
default_drivers = [ default_drivers = [
'upektc_img', 'upektc_img',
'vfs5011', 'vfs5011',
@@ -113,6 +118,13 @@ default_drivers = [
'goodixmoc', '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 all_drivers = default_drivers + virtual_drivers
if drivers == [ 'all' ] if drivers == [ 'all' ]
@@ -127,6 +139,18 @@ if drivers.length() == 0 or drivers[0] == ''
error('Cannot build libfprint without drivers, please specify a valid value for the drivers option') error('Cannot build libfprint without drivers, please specify a valid value for the drivers option')
endif 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) nss_dep = dependency('', required: false)
imaging_dep = dependency('', required: false) imaging_dep = dependency('', required: false)
libfprint_conf.set10('HAVE_PIXMAN', false) libfprint_conf.set10('HAVE_PIXMAN', false)
@@ -150,6 +174,20 @@ foreach driver: drivers
endif endif
endforeach 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
if default_drivers_are_enabled and supported_drivers != drivers
default_drivers_are_enabled = false
endif
# Export the drivers' types to the core code # Export the drivers' types to the core code
drivers_type_list = [] drivers_type_list = []
drivers_type_func = [] drivers_type_func = []
@@ -162,7 +200,7 @@ drivers_type_func += '{'
drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));' drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));'
drivers_type_func += ' GType t;' drivers_type_func += ' GType t;'
drivers_type_func += '' drivers_type_func += ''
foreach driver: drivers foreach driver: supported_drivers
drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);' drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);'
drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();' drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();'
drivers_type_func += ' g_array_append_val (drivers, t);' drivers_type_func += ' g_array_append_val (drivers, t);'
@@ -175,12 +213,14 @@ drivers_type_func += '}'
root_inc = include_directories('.') root_inc = include_directories('.')
if get_option('udev_rules') 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_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
else
udev_hwdb_dir = false
endif endif
if get_option('gtk-examples') if get_option('gtk-examples')
@@ -204,6 +244,7 @@ if get_option('gtk-examples')
subdir('demo') subdir('demo')
endif endif
subdir('data')
subdir('tests') subdir('tests')
pkgconfig = import('pkgconfig') pkgconfig = import('pkgconfig')
+2 -2
View File
@@ -10,8 +10,8 @@ option('udev_rules',
description: 'Whether to create a udev rules file', description: 'Whether to create a udev rules file',
type: 'boolean', type: 'boolean',
value: true) value: true)
option('udev_rules_dir', option('udev_hwdb_dir',
description: 'Installation path for udev rules', description: 'Installation path for udev hwdb',
type: 'string', type: 'string',
value: 'auto') value: 'auto')
option('gtk-examples', option('gtk-examples',
+8 -8
View File
@@ -35,11 +35,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0000 A: bcdDevice=0000
A: bmAttributes=80 A: bmAttributes=80
A: busnum=3 A: busnum=3\n
A: configuration= A: configuration=
H: descriptors=12011001FFFFFF08FF0831570000000100010902200001010080320904000002FFFFFF000705810240000007050202080000 H: descriptors=12011001FFFFFF08FF0831570000000100010902200001010080320904000002FFFFFF000705810240000007050202080000
A: dev=189:259 A: dev=189:259
A: devnum=4 A: devnum=4\n
A: devpath=1.1.3 A: devpath=1.1.3
L: driver=../../../../../../../../../../bus/usb/drivers/usb L: driver=../../../../../../../../../../bus/usb/drivers/usb
A: idProduct=5731 A: idProduct=5731
@@ -106,11 +106,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=9100 A: bcdDevice=9100
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=3 A: busnum=3\n
A: configuration= A: configuration=
H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
A: dev=189:258 A: dev=189:258
A: devnum=3 A: devnum=3\n
A: devpath=1.1 A: devpath=1.1
L: driver=../../../../../../../../../bus/usb/drivers/usb L: driver=../../../../../../../../../bus/usb/drivers/usb
A: idProduct=0006 A: idProduct=0006
@@ -186,11 +186,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=9100 A: bcdDevice=9100
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=3 A: busnum=3\n
A: configuration= A: configuration=
H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
A: dev=189:257 A: dev=189:257
A: devnum=2 A: devnum=2\n
A: devpath=1 A: devpath=1
L: driver=../../../../../../../../bus/usb/drivers/usb L: driver=../../../../../../../../bus/usb/drivers/usb
A: idProduct=0006 A: idProduct=0006
@@ -270,11 +270,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0415 A: bcdDevice=0415
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=3 A: busnum=3\n
A: configuration= A: configuration=
H: descriptors=12010002090001406B1D020015040302010109021900010100E0000904000001090000000705810304000C H: descriptors=12010002090001406B1D020015040302010109021900010100E0000904000001090000000705810304000C
A: dev=189:256 A: dev=189:256
A: devnum=1 A: devnum=1\n
A: devpath=0 A: devpath=0
L: driver=../../../../../../../bus/usb/drivers/usb L: driver=../../../../../../../bus/usb/drivers/usb
A: idProduct=0002 A: idProduct=0002
+6 -6
View File
@@ -36,11 +36,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0140 A: bcdDevice=0140
A: bmAttributes=80 A: bmAttributes=80
A: busnum=1 A: busnum=1\n
A: configuration= A: configuration=
H: descriptors=1201000200000008F304260C40010102000109023E0001010080320904000005FF0000000921100100012215000705810240000107050102400001070582024000010705830240000107050302400001 H: descriptors=1201000200000008F304260C40010102000109023E0001010080320904000005FF0000000921100100012215000705810240000107050102400001070582024000010705830240000107050302400001
A: dev=189:93 A: dev=189:93
A: devnum=94 A: devnum=94\n
A: devpath=4.4 A: devpath=4.4
L: driver=../../../../../../bus/usb/drivers/usb L: driver=../../../../../../bus/usb/drivers/usb
A: idProduct=0c26 A: idProduct=0c26
@@ -107,11 +107,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=5284 A: bcdDevice=5284
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=1 A: busnum=1\n
A: configuration= A: configuration=
H: descriptors=1201100209000140EF17181084520102000109021900010100E0000904000001090000000705810301000C H: descriptors=1201100209000140EF17181084520102000109021900010100E0000904000001090000000705810301000C
A: dev=189:82 A: dev=189:82
A: devnum=83 A: devnum=83\n
A: devpath=4 A: devpath=4
L: driver=../../../../../bus/usb/drivers/usb L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=1018 A: idProduct=1018
@@ -189,11 +189,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0503 A: bcdDevice=0503
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=1 A: busnum=1\n
A: configuration= A: configuration=
H: descriptors=12010002090001406B1D020003050302010109021900010100E0000904000001090000000705810304000C H: descriptors=12010002090001406B1D020003050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0 A: dev=189:0
A: devnum=1 A: devnum=1\n
A: devpath=0 A: devpath=0
L: driver=../../../../bus/usb/drivers/usb L: driver=../../../../bus/usb/drivers/usb
A: idProduct=0002 A: idProduct=0002
+4 -4
View File
@@ -37,11 +37,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0100 A: bcdDevice=0100
A: bmAttributes=a0 A: bmAttributes=a0
A: busnum=1 A: busnum=1\n
A: configuration=UIDCBEE4D7B_XXXX_MOC_B0 A: configuration=UIDCBEE4D7B_XXXX_MOC_B0
H: descriptors=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000 H: descriptors=12010002EF000040C627A26000010102030109022000010103A0320904000002FF0000040705830240000007050102400000
A: dev=189:2 A: dev=189:2
A: devnum=3 A: devnum=3\n
A: devpath=8 A: devpath=8
L: driver=../../../../../bus/usb/drivers/usb L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=60a2 A: idProduct=60a2
@@ -125,11 +125,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0504 A: bcdDevice=0504
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=1 A: busnum=1\n
A: configuration= A: configuration=
H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0 A: dev=189:0
A: devnum=1 A: devnum=1\n
A: devpath=0 A: devpath=0
L: driver=../../../../bus/usb/drivers/usb L: driver=../../../../bus/usb/drivers/usb
A: idProduct=0002 A: idProduct=0002
+54
View File
@@ -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)
+54 -33
View File
@@ -5,6 +5,7 @@ envs.set('G_MESSAGES_DEBUG', 'all')
# Setup paths # Setup paths
envs.set('MESON_SOURCE_ROOT', meson.source_root()) 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')) 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 # Set FP_DEVICE_EMULATION so that drivers can adapt (e.g. to use fixed
@@ -12,7 +13,11 @@ envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint'))
envs.set('FP_DEVICE_EMULATION', '1') envs.set('FP_DEVICE_EMULATION', '1')
# Set a colon-separated list of native drivers we enable in tests # 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') envs.set('NO_AT_BRIDGE', '1')
@@ -28,49 +33,58 @@ drivers_tests = [
if get_option('introspection') if get_option('introspection')
envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint')) envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint'))
virtual_devices_tests = [
'virtual-image',
'virtual-device',
]
if 'virtual_image' in drivers unittest_inspector = find_program('unittest_inspector.py')
python3 = find_program('python3')
unittest_inspector = find_program('unittest_inspector.py')
base_args = files('virtual-image.py')
suite = []
r = run_command(unittest_inspector, files('virtual-image.py')) foreach vdtest: virtual_devices_tests
unit_tests = r.stdout().strip().split('\n') 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 r = run_command(unittest_inspector, files(vdtest + '.py'))
suite += 'virtual-image' unit_tests = r.stdout().strip().split('\n')
else
unit_tests = ['virtual-image']
endif
foreach ut: unit_tests if r.returncode() == 0 and unit_tests.length() > 0
ut_suite = suite suite += vdtest
ut_args = base_args else
if unit_tests.length() > 1 unit_tests = [vdtest]
ut_args += ut
ut_suite += ut.split('.')[0]
endif endif
test(ut,
python3, foreach ut: unit_tests
args: ut_args, ut_suite = suite
suite: ut_suite, ut_args = base_args
depends: libfprint_typelib, if unit_tests.length() > 1
env: envs, 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 endif
else endforeach
test('virtual-image',
find_program('sh'),
args: ['-c', 'exit 77']
)
endif
foreach driver_test: drivers_tests foreach driver_test: drivers_tests
driver_envs = envs driver_envs = envs
driver_envs.set('FP_DRIVERS_WHITELIST', driver_test) 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, test(driver_test,
find_program('umockdev-test.py'), find_program('umockdev-test.py'),
args: join_paths(meson.current_source_dir(), driver_test), args: join_paths(meson.current_source_dir(), driver_test),
@@ -168,6 +182,13 @@ foreach test_name: unit_tests
) )
endforeach 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',
find_program('test-generated-hwdb.sh'),
env: envs)
gdb = find_program('gdb', required: false) gdb = find_program('gdb', required: false)
if gdb.found() if gdb.found()
add_test_setup('gdb', add_test_setup('gdb',
+2 -2
View File
@@ -34,11 +34,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0000 A: bcdDevice=0000
A: bmAttributes=a0 A: bmAttributes=a0
A: busnum=1 A: busnum=1\n
A: configuration= A: configuration=
H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004 H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004
A: dev=189:69 A: dev=189:69
A: devnum=70 A: devnum=70\n
A: devpath=1 A: devpath=1
L: driver=../../../../../bus/usb/drivers/usb L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=00bd A: idProduct=00bd
+7 -7
View File
@@ -50,7 +50,7 @@ test_context_has_virtual_device (void)
GPtrArray *devices; GPtrArray *devices;
unsigned int i; unsigned int i;
fpt_setup_virtual_device_environment (); fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
context = fp_context_new (); context = fp_context_new ();
devices = fp_context_get_devices (context); devices = fp_context_get_devices (context);
@@ -82,7 +82,7 @@ test_context_enumerates_new_devices (void)
context = fp_context_new (); context = fp_context_new ();
fpt_setup_virtual_device_environment (); fpt_setup_virtual_device_environment (FPT_VIRTUAL_DEVICE_IMAGE);
fp_context_enumerate (context); fp_context_enumerate (context);
devices = fp_context_get_devices (context); devices = fp_context_get_devices (context);
@@ -120,7 +120,7 @@ context_device_removed_cb (FpContext *ctx, FpDevice *device, FptContext *tctx)
static void static void
test_context_remove_device_closed (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; gboolean removed;
tctx->user_data = NULL; tctx->user_data = NULL;
@@ -162,7 +162,7 @@ close_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
static void static void
test_context_remove_device_closing (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) close_error = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
gboolean removed; gboolean removed;
@@ -207,7 +207,7 @@ test_context_remove_device_closing (void)
static void static void
test_context_remove_device_open (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; g_autoptr(GError) error = NULL;
gboolean removed = FALSE; gboolean removed = FALSE;
@@ -267,7 +267,7 @@ open_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
static void static void
test_context_remove_device_opening (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; g_autoptr(GError) close_error = NULL;
gboolean open_done = FALSE; gboolean open_done = FALSE;
gboolean removed; gboolean removed;
@@ -327,7 +327,7 @@ enroll_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
static void static void
test_context_remove_device_active (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(GError) error = NULL;
g_autoptr(GCancellable) cancellable = NULL; g_autoptr(GCancellable) cancellable = NULL;
g_autoptr(GError) enroll_error = NULL; g_autoptr(GError) enroll_error = NULL;
+15 -15
View File
@@ -36,7 +36,7 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, FptContext *tctx)
static void static void
test_device_open_async (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); 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 static void
test_device_close_async (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); fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx);
while (!tctx->user_data) while (!tctx->user_data)
@@ -76,7 +76,7 @@ static void
test_device_open_sync (void) test_device_open_sync (void)
{ {
g_autoptr(GError) error = NULL; 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); fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error); g_assert_no_error (error);
@@ -97,7 +97,7 @@ static void
test_device_open_sync_notify (void) test_device_open_sync_notify (void)
{ {
g_autoptr(GError) error = NULL; 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); g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_open_notify), tctx);
fp_device_open_sync (tctx->device, NULL, &error); fp_device_open_sync (tctx->device, NULL, &error);
@@ -109,7 +109,7 @@ static void
test_device_close_sync (void) test_device_close_sync (void)
{ {
g_autoptr(GError) error = NULL; 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_open_sync (tctx->device, NULL, NULL);
fp_device_close_sync (tctx->device, NULL, &error); fp_device_close_sync (tctx->device, NULL, &error);
@@ -131,7 +131,7 @@ static void
test_device_close_sync_notify (void) test_device_close_sync_notify (void)
{ {
g_autoptr(GError) error = NULL; 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_open_sync (tctx->device, NULL, NULL);
@@ -144,7 +144,7 @@ test_device_close_sync_notify (void)
static void static void
test_device_get_driver (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image"); g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image");
@@ -153,7 +153,7 @@ test_device_get_driver (void)
static void static void
test_device_get_device_id (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0"); g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0");
@@ -162,7 +162,7 @@ test_device_get_device_id (void)
static void static void
test_device_get_name (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpstr (fp_device_get_name (tctx->device), ==, g_assert_cmpstr (fp_device_get_name (tctx->device), ==,
@@ -172,7 +172,7 @@ test_device_get_name (void)
static void static void
test_device_get_scan_type (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE); 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 static void
test_device_get_finger_status (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpint (fp_device_get_finger_status (tctx->device), ==, FP_FINGER_STATUS_NONE); 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 static void
test_device_get_nr_enroll_stages (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpuint (fp_device_get_nr_enroll_stages (tctx->device), ==, 5); 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 static void
test_device_supports_identify (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_true (fp_device_supports_identify (tctx->device)); g_assert_true (fp_device_supports_identify (tctx->device));
@@ -208,7 +208,7 @@ test_device_supports_identify (void)
static void static void
test_device_supports_capture (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_true (fp_device_supports_capture (tctx->device)); g_assert_true (fp_device_supports_capture (tctx->device));
@@ -217,7 +217,7 @@ test_device_supports_capture (void)
static void static void
test_device_has_storage (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); fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_false (fp_device_has_storage (tctx->device)); g_assert_false (fp_device_has_storage (tctx->device));
+24
View File
@@ -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 ! 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
fi
rm "$generated_rules"
+31 -9
View File
@@ -22,16 +22,31 @@
#include "test-utils.h" #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 */
{ "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;
void void
fpt_teardown_virtual_device_environment (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) if (path)
{ {
g_autofree char *temp_dir = g_path_get_dirname (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_unlink (path);
g_rmdir (temp_dir); g_rmdir (temp_dir);
} }
@@ -44,19 +59,23 @@ on_signal_event (int sig)
} }
void void
fpt_setup_virtual_device_environment (void) fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype)
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
g_autofree char *temp_dir = NULL; g_autofree char *temp_dir = NULL;
g_autofree char *temp_path = 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); temp_dir = g_dir_make_tmp ("libfprint-XXXXXX", &error);
g_assert_no_error (error); g_assert_no_error (error);
temp_path = g_build_filename (temp_dir, "virtual-image.socket", NULL); filename = g_strdup_printf ("%s.socket", devtype_vars[devtype].device_id);
g_setenv ("FP_VIRTUAL_IMAGE", temp_path, TRUE); 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 (SIGKILL, on_signal_event);
signal (SIGABRT, on_signal_event); signal (SIGABRT, on_signal_event);
@@ -78,13 +97,16 @@ fpt_context_new (void)
} }
FptContext * FptContext *
fpt_context_new_with_virtual_imgdev (void) fpt_context_new_with_virtual_device (FptVirtualDeviceType devtype)
{ {
FptContext *tctx; FptContext *tctx;
GPtrArray *devices; GPtrArray *devices;
unsigned int i; 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 (); tctx = fpt_context_new ();
devices = fp_context_get_devices (tctx->fp_context); devices = fp_context_get_devices (tctx->fp_context);
@@ -96,7 +118,7 @@ fpt_context_new_with_virtual_imgdev (void)
{ {
FpDevice *device = devices->pdata[i]; 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; tctx->device = device;
break; break;
+9 -2
View File
@@ -19,7 +19,14 @@
#include <glib.h> #include <glib.h>
void fpt_setup_virtual_device_environment (void); typedef enum {
FPT_VIRTUAL_DEVICE_IMAGE = 0,
FPT_VIRTUAL_DEVICE_NONIMAGE,
FPT_VIRTUAL_DEVICE_NONIMAGE_STORAGE,
FPT_NUM_VIRTUAL_DEVICE_TYPES
} FptVirtualDeviceType;
void fpt_setup_virtual_device_environment (FptVirtualDeviceType devtype);
void fpt_teardown_virtual_device_environment (void); void fpt_teardown_virtual_device_environment (void);
typedef struct _FptContext typedef struct _FptContext
@@ -30,7 +37,7 @@ typedef struct _FptContext
} FptContext; } FptContext;
FptContext * fpt_context_new (void); 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); void fpt_context_free (FptContext *test_context);
Regular → Executable
View File
+2 -2
View File
@@ -38,11 +38,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0060 A: bcdDevice=0060
A: bmAttributes=a0 A: bmAttributes=a0
A: busnum=1 A: busnum=1\n
A: configuration= A: configuration=
H: descriptors=12011001FF10FF088A13500060000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 H: descriptors=12011001FF10FF088A13500060000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004
A: dev=189:3 A: dev=189:3
A: devnum=4 A: devnum=4\n
A: devpath=9 A: devpath=9
L: driver=../../../../../bus/usb/drivers/usb L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=0050 A: idProduct=0050
+6 -6
View File
@@ -37,11 +37,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0c90 A: bcdDevice=0c90
A: bmAttributes=a0 A: bmAttributes=a0
A: busnum=2 A: busnum=2\n
A: configuration= A: configuration=
H: descriptors=12011001FF10FF088A130500900C0000000109022700010100A0320904000003FF000000070501024000000705810240000007058202400000 H: descriptors=12011001FF10FF088A130500900C0000000109022700010100A0320904000003FF000000070501024000000705810240000007058202400000
A: dev=189:132 A: dev=189:132
A: devnum=5 A: devnum=5\n
A: devpath=1.3 A: devpath=1.3
L: driver=../../../../../../bus/usb/drivers/usb L: driver=../../../../../../bus/usb/drivers/usb
A: idProduct=0005 A: idProduct=0005
@@ -120,11 +120,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0000 A: bcdDevice=0000
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=2 A: busnum=2\n
A: configuration= A: configuration=
H: descriptors=12010002090001408780200000000000000109021900010100E0000904000001090000000705810302000C H: descriptors=12010002090001408780200000000000000109021900010100E0000904000001090000000705810302000C
A: dev=189:129 A: dev=189:129
A: devnum=2 A: devnum=2\n
A: devpath=1 A: devpath=1
L: driver=../../../../../bus/usb/drivers/usb L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=0020 A: idProduct=0020
@@ -204,11 +204,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0504 A: bcdDevice=0504
A: bmAttributes=e0 A: bmAttributes=e0
A: busnum=2 A: busnum=2\n
A: configuration= A: configuration=
H: descriptors=12010002090000406B1D020004050302010109021900010100E0000904000001090000000705810304000C H: descriptors=12010002090000406B1D020004050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:128 A: dev=189:128
A: devnum=1 A: devnum=1\n
A: devpath=0 A: devpath=0
L: driver=../../../../bus/usb/drivers/usb L: driver=../../../../bus/usb/drivers/usb
A: idProduct=0002 A: idProduct=0002
+2 -2
View File
@@ -35,11 +35,11 @@ A: bNumConfigurations=1
A: bNumInterfaces= 1 A: bNumInterfaces= 1
A: bcdDevice=0078 A: bcdDevice=0078
A: bmAttributes=a0 A: bmAttributes=a0
A: busnum=2 A: busnum=2\n
A: configuration= A: configuration=
H: descriptors=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004 H: descriptors=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004
A: dev=189:144 A: dev=189:144
A: devnum=17 A: devnum=17\n
A: devpath=6 A: devpath=6
L: driver=../../../../../bus/usb/drivers/usb L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=0017 A: idProduct=0017
+247
View File
@@ -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'(?<!^)(?=[A-Z])').sub(
'_', cls.__name__).lower()
sock_name = driver_name.replace('_', '-')
cls.sockaddr = os.path.join(cls.tmpdir, '{}.socket'.format(sock_name))
os.environ['FP_{}'.format(driver_name.upper())] = cls.sockaddr
cls.ctx = FPrint.Context()
cls.dev = None
for dev in cls.ctx.get_devices():
# We might have a USB device in the test system that needs skipping
if dev.get_driver() == driver_name:
cls.dev = dev
break
assert cls.dev is not None, "You need to compile with {} for testing".format(driver_name)
@classmethod
def tearDownClass(cls):
shutil.rmtree(cls.tmpdir)
del cls.dev
del cls.ctx
unittest.TestCase.tearDownClass()
def setUp(self):
super().setUp()
self.assertFalse(self.dev.is_open())
self.dev.open_sync()
self.assertTrue(self.dev.is_open())
def tearDown(self):
self.assertTrue(self.dev.is_open())
self.dev.close_sync()
self.assertFalse(self.dev.is_open())
super().tearDown()
def send_command(self, command, *args):
self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR'])
with Connection(self.sockaddr) as con:
params = ' '.join(str(p) for p in args)
con.sendall('{} {}'.format(command, params).encode('utf-8'))
while ctx.pending():
ctx.iteration(False)
def enroll_print(self, nick, finger, username='testuser'):
self._enrolled = None
def done_cb(dev, res):
print("Enroll done")
self._enrolled = dev.enroll_finish(res)
self.send_command('SCAN', nick)
template = FPrint.Print.new(self.dev)
template.set_finger(finger)
template.set_username(username)
self.dev.enroll(template, None, None, tuple(), done_cb)
while self._enrolled is None:
ctx.iteration(False)
self.assertEqual(self._enrolled.get_device_stored(),
self.dev.has_storage())
return self._enrolled
def check_verify(self, p, scan_nick, match):
self._verify_match = None
self._verify_fp = None
self._verify_error = None
if isinstance(scan_nick, str):
self.send_command('SCAN', scan_nick)
else:
self.send_command('ERROR', scan_nick)
def verify_cb(dev, res):
try:
self._verify_match, self._verify_fp = dev.verify_finish(res)
except gi.repository.GLib.Error as e:
self._verify_error = e
self.dev.verify(p, callback=verify_cb)
while self._verify_match is None and self._verify_error is None:
ctx.iteration(True)
if match:
assert self._verify_fp.equal(p)
if isinstance(scan_nick, str):
self.assertEqual(self._verify_fp.props.fpi_data.get_string(), scan_nick)
if self._verify_error is not None:
raise self._verify_error
def test_device_properties(self):
self.assertEqual(self.dev.get_driver(), 'virtual_device')
self.assertEqual(self.dev.get_device_id(), '0')
self.assertEqual(self.dev.get_name(), 'Virtual device for debugging')
self.assertTrue(self.dev.is_open())
self.assertEqual(self.dev.get_scan_type(), FPrint.ScanType.SWIPE)
self.assertEqual(self.dev.get_nr_enroll_stages(), 5)
self.assertFalse(self.dev.supports_identify())
self.assertFalse(self.dev.supports_capture())
self.assertFalse(self.dev.has_storage())
def test_enroll(self):
matching = self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE)
self.assertEqual(matching.get_username(), 'testuser')
self.assertEqual(matching.get_finger(), FPrint.Finger.LEFT_LITTLE)
def test_enroll_verify_match(self):
matching = self.enroll_print('testprint', FPrint.Finger.LEFT_THUMB)
self.check_verify(matching, 'testprint', match=True)
def test_enroll_verify_no_match(self):
matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING)
self.check_verify(matching, 'not-testprint', match=False)
def test_enroll_verify_error(self):
matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING)
with self.assertRaisesRegex(GLib.Error, r"An unspecified error occurred"):
self.check_verify(matching, 0, match=False)
class VirtualDeviceStorage(VirtualDevice):
def cleanup_device_storage(self):
for print in self.dev.list_prints_sync():
self.assertTrue(self.dev.delete_print_sync(print, None))
def test_device_properties(self):
self.assertEqual(self.dev.get_driver(), 'virtual_device_storage')
self.assertEqual(self.dev.get_device_id(), '0')
self.assertEqual(self.dev.get_name(),
'Virtual device with storage and identification for debugging')
self.assertTrue(self.dev.is_open())
self.assertEqual(self.dev.get_scan_type(), FPrint.ScanType.SWIPE)
self.assertEqual(self.dev.get_nr_enroll_stages(), 5)
self.assertTrue(self.dev.supports_identify())
self.assertFalse(self.dev.supports_capture())
self.assertTrue(self.dev.has_storage())
def test_list_empty(self):
self.cleanup_device_storage()
self.assertFalse(self.dev.list_prints_sync())
def test_list_populated(self):
self.cleanup_device_storage()
self.send_command('INSERT', 'p1')
print2 = self.enroll_print('p2', FPrint.Finger.LEFT_LITTLE)
self.assertEqual({'p1', 'p2'}, {p.props.fpi_data.get_string() for p in self.dev.list_prints_sync()})
def test_list_delete(self):
self.cleanup_device_storage()
p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB)
l = self.dev.list_prints_sync()
print(l[0])
self.assertEqual(len(l), 1)
print('blub', p.props.fpi_data, type(l[0].props.fpi_data))
assert p.equal(l[0])
self.dev.delete_print_sync(p)
self.assertFalse(self.dev.list_prints_sync())
def test_list_delete_missing(self):
self.cleanup_device_storage()
p = self.enroll_print('testprint', FPrint.Finger.RIGHT_THUMB)
self.send_command('REMOVE', 'testprint')
with self.assertRaisesRegex(GLib.GError, 'Print was not found'):
self.dev.delete_print_sync(p)
if __name__ == '__main__':
try:
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint
except Exception as e:
print("Missing dependencies: %s" % str(e))
sys.exit(77)
# avoid writing to stderr
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))