mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-12-29 02:10:10 +01:00
Add +crfpmoc_cmd_wait_event_fingerprint
This commit is contained in:
parent
1cb49d25df
commit
84fc9129ba
4 changed files with 228 additions and 106 deletions
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
#define FP_COMPONENT "crfpmoc"
|
||||
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include "drivers_api.h"
|
||||
#include "crfpmoc.h"
|
||||
|
|
@ -47,36 +48,36 @@ static const FpIdEntry crfpmoc_id_table[] = {
|
|||
};
|
||||
|
||||
static const gchar *const crfpmoc_meanings[] = {
|
||||
"SUCCESS",
|
||||
"INVALID_COMMAND",
|
||||
"ERROR",
|
||||
"INVALID_PARAM",
|
||||
"ACCESS_DENIED",
|
||||
"INVALID_RESPONSE",
|
||||
"INVALID_VERSION",
|
||||
"INVALID_CHECKSUM",
|
||||
"IN_PROGRESS",
|
||||
"UNAVAILABLE",
|
||||
"TIMEOUT",
|
||||
"OVERFLOW",
|
||||
"INVALID_HEADER",
|
||||
"REQUEST_TRUNCATED",
|
||||
"RESPONSE_TOO_BIG",
|
||||
"BUS_ERROR",
|
||||
"BUSY",
|
||||
"INVALID_HEADER_VERSION",
|
||||
"INVALID_HEADER_CRC",
|
||||
"INVALID_DATA_CRC",
|
||||
"DUP_UNAVAILABLE",
|
||||
"SUCCESS",
|
||||
"INVALID_COMMAND",
|
||||
"ERROR",
|
||||
"INVALID_PARAM",
|
||||
"ACCESS_DENIED",
|
||||
"INVALID_RESPONSE",
|
||||
"INVALID_VERSION",
|
||||
"INVALID_CHECKSUM",
|
||||
"IN_PROGRESS",
|
||||
"UNAVAILABLE",
|
||||
"TIMEOUT",
|
||||
"OVERFLOW",
|
||||
"INVALID_HEADER",
|
||||
"REQUEST_TRUNCATED",
|
||||
"RESPONSE_TOO_BIG",
|
||||
"BUS_ERROR",
|
||||
"BUSY",
|
||||
"INVALID_HEADER_VERSION",
|
||||
"INVALID_HEADER_CRC",
|
||||
"INVALID_DATA_CRC",
|
||||
"DUP_UNAVAILABLE",
|
||||
};
|
||||
|
||||
static const gchar *
|
||||
crfpmoc_strresult (int i)
|
||||
{
|
||||
int crfpmoc_meanings_len = sizeof (crfpmoc_meanings) / sizeof (crfpmoc_meanings[0]);
|
||||
if (i < 0 || i >= crfpmoc_meanings_len)
|
||||
return "<unknown>";
|
||||
return crfpmoc_meanings[i];
|
||||
if (i < 0 || i >= crfpmoc_meanings_len)
|
||||
return "<unknown>";
|
||||
return crfpmoc_meanings[i];
|
||||
}
|
||||
|
||||
static char *
|
||||
|
|
@ -145,15 +146,6 @@ crfpmoc_ec_command (FpiDeviceCrfpMoc *self, int command, int version, const void
|
|||
fp_warn ("ioctl %d, errno %d (%s), EC result %d (%s)", r, errno, strerror (errno), s_cmd->result, crfpmoc_strresult (s_cmd->result));
|
||||
}
|
||||
}
|
||||
else if (errno == ETIMEDOUT)
|
||||
{
|
||||
g_usleep (CRFPMOC_TIMEOUT_RETRY_DELAY_MICROSECONDS);
|
||||
r = ioctl (self->fd, CRFPMOC_CROS_EC_DEV_IOCXCMD_V2, s_cmd);
|
||||
if (r < 0)
|
||||
{
|
||||
fp_warn ("ioctl %d, errno %d (%s), EC result %d (%s)", r, errno, strerror (errno), s_cmd->result, crfpmoc_strresult (s_cmd->result));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_warn ("ioctl %d, errno %d (%s), EC result %d (%s)", r, errno, strerror (errno), s_cmd->result, crfpmoc_strresult (s_cmd->result));
|
||||
|
|
@ -177,11 +169,37 @@ crfpmoc_ec_command (FpiDeviceCrfpMoc *self, int command, int version, const void
|
|||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
crfpmoc_ec_pollevent (FpiDeviceCrfpMoc *self, unsigned long mask, void *buffer, size_t buf_size, int timeout)
|
||||
{
|
||||
int rv;
|
||||
struct pollfd pf = { .fd = self->fd, .events = POLLIN };
|
||||
|
||||
rv = ioctl (self->fd, CRFPMOC_CROS_EC_DEV_IOCEVENTMASK_V2, mask);
|
||||
if (rv < 0)
|
||||
{
|
||||
return -rv;
|
||||
}
|
||||
|
||||
rv = poll (&pf, 1, timeout);
|
||||
if (rv != 1)
|
||||
{
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (pf.revents != POLLIN)
|
||||
{
|
||||
return -pf.revents;
|
||||
}
|
||||
|
||||
return read (self->fd, buffer, buf_size);
|
||||
}
|
||||
|
||||
static int
|
||||
crfpmoc_cmd_fp_mode (FpiDeviceCrfpMoc *self, guint32 inmode, guint32 *outmode, const gchar **error_msg)
|
||||
{
|
||||
struct crfpmoc_ec_params_fp_mode p;
|
||||
struct crfpmoc_ec_response_fp_mode r;
|
||||
struct crfpmoc_ec_response_fp_mode r;
|
||||
int rv;
|
||||
|
||||
p.mode = inmode;
|
||||
|
|
@ -240,6 +258,30 @@ crfpmoc_cmd_fp_stats (FpiDeviceCrfpMoc *self, gint8 *template, const gchar **err
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crfpmoc_cmd_wait_event_fingerprint (FpiDeviceCrfpMoc *self)
|
||||
{
|
||||
int rv;
|
||||
struct crfpmoc_ec_response_get_next_event_v1 buffer;
|
||||
long timeout = 5000;
|
||||
long event_type = CRFPMOC_EC_MKBP_EVENT_FINGERPRINT;
|
||||
|
||||
rv = crfpmoc_ec_pollevent (self, 1 << event_type, &buffer, sizeof (buffer), timeout);
|
||||
if (rv == 0)
|
||||
{
|
||||
fp_warn ("Timeout waiting for MKBP event");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
else if (rv < 0)
|
||||
{
|
||||
fp_warn ("Error polling for MKBP event");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fp_dbg ("MKBP event %d data", buffer.event_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
crfpmoc_task_ssm_done (FpiSsm *ssm, FpDevice *device, GError *error)
|
||||
{
|
||||
|
|
@ -345,7 +387,22 @@ crfpmoc_enroll_run_state (FpiSsm *ssm, FpDevice *device)
|
|||
|
||||
case ENROLL_WAIT_FINGER:
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NEEDED);
|
||||
fpi_ssm_next_state (ssm);
|
||||
r = crfpmoc_cmd_wait_event_fingerprint (self);
|
||||
if (r < 0)
|
||||
{
|
||||
if (r == -ETIMEDOUT)
|
||||
{
|
||||
fpi_ssm_jump_to_state (ssm, ENROLL_WAIT_FINGER);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
break;
|
||||
|
||||
case ENROLL_SENSOR_CHECK:
|
||||
|
|
@ -454,7 +511,22 @@ crfpmoc_verify_run_state (FpiSsm *ssm, FpDevice *device)
|
|||
|
||||
case VERIFY_WAIT_FINGER:
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NEEDED);
|
||||
fpi_ssm_next_state (ssm);
|
||||
r = crfpmoc_cmd_wait_event_fingerprint (self);
|
||||
if (r < 0)
|
||||
{
|
||||
if (r == -ETIMEDOUT)
|
||||
{
|
||||
fpi_ssm_jump_to_state (ssm, VERIFY_WAIT_FINGER);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
break;
|
||||
|
||||
case VERIFY_SENSOR_CHECK:
|
||||
|
|
|
|||
|
|
@ -37,8 +37,6 @@ G_DECLARE_FINAL_TYPE (FpiDeviceCrfpMoc, fpi_device_crfpmoc, FPI, DEVICE_CRFPMOC,
|
|||
|
||||
#define CRFPMOC_NR_ENROLL_STAGES 5
|
||||
|
||||
#define CRFPMOC_TIMEOUT_RETRY_DELAY_MICROSECONDS 100000
|
||||
|
||||
/* crfpmoc_ec_command return value for non-success result from EC */
|
||||
#define CRFPMOC_EECRESULT 1000
|
||||
|
||||
|
|
@ -62,45 +60,96 @@ G_DECLARE_FINAL_TYPE (FpiDeviceCrfpMoc, fpi_device_crfpmoc, FPI, DEVICE_CRFPMOC,
|
|||
|
||||
#define CRFPMOC_FPSTATS_MATCHING_INV (1U << 1)
|
||||
|
||||
/* New Fingerprint sensor event, the event data is fp_events bitmap. */
|
||||
#define CRFPMOC_EC_MKBP_EVENT_FINGERPRINT 5
|
||||
|
||||
struct crfpmoc_ec_params_fp_mode {
|
||||
guint32 mode; /* as defined by CRFPMOC_FP_MODE_ constants */
|
||||
guint32 mode; /* as defined by CRFPMOC_FP_MODE_ constants */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct crfpmoc_ec_response_fp_mode {
|
||||
guint32 mode; /* as defined by CRFPMOC_FP_MODE_ constants */
|
||||
guint32 mode; /* as defined by CRFPMOC_FP_MODE_ constants */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct crfpmoc_ec_response_fp_stats {
|
||||
guint32 capture_time_us;
|
||||
guint32 matching_time_us;
|
||||
guint32 overall_time_us;
|
||||
struct {
|
||||
guint32 lo;
|
||||
guint32 hi;
|
||||
} overall_t0;
|
||||
guint8 timestamps_invalid;
|
||||
gint8 template_matched;
|
||||
guint32 capture_time_us;
|
||||
guint32 matching_time_us;
|
||||
guint32 overall_time_us;
|
||||
struct {
|
||||
guint32 lo;
|
||||
guint32 hi;
|
||||
} overall_t0;
|
||||
guint8 timestamps_invalid;
|
||||
gint8 template_matched;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct crfpmoc_ec_response_fp_info {
|
||||
/* Sensor identification */
|
||||
guint32 vendor_id;
|
||||
guint32 product_id;
|
||||
guint32 model_id;
|
||||
guint32 version;
|
||||
/* Image frame characteristics */
|
||||
guint32 frame_size;
|
||||
guint32 pixel_format;
|
||||
guint16 width;
|
||||
guint16 height;
|
||||
guint16 bpp;
|
||||
guint16 errors;
|
||||
/* Template/finger current information */
|
||||
guint32 template_size; /* max template size in bytes */
|
||||
guint16 template_max; /* maximum number of fingers/templates */
|
||||
guint16 template_valid; /* number of valid fingers/templates */
|
||||
guint32 template_dirty; /* bitmap of templates with MCU side changes */
|
||||
guint32 template_version; /* version of the template format */
|
||||
/* Sensor identification */
|
||||
guint32 vendor_id;
|
||||
guint32 product_id;
|
||||
guint32 model_id;
|
||||
guint32 version;
|
||||
/* Image frame characteristics */
|
||||
guint32 frame_size;
|
||||
guint32 pixel_format;
|
||||
guint16 width;
|
||||
guint16 height;
|
||||
guint16 bpp;
|
||||
guint16 errors;
|
||||
/* Template/finger current information */
|
||||
guint32 template_size; /* max template size in bytes */
|
||||
guint16 template_max; /* maximum number of fingers/templates */
|
||||
guint16 template_valid; /* number of valid fingers/templates */
|
||||
guint32 template_dirty; /* bitmap of templates with MCU side changes */
|
||||
guint32 template_version; /* version of the template format */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Note: used in crfpmoc_ec_response_get_next_data_v1 */
|
||||
struct crfpmoc_ec_response_motion_sense_fifo_info {
|
||||
/* Size of the fifo */
|
||||
guint16 size;
|
||||
/* Amount of space used in the fifo */
|
||||
guint16 count;
|
||||
/* Timestamp recorded in us.
|
||||
* aka accurate timestamp when host event was triggered.
|
||||
*/
|
||||
guint32 timestamp;
|
||||
/* Total amount of vector lost */
|
||||
guint16 total_lost;
|
||||
/* Lost events since the last fifo_info, per sensors */
|
||||
guint16 lost[0];
|
||||
};
|
||||
|
||||
union __attribute__((packed)) crfpmoc_ec_response_get_next_data_v1 {
|
||||
guint8 key_matrix[16];
|
||||
|
||||
/* Unaligned */
|
||||
guint32 host_event;
|
||||
guint64 host_event64;
|
||||
|
||||
struct {
|
||||
/* For aligning the fifo_info */
|
||||
guint8 reserved[3];
|
||||
struct crfpmoc_ec_response_motion_sense_fifo_info info;
|
||||
} sensor_fifo;
|
||||
|
||||
guint32 buttons;
|
||||
|
||||
guint32 switches;
|
||||
|
||||
guint32 fp_events;
|
||||
|
||||
guint32 sysrq;
|
||||
|
||||
guint32 cec_events;
|
||||
|
||||
guint8 cec_message[16];
|
||||
};
|
||||
|
||||
struct crfpmoc_ec_response_get_next_event_v1 {
|
||||
guint8 event_type;
|
||||
/* Followed by event data if any */
|
||||
union crfpmoc_ec_response_get_next_data_v1 data;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
|
|
@ -112,47 +161,48 @@ struct crfpmoc_ec_response_fp_info {
|
|||
* @data: Where to put the incoming data from EC and outgoing data to EC
|
||||
*/
|
||||
struct crfpmoc_cros_ec_command_v2 {
|
||||
guint32 version;
|
||||
guint32 command;
|
||||
guint32 outsize;
|
||||
guint32 insize;
|
||||
guint32 result;
|
||||
guint8 data[0];
|
||||
guint32 version;
|
||||
guint32 command;
|
||||
guint32 outsize;
|
||||
guint32 insize;
|
||||
guint32 result;
|
||||
guint8 data[0];
|
||||
};
|
||||
|
||||
#define CRFPMOC_CROS_EC_DEV_IOC_V2 0xEC
|
||||
#define CRFPMOC_CROS_EC_DEV_IOCXCMD_V2 \
|
||||
_IOWR(CRFPMOC_CROS_EC_DEV_IOC_V2, 0, struct crfpmoc_cros_ec_command_v2)
|
||||
_IOWR(CRFPMOC_CROS_EC_DEV_IOC_V2, 0, struct crfpmoc_cros_ec_command_v2)
|
||||
#define CRFPMOC_CROS_EC_DEV_IOCEVENTMASK_V2 _IO(CRFPMOC_CROS_EC_DEV_IOC_V2, 2)
|
||||
|
||||
/*
|
||||
* Host command response codes (16-bit).
|
||||
*/
|
||||
enum crfpmoc_ec_status {
|
||||
EC_RES_SUCCESS = 0,
|
||||
EC_RES_INVALID_COMMAND = 1,
|
||||
EC_RES_ERROR = 2,
|
||||
EC_RES_INVALID_PARAM = 3,
|
||||
EC_RES_ACCESS_DENIED = 4,
|
||||
EC_RES_INVALID_RESPONSE = 5,
|
||||
EC_RES_INVALID_VERSION = 6,
|
||||
EC_RES_INVALID_CHECKSUM = 7,
|
||||
EC_RES_IN_PROGRESS = 8, /* Accepted, command in progress */
|
||||
EC_RES_UNAVAILABLE = 9, /* No response available */
|
||||
EC_RES_TIMEOUT = 10, /* We got a timeout */
|
||||
EC_RES_OVERFLOW = 11, /* Table / data overflow */
|
||||
EC_RES_INVALID_HEADER = 12, /* Header contains invalid data */
|
||||
EC_RES_REQUEST_TRUNCATED = 13, /* Didn't get the entire request */
|
||||
EC_RES_RESPONSE_TOO_BIG = 14, /* Response was too big to handle */
|
||||
EC_RES_BUS_ERROR = 15, /* Communications bus error */
|
||||
EC_RES_BUSY = 16, /* Up but too busy. Should retry */
|
||||
EC_RES_INVALID_HEADER_VERSION = 17, /* Header version invalid */
|
||||
EC_RES_INVALID_HEADER_CRC = 18, /* Header CRC invalid */
|
||||
EC_RES_INVALID_DATA_CRC = 19, /* Data CRC invalid */
|
||||
EC_RES_DUP_UNAVAILABLE = 20, /* Can't resend response */
|
||||
EC_RES_SUCCESS = 0,
|
||||
EC_RES_INVALID_COMMAND = 1,
|
||||
EC_RES_ERROR = 2,
|
||||
EC_RES_INVALID_PARAM = 3,
|
||||
EC_RES_ACCESS_DENIED = 4,
|
||||
EC_RES_INVALID_RESPONSE = 5,
|
||||
EC_RES_INVALID_VERSION = 6,
|
||||
EC_RES_INVALID_CHECKSUM = 7,
|
||||
EC_RES_IN_PROGRESS = 8, /* Accepted, command in progress */
|
||||
EC_RES_UNAVAILABLE = 9, /* No response available */
|
||||
EC_RES_TIMEOUT = 10, /* We got a timeout */
|
||||
EC_RES_OVERFLOW = 11, /* Table / data overflow */
|
||||
EC_RES_INVALID_HEADER = 12, /* Header contains invalid data */
|
||||
EC_RES_REQUEST_TRUNCATED = 13, /* Didn't get the entire request */
|
||||
EC_RES_RESPONSE_TOO_BIG = 14, /* Response was too big to handle */
|
||||
EC_RES_BUS_ERROR = 15, /* Communications bus error */
|
||||
EC_RES_BUSY = 16, /* Up but too busy. Should retry */
|
||||
EC_RES_INVALID_HEADER_VERSION = 17, /* Header version invalid */
|
||||
EC_RES_INVALID_HEADER_CRC = 18, /* Header CRC invalid */
|
||||
EC_RES_INVALID_DATA_CRC = 19, /* Data CRC invalid */
|
||||
EC_RES_DUP_UNAVAILABLE = 20, /* Can't resend response */
|
||||
|
||||
EC_RES_COUNT,
|
||||
EC_RES_COUNT,
|
||||
|
||||
EC_RES_MAX = UINT16_MAX, /**< Force enum to be 16 bits */
|
||||
EC_RES_MAX = UINT16_MAX, /**< Force enum to be 16 bits */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* SSM task states and various status enums */
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000000000000
|
|||
CROS_EC_DEV_IOCXCMD_V2 48 010000000304000000000000300000000000000046504320090000001B020000010000009466000047524559A000A0000800FF0324140000050001000100000004000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000040000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000000000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 22 000000000704000000000000160000000000000065630100B44A020007B30300DC33505A070000000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 22 00000000070400000000000016000000000000007B630100C746020033AF0300FA095D6D040000000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000040000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000000000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 22 000000000704000000000000160000000000000060630100874E0200D6B6030027289A5A070000000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 22 00000000070400000000000016000000000000007F630100A949020019B20300FBAA6D6D040000000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000080000000
|
||||
CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000000000000
|
||||
|
|
|
|||
|
|
@ -60,9 +60,9 @@ E: SUBSYSTEM=serial-base
|
|||
L: driver=../../../../../bus/serial-base/drivers/port
|
||||
A: power/autosuspend_delay_ms=500\n
|
||||
A: power/control=auto\n
|
||||
A: power/runtime_active_time=31736669\n
|
||||
A: power/runtime_active_time=19045089\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=5190\n
|
||||
A: power/runtime_suspended_time=1840\n
|
||||
|
||||
P: /devices/platform/AMDI0020:01/AMDI0020:01:0
|
||||
E: DEVTYPE=ctrl
|
||||
|
|
@ -70,9 +70,9 @@ E: DRIVER=ctrl
|
|||
E: SUBSYSTEM=serial-base
|
||||
L: driver=../../../../bus/serial-base/drivers/ctrl
|
||||
A: power/control=auto\n
|
||||
A: power/runtime_active_time=31736676\n
|
||||
A: power/runtime_active_time=19045095\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=5190\n
|
||||
A: power/runtime_suspended_time=1840\n
|
||||
|
||||
P: /devices/platform/AMDI0020:01
|
||||
E: DRIVER=dw-apb-uart
|
||||
|
|
@ -86,8 +86,8 @@ A: driver_override=(null)\n
|
|||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/AMDI0020:01
|
||||
A: modalias=acpi:AMDI0020:\n
|
||||
A: power/control=auto\n
|
||||
A: power/runtime_active_time=31736687\n
|
||||
A: power/runtime_active_time=19045115\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=5189\n
|
||||
A: power/runtime_suspended_time=1826\n
|
||||
L: software_node=../../../kernel/software_nodes/node1
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue