mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-06-11 02:28:05 +00:00
Merge tag 'v1.94.5' into tod
v1.94.5 * New driver: fpcmoc, supporting various FPC MOC Fingerprint Sensors * goodixmoc: New PIDs 0x6014, 0x6094, 0x631C, 0x634C, 0x6384, 0x659A. * goodixmoc: Support resetting device on firmware failure due to corrupted DB. * elanmoc: New PIDs 0x0c88, 0x0c8c, 0x0c8d. * synaptics: New PID 0x0104. * upektc: New PID 0x2017. * Fixed various memory leaks * More tests Git-EVTag-v0-SHA512: a36e4b627ffc830a78932266119b73e53921965990bd1b6cae6fd8d166b1b8e62f5a538151a74b82a2a2d83a4ab7399ed17cb2bef39441f881a38a24252e4efa
This commit is contained in:
@@ -190,7 +190,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
|
||||
{
|
||||
if (!self->stop && (self->strips_len > 0))
|
||||
{
|
||||
FpImage *img;
|
||||
g_autoptr(FpImage) img = NULL;
|
||||
self->strips = g_slist_reverse (self->strips);
|
||||
fpi_do_movement_estimation (&assembling_ctx, self->strips);
|
||||
img = fpi_assemble_frames (&assembling_ctx, self->strips);
|
||||
@@ -199,7 +199,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
|
||||
self->strips = NULL;
|
||||
self->strips_len = 0;
|
||||
FpImage *resizeImage = fpi_image_resize (img, EGIS0570_RESIZE, EGIS0570_RESIZE);
|
||||
fpi_image_device_image_captured (img_self, resizeImage);
|
||||
fpi_image_device_image_captured (img_self, g_steal_pointer (&resizeImage));
|
||||
}
|
||||
|
||||
fpi_image_device_report_finger_status (img_self, FALSE);
|
||||
|
||||
@@ -357,7 +357,7 @@ elan_cmd_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
||||
if (transfer->endpoint & FPI_USB_ENDPOINT_IN)
|
||||
{
|
||||
/* just finished receiving */
|
||||
self->last_read = g_memdup (transfer->buffer, transfer->actual_length);
|
||||
self->last_read = g_memdup2 (transfer->buffer, transfer->actual_length);
|
||||
elan_cmd_done (ssm);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -215,6 +215,7 @@ static const FpIdEntry elan_id_table[] = {
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c3d, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c4b, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c4d, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c4f, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c63, .driver_data = ELAN_ALL_DEV},
|
||||
|
||||
@@ -27,6 +27,10 @@ G_DEFINE_TYPE (FpiDeviceElanmoc, fpi_device_elanmoc, FP_TYPE_DEVICE)
|
||||
static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x04f3, .pid = 0x0c7d, },
|
||||
{ .vid = 0x04f3, .pid = 0x0c7e, },
|
||||
{ .vid = 0x04f3, .pid = 0x0c82, },
|
||||
{ .vid = 0x04f3, .pid = 0x0c88, },
|
||||
{ .vid = 0x04f3, .pid = 0x0c8c, },
|
||||
{ .vid = 0x04f3, .pid = 0x0c8d, },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||
};
|
||||
|
||||
@@ -375,9 +379,9 @@ elanmoc_enroll_cb (FpiDeviceElanmoc *self,
|
||||
enroll_status_report (self, ENROLL_RSP_RETRY, self->num_frames, NULL);
|
||||
}
|
||||
|
||||
if (self->num_frames == ELAN_MOC_ENROLL_TIMES && buffer_in[1] == ELAN_MSG_OK)
|
||||
if (self->num_frames == self->max_moc_enroll_time && buffer_in[1] == ELAN_MSG_OK)
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
else if (self->num_frames < ELAN_MOC_ENROLL_TIMES)
|
||||
else if (self->num_frames < self->max_moc_enroll_time)
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
|
||||
else
|
||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||
@@ -440,7 +444,7 @@ elan_enroll_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
case MOC_ENROLL_WAIT_FINGER:
|
||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_enroll_cmd);
|
||||
cmd_buf[3] = self->curr_enrolled;
|
||||
cmd_buf[4] = ELAN_MOC_ENROLL_TIMES;
|
||||
cmd_buf[4] = self->max_moc_enroll_time;
|
||||
cmd_buf[5] = self->num_frames;
|
||||
elanmoc_get_cmd (dev, cmd_buf, elanmoc_enroll_cmd.cmd_len, elanmoc_enroll_cmd.resp_len, 1, elanmoc_enroll_cb);
|
||||
break;
|
||||
@@ -505,7 +509,7 @@ create_print_from_response (FpiDeviceElanmoc *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
userid = g_memdup (&buffer_in[5], userid_len);
|
||||
userid = g_memdup2 (&buffer_in[5], userid_len);
|
||||
userid_safe = g_strndup ((const char *) &buffer_in[5], userid_len);
|
||||
print = fp_print_new (FP_DEVICE (self));
|
||||
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, userid, userid_len, 1);
|
||||
@@ -757,6 +761,7 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
||||
}
|
||||
|
||||
enum identify_states {
|
||||
IDENTIFY_SET_MODE,
|
||||
IDENTIFY_WAIT_FINGER,
|
||||
IDENTIFY_NUM_STATES,
|
||||
};
|
||||
@@ -792,6 +797,13 @@ elan_identify_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
fp_info ("elanmoc %s ", __func__);
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case IDENTIFY_SET_MODE:
|
||||
fp_info ("elanmoc %s IDENTIFY_SET_MODE", __func__);
|
||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_set_mod_cmd);
|
||||
cmd_buf[3] = 0x03;
|
||||
elanmoc_get_cmd (dev, cmd_buf, elanmoc_set_mod_cmd.cmd_len, elanmoc_set_mod_cmd.resp_len, 0, elanmoc_cmd_ack_cb);
|
||||
break;
|
||||
|
||||
case IDENTIFY_WAIT_FINGER:
|
||||
fp_info ("elanmoc %s VERIFY_WAIT_FINGER", __func__);
|
||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_verify_cmd);
|
||||
@@ -998,6 +1010,12 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
|
||||
}
|
||||
|
||||
if (buffer_in[1] != 0x03 && self->cmd_retry_cnt != 0)
|
||||
{
|
||||
self->cmd_retry_cnt--;
|
||||
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
|
||||
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(self->cmd_retry_cnt == 0)
|
||||
{
|
||||
@@ -1006,12 +1024,6 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
|
||||
"Sensor not ready"));
|
||||
return;
|
||||
}
|
||||
self->cmd_retry_cnt--;
|
||||
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
|
||||
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
}
|
||||
@@ -1059,6 +1071,7 @@ elanmoc_open (FpDevice *device)
|
||||
{
|
||||
FpiDeviceElanmoc *self = FPI_DEVICE_ELANMOC (device);
|
||||
GError *error = NULL;
|
||||
gint productid = 0;
|
||||
|
||||
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
|
||||
goto error;
|
||||
@@ -1066,6 +1079,24 @@ elanmoc_open (FpDevice *device)
|
||||
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
|
||||
goto error;
|
||||
|
||||
productid = g_usb_device_get_pid (fpi_device_get_usb_device (device));
|
||||
switch (productid)
|
||||
{
|
||||
case 0x0c8c:
|
||||
self->max_moc_enroll_time = 11;
|
||||
break;
|
||||
|
||||
case 0x0c8d:
|
||||
self->max_moc_enroll_time = 17;
|
||||
break;
|
||||
|
||||
default:
|
||||
self->max_moc_enroll_time = ELAN_MOC_ENROLL_TIMES;
|
||||
break;
|
||||
}
|
||||
|
||||
fpi_device_set_nr_enroll_stages (device, self->max_moc_enroll_time);
|
||||
|
||||
self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_init_handler, DEV_INIT_STATES);
|
||||
fpi_ssm_start (self->task_ssm, task_ssm_init_done);
|
||||
return;
|
||||
|
||||
@@ -188,6 +188,7 @@ struct _FpiDeviceElanmoc
|
||||
unsigned char y_trace;
|
||||
int num_frames;
|
||||
int curr_enrolled;
|
||||
int max_moc_enroll_time;
|
||||
int cancel_result;
|
||||
int cmd_retry_cnt;
|
||||
int list_index;
|
||||
|
||||
@@ -348,6 +348,7 @@ static const FpIdEntry elanspi_id_table[] = {
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x241f}, .driver_data = ELANSPI_NO_ROTATE},
|
||||
{.udev_types = 0}
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Fingerprint Cards AB <tech@fingerprints.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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fpi-device.h"
|
||||
#include "fpi-ssm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TEMPLATE_ID_SIZE (32)
|
||||
#define MAX_FW_VERSION_STR_LEN (16)
|
||||
#define FPC_CMD_INIT (0x01)
|
||||
#define FPC_CMD_ARM (0x02)
|
||||
#define FPC_CMD_ABORT (0x03)
|
||||
#define FPC_CMD_INDICATE_S_STATE (0x08)
|
||||
#define FPC_CMD_GET_IMG (0x09)
|
||||
#define FPC_CMD_GET_KPI (0x0C)
|
||||
#define FPC_CMD_LOAD_DB (0x60)
|
||||
#define FPC_CMD_STORE_DB (0x61)
|
||||
#define FPC_CMD_DELETE_DB (0x62)
|
||||
#define FPC_CMD_DELETE_TEMPLATE (0x63)
|
||||
#define FPC_CMD_BEGIN_ENROL (0x67)
|
||||
#define FPC_CMD_ENROL (0x68)
|
||||
#define FPC_CMD_END_ENROL (0x69)
|
||||
#define FPC_CMD_BIND_IDENTITY (0x6A)
|
||||
#define FPC_CMD_IDENTIFY (0x6B)
|
||||
#define FPC_CMD_ENUM (0x70)
|
||||
#define FPC_EVT_INIT_RESULT (0x02)
|
||||
#define FPC_EVT_FINGER_DWN (0x06)
|
||||
#define FPC_EVT_IMG (0x08)
|
||||
#define FPC_EVT_FID_DATA (0x31)
|
||||
#define FPC_DB_ID_LEN (16)
|
||||
#define FPC_IDENTITY_TYPE_WILDCARD (0x1)
|
||||
#define FPC_IDENTITY_TYPE_RESERVED (0x3)
|
||||
#define FPC_IDENTITY_WILDCARD (0x25066282)
|
||||
#define FPC_SUBTYPE_ANY (0xFF)
|
||||
#define FPC_SUBTYPE_RESERVED (0xF5)
|
||||
#define FPC_SUBTYPE_NOINFORMATION (0x00)
|
||||
#define FPC_CAPTUREID_RESERVED (0x701100F)
|
||||
#define FPC_SESSIONID_RESERVED (0x0077FF12)
|
||||
#define FPC_TEMPLATES_MAX (10)
|
||||
#define SECURITY_MAX_SID_SIZE (68)
|
||||
#define FPC_HOST_MS_S0 (0x10)
|
||||
#define FPC_HOST_MS_SX (0x11)
|
||||
|
||||
G_DECLARE_FINAL_TYPE (FpiDeviceFpcMoc, fpi_device_fpcmoc, FPI,
|
||||
DEVICE_FPCMOC, FpDevice);
|
||||
|
||||
typedef struct _FPC_FID_DATA
|
||||
{
|
||||
guint32 identity_type;
|
||||
guint32 reserved;
|
||||
guint32 identity_size;
|
||||
guint32 subfactor;
|
||||
guint8 data[SECURITY_MAX_SID_SIZE];
|
||||
} FPC_FID_DATA, *PFPC_FID_DATA;
|
||||
|
||||
typedef struct _FPC_LOAD_DB
|
||||
{
|
||||
gint32 status;
|
||||
guint32 reserved;
|
||||
guint32 database_id_size;
|
||||
guint8 data[FPC_DB_ID_LEN];
|
||||
} FPC_LOAD_DB, *PFPC_LOAD_DB;
|
||||
|
||||
typedef union _FPC_DELETE_DB
|
||||
{
|
||||
guint32 reserved;
|
||||
guint32 database_id_size;
|
||||
guint8 data[FPC_DB_ID_LEN];
|
||||
} FPC_DB_OP, *PFPC_DB_OP;
|
||||
|
||||
typedef struct _FPC_BEGIN_ENROL
|
||||
{
|
||||
gint32 status;
|
||||
guint32 reserved1;
|
||||
guint32 reserved2;
|
||||
} FPC_BEGIN_ENROL, *PFPC_BEGIN_ENROL;
|
||||
|
||||
typedef struct _FPC_ENROL
|
||||
{
|
||||
gint32 status;
|
||||
guint32 remaining;
|
||||
} FPC_ENROL, *PFPC_ENROL;
|
||||
|
||||
typedef struct _FPC_END_ENROL
|
||||
{
|
||||
gint32 status;
|
||||
guint32 fid;
|
||||
} FPC_END_ENROL, *PFPC_END_ENROL;
|
||||
|
||||
typedef struct _FPC_IDENTIFY
|
||||
{
|
||||
gint32 status;
|
||||
guint32 identity_type;
|
||||
guint32 identity_offset;
|
||||
guint32 identity_size;
|
||||
guint32 subfactor;
|
||||
guint8 data[SECURITY_MAX_SID_SIZE];
|
||||
} FPC_IDENTIFY, *PFPC_IDENTIFY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint32 cmdid;
|
||||
guint32 length;
|
||||
guint32 status;
|
||||
} evt_hdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
evt_hdr_t hdr;
|
||||
guint16 sensor;
|
||||
guint16 hw_id;
|
||||
guint16 img_w;
|
||||
guint16 img_h;
|
||||
guint8 fw_version[MAX_FW_VERSION_STR_LEN];
|
||||
guint16 fw_capabilities;
|
||||
} evt_initiated_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint8 subfactor;
|
||||
guint32 identity_type;
|
||||
guint32 identity_size;
|
||||
guint8 identity[SECURITY_MAX_SID_SIZE];
|
||||
} __attribute__((packed)) fpc_fid_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
evt_hdr_t hdr;
|
||||
gint status;
|
||||
guint32 num_ids;
|
||||
fpc_fid_data_t fid_data[FPC_TEMPLATES_MAX];
|
||||
} __attribute__((packed)) evt_enum_fids_t;
|
||||
|
||||
typedef struct _fp_cmd_response
|
||||
{
|
||||
union
|
||||
{
|
||||
evt_hdr_t evt_hdr;
|
||||
evt_initiated_t evt_inited;
|
||||
evt_enum_fids_t evt_enum_fids;
|
||||
};
|
||||
} fpc_cmd_response_t, *pfpc_cmd_response_t;
|
||||
|
||||
enum {
|
||||
FPC_ENROL_STATUS_COMPLETED = 0,
|
||||
FPC_ENROL_STATUS_PROGRESS = 1,
|
||||
FPC_ENROL_STATUS_FAILED_COULD_NOT_COMPLETE = 2,
|
||||
FPC_ENROL_STATUS_FAILED_ALREADY_ENROLED = 3,
|
||||
FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE = 4,
|
||||
FPC_ENROL_STATUS_IMAGE_TOO_SIMILAR = 5,
|
||||
FPC_ENROL_STATUS_IMAGE_LOW_QUALITY = 6,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FPC_CMDTYPE_UNKNOWN = 0,
|
||||
FPC_CMDTYPE_TO_DEVICE,
|
||||
FPC_CMDTYPE_TO_DEVICE_EVTDATA,
|
||||
FPC_CMDTYPE_FROM_DEVICE,
|
||||
} FpcCmdType;
|
||||
|
||||
typedef enum {
|
||||
FP_CMD_SEND = 0,
|
||||
FP_CMD_GET_DATA,
|
||||
FP_CMD_SUSPENDED,
|
||||
FP_CMD_RESUME,
|
||||
FP_CMD_NUM_STATES,
|
||||
} FpCmdState;
|
||||
|
||||
typedef enum {
|
||||
FP_INIT = 0,
|
||||
FP_LOAD_DB,
|
||||
FP_INIT_NUM_STATES,
|
||||
} FpInitState;
|
||||
|
||||
typedef enum {
|
||||
FP_ENROLL_ENUM = 0,
|
||||
FP_ENROLL_CREATE,
|
||||
FP_ENROLL_CAPTURE,
|
||||
FP_ENROLL_GET_IMG,
|
||||
FP_ENROLL_UPDATE,
|
||||
FP_ENROLL_COMPLETE,
|
||||
FP_ENROLL_CHECK_DUPLICATE,
|
||||
FP_ENROLL_BINDID,
|
||||
FP_ENROLL_COMMIT,
|
||||
FP_ENROLL_DICARD,
|
||||
FP_ENROLL_CLEANUP,
|
||||
FP_ENROLL_NUM_STATES,
|
||||
} FpEnrollState;
|
||||
|
||||
typedef enum {
|
||||
FP_VERIFY_CAPTURE = 0,
|
||||
FP_VERIFY_GET_IMG,
|
||||
FP_VERIFY_IDENTIFY,
|
||||
FP_VERIFY_CANCEL,
|
||||
FP_VERIFY_NUM_STATES,
|
||||
} FpVerifyState;
|
||||
|
||||
typedef enum {
|
||||
FP_CLEAR_DELETE_DB = 0,
|
||||
FP_CLEAR_CREATE_DB,
|
||||
FP_CLEAR_NUM_STATES,
|
||||
} FpClearState;
|
||||
@@ -661,7 +661,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
|
||||
/* */
|
||||
if (resp->result >= GX_FAILED)
|
||||
{
|
||||
fp_warn ("Capture sample failed, result: 0x%x", resp->result);
|
||||
fp_info ("Capture sample failed, result: 0x%x", resp->result);
|
||||
fpi_device_enroll_progress (FP_DEVICE (self),
|
||||
self->enroll_stage,
|
||||
NULL,
|
||||
@@ -675,7 +675,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
|
||||
if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) ||
|
||||
(resp->capture_data_resp.img_coverage < self->sensorcfg->config[5]))
|
||||
{
|
||||
fp_warn ("Capture sample poor quality(%d): %d or coverage(%d): %d",
|
||||
fp_info ("Capture sample poor quality(%d): %d or coverage(%d): %d",
|
||||
self->sensorcfg->config[4],
|
||||
resp->capture_data_resp.img_quality,
|
||||
self->sensorcfg->config[5],
|
||||
@@ -1041,6 +1041,47 @@ fp_init_config_cb (FpiDeviceGoodixMoc *self,
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_init_cb_reset_or_complete (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
fp_warn ("Template storage appears to have been corrupted! Error was: %s", error->message);
|
||||
fp_warn ("A known reason for this to happen is a firmware bug triggered by another storage area being initialized.");
|
||||
fpi_ssm_jump_to_state (self->task_ssm, FP_INIT_RESET_DEVICE);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_mark_completed (self->task_ssm);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fp_init_reset_device_cb (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
fp_warn ("Reset failed: %s", error->message);
|
||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||
return;
|
||||
}
|
||||
if ((resp->result >= GX_FAILED) && (resp->result != GX_ERROR_FINGER_ID_NOEXIST))
|
||||
{
|
||||
fp_warn ("Reset failed, device reported: 0x%x", resp->result);
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"Failed clear storage, result: 0x%x",
|
||||
resp->result));
|
||||
return;
|
||||
}
|
||||
|
||||
fp_warn ("Reset completed");
|
||||
fpi_ssm_mark_completed (self->task_ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
@@ -1065,6 +1106,30 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
sizeof (gxfp_sensor_cfg_t),
|
||||
fp_init_config_cb);
|
||||
break;
|
||||
|
||||
case FP_INIT_TEMPLATE_LIST:
|
||||
/* List prints to check whether the template DB was corrupted.
|
||||
* As of 2022-06-13 there is a known firmware issue that can cause the
|
||||
* stored templates for Linux to be corrupted when the Windows storage
|
||||
* area is initialized.
|
||||
* In that case, we'll get a protocol failure trying to retrieve the
|
||||
* list of prints.
|
||||
*/
|
||||
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
|
||||
FALSE,
|
||||
(const guint8 *) &dummy,
|
||||
1,
|
||||
fp_init_cb_reset_or_complete);
|
||||
break;
|
||||
|
||||
case FP_INIT_RESET_DEVICE:
|
||||
fp_warn ("Resetting device storage, you will need to enroll all prints again!");
|
||||
goodix_sensor_cmd (self, MOC_CMD0_DELETETEMPLATE, MOC_CMD1_DELETE_ALL,
|
||||
FALSE,
|
||||
NULL,
|
||||
0,
|
||||
fp_init_reset_device_cb);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1294,12 +1359,18 @@ gx_fp_probe (FpDevice *device)
|
||||
{
|
||||
case 0x6496:
|
||||
case 0x60A2:
|
||||
case 0x6014:
|
||||
case 0x6094:
|
||||
case 0x609C:
|
||||
case 0x631C:
|
||||
case 0x634C:
|
||||
case 0x6384:
|
||||
case 0x639C:
|
||||
case 0x63AC:
|
||||
case 0x63BC:
|
||||
case 0x63CC:
|
||||
case 0x6A94:
|
||||
case 0x659A:
|
||||
self->max_enroll_stage = 12;
|
||||
break;
|
||||
|
||||
@@ -1530,8 +1601,13 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
|
||||
|
||||
static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x27c6, .pid = 0x5840, },
|
||||
{ .vid = 0x27c6, .pid = 0x6014, },
|
||||
{ .vid = 0x27c6, .pid = 0x6094, },
|
||||
{ .vid = 0x27c6, .pid = 0x609C, },
|
||||
{ .vid = 0x27c6, .pid = 0x60A2, },
|
||||
{ .vid = 0x27c6, .pid = 0x631C, },
|
||||
{ .vid = 0x27c6, .pid = 0x634C, },
|
||||
{ .vid = 0x27c6, .pid = 0x6384, },
|
||||
{ .vid = 0x27c6, .pid = 0x639C, },
|
||||
{ .vid = 0x27c6, .pid = 0x63AC, },
|
||||
{ .vid = 0x27c6, .pid = 0x63BC, },
|
||||
@@ -1541,6 +1617,7 @@ static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x27c6, .pid = 0x658C, },
|
||||
{ .vid = 0x27c6, .pid = 0x6592, },
|
||||
{ .vid = 0x27c6, .pid = 0x6594, },
|
||||
{ .vid = 0x27c6, .pid = 0x659A, },
|
||||
{ .vid = 0x27c6, .pid = 0x659C, },
|
||||
{ .vid = 0x27c6, .pid = 0x6A94, },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||
|
||||
@@ -35,6 +35,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
FP_INIT_VERSION = 0,
|
||||
FP_INIT_CONFIG,
|
||||
FP_INIT_TEMPLATE_LIST,
|
||||
FP_INIT_RESET_DEVICE,
|
||||
FP_INIT_NUM_STATES,
|
||||
} FpInitState;
|
||||
|
||||
|
||||
@@ -393,10 +393,8 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
||||
fingerid_length,
|
||||
&presp->finger_list_resp.finger_list[num]) != 0)
|
||||
{
|
||||
g_error ("parse fingerlist error");
|
||||
presp->finger_list_resp.finger_num = 0;
|
||||
presp->result = GX_FAILED;
|
||||
break;
|
||||
g_warning ("Failed to parse finger list");
|
||||
return -1;
|
||||
}
|
||||
offset += fingerid_length;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,9 @@ static const FpIdEntry id_table[] = {
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||
};
|
||||
|
||||
@@ -224,6 +227,7 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_critical_leave (device);
|
||||
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
|
||||
0,
|
||||
NULL,
|
||||
|
||||
@@ -431,6 +431,7 @@ dev_deinit (FpImageDevice *dev)
|
||||
|
||||
static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x0483, .pid = 0x2015, .driver_data = UPEKTC_2015 },
|
||||
{ .vid = 0x0483, .pid = 0x2017, .driver_data = UPEKTC_2015 },
|
||||
{ .vid = 0x147e, .pid = 0x3001, .driver_data = UPEKTC_3001 },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||
};
|
||||
|
||||
@@ -317,6 +317,7 @@ irq_handler (FpiUsbTransfer *transfer,
|
||||
if (urudev->irqs_stopped_cb)
|
||||
urudev->irqs_stopped_cb (imgdev);
|
||||
urudev->irqs_stopped_cb = NULL;
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
else if (error)
|
||||
@@ -551,7 +552,7 @@ image_transfer_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
||||
}
|
||||
else
|
||||
{
|
||||
self->img_data = g_memdup (transfer->buffer, sizeof (struct uru4k_image));
|
||||
self->img_data = g_memdup2 (transfer->buffer, sizeof (struct uru4k_image));
|
||||
self->img_data_actual_length = transfer->actual_length;
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
@@ -1413,6 +1414,9 @@ dev_deinit (FpImageDevice *dev)
|
||||
SECITEM_FreeItem (self->param, PR_TRUE);
|
||||
if (self->slot)
|
||||
PK11_FreeSlot (self->slot);
|
||||
|
||||
NSS_Shutdown ();
|
||||
|
||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
|
||||
self->interface, 0, &error);
|
||||
g_clear_pointer (&self->rand, g_rand_free);
|
||||
|
||||
@@ -581,7 +581,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||
/* Initialize fingerprint buffer */
|
||||
g_free (self->lines_buffer);
|
||||
self->memory = VFS_USB_BUFFER_SIZE;
|
||||
self->lines_buffer = g_malloc (self->memory);
|
||||
self->lines_buffer = g_malloc0 (self->memory);
|
||||
self->bytes = 0;
|
||||
|
||||
/* Finger is on the scanner */
|
||||
@@ -589,12 +589,15 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||
}
|
||||
|
||||
/* Increase buffer size while it's insufficient */
|
||||
while (self->bytes + VFS_USB_BUFFER_SIZE > self->memory)
|
||||
while (self->memory < self->bytes + VFS_USB_BUFFER_SIZE)
|
||||
{
|
||||
self->memory <<= 1;
|
||||
int pre_memory = self->memory;
|
||||
self->memory += VFS_USB_BUFFER_SIZE;
|
||||
self->lines_buffer =
|
||||
(struct vfs_line *) g_realloc (self->lines_buffer,
|
||||
self->memory);
|
||||
memset ((guint8 *) self->lines_buffer + pre_memory, 0,
|
||||
VFS_USB_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/* Receive chunk of data */
|
||||
|
||||
@@ -432,7 +432,7 @@ img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int l
|
||||
usb_send (dev, data, len, NULL); \
|
||||
}
|
||||
|
||||
#define RAW_DATA(x) g_memdup (x, sizeof (x)), sizeof (x)
|
||||
#define RAW_DATA(x) g_memdup2 (x, sizeof (x)), sizeof (x)
|
||||
|
||||
#define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe))
|
||||
|
||||
|
||||
@@ -526,8 +526,8 @@ dev_verify (FpDevice *dev)
|
||||
|
||||
if (scan_id)
|
||||
{
|
||||
g_autoptr(FpPrint) new_scan = NULL;
|
||||
GVariant *data = NULL;
|
||||
FpPrint *new_scan;
|
||||
FpPrint *print;
|
||||
gboolean success;
|
||||
|
||||
@@ -556,7 +556,7 @@ dev_verify (FpDevice *dev)
|
||||
self->match_reported = TRUE;
|
||||
fpi_device_verify_report (dev,
|
||||
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
|
||||
new_scan,
|
||||
g_steal_pointer (&new_scan),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,11 +295,10 @@ fp_context_finalize (GObject *object)
|
||||
FpContext *self = (FpContext *) object;
|
||||
FpContextPrivate *priv = fp_context_get_instance_private (self);
|
||||
|
||||
g_clear_pointer (&priv->devices, g_ptr_array_unref);
|
||||
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
g_clear_object (&priv->cancellable);
|
||||
g_clear_pointer (&priv->drivers, g_array_unref);
|
||||
g_clear_pointer (&priv->devices, g_ptr_array_unref);
|
||||
|
||||
g_slist_free_full (g_steal_pointer (&priv->sources), (GDestroyNotify) g_source_destroy);
|
||||
|
||||
@@ -368,6 +367,8 @@ fp_context_init (FpContext *self)
|
||||
FpContextPrivate *priv = fp_context_get_instance_private (self);
|
||||
guint i;
|
||||
|
||||
g_debug ("Initializing FpContext (libfprint version " LIBFPRINT_VERSION ")");
|
||||
|
||||
priv->drivers = fpi_get_driver_types ();
|
||||
|
||||
fpi_tod_shared_drivers_register ();
|
||||
|
||||
@@ -126,6 +126,10 @@ typedef struct
|
||||
GDestroyNotify match_destroy;
|
||||
} FpMatchData;
|
||||
|
||||
|
||||
void fpi_device_suspend (FpDevice *device);
|
||||
void fpi_device_resume (FpDevice *device);
|
||||
|
||||
void fpi_device_configure_wakeup (FpDevice *device,
|
||||
gboolean enabled);
|
||||
void fpi_device_update_temp (FpDevice *device,
|
||||
|
||||
+26
-102
@@ -225,6 +225,7 @@ fp_device_finalize (GObject *object)
|
||||
|
||||
g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
|
||||
g_clear_pointer (&priv->current_task_idle_return_source, g_source_destroy);
|
||||
g_clear_pointer (&priv->critical_section_flush_source, g_source_destroy);
|
||||
|
||||
g_clear_pointer (&priv->device_id, g_free);
|
||||
g_clear_pointer (&priv->device_name, g_free);
|
||||
@@ -948,16 +949,6 @@ fp_device_close_finish (FpDevice *device,
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_suspend_resume_task (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_assert (priv->suspend_resume_task);
|
||||
|
||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_suspend:
|
||||
* @device: a #FpDevice
|
||||
@@ -1008,48 +999,7 @@ fp_device_suspend (FpDevice *device,
|
||||
|
||||
priv->suspend_resume_task = g_steal_pointer (&task);
|
||||
|
||||
/* If the device is currently idle, just complete immediately.
|
||||
* For long running tasks, call the driver handler right away, for short
|
||||
* tasks, wait for completion and then return the task.
|
||||
*/
|
||||
switch (priv->current_action)
|
||||
{
|
||||
case FPI_DEVICE_ACTION_NONE:
|
||||
fpi_device_suspend_complete (device, NULL);
|
||||
break;
|
||||
|
||||
case FPI_DEVICE_ACTION_ENROLL:
|
||||
case FPI_DEVICE_ACTION_VERIFY:
|
||||
case FPI_DEVICE_ACTION_IDENTIFY:
|
||||
case FPI_DEVICE_ACTION_CAPTURE:
|
||||
if (FP_DEVICE_GET_CLASS (device)->suspend)
|
||||
{
|
||||
if (priv->critical_section)
|
||||
priv->suspend_queued = TRUE;
|
||||
else
|
||||
FP_DEVICE_GET_CLASS (device)->suspend (device);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FPI_DEVICE_ACTION_PROBE:
|
||||
case FPI_DEVICE_ACTION_OPEN:
|
||||
case FPI_DEVICE_ACTION_CLOSE:
|
||||
case FPI_DEVICE_ACTION_DELETE:
|
||||
case FPI_DEVICE_ACTION_LIST:
|
||||
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
|
||||
g_signal_connect_object (priv->current_task,
|
||||
"notify::completed",
|
||||
G_CALLBACK (complete_suspend_resume_task),
|
||||
device,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
break;
|
||||
}
|
||||
fpi_device_suspend (device);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1114,41 +1064,7 @@ fp_device_resume (FpDevice *device,
|
||||
|
||||
priv->suspend_resume_task = g_steal_pointer (&task);
|
||||
|
||||
switch (priv->current_action)
|
||||
{
|
||||
case FPI_DEVICE_ACTION_NONE:
|
||||
fpi_device_resume_complete (device, NULL);
|
||||
break;
|
||||
|
||||
case FPI_DEVICE_ACTION_ENROLL:
|
||||
case FPI_DEVICE_ACTION_VERIFY:
|
||||
case FPI_DEVICE_ACTION_IDENTIFY:
|
||||
case FPI_DEVICE_ACTION_CAPTURE:
|
||||
if (FP_DEVICE_GET_CLASS (device)->resume)
|
||||
{
|
||||
if (priv->critical_section)
|
||||
priv->resume_queued = TRUE;
|
||||
else
|
||||
FP_DEVICE_GET_CLASS (device)->resume (device);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FPI_DEVICE_ACTION_PROBE:
|
||||
case FPI_DEVICE_ACTION_OPEN:
|
||||
case FPI_DEVICE_ACTION_CLOSE:
|
||||
case FPI_DEVICE_ACTION_DELETE:
|
||||
case FPI_DEVICE_ACTION_LIST:
|
||||
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
|
||||
/* cannot happen as we make sure these tasks complete before suspend */
|
||||
g_assert_not_reached ();
|
||||
complete_suspend_resume_task (device);
|
||||
break;
|
||||
}
|
||||
fpi_device_resume (device);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1265,10 +1181,6 @@ fp_device_enroll (FpDevice *device,
|
||||
}
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
@@ -1277,6 +1189,10 @@ fp_device_enroll (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
data = g_new0 (FpEnrollData, 1);
|
||||
data->print = g_object_ref_sink (template_print);
|
||||
data->enroll_progress_cb = progress_cb;
|
||||
@@ -1383,10 +1299,6 @@ fp_device_verify (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
@@ -1395,6 +1307,10 @@ fp_device_verify (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
data = g_new0 (FpMatchData, 1);
|
||||
data->enrolled_print = g_object_ref (enrolled_print);
|
||||
data->match_cb = match_cb;
|
||||
@@ -1510,9 +1426,13 @@ fp_device_identify (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
if (prints == NULL)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
|
||||
"Invalid gallery array"));
|
||||
return;
|
||||
}
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
@@ -1522,6 +1442,10 @@ fp_device_identify (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
data = g_new0 (FpMatchData, 1);
|
||||
/* We cannot store the gallery directly, because the ptr array may not own
|
||||
* a reference to each print. Also, the caller could in principle modify the
|
||||
@@ -1635,10 +1559,6 @@ fp_device_capture (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
@@ -1647,6 +1567,10 @@ fp_device_capture (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
priv->wait_for_finger = wait_for_finger;
|
||||
|
||||
cls->capture (device);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#define FP_COMPONENT "image"
|
||||
|
||||
#include "fpi-compat.h"
|
||||
#include "fpi-image.h"
|
||||
#include "fpi-log.h"
|
||||
|
||||
@@ -296,7 +297,7 @@ fp_image_detect_minutiae_thread_func (GTask *task,
|
||||
|
||||
data->flags &= ~(FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_COLORS_INVERTED);
|
||||
|
||||
lfsparms = g_memdup (&g_lfsparms_V2, sizeof (LFSPARMS));
|
||||
lfsparms = g_memdup2 (&g_lfsparms_V2, sizeof (LFSPARMS));
|
||||
lfsparms->remove_perimeter_pts = data->flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
|
||||
|
||||
timer = g_timer_new ();
|
||||
|
||||
@@ -339,7 +339,7 @@ fp_print_init (FpPrint *self)
|
||||
* create a new print, fill in the relevant metadata, and then start
|
||||
* enrollment.
|
||||
*
|
||||
* Returns: (transfer floating): A newyl created #FpPrint
|
||||
* Returns: (transfer floating): A newly created #FpPrint
|
||||
*/
|
||||
FpPrint *
|
||||
fp_print_new (FpDevice *device)
|
||||
|
||||
@@ -1181,7 +1181,7 @@ fpi_byte_reader_dup_string_utf##bits (FpiByteReader * reader, type ** str) \
|
||||
*str = NULL; \
|
||||
return FALSE; \
|
||||
} \
|
||||
*str = g_memdup (reader->data + reader->byte, size); \
|
||||
*str = g_memdup2 (reader->data + reader->byte, size); \
|
||||
reader->byte += size; \
|
||||
return TRUE; \
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include "fpi-compat.h"
|
||||
#include "fpi-byte-utils.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -360,7 +361,7 @@ static inline guint8 *
|
||||
fpi_byte_reader_dup_data_unchecked (FpiByteReader * reader, guint size)
|
||||
{
|
||||
gconstpointer data = fpi_byte_reader_get_data_unchecked (reader, size);
|
||||
return (guint8 *) g_memdup (data, size);
|
||||
return (guint8 *) g_memdup2 (data, size);
|
||||
}
|
||||
|
||||
/* Unchecked variants that should not be used */
|
||||
|
||||
@@ -211,7 +211,7 @@ fpi_byte_writer_reset_and_get_data (FpiByteWriter * writer)
|
||||
|
||||
data = (guint8 *) writer->parent.data;
|
||||
if (!writer->owned)
|
||||
data = g_memdup (data, writer->parent.size);
|
||||
data = g_memdup2 (data, writer->parent.size);
|
||||
writer->parent.data = NULL;
|
||||
fpi_byte_writer_reset (writer);
|
||||
|
||||
|
||||
@@ -39,6 +39,17 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpDeviceClass, g_type_class_unref);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDate, g_date_free);
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 68, 0)
|
||||
#define g_memdup2(data, size) g_memdup ((data), (size))
|
||||
#else
|
||||
#define g_memdup2(data, size) \
|
||||
(G_GNUC_EXTENSION ({ \
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
|
||||
g_memdup2 ((data), (size)); \
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS \
|
||||
}))
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 1)
|
||||
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
|
||||
#else
|
||||
|
||||
+221
-56
@@ -21,6 +21,7 @@
|
||||
#define FP_COMPONENT "device"
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "fpi-log.h"
|
||||
|
||||
@@ -594,7 +595,14 @@ fpi_device_get_verify_data (FpDevice *device,
|
||||
* @device: The #FpDevice
|
||||
* @prints: (out) (transfer none) (element-type FpPrint): The gallery of prints
|
||||
*
|
||||
* Get data for identify.
|
||||
* Get prints gallery for identification.
|
||||
*
|
||||
* The @prints array is always non-%NULL and may contain a list of #FpPrint's
|
||||
* that the device should match against.
|
||||
*
|
||||
* Note that @prints can be an empty array, in such case the device is expected
|
||||
* to report the scanned print matching the one in its internal storage, if any.
|
||||
*
|
||||
*/
|
||||
void
|
||||
fpi_device_get_identify_data (FpDevice *device,
|
||||
@@ -839,16 +847,16 @@ fpi_device_critical_section_flush_idle_cb (FpDevice *device)
|
||||
|
||||
if (priv->suspend_queued)
|
||||
{
|
||||
cls->suspend (device);
|
||||
priv->suspend_queued = FALSE;
|
||||
fpi_device_suspend (device);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
if (priv->resume_queued)
|
||||
{
|
||||
cls->resume (device);
|
||||
priv->resume_queued = FALSE;
|
||||
fpi_device_resume (device);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
@@ -885,6 +893,7 @@ fpi_device_critical_leave (FpDevice *device)
|
||||
return;
|
||||
|
||||
priv->critical_section_flush_source = g_idle_source_new ();
|
||||
g_source_set_priority (priv->critical_section_flush_source, G_PRIORITY_HIGH);
|
||||
g_source_set_callback (priv->critical_section_flush_source,
|
||||
(GSourceFunc) fpi_device_critical_section_flush_idle_cb,
|
||||
device,
|
||||
@@ -1283,12 +1292,14 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
||||
* @device: The #FpDevice
|
||||
* @error: A #GError if result is %FPI_MATCH_ERROR
|
||||
*
|
||||
* Finish an ongoing verify operation. The returned print should be
|
||||
* representing the new scan and not the one passed for verification.
|
||||
* Finish an ongoing verify operation.
|
||||
*
|
||||
* Note that @error should only be set for actual errors. In the case
|
||||
* of retry errors, report these using fpi_device_verify_report()
|
||||
* and then call this function without any error argument.
|
||||
*
|
||||
* If @error is not set, we expect that a result (and print, in case)
|
||||
* have been already reported via fpi_device_verify_report().
|
||||
*/
|
||||
void
|
||||
fpi_device_verify_complete (FpDevice *device,
|
||||
@@ -1346,9 +1357,14 @@ fpi_device_verify_complete (FpDevice *device,
|
||||
* @device: The #FpDevice
|
||||
* @error: The #GError or %NULL on success
|
||||
*
|
||||
* Finish an ongoing identify operation. The match that was identified is
|
||||
* returned in @match. The @print parameter returns the newly created scan
|
||||
* that was used for matching.
|
||||
* Finish an ongoing identify operation.
|
||||
*
|
||||
* Note that @error should only be set for actual errors. In the case
|
||||
* of retry errors, report these using fpi_device_identify_report()
|
||||
* and then call this function without any error argument.
|
||||
*
|
||||
* If @error is not set, we expect that a match and / or a print have been
|
||||
* already reported via fpi_device_identify_report()
|
||||
*/
|
||||
void
|
||||
fpi_device_identify_complete (FpDevice *device,
|
||||
@@ -1523,6 +1539,150 @@ fpi_device_list_complete (FpDevice *device,
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
}
|
||||
|
||||
static int
|
||||
update_attr (const char *attr, const char *value)
|
||||
{
|
||||
int fd, err;
|
||||
gssize r;
|
||||
char buf[50] = { 0 };
|
||||
|
||||
fd = open (attr, O_RDONLY);
|
||||
err = -errno;
|
||||
if (fd < 0)
|
||||
return -err;
|
||||
|
||||
r = read (fd, buf, sizeof (buf) - 1);
|
||||
err = errno;
|
||||
close (fd);
|
||||
if (r < 0)
|
||||
return -err;
|
||||
|
||||
g_strchomp (buf);
|
||||
if (g_strcmp0 (buf, value) == 0)
|
||||
return 0;
|
||||
|
||||
/* O_TRUNC makes things work in the umockdev environment */
|
||||
fd = open (attr, O_WRONLY | O_TRUNC);
|
||||
err = errno;
|
||||
if (fd < 0)
|
||||
return -err;
|
||||
|
||||
r = write (fd, value, strlen (value));
|
||||
err = -errno;
|
||||
close (fd);
|
||||
if (r < 0)
|
||||
{
|
||||
/* Write failures are weird, and are worth a warning */
|
||||
g_warning ("Could not write %s to %s", value, attr);
|
||||
return -err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
complete_suspend_resume_task (FpDevice *device)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_assert (priv->suspend_resume_task);
|
||||
task = g_steal_pointer (&priv->suspend_resume_task);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
fpi_device_suspend (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
/* If the device is currently idle, just complete immediately.
|
||||
* For long running tasks, call the driver handler right away, for short
|
||||
* tasks, wait for completion and then return the task.
|
||||
*/
|
||||
switch (priv->current_action)
|
||||
{
|
||||
case FPI_DEVICE_ACTION_NONE:
|
||||
fpi_device_suspend_complete (device, NULL);
|
||||
break;
|
||||
|
||||
case FPI_DEVICE_ACTION_ENROLL:
|
||||
case FPI_DEVICE_ACTION_VERIFY:
|
||||
case FPI_DEVICE_ACTION_IDENTIFY:
|
||||
case FPI_DEVICE_ACTION_CAPTURE:
|
||||
if (FP_DEVICE_GET_CLASS (device)->suspend)
|
||||
{
|
||||
if (priv->critical_section)
|
||||
priv->suspend_queued = TRUE;
|
||||
else
|
||||
FP_DEVICE_GET_CLASS (device)->suspend (device);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FPI_DEVICE_ACTION_PROBE:
|
||||
case FPI_DEVICE_ACTION_OPEN:
|
||||
case FPI_DEVICE_ACTION_CLOSE:
|
||||
case FPI_DEVICE_ACTION_DELETE:
|
||||
case FPI_DEVICE_ACTION_LIST:
|
||||
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
|
||||
g_signal_connect_object (priv->current_task,
|
||||
"notify::completed",
|
||||
G_CALLBACK (complete_suspend_resume_task),
|
||||
device,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fpi_device_resume (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
switch (priv->current_action)
|
||||
{
|
||||
case FPI_DEVICE_ACTION_NONE:
|
||||
fpi_device_resume_complete (device, NULL);
|
||||
break;
|
||||
|
||||
case FPI_DEVICE_ACTION_ENROLL:
|
||||
case FPI_DEVICE_ACTION_VERIFY:
|
||||
case FPI_DEVICE_ACTION_IDENTIFY:
|
||||
case FPI_DEVICE_ACTION_CAPTURE:
|
||||
if (FP_DEVICE_GET_CLASS (device)->resume)
|
||||
{
|
||||
if (priv->critical_section)
|
||||
priv->resume_queued = TRUE;
|
||||
else
|
||||
FP_DEVICE_GET_CLASS (device)->resume (device);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case FPI_DEVICE_ACTION_PROBE:
|
||||
case FPI_DEVICE_ACTION_OPEN:
|
||||
case FPI_DEVICE_ACTION_CLOSE:
|
||||
case FPI_DEVICE_ACTION_DELETE:
|
||||
case FPI_DEVICE_ACTION_LIST:
|
||||
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
|
||||
/* cannot happen as we make sure these tasks complete before suspend */
|
||||
g_assert_not_reached ();
|
||||
complete_suspend_resume_task (device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
||||
{
|
||||
@@ -1533,42 +1693,38 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
||||
case FP_DEVICE_TYPE_USB:
|
||||
{
|
||||
g_autoptr(GString) ports = NULL;
|
||||
GUsbDevice *dev, *parent;
|
||||
g_autoptr(GUsbDevice) dev = NULL;
|
||||
const char *wakeup_command = enabled ? "enabled" : "disabled";
|
||||
guint8 bus, port;
|
||||
guint8 bus;
|
||||
g_autofree gchar *sysfs_wakeup = NULL;
|
||||
g_autofree gchar *sysfs_persist = NULL;
|
||||
gssize r;
|
||||
int fd;
|
||||
int res;
|
||||
|
||||
ports = g_string_new (NULL);
|
||||
bus = g_usb_device_get_bus (priv->usb_device);
|
||||
|
||||
/* Walk up, skipping the root hub. */
|
||||
dev = priv->usb_device;
|
||||
while ((parent = g_usb_device_get_parent (dev)))
|
||||
g_set_object (&dev, priv->usb_device);
|
||||
while (TRUE)
|
||||
{
|
||||
g_autoptr(GUsbDevice) parent = g_usb_device_get_parent (dev);
|
||||
g_autofree gchar *port_str = NULL;
|
||||
guint8 port;
|
||||
|
||||
if (!parent)
|
||||
break;
|
||||
|
||||
port = g_usb_device_get_port_number (dev);
|
||||
g_string_prepend (ports, g_strdup_printf ("%d.", port));
|
||||
dev = parent;
|
||||
port_str = g_strdup_printf ("%d.", port);
|
||||
g_string_prepend (ports, port_str);
|
||||
g_set_object (&dev, parent);
|
||||
}
|
||||
g_string_set_size (ports, ports->len - 1);
|
||||
|
||||
sysfs_wakeup = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/wakeup", bus, ports->str);
|
||||
fd = open (sysfs_wakeup, O_WRONLY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
/* Wakeup not existing appears to be relatively normal. */
|
||||
g_debug ("Failed to open %s", sysfs_wakeup);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = write (fd, wakeup_command, strlen (wakeup_command));
|
||||
if (r < 0)
|
||||
g_warning ("Could not configure wakeup to %s by writing %s", wakeup_command, sysfs_wakeup);
|
||||
close (fd);
|
||||
}
|
||||
res = update_attr (sysfs_wakeup, wakeup_command);
|
||||
if (res < 0)
|
||||
g_debug ("Failed to set %s to %s", sysfs_wakeup, wakeup_command);
|
||||
|
||||
/* Persist means that the kernel tries to keep the USB device open
|
||||
* in case it is "replugged" due to suspend.
|
||||
@@ -1576,20 +1732,9 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
||||
* state. Instead, seeing an unplug and a new device makes more sense.
|
||||
*/
|
||||
sysfs_persist = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/persist", bus, ports->str);
|
||||
fd = open (sysfs_persist, O_WRONLY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
g_warning ("Failed to open %s", sysfs_persist);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = write (fd, "0", 1);
|
||||
if (r < 0)
|
||||
g_message ("Could not disable USB persist by writing to %s", sysfs_persist);
|
||||
close (fd);
|
||||
}
|
||||
res = update_attr (sysfs_persist, "0");
|
||||
if (res < 0)
|
||||
g_warning ("Failed to disable USB persist by writing to %s", sysfs_persist);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1609,6 +1754,7 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
||||
static void
|
||||
fpi_device_suspend_completed (FpDevice *device)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
/* We have an ongoing operation, allow the device to wake up the machine. */
|
||||
@@ -1618,11 +1764,12 @@ fpi_device_suspend_completed (FpDevice *device)
|
||||
if (priv->critical_section)
|
||||
g_warning ("Driver was in a critical section at suspend time. It likely deadlocked!");
|
||||
|
||||
task = g_steal_pointer (&priv->suspend_resume_task);
|
||||
|
||||
if (priv->suspend_error)
|
||||
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task),
|
||||
g_steal_pointer (&priv->suspend_error));
|
||||
g_task_return_error (task, g_steal_pointer (&priv->suspend_error));
|
||||
else
|
||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1650,11 +1797,12 @@ fpi_device_suspend_complete (FpDevice *device,
|
||||
g_return_if_fail (priv->suspend_resume_task);
|
||||
g_return_if_fail (priv->suspend_error == NULL);
|
||||
|
||||
priv->suspend_error = error;
|
||||
priv->suspend_error = g_steal_pointer (&error);
|
||||
priv->is_suspended = TRUE;
|
||||
|
||||
/* If there is no error, we have no running task, return immediately. */
|
||||
if (error == NULL || !priv->current_task || g_task_get_completed (priv->current_task))
|
||||
if (!priv->suspend_error || !priv->current_task ||
|
||||
g_task_get_completed (priv->current_task))
|
||||
{
|
||||
fpi_device_suspend_completed (device);
|
||||
return;
|
||||
@@ -1686,6 +1834,7 @@ void
|
||||
fpi_device_resume_complete (FpDevice *device,
|
||||
GError *error)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
@@ -1694,10 +1843,12 @@ fpi_device_resume_complete (FpDevice *device,
|
||||
priv->is_suspended = FALSE;
|
||||
fpi_device_configure_wakeup (device, FALSE);
|
||||
|
||||
task = g_steal_pointer (&priv->suspend_resume_task);
|
||||
|
||||
if (error)
|
||||
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task), error);
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1854,12 +2005,26 @@ fpi_device_verify_report (FpDevice *device,
|
||||
* fpi_device_identify_report:
|
||||
* @device: The #FpDevice
|
||||
* @match: (transfer none): The #FpPrint from the gallery that matched
|
||||
* @print: (transfer floating): The scanned #FpPrint
|
||||
* @error: A #GError if result is %FPI_MATCH_ERROR
|
||||
* @print: (transfer floating): The scanned #FpPrint, set in the absence
|
||||
* of an error.
|
||||
* @error: A #GError of %FP_DEVICE_RETRY type if @match and @print are unset.
|
||||
*
|
||||
* Report the result of a identify operation. Note that the passed @error must be
|
||||
* a retry error with the %FP_DEVICE_RETRY domain. For all other error cases,
|
||||
* the error should passed to fpi_device_identify_complete().
|
||||
* Report the results of an identify operation.
|
||||
*
|
||||
* In case of successful identification @match is expected to be set to a
|
||||
* #FpPrint that matches one from the provided gallery, while @print
|
||||
* represents the scanned print and will be different.
|
||||
*
|
||||
* If there are no errors, it's expected that the device always reports the
|
||||
* recognized @print even if there is no @match with the provided gallery (that
|
||||
* can be potentially empty). This is required for application logic further
|
||||
* up in the stack, such as for enroll-duplicate checking. @print needs to be
|
||||
* sufficiently filled to do a comparison.
|
||||
*
|
||||
* In case of error, both @match and @print are expected to be %NULL.
|
||||
* Note that the passed @error must be a retry error from the %FP_DEVICE_RETRY
|
||||
* domain. For all other error cases, the error should passed to
|
||||
* fpi_device_identify_complete().
|
||||
*/
|
||||
void
|
||||
fpi_device_identify_report (FpDevice *device,
|
||||
|
||||
@@ -50,7 +50,7 @@ fpi_print_add_print (FpPrint *print, FpPrint *add)
|
||||
g_return_if_fail (add->type == FPI_PRINT_NBIS);
|
||||
|
||||
g_assert (add->prints->len == 1);
|
||||
g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
||||
g_ptr_array_add (print->prints, g_memdup2 (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,9 +42,9 @@ gboolean fpi_print_add_from_image (FpPrint *print,
|
||||
FpImage *image,
|
||||
GError **error);
|
||||
|
||||
FpiMatchResult fpi_print_bz3_match (FpPrint * template,
|
||||
FpPrint * print,
|
||||
gint bz3_threshold,
|
||||
FpiMatchResult fpi_print_bz3_match (FpPrint *temp,
|
||||
FpPrint *print,
|
||||
gint bz3_threshold,
|
||||
GError **error);
|
||||
|
||||
/* Helpers to encode metadata into user ID strings. */
|
||||
|
||||
@@ -29,13 +29,19 @@ static const FpIdEntry whitelist_id_table[] = {
|
||||
* You can generate this list from the wiki page using e.g.:
|
||||
* gio cat https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md | sed -n 's!|.*\([0-9a-fA-F]\{4\}\):\([0-9a-fA-F]\{4\}\).*|.*! { .vid = 0x\1, .pid = 0x\2 },!p'
|
||||
*/
|
||||
{ .vid = 0x04e8, .pid = 0x730b },
|
||||
{ .vid = 0x04f3, .pid = 0x036b },
|
||||
{ .vid = 0x04f3, .pid = 0x0c00 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c4b },
|
||||
{ .vid = 0x04f3, .pid = 0x0c4c },
|
||||
{ .vid = 0x04f3, .pid = 0x0c57 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c5e },
|
||||
{ .vid = 0x04f3, .pid = 0x0c5a },
|
||||
{ .vid = 0x04f3, .pid = 0x0c70 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c72 },
|
||||
{ .vid = 0x04f3, .pid = 0x2706 },
|
||||
{ .vid = 0x04f3, .pid = 0x3057 },
|
||||
{ .vid = 0x04f3, .pid = 0x3104 },
|
||||
{ .vid = 0x04f3, .pid = 0x310d },
|
||||
{ .vid = 0x06cb, .pid = 0x0081 },
|
||||
{ .vid = 0x06cb, .pid = 0x0088 },
|
||||
{ .vid = 0x06cb, .pid = 0x008a },
|
||||
@@ -52,6 +58,7 @@ static const FpIdEntry whitelist_id_table[] = {
|
||||
{ .vid = 0x06cb, .pid = 0x00d8 },
|
||||
{ .vid = 0x06cb, .pid = 0x00da },
|
||||
{ .vid = 0x06cb, .pid = 0x00dc },
|
||||
{ .vid = 0x06cb, .pid = 0x00e4 },
|
||||
{ .vid = 0x06cb, .pid = 0x00e7 },
|
||||
{ .vid = 0x06cb, .pid = 0x00e9 },
|
||||
{ .vid = 0x06cb, .pid = 0x00fd },
|
||||
@@ -67,6 +74,7 @@ static const FpIdEntry whitelist_id_table[] = {
|
||||
{ .vid = 0x0bda, .pid = 0x5812 },
|
||||
{ .vid = 0x10a5, .pid = 0x0007 },
|
||||
{ .vid = 0x10a5, .pid = 0x9200 },
|
||||
{ .vid = 0x10a5, .pid = 0x9800 },
|
||||
{ .vid = 0x1188, .pid = 0x9545 },
|
||||
{ .vid = 0x138a, .pid = 0x0007 },
|
||||
{ .vid = 0x138a, .pid = 0x003a },
|
||||
@@ -88,24 +96,32 @@ static const FpIdEntry whitelist_id_table[] = {
|
||||
{ .vid = 0x27c6, .pid = 0x5042 },
|
||||
{ .vid = 0x27c6, .pid = 0x5110 },
|
||||
{ .vid = 0x27c6, .pid = 0x5117 },
|
||||
{ .vid = 0x27c6, .pid = 0x5120 },
|
||||
{ .vid = 0x27c6, .pid = 0x5125 },
|
||||
{ .vid = 0x27c6, .pid = 0x5201 },
|
||||
{ .vid = 0x27c6, .pid = 0x521d },
|
||||
{ .vid = 0x27c6, .pid = 0x5301 },
|
||||
{ .vid = 0x27c6, .pid = 0x530c },
|
||||
{ .vid = 0x27c6, .pid = 0x532d },
|
||||
{ .vid = 0x27c6, .pid = 0x5335 },
|
||||
{ .vid = 0x27c6, .pid = 0x533c },
|
||||
{ .vid = 0x27c6, .pid = 0x5381 },
|
||||
{ .vid = 0x27c6, .pid = 0x5385 },
|
||||
{ .vid = 0x27c6, .pid = 0x538c },
|
||||
{ .vid = 0x27c6, .pid = 0x538d },
|
||||
{ .vid = 0x27c6, .pid = 0x5395 },
|
||||
{ .vid = 0x27c6, .pid = 0x5503 },
|
||||
{ .vid = 0x27c6, .pid = 0x550a },
|
||||
{ .vid = 0x27c6, .pid = 0x550c },
|
||||
{ .vid = 0x27c6, .pid = 0x5584 },
|
||||
{ .vid = 0x27c6, .pid = 0x55a2 },
|
||||
{ .vid = 0x27c6, .pid = 0x55a4 },
|
||||
{ .vid = 0x27c6, .pid = 0x55b4 },
|
||||
{ .vid = 0x27c6, .pid = 0x5740 },
|
||||
{ .vid = 0x27c6, .pid = 0x5e0a },
|
||||
{ .vid = 0x27c6, .pid = 0x581a },
|
||||
{ .vid = 0x2808, .pid = 0x9338 },
|
||||
{ .vid = 0x2808, .pid = 0x93a9 },
|
||||
{ .vid = 0x298d, .pid = 0x2020 },
|
||||
{ .vid = 0x298d, .pid = 0x2033 },
|
||||
{ .vid = 0x3538, .pid = 0x0930 },
|
||||
|
||||
@@ -139,6 +139,8 @@ driver_sources = {
|
||||
[ 'drivers/synaptics/synaptics.c', 'drivers/synaptics/bmkt_message.c' ],
|
||||
'goodixmoc' :
|
||||
[ 'drivers/goodixmoc/goodix.c', 'drivers/goodixmoc/goodix_proto.c' ],
|
||||
'fpcmoc' :
|
||||
[ 'drivers/fpcmoc/fpc.c' ],
|
||||
}
|
||||
|
||||
helper_sources = {
|
||||
@@ -334,7 +336,7 @@ if install_udev_rules
|
||||
)
|
||||
endif
|
||||
|
||||
custom_target('sync-udev-hwdb',
|
||||
sync_udev_udb = custom_target('sync-udev-hwdb',
|
||||
depends: udev_hwdb_generator,
|
||||
output: 'sync-udev-hwdb',
|
||||
install: false,
|
||||
@@ -345,6 +347,8 @@ custom_target('sync-udev-hwdb',
|
||||
]
|
||||
)
|
||||
|
||||
alias_target('sync-udev-hwdb', sync_udev_udb)
|
||||
|
||||
supported_devices = executable('fprint-list-supported-devices',
|
||||
'fprint-list-supported-devices.c',
|
||||
dependencies: libfprint_private_dep,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
From 2584d440afc87d463cb8dc809d48c660e091c2c4 Mon Sep 17 00:00:00 2001
|
||||
From: Sam James <sam@gentoo.org>
|
||||
Date: Thu, 23 Jun 2022 05:57:46 +0100
|
||||
Subject: [PATCH] nbis: fix build on musl
|
||||
|
||||
Drop re-definition of stderr. There's no need for this anywhere
|
||||
(including glibc). This breaks in particular on musl because
|
||||
stderr (and stdin) are both const, and macros unlike in glibc.
|
||||
|
||||
Bug: https://bugs.gentoo.org/853811
|
||||
---
|
||||
nbis/include/bozorth.h | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/nbis/include/bozorth.h b/nbis/include/bozorth.h
|
||||
index a705da98..fd8975bf 100644
|
||||
--- a/nbis/include/bozorth.h
|
||||
+++ b/nbis/include/bozorth.h
|
||||
@@ -217,8 +217,6 @@ struct xytq_struct {
|
||||
/**************************************************************************/
|
||||
/* Globals supporting command line options */
|
||||
extern int verbose_threshold;
|
||||
-/* Global supporting error reporting */
|
||||
-extern FILE *stderr;
|
||||
|
||||
/**************************************************************************/
|
||||
/* In: BZ_GBLS.C */
|
||||
--
|
||||
GitLab
|
||||
|
||||
|
||||
@@ -217,8 +217,6 @@ struct xytq_struct {
|
||||
/**************************************************************************/
|
||||
/* Globals supporting command line options */
|
||||
extern int verbose_threshold;
|
||||
/* Global supporting error reporting */
|
||||
extern FILE *stderr;
|
||||
|
||||
/**************************************************************************/
|
||||
/* In: BZ_GBLS.C */
|
||||
|
||||
@@ -198,3 +198,6 @@ patch -p0 < fix-scan-build-reports.patch
|
||||
|
||||
# Add pass to remove perimeter points
|
||||
patch -p0 < remove-perimeter-pts.patch
|
||||
|
||||
# Fix build on musl by dropping unnecessary redeclaration of stderr
|
||||
patch -p0 < fix-musl-build.patch
|
||||
|
||||
Reference in New Issue
Block a user