mirror of
https://github.com/morgan9e/libfprint-fpc1020
synced 2026-04-14 00:14:16 +09:00
1879 lines
55 KiB
C
1879 lines
55 KiB
C
/*
|
|
* Copyright (C) 2022 FocalTech Electronics Inc
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include "focaltech_moc.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
#define FP_COMPONENT "focaltech_moc"
|
|
|
|
#include "drivers_api.h"
|
|
|
|
G_DEFINE_TYPE (FpiDeviceFocaltechMoc, fpi_device_focaltech_moc, FP_TYPE_DEVICE)
|
|
|
|
static const FpIdEntry id_table[] = {
|
|
{ .vid = 0x2808, .pid = 0x9e48, },
|
|
{ .vid = 0x2808, .pid = 0xd979, },
|
|
{ .vid = 0x2808, .pid = 0xa959, },
|
|
{ .vid = 0x2808, .pid = 0xa99a, },
|
|
{ .vid = 0x2808, .pid = 0xa57a, },
|
|
{ .vid = 0x2808, .pid = 0xa78a, },
|
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
|
};
|
|
|
|
typedef void (*SynCmdMsgCallback) (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error);
|
|
|
|
typedef struct
|
|
{
|
|
SynCmdMsgCallback callback;
|
|
} CommandData;
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t h;
|
|
uint8_t l;
|
|
} FpCmdLen;
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t magic;
|
|
FpCmdLen len;
|
|
} FpCmdHeader;
|
|
|
|
typedef struct
|
|
{
|
|
FpCmdHeader header;
|
|
uint8_t code;
|
|
uint8_t payload[0];
|
|
} FpCmd;
|
|
|
|
typedef struct
|
|
{
|
|
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
|
|
uint8_t b0;
|
|
uint8_t b1;
|
|
#else
|
|
uint8_t b1;
|
|
uint8_t b0;
|
|
#endif
|
|
} u16_bytes_t;
|
|
|
|
typedef union
|
|
{
|
|
u16_bytes_t s;
|
|
uint16_t v;
|
|
} u_u16_bytes_t;
|
|
|
|
static inline uint16_t
|
|
get_u16_from_u8_lh (uint8_t l, uint8_t h)
|
|
{
|
|
u_u16_bytes_t u_u16_bytes;
|
|
|
|
u_u16_bytes.v = 0;
|
|
u_u16_bytes.s.b0 = l;
|
|
u_u16_bytes.s.b1 = h;
|
|
|
|
return u_u16_bytes.v;
|
|
}
|
|
|
|
static inline uint8_t
|
|
get_u8_l_from_u16 (uint16_t v)
|
|
{
|
|
u_u16_bytes_t u_u16_bytes;
|
|
|
|
u_u16_bytes.v = v;
|
|
|
|
return u_u16_bytes.s.b0;
|
|
}
|
|
|
|
static inline uint8_t
|
|
get_u8_h_from_u16 (uint16_t v)
|
|
{
|
|
u_u16_bytes_t u_u16_bytes;
|
|
|
|
u_u16_bytes.v = v;
|
|
|
|
return u_u16_bytes.s.b1;
|
|
}
|
|
|
|
static uint8_t
|
|
fp_cmd_bcc (uint8_t *data, uint16_t len)
|
|
{
|
|
int i;
|
|
uint8_t bcc = 0;
|
|
|
|
for (i = 0; i < len; i++)
|
|
bcc ^= data[i];
|
|
|
|
return bcc;
|
|
}
|
|
|
|
static uint8_t *
|
|
focaltech_moc_compose_cmd (uint8_t cmd, const uint8_t *data, uint16_t len)
|
|
{
|
|
g_autofree uint8_t *cmd_buf = NULL;
|
|
FpCmd *fp_cmd = NULL;
|
|
uint8_t *bcc = NULL;
|
|
uint16_t header_len = len + sizeof (*bcc);
|
|
|
|
cmd_buf = g_new0 (uint8_t, sizeof (FpCmd) + header_len);
|
|
|
|
fp_cmd = (FpCmd *) cmd_buf;
|
|
|
|
fp_cmd->header.magic = 0x02;
|
|
fp_cmd->header.len.l = get_u8_l_from_u16 (header_len);
|
|
fp_cmd->header.len.h = get_u8_h_from_u16 (header_len);
|
|
fp_cmd->code = cmd;
|
|
|
|
if (data != NULL)
|
|
memcpy (fp_cmd->payload, data, len);
|
|
|
|
bcc = fp_cmd->payload + len;
|
|
*bcc = fp_cmd_bcc ((uint8_t *) &fp_cmd->header.len, bcc - (uint8_t *) &fp_cmd->header.len);
|
|
|
|
return g_steal_pointer (&cmd_buf);
|
|
}
|
|
|
|
static int
|
|
focaltech_moc_check_cmd (uint8_t *response_buf, uint16_t len)
|
|
{
|
|
int ret = -1;
|
|
FpCmd *fp_cmd = NULL;
|
|
uint8_t *bcc = NULL;
|
|
uint16_t header_len;
|
|
uint16_t data_len;
|
|
|
|
fp_cmd = (FpCmd *) response_buf;
|
|
|
|
if (len < sizeof (FpCmd) + sizeof (*bcc))
|
|
return ret;
|
|
|
|
if (fp_cmd->header.magic != 0x02)
|
|
return ret;
|
|
|
|
header_len = get_u16_from_u8_lh (fp_cmd->header.len.l, fp_cmd->header.len.h);
|
|
|
|
if (header_len < sizeof (*bcc))
|
|
return ret;
|
|
|
|
if ((sizeof (FpCmd) + header_len) > len)
|
|
return ret;
|
|
|
|
data_len = header_len - sizeof (*bcc);
|
|
|
|
bcc = fp_cmd->payload + data_len;
|
|
|
|
if (fp_cmd_bcc ((uint8_t *) &fp_cmd->header.len,
|
|
bcc - (uint8_t *) &fp_cmd->header.len) != *bcc)
|
|
return ret;
|
|
|
|
ret = 0;
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|
FpDevice *device,
|
|
gpointer userdata,
|
|
GError *error)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
CommandData *data = userdata;
|
|
int ssm_state = 0;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (transfer->ssm, g_steal_pointer (&error));
|
|
return;
|
|
}
|
|
|
|
if (data == NULL)
|
|
{
|
|
fpi_ssm_mark_failed (transfer->ssm,
|
|
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
|
return;
|
|
}
|
|
|
|
ssm_state = fpi_ssm_get_cur_state (transfer->ssm);
|
|
|
|
/* skip zero length package */
|
|
if (transfer->actual_length == 0)
|
|
{
|
|
fpi_ssm_jump_to_state (transfer->ssm, ssm_state);
|
|
return;
|
|
}
|
|
|
|
if (focaltech_moc_check_cmd (transfer->buffer, transfer->actual_length) != 0)
|
|
{
|
|
fpi_ssm_mark_failed (transfer->ssm,
|
|
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
|
return;
|
|
}
|
|
|
|
if (data->callback)
|
|
data->callback (self, transfer->buffer, transfer->actual_length, NULL);
|
|
|
|
fpi_ssm_mark_completed (transfer->ssm);
|
|
}
|
|
|
|
typedef enum {
|
|
FOCALTECH_CMD_SEND = 0,
|
|
FOCALTECH_CMD_GET,
|
|
FOCALTECH_CMD_NUM_STATES,
|
|
} FocaltechCmdState;
|
|
|
|
static void
|
|
fp_cmd_run_state (FpiSsm *ssm,
|
|
FpDevice *device)
|
|
{
|
|
FpiUsbTransfer *transfer;
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
switch (fpi_ssm_get_cur_state (ssm))
|
|
{
|
|
case FOCALTECH_CMD_SEND:
|
|
if (self->cmd_transfer)
|
|
{
|
|
self->cmd_transfer->ssm = ssm;
|
|
fpi_usb_transfer_submit (g_steal_pointer (&self->cmd_transfer),
|
|
FOCALTECH_MOC_CMD_TIMEOUT,
|
|
NULL,
|
|
fpi_ssm_usb_transfer_cb,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
fpi_ssm_next_state (ssm);
|
|
}
|
|
|
|
break;
|
|
|
|
case FOCALTECH_CMD_GET:
|
|
if (self->cmd_len_in == 0)
|
|
{
|
|
CommandData *data = fpi_ssm_get_data (ssm);
|
|
|
|
if (data->callback)
|
|
data->callback (self, NULL, 0, 0);
|
|
|
|
fpi_ssm_mark_completed (ssm);
|
|
return;
|
|
}
|
|
|
|
transfer = fpi_usb_transfer_new (device);
|
|
transfer->ssm = ssm;
|
|
fpi_usb_transfer_fill_bulk (transfer, self->bulk_in_ep, self->cmd_len_in);
|
|
fpi_usb_transfer_submit (transfer,
|
|
self->cmd_cancelable ? 0 : FOCALTECH_MOC_CMD_TIMEOUT,
|
|
self->cmd_cancelable ? fpi_device_get_cancellable (device) : NULL,
|
|
fp_cmd_receive_cb,
|
|
fpi_ssm_get_data (ssm));
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
fp_cmd_ssm_done (FpiSsm *ssm, FpDevice *device, GError *error)
|
|
{
|
|
g_autoptr(GError) local_error = error;
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
CommandData *data = fpi_ssm_get_data (ssm);
|
|
|
|
self->cmd_ssm = NULL;
|
|
|
|
if (local_error && data->callback)
|
|
data->callback (self, NULL, 0, g_steal_pointer (&local_error));
|
|
}
|
|
|
|
static void
|
|
fp_cmd_ssm_done_data_free (CommandData *data)
|
|
{
|
|
g_free (data);
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_get_cmd (FpDevice *device, guint8 *buffer_out,
|
|
gsize length_out, gsize length_in,
|
|
gboolean can_be_cancelled,
|
|
SynCmdMsgCallback callback)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
|
CommandData *data = g_new0 (CommandData, 1);
|
|
|
|
transfer = fpi_usb_transfer_new (device);
|
|
transfer->short_is_error = TRUE;
|
|
fpi_usb_transfer_fill_bulk_full (transfer, self->bulk_out_ep, buffer_out,
|
|
length_out, g_free);
|
|
data->callback = callback;
|
|
|
|
self->cmd_transfer = g_steal_pointer (&transfer);
|
|
self->cmd_len_in = length_in + 1;
|
|
self->cmd_cancelable = can_be_cancelled;
|
|
|
|
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
|
|
fp_cmd_run_state,
|
|
FOCALTECH_CMD_NUM_STATES);
|
|
|
|
fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
|
|
|
|
fpi_ssm_start (self->cmd_ssm, fp_cmd_ssm_done);
|
|
}
|
|
|
|
struct UserId
|
|
{
|
|
uint8_t uid[32];
|
|
};
|
|
|
|
static void
|
|
fprint_set_uid (FpPrint *print, uint8_t *uid, size_t size)
|
|
{
|
|
GVariant *var_uid;
|
|
GVariant *var_data;
|
|
|
|
var_uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, uid, size, 1);
|
|
var_data = g_variant_new ("(@ay)", var_uid);
|
|
fpi_print_set_type (print, FPI_PRINT_RAW);
|
|
fpi_print_set_device_stored (print, TRUE);
|
|
g_object_set (print, "fpi-data", var_data, NULL);
|
|
}
|
|
|
|
enum enroll_states {
|
|
ENROLL_RSP_RETRY,
|
|
ENROLL_RSP_ENROLL_REPORT,
|
|
ENROLL_RSP_ENROLL_OK,
|
|
ENROLL_RSP_ENROLL_CANCEL_REPORT,
|
|
};
|
|
|
|
static void
|
|
enroll_status_report (FpiDeviceFocaltechMoc *self, int enroll_status_id,
|
|
int data, GError *error)
|
|
{
|
|
FpDevice *device = FP_DEVICE (self);
|
|
|
|
switch (enroll_status_id)
|
|
{
|
|
case ENROLL_RSP_RETRY:
|
|
{
|
|
fpi_device_enroll_progress (device, self->num_frames, NULL,
|
|
fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
|
|
break;
|
|
}
|
|
|
|
case ENROLL_RSP_ENROLL_REPORT:
|
|
{
|
|
fpi_device_enroll_progress (device, self->num_frames, NULL, NULL);
|
|
break;
|
|
}
|
|
|
|
case ENROLL_RSP_ENROLL_OK:
|
|
{
|
|
FpPrint *print = NULL;
|
|
fp_info ("Enrollment was successful!");
|
|
fpi_device_get_enroll_data (device, &print);
|
|
fpi_device_enroll_complete (device, g_object_ref (print), NULL);
|
|
break;
|
|
}
|
|
|
|
case ENROLL_RSP_ENROLL_CANCEL_REPORT:
|
|
{
|
|
fpi_device_enroll_complete (device, NULL,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
"Enrollment failed (%d) (ENROLL_RSP_ENROLL_CANCEL_REPORT)",
|
|
data));
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
task_ssm_done (FpiSsm *ssm, FpDevice *device, GError *error)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
self->num_frames = 0;
|
|
self->task_ssm = NULL;
|
|
|
|
if (error)
|
|
fpi_device_action_error (device, g_steal_pointer (&error));
|
|
}
|
|
|
|
static const char *
|
|
get_g_usb_device_direction_des (GUsbDeviceDirection dir)
|
|
{
|
|
switch (dir)
|
|
{
|
|
case G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST:
|
|
return "G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST";
|
|
|
|
case G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE:
|
|
return "G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE";
|
|
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
static int
|
|
usb_claim_interface_probe (FpDevice *device, int claim, GError **error)
|
|
{
|
|
g_autoptr(GPtrArray) interfaces = NULL;
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
int ret = -1;
|
|
int i;
|
|
|
|
interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (device), error);
|
|
|
|
for (i = 0; i < interfaces->len; i++)
|
|
{
|
|
GUsbInterface *cur_iface = g_ptr_array_index (interfaces, i);
|
|
g_autoptr(GPtrArray) endpoints = g_usb_interface_get_endpoints (cur_iface);
|
|
|
|
fp_dbg ("class:%x, subclass:%x, protocol:%x",
|
|
g_usb_interface_get_class (cur_iface),
|
|
g_usb_interface_get_subclass (cur_iface),
|
|
g_usb_interface_get_protocol (cur_iface));
|
|
|
|
if (claim == 1)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < endpoints->len; j++)
|
|
{
|
|
GUsbEndpoint *endpoint = g_ptr_array_index (endpoints, j);
|
|
GBytes *bytes = g_usb_endpoint_get_extra (endpoint);
|
|
|
|
fp_dbg ("bytes size:%ld", g_bytes_get_size (bytes));
|
|
|
|
fp_dbg ("kind:%x, max packet size:%d, poll interval:%d, refresh:%x, "
|
|
"sync address:%x, address:%x, number:%d, direction:%s",
|
|
g_usb_endpoint_get_kind (endpoint),
|
|
g_usb_endpoint_get_maximum_packet_size (endpoint),
|
|
g_usb_endpoint_get_polling_interval (endpoint),
|
|
g_usb_endpoint_get_refresh (endpoint),
|
|
g_usb_endpoint_get_synch_address (endpoint),
|
|
g_usb_endpoint_get_address (endpoint),
|
|
g_usb_endpoint_get_number (endpoint),
|
|
get_g_usb_device_direction_des (g_usb_endpoint_get_direction (endpoint)));
|
|
|
|
if (g_usb_endpoint_get_direction (endpoint) == G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST)
|
|
self->bulk_in_ep = g_usb_endpoint_get_address (endpoint);
|
|
else
|
|
self->bulk_out_ep = g_usb_endpoint_get_address (endpoint);
|
|
}
|
|
|
|
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device),
|
|
g_usb_interface_get_number (cur_iface),
|
|
0, error))
|
|
return ret;
|
|
}
|
|
else if (!g_usb_device_release_interface (fpi_device_get_usb_device (device),
|
|
g_usb_interface_get_number (cur_iface),
|
|
0, error))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
task_ssm_init_done (FpiSsm *ssm, FpDevice *device, GError *error)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
if (error)
|
|
usb_claim_interface_probe (device, 0, &error);
|
|
|
|
fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
|
|
}
|
|
|
|
struct EnrollTimes
|
|
{
|
|
uint8_t enroll_times;
|
|
};
|
|
|
|
static void
|
|
focaltech_moc_get_enroll_times (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
struct EnrollTimes *enroll_times = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
enroll_times = (struct EnrollTimes *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
fp_dbg ("focaltechmoc enroll_times: %d", enroll_times->enroll_times + 1);
|
|
fpi_device_set_nr_enroll_stages (FP_DEVICE (self), enroll_times->enroll_times + 1);
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_release_finger (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
}
|
|
|
|
enum dev_init_states {
|
|
DEV_INIT_GET_ENROLL_TIMES,
|
|
DEV_INIT_RELEASE_FINGER,
|
|
DEV_INIT_STATES,
|
|
};
|
|
|
|
static void
|
|
dev_init_handler (FpiSsm *ssm, FpDevice *device)
|
|
{
|
|
guint8 *cmd_buf = NULL;
|
|
uint16_t cmd_len = 0;
|
|
uint16_t resp_len = 0;
|
|
|
|
switch (fpi_ssm_get_cur_state (ssm))
|
|
{
|
|
case DEV_INIT_GET_ENROLL_TIMES:
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct EnrollTimes);
|
|
cmd_buf = focaltech_moc_compose_cmd (0xa5, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_get_enroll_times);
|
|
break;
|
|
|
|
case DEV_INIT_RELEASE_FINGER:
|
|
{
|
|
uint8_t d1 = 0x78;
|
|
cmd_len = sizeof (d1);
|
|
resp_len = 0;
|
|
cmd_buf = focaltech_moc_compose_cmd (0x82, &d1, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_release_finger);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_open (FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
GError *error = NULL;
|
|
|
|
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
|
|
{
|
|
fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
|
|
return;
|
|
}
|
|
|
|
if (usb_claim_interface_probe (device, 1, &error) != 0)
|
|
{
|
|
fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static void
|
|
task_ssm_exit_done (FpiSsm *ssm, FpDevice *device, GError *error)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
if (!error)
|
|
{
|
|
GError *local_error = NULL;
|
|
|
|
if (usb_claim_interface_probe (device, 0, &local_error) < 0)
|
|
g_propagate_error (&error, g_steal_pointer (&local_error));
|
|
}
|
|
|
|
fpi_device_close_complete (FP_DEVICE (self), error);
|
|
self->task_ssm = NULL;
|
|
}
|
|
|
|
enum dev_exit_states {
|
|
DEV_EXIT_START,
|
|
DEV_EXIT_STATES,
|
|
};
|
|
|
|
static void
|
|
dev_exit_handler (FpiSsm *ssm, FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
switch (fpi_ssm_get_cur_state (ssm))
|
|
{
|
|
case DEV_EXIT_START:
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_close (FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
fp_info ("Focaltechmoc dev_exit");
|
|
self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_exit_handler, DEV_EXIT_STATES);
|
|
fpi_ssm_start (self->task_ssm, task_ssm_exit_done);
|
|
}
|
|
|
|
enum identify_states {
|
|
MOC_IDENTIFY_RELEASE_FINGER,
|
|
MOC_IDENTIFY_WAIT_FINGER,
|
|
MOC_IDENTIFY_WAIT_FINGER_DELAY,
|
|
MOC_IDENTIFY_CAPTURE,
|
|
MOC_IDENTIFY_MATCH,
|
|
MOC_IDENTIFY_NUM_STATES,
|
|
};
|
|
|
|
static void
|
|
focaltech_moc_identify_wait_finger_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
uint8_t *finger_status = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
finger_status = (uint8_t *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
|
|
if (*finger_status == 0x01)
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_IDENTIFY_CAPTURE);
|
|
else
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_IDENTIFY_WAIT_FINGER_DELAY);
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_identify_wait_finger_delay (FpDevice *device,
|
|
void *user_data)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_IDENTIFY_WAIT_FINGER);
|
|
}
|
|
|
|
enum FprintError {
|
|
ERROR_NONE,
|
|
ERROR_QUALITY,
|
|
ERROR_SHORT,
|
|
ERROR_LEFT,
|
|
ERROR_RIGHT,
|
|
ERROR_NONFINGER,
|
|
ERROR_NOMOVE,
|
|
ERROR_OTHER,
|
|
};
|
|
|
|
struct CaptureResult
|
|
{
|
|
uint8_t error;
|
|
uint8_t remain;
|
|
};
|
|
|
|
static void
|
|
focaltech_moc_identify_capture_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
struct CaptureResult *capture_result = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
capture_result = (struct CaptureResult *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
if (capture_result->error == ERROR_NONE)
|
|
{
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
else
|
|
{
|
|
if (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_VERIFY)
|
|
{
|
|
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
|
|
fpi_device_verify_complete (FP_DEVICE (self), NULL);
|
|
}
|
|
else
|
|
{
|
|
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
|
fpi_device_identify_complete (FP_DEVICE (self), NULL);
|
|
}
|
|
|
|
fpi_ssm_mark_failed (self->task_ssm, fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
identify_status_report (FpiDeviceFocaltechMoc *self, FpPrint *print, GError *error)
|
|
{
|
|
FpDevice *device = FP_DEVICE (self);
|
|
|
|
if (print == NULL)
|
|
{
|
|
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
|
{
|
|
fpi_device_identify_report (device, NULL, NULL, NULL);
|
|
fpi_device_identify_complete (device, NULL);
|
|
}
|
|
else
|
|
{
|
|
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
|
|
fpi_device_verify_complete (device, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
|
{
|
|
GPtrArray *prints;
|
|
gboolean found = FALSE;
|
|
guint index;
|
|
|
|
fpi_device_get_identify_data (device, &prints);
|
|
found = g_ptr_array_find_with_equal_func (prints,
|
|
print,
|
|
(GEqualFunc) fp_print_equal,
|
|
&index);
|
|
|
|
if (found)
|
|
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
|
else
|
|
fpi_device_identify_report (device, NULL, print, NULL);
|
|
|
|
fpi_device_identify_complete (device, NULL);
|
|
}
|
|
else
|
|
{
|
|
FpPrint *verify_print = NULL;
|
|
fpi_device_get_verify_data (device, &verify_print);
|
|
|
|
if (fp_print_equal (verify_print, print))
|
|
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, print, NULL);
|
|
else
|
|
fpi_device_verify_report (device, FPI_MATCH_FAIL, print, NULL);
|
|
|
|
fpi_device_verify_complete (device, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_identify_match_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
struct UserId *user_id = NULL;
|
|
FpPrint *print = NULL;
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
user_id = (struct UserId *) (fp_cmd + 1);
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
if (fp_cmd->code == 0x04)
|
|
{
|
|
print = fp_print_new (FP_DEVICE (self));
|
|
fprint_set_uid (print, user_id->uid, sizeof (user_id->uid));
|
|
}
|
|
|
|
identify_status_report (self, print, error);
|
|
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
|
|
static void
|
|
focaltech_identify_run_state (FpiSsm *ssm, FpDevice *device)
|
|
{
|
|
guint8 *cmd_buf = NULL;
|
|
uint16_t cmd_len = 0;
|
|
uint16_t resp_len = 0;
|
|
|
|
switch (fpi_ssm_get_cur_state (ssm))
|
|
{
|
|
case MOC_IDENTIFY_RELEASE_FINGER:
|
|
{
|
|
uint8_t d1 = 0x78;
|
|
cmd_len = sizeof (d1);
|
|
resp_len = 0;
|
|
cmd_buf = focaltech_moc_compose_cmd (0x82, &d1, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_release_finger);
|
|
break;
|
|
}
|
|
|
|
case MOC_IDENTIFY_WAIT_FINGER:
|
|
{
|
|
uint8_t data = 0x02;
|
|
cmd_len = sizeof (uint8_t);
|
|
resp_len = sizeof (uint8_t);
|
|
cmd_buf = focaltech_moc_compose_cmd (0x80, &data, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_identify_wait_finger_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_IDENTIFY_WAIT_FINGER_DELAY:
|
|
fpi_device_add_timeout (device, 50,
|
|
focaltech_moc_identify_wait_finger_delay,
|
|
NULL, NULL);
|
|
break;
|
|
|
|
case MOC_IDENTIFY_CAPTURE:
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct CaptureResult);
|
|
cmd_buf = focaltech_moc_compose_cmd (0xa6, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_identify_capture_cb);
|
|
break;
|
|
|
|
case MOC_IDENTIFY_MATCH:
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct UserId);
|
|
cmd_buf = focaltech_moc_compose_cmd (0xaa, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_identify_match_cb);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_identify (FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
self->task_ssm = fpi_ssm_new (device,
|
|
focaltech_identify_run_state,
|
|
MOC_IDENTIFY_NUM_STATES);
|
|
fpi_ssm_start (self->task_ssm, task_ssm_done);
|
|
}
|
|
|
|
enum moc_enroll_states {
|
|
MOC_ENROLL_GET_ENROLLED_INFO,
|
|
MOC_ENROLL_GET_ENROLLED_LIST,
|
|
MOC_ENROLL_RELEASE_FINGER,
|
|
MOC_ENROLL_START_ENROLL,
|
|
MOC_ENROLL_WAIT_FINGER,
|
|
MOC_ENROLL_WAIT_FINGER_DELAY,
|
|
MOC_ENROLL_ENROLL_CAPTURE,
|
|
MOC_ENROLL_SET_ENROLLED_INFO,
|
|
MOC_ENROLL_COMMIT_RESULT,
|
|
MOC_ENROLL_NUM_STATES,
|
|
};
|
|
|
|
struct EnrolledInfoItem
|
|
{
|
|
uint8_t uid[FOCALTECH_MOC_UID_PREFIX_LENGTH];
|
|
uint8_t user_id[FOCALTECH_MOC_USER_ID_LENGTH];
|
|
};
|
|
|
|
struct UserDes
|
|
{
|
|
uint8_t finger;
|
|
char username[FOCALTECH_MOC_USER_ID_LENGTH];
|
|
};
|
|
|
|
struct EnrolledInfo
|
|
{
|
|
uint8_t actived[FOCALTECH_MOC_MAX_FINGERS];
|
|
struct EnrolledInfoItem items[FOCALTECH_MOC_MAX_FINGERS];
|
|
struct UserId user_id[FOCALTECH_MOC_MAX_FINGERS];
|
|
struct UserDes user_des[FOCALTECH_MOC_MAX_FINGERS];
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
GPtrArray *list_result;
|
|
struct EnrolledInfo *enrolled_info;
|
|
} FpActionData;
|
|
|
|
struct EnrolledInfoSetData
|
|
{
|
|
uint8_t data;
|
|
struct EnrolledInfoItem items[FOCALTECH_MOC_MAX_FINGERS];
|
|
};
|
|
|
|
static void
|
|
fp_action_ssm_done_data_free (FpActionData *data)
|
|
{
|
|
g_clear_pointer (&data->list_result, g_ptr_array_unref);
|
|
g_clear_pointer (&data->enrolled_info, g_free);
|
|
g_free (data);
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_get_enrolled_info_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
struct EnrolledInfoItem *items = NULL;
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
items = (struct EnrolledInfoItem *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
memcpy (&data->enrolled_info->items[0], items,
|
|
FOCALTECH_MOC_MAX_FINGERS * sizeof (struct EnrolledInfoItem));
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
}
|
|
|
|
struct UidList
|
|
{
|
|
uint8_t actived[FOCALTECH_MOC_MAX_FINGERS];
|
|
struct UserId uid[FOCALTECH_MOC_MAX_FINGERS];
|
|
};
|
|
|
|
static int
|
|
focaltech_moc_get_enrolled_info_item (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *uid,
|
|
struct EnrolledInfoItem **pitem, int *index)
|
|
{
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
int ret = -1;
|
|
int i;
|
|
|
|
for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
|
|
{
|
|
struct EnrolledInfoItem *item = &data->enrolled_info->items[i];
|
|
|
|
if (memcmp (item->uid, uid, FOCALTECH_MOC_UID_PREFIX_LENGTH) == 0)
|
|
{
|
|
data->enrolled_info->actived[i] = 1;
|
|
*pitem = item;
|
|
*index = i;
|
|
ret = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_get_enrolled_list_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
struct UidList *uid_list = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
uid_list = (struct UidList *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
int i;
|
|
|
|
for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
|
|
{
|
|
if (uid_list->actived[i] != 0)
|
|
{
|
|
struct UserId *user_id = &uid_list->uid[i];
|
|
FpPrint *print = fp_print_new (FP_DEVICE (self));
|
|
struct EnrolledInfoItem *item = NULL;
|
|
int index;
|
|
|
|
fp_info ("focaltechmoc add slot: %d", i);
|
|
|
|
fprint_set_uid (print, user_id->uid, sizeof (user_id->uid));
|
|
|
|
if (focaltech_moc_get_enrolled_info_item (self, user_id->uid, &item, &index) == 0)
|
|
{
|
|
g_autofree gchar *userid_safe = NULL;
|
|
const gchar *username;
|
|
userid_safe = g_strndup ((const char *) &item->user_id, FOCALTECH_MOC_USER_ID_LENGTH);
|
|
fp_dbg ("%s", userid_safe);
|
|
fpi_print_fill_from_user_id (print, userid_safe);
|
|
memcpy (data->enrolled_info->user_id[index].uid, user_id->uid, 32);
|
|
data->enrolled_info->user_des[index].finger = fp_print_get_finger (print);
|
|
username = fp_print_get_username (print);
|
|
|
|
if (username != NULL)
|
|
strncpy (data->enrolled_info->user_des[index].username, username, 64);
|
|
}
|
|
|
|
g_ptr_array_add (data->list_result, g_object_ref_sink (print));
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
|
|
{
|
|
struct EnrolledInfoItem *item = &data->enrolled_info->items[i];
|
|
|
|
if (data->enrolled_info->actived[i] == 0)
|
|
memset (item, 0, sizeof (struct EnrolledInfoItem));
|
|
}
|
|
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_enroll_wait_finger_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
uint8_t *finger_status = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
finger_status = (uint8_t *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER_DELAY);
|
|
}
|
|
else
|
|
{
|
|
|
|
if (*finger_status == 0x01)
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_ENROLL_CAPTURE);
|
|
else
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER_DELAY);
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_enroll_wait_finger_delay (FpDevice *device,
|
|
void *user_data
|
|
)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_start_enroll_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
struct UserId *user_id = NULL;
|
|
FpPrint *print = NULL;
|
|
struct EnrolledInfoItem *item = NULL;
|
|
int index;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
user_id = (struct UserId *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
if (fp_cmd->code == 0x05)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_FULL,
|
|
"device data full!!"));
|
|
}
|
|
else
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (focaltech_moc_get_enrolled_info_item (self, user_id->uid, &item, &index) == 0)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"uid error!!"));
|
|
}
|
|
else
|
|
{
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
g_autofree gchar *userid_safe = NULL;
|
|
gsize userid_len;
|
|
uint8_t found = 0;
|
|
int i;
|
|
struct EnrolledInfoItem *free_item = NULL;
|
|
|
|
for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
|
|
{
|
|
item = &data->enrolled_info->items[i];
|
|
|
|
if (data->enrolled_info->actived[i] == 0)
|
|
{
|
|
found = 1;
|
|
free_item = item;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found == 0)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"no uid slot!!"));
|
|
}
|
|
else
|
|
{
|
|
fpi_device_get_enroll_data (FP_DEVICE (self), &print);
|
|
fprint_set_uid (print, user_id->uid, sizeof (user_id->uid));
|
|
userid_safe = fpi_print_generate_user_id (print);
|
|
userid_len = strlen (userid_safe);
|
|
userid_len = MIN (FOCALTECH_MOC_USER_ID_LENGTH, userid_len);
|
|
fp_info ("focaltechmoc user id: %s", userid_safe);
|
|
memcpy (free_item->uid, user_id->uid, FOCALTECH_MOC_UID_PREFIX_LENGTH);
|
|
memcpy (free_item->user_id, userid_safe, userid_len);
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_enroll_capture_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
struct CaptureResult *capture_result = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
capture_result = (struct CaptureResult *) (fp_cmd + 1);
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
if (capture_result->error == ERROR_NONE)
|
|
{
|
|
self->num_frames += 1;
|
|
enroll_status_report (self, ENROLL_RSP_ENROLL_REPORT, self->num_frames, NULL);
|
|
fp_info ("focaltechmoc remain: %d", capture_result->remain);
|
|
}
|
|
else
|
|
{
|
|
enroll_status_report (self, ENROLL_RSP_RETRY, self->num_frames, NULL);
|
|
}
|
|
|
|
if (self->num_frames == fp_device_get_nr_enroll_stages (FP_DEVICE (self)))
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
else
|
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_set_enrolled_info_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
return;
|
|
}
|
|
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_commit_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
fp_info ("focaltech_moc_commit_cb success");
|
|
enroll_status_report (self, ENROLL_RSP_ENROLL_OK, self->num_frames, NULL);
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_enroll_run_state (FpiSsm *ssm, FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
guint8 *cmd_buf = NULL;
|
|
uint16_t cmd_len = 0;
|
|
uint16_t resp_len = 0;
|
|
|
|
switch (fpi_ssm_get_cur_state (ssm))
|
|
{
|
|
case MOC_ENROLL_GET_ENROLLED_INFO:
|
|
{
|
|
uint8_t data = 0x00;
|
|
cmd_len = sizeof (uint8_t);
|
|
resp_len = sizeof (struct EnrolledInfoItem) * FOCALTECH_MOC_MAX_FINGERS;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xaf, &data, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_get_enrolled_info_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_ENROLL_GET_ENROLLED_LIST:
|
|
{
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct UidList);
|
|
cmd_buf = focaltech_moc_compose_cmd (0xab, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_get_enrolled_list_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_ENROLL_RELEASE_FINGER:
|
|
{
|
|
uint8_t d1 = 0x78;
|
|
cmd_len = sizeof (d1);
|
|
resp_len = 0;
|
|
cmd_buf = focaltech_moc_compose_cmd (0x82, &d1, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_release_finger);
|
|
break;
|
|
}
|
|
|
|
case MOC_ENROLL_START_ENROLL:
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct UserId);
|
|
cmd_buf = focaltech_moc_compose_cmd (0xa9, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_start_enroll_cb);
|
|
break;
|
|
|
|
|
|
case MOC_ENROLL_WAIT_FINGER:
|
|
{
|
|
uint8_t data = 0x02;
|
|
cmd_len = sizeof (uint8_t);
|
|
resp_len = sizeof (uint8_t);
|
|
cmd_buf = focaltech_moc_compose_cmd (0x80, &data, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_enroll_wait_finger_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_ENROLL_WAIT_FINGER_DELAY:
|
|
fpi_device_add_timeout (device, 50,
|
|
focaltech_moc_enroll_wait_finger_delay,
|
|
NULL, NULL);
|
|
break;
|
|
|
|
case MOC_ENROLL_ENROLL_CAPTURE:
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct CaptureResult);
|
|
cmd_buf = focaltech_moc_compose_cmd (0xa6, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_enroll_capture_cb);
|
|
break;
|
|
|
|
case MOC_ENROLL_SET_ENROLLED_INFO:
|
|
{
|
|
g_autofree struct EnrolledInfoSetData *set_data = NULL;
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
|
|
cmd_len = sizeof (struct EnrolledInfoSetData);
|
|
resp_len = 0;
|
|
set_data = (struct EnrolledInfoSetData *) g_malloc0 (cmd_len);
|
|
set_data->data = 0x01;
|
|
memcpy (&set_data->items[0], &data->enrolled_info->items[0],
|
|
FOCALTECH_MOC_MAX_FINGERS * sizeof (struct EnrolledInfoItem));
|
|
cmd_buf = focaltech_moc_compose_cmd (0xaf, (const uint8_t *) set_data, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_set_enrolled_info_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_ENROLL_COMMIT_RESULT:
|
|
{
|
|
FpPrint *print = NULL;
|
|
g_autoptr(GVariant) data = NULL;
|
|
g_autoptr(GVariant) user_id_var = NULL;
|
|
const guint8 *user_id;
|
|
gsize user_id_len = 0;
|
|
|
|
fpi_device_get_enroll_data (FP_DEVICE (self), &print);
|
|
g_object_get (print, "fpi-data", &data, NULL);
|
|
|
|
if (!g_variant_check_format_string (data, "(@ay)", FALSE))
|
|
{
|
|
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
|
|
return;
|
|
}
|
|
|
|
g_variant_get (data,
|
|
"(@ay)",
|
|
&user_id_var);
|
|
user_id = g_variant_get_fixed_array (user_id_var, &user_id_len, 1);
|
|
|
|
cmd_len = user_id_len;
|
|
resp_len = 0;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xa3, user_id, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_commit_cb);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_enroll (FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
FpActionData *data = g_new0 (FpActionData, 1);
|
|
|
|
data->enrolled_info = g_new0 (struct EnrolledInfo, 1);
|
|
data->list_result = g_ptr_array_new_with_free_func (g_object_unref);
|
|
|
|
self->task_ssm = fpi_ssm_new (FP_DEVICE (self),
|
|
focaltech_enroll_run_state,
|
|
MOC_ENROLL_NUM_STATES);
|
|
fpi_ssm_set_data (self->task_ssm, data, (GDestroyNotify) fp_action_ssm_done_data_free);
|
|
fpi_ssm_start (self->task_ssm, task_ssm_done);
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_delete_cb (FpiDeviceFocaltechMoc *self,
|
|
uint8_t *buffer_in,
|
|
gsize length_in,
|
|
GError *error)
|
|
{
|
|
FpCmd *fp_cmd = NULL;
|
|
|
|
if (error)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
|
return;
|
|
}
|
|
|
|
fp_cmd = (FpCmd *) buffer_in;
|
|
|
|
if (fp_cmd->code != 0x04)
|
|
{
|
|
fpi_ssm_mark_failed (self->task_ssm,
|
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
"Can't get response!!"));
|
|
}
|
|
else
|
|
{
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
int ssm_state;
|
|
|
|
if (self->delete_slot != -1)
|
|
{
|
|
fp_dbg ("delete slot %d", self->delete_slot);
|
|
data->enrolled_info->actived[self->delete_slot] = 0;
|
|
memset (&data->enrolled_info->items[self->delete_slot], 0, sizeof (struct EnrolledInfoItem));
|
|
memset (&data->enrolled_info->user_id[self->delete_slot], 0, sizeof (struct UserId));
|
|
memset (&data->enrolled_info->user_des[self->delete_slot], 0, sizeof (struct UserDes));
|
|
}
|
|
|
|
ssm_state = fpi_ssm_get_cur_state (self->task_ssm);
|
|
fpi_ssm_jump_to_state (self->task_ssm, ssm_state);
|
|
}
|
|
}
|
|
|
|
enum delete_states {
|
|
MOC_DELETE_GET_ENROLLED_INFO,
|
|
MOC_DELETE_GET_ENROLLED_LIST,
|
|
MOC_DELETE_SET_ENROLLED_INFO,
|
|
MOC_DELETE_BY_UID,
|
|
MOC_DELETE_BY_USER_INFO,
|
|
MOC_DELETE_NUM_STATES,
|
|
};
|
|
|
|
static void
|
|
focaltech_delete_run_state (FpiSsm *ssm, FpDevice *device)
|
|
{
|
|
guint8 *cmd_buf = NULL;
|
|
uint16_t cmd_len = 0;
|
|
uint16_t resp_len = 0;
|
|
|
|
switch (fpi_ssm_get_cur_state (ssm))
|
|
{
|
|
case MOC_DELETE_GET_ENROLLED_INFO:
|
|
{
|
|
uint8_t data = 0x00;
|
|
cmd_len = sizeof (uint8_t);
|
|
resp_len = sizeof (struct EnrolledInfoItem) * FOCALTECH_MOC_MAX_FINGERS;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xaf, &data, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_get_enrolled_info_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_DELETE_GET_ENROLLED_LIST:
|
|
{
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct UidList) + sizeof (struct UserId) * FOCALTECH_MOC_MAX_FINGERS;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xab, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_get_enrolled_list_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_DELETE_SET_ENROLLED_INFO:
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
g_autofree struct EnrolledInfoSetData *set_data = NULL;
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
|
|
cmd_len = sizeof (struct EnrolledInfoSetData);
|
|
resp_len = 0;
|
|
set_data = (struct EnrolledInfoSetData *) g_malloc0 (cmd_len);
|
|
set_data->data = 0x01;
|
|
memcpy (&set_data->items[0], &data->enrolled_info->items[0], FOCALTECH_MOC_MAX_FINGERS * sizeof (struct EnrolledInfoItem));
|
|
cmd_buf = focaltech_moc_compose_cmd (0xaf, (const uint8_t *) set_data, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_set_enrolled_info_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_DELETE_BY_UID:
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
FpPrint *print = NULL;
|
|
g_autoptr(GVariant) data = NULL;
|
|
g_autoptr(GVariant) user_id_var = NULL;
|
|
const guint8 *user_id;
|
|
gsize user_id_len = 0;
|
|
struct EnrolledInfoItem *item = NULL;
|
|
int index;
|
|
|
|
self->delete_slot = -1;
|
|
fpi_device_get_delete_data (device, &print);
|
|
g_object_get (print, "fpi-data", &data, NULL);
|
|
|
|
if (!g_variant_check_format_string (data, "(@ay)", FALSE))
|
|
{
|
|
fpi_device_delete_complete (device,
|
|
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
|
|
return;
|
|
}
|
|
|
|
g_variant_get (data, "(@ay)", &user_id_var);
|
|
user_id = g_variant_get_fixed_array (user_id_var, &user_id_len, 1);
|
|
|
|
if (focaltech_moc_get_enrolled_info_item (self, (uint8_t *) user_id, &item, &index) == 0)
|
|
self->delete_slot = index;
|
|
|
|
if (self->delete_slot != -1)
|
|
{
|
|
cmd_len = sizeof (struct UserId);
|
|
resp_len = 0;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xa8, user_id, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_delete_cb);
|
|
}
|
|
else
|
|
{
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case MOC_DELETE_BY_USER_INFO:
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
FpPrint *print = NULL;
|
|
const guint8 *user_id;
|
|
const gchar *username;
|
|
uint8_t finger;
|
|
int i;
|
|
|
|
self->delete_slot = -1;
|
|
fpi_device_get_delete_data (device, &print);
|
|
username = fp_print_get_username (print);
|
|
finger = fp_print_get_finger (print);
|
|
|
|
for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
|
|
{
|
|
struct UserDes *user_des = &data->enrolled_info->user_des[i];
|
|
|
|
if (username == NULL)
|
|
continue;
|
|
|
|
if (strncmp (user_des->username, username, FOCALTECH_MOC_USER_ID_LENGTH) != 0)
|
|
continue;
|
|
|
|
if (finger != user_des->finger)
|
|
continue;
|
|
|
|
self->delete_slot = i;
|
|
}
|
|
|
|
if (self->delete_slot != -1)
|
|
{
|
|
user_id = (const guint8 *) &data->enrolled_info->user_id[self->delete_slot].uid[0];
|
|
cmd_len = sizeof (struct UserId);
|
|
resp_len = 0;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xa8, user_id, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_delete_cb);
|
|
}
|
|
else
|
|
{
|
|
fpi_device_delete_complete (FP_DEVICE (self), NULL);
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_delete_print (FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
FpActionData *data = g_new0 (FpActionData, 1);
|
|
|
|
data->enrolled_info = g_new0 (struct EnrolledInfo, 1);
|
|
data->list_result = g_ptr_array_new_with_free_func (g_object_unref);
|
|
|
|
self->task_ssm = fpi_ssm_new (device,
|
|
focaltech_delete_run_state,
|
|
MOC_DELETE_NUM_STATES);
|
|
fpi_ssm_set_data (self->task_ssm, data, (GDestroyNotify) fp_action_ssm_done_data_free);
|
|
fpi_ssm_start (self->task_ssm, task_ssm_done);
|
|
}
|
|
|
|
enum moc_list_states {
|
|
MOC_LIST_GET_ENROLLED_INFO,
|
|
MOC_LIST_GET_ENROLLED_LIST,
|
|
MOC_LIST_REPORT,
|
|
MOC_LIST_NUM_STATES,
|
|
};
|
|
|
|
static void
|
|
focaltech_list_run_state (FpiSsm *ssm, FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
guint8 *cmd_buf = NULL;
|
|
uint16_t cmd_len = 0;
|
|
uint16_t resp_len = 0;
|
|
|
|
switch (fpi_ssm_get_cur_state (ssm))
|
|
{
|
|
case MOC_LIST_GET_ENROLLED_INFO:
|
|
{
|
|
uint8_t data = 0x00;
|
|
cmd_len = sizeof (uint8_t);
|
|
resp_len = sizeof (struct EnrolledInfoItem) * FOCALTECH_MOC_MAX_FINGERS;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xaf, &data, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_get_enrolled_info_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_LIST_GET_ENROLLED_LIST:
|
|
{
|
|
cmd_len = 0;
|
|
resp_len = sizeof (struct UidList) + sizeof (struct UserId) * FOCALTECH_MOC_MAX_FINGERS;
|
|
cmd_buf = focaltech_moc_compose_cmd (0xab, NULL, cmd_len);
|
|
focaltech_moc_get_cmd (device, cmd_buf,
|
|
sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
|
|
sizeof (FpCmd) + resp_len + sizeof (uint8_t),
|
|
1,
|
|
focaltech_moc_get_enrolled_list_cb);
|
|
break;
|
|
}
|
|
|
|
case MOC_LIST_REPORT:
|
|
{
|
|
FpActionData *data = fpi_ssm_get_data (self->task_ssm);
|
|
fpi_device_list_complete (FP_DEVICE (self), g_steal_pointer (&data->list_result), NULL);
|
|
fpi_ssm_next_state (self->task_ssm);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
focaltech_moc_list (FpDevice *device)
|
|
{
|
|
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
|
FpActionData *data = g_new0 (FpActionData, 1);
|
|
|
|
data->enrolled_info = g_new0 (struct EnrolledInfo, 1);
|
|
data->list_result = g_ptr_array_new_with_free_func (g_object_unref);
|
|
self->task_ssm = fpi_ssm_new (device,
|
|
focaltech_list_run_state,
|
|
MOC_LIST_NUM_STATES);
|
|
fpi_ssm_set_data (self->task_ssm, data, (GDestroyNotify) fp_action_ssm_done_data_free);
|
|
fpi_ssm_start (self->task_ssm, task_ssm_done);
|
|
}
|
|
|
|
static void
|
|
fpi_device_focaltech_moc_init (FpiDeviceFocaltechMoc *self)
|
|
{
|
|
G_DEBUG_HERE ();
|
|
}
|
|
|
|
static void
|
|
fpi_device_focaltech_moc_class_init (FpiDeviceFocaltechMocClass *klass)
|
|
{
|
|
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
|
|
|
dev_class->id = FP_COMPONENT;
|
|
dev_class->full_name = FOCALTECH_MOC_DRIVER_FULLNAME;
|
|
|
|
dev_class->type = FP_DEVICE_TYPE_USB;
|
|
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
|
dev_class->id_table = id_table;
|
|
dev_class->nr_enroll_stages = FOCALTECH_MOC_MAX_FINGERS;
|
|
dev_class->temp_hot_seconds = -1;
|
|
|
|
dev_class->open = focaltech_moc_open;
|
|
dev_class->close = focaltech_moc_close;
|
|
dev_class->verify = focaltech_moc_identify;
|
|
dev_class->enroll = focaltech_moc_enroll;
|
|
dev_class->identify = focaltech_moc_identify;
|
|
dev_class->delete = focaltech_moc_delete_print;
|
|
dev_class->list = focaltech_moc_list;
|
|
|
|
fpi_device_class_auto_initialize_features (dev_class);
|
|
}
|