...
 
Commits (12)
......@@ -27,6 +27,7 @@ private_headers = [
'vfs301_proto_fragments.h',
'vfs301_proto.h',
'vfs5011_proto.h',
'synaptics.h',
# NBIS
'morph.h',
......
/*
* Example fingerprint delete finger program, which delete the right index
* finger which has been previously enrolled to disk.
* Copyright (C) 2019 Synaptics 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libfprint/fprint.h>
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{
struct fp_dscv_dev *ddev = discovered_devs[0];
struct fp_driver *drv;
if (!ddev)
return NULL;
drv = fp_dscv_dev_get_driver(ddev);
printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv));
return ddev;
}
int main(void)
{
int r = 1;
struct fp_dscv_dev *ddev;
struct fp_dscv_dev **discovered_devs;
struct fp_dev *dev;
struct fp_print_data *data;
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
r = fp_init();
if (r < 0) {
fprintf(stderr, "Failed to initialize libfprint\n");
exit(1);
}
discovered_devs = fp_discover_devs();
if (!discovered_devs) {
fprintf(stderr, "Could not discover devices\n");
goto out;
}
ddev = discover_device(discovered_devs);
if (!ddev) {
fprintf(stderr, "No devices detected.\n");
goto out;
}
dev = fp_dev_open(ddev);
fp_dscv_devs_free(discovered_devs);
if (!dev) {
fprintf(stderr, "Could not open device.\n");
goto out;
}
printf("Opened device. Loading previously enrolled right index finger "
"data...\n");
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
if (r != 0) {
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
fprintf(stderr, "Did you remember to enroll your right index finger "
"first?\n");
goto out_close;
}
printf("Print loaded. delete data in sensor.\n");
if(!fp_dev_supports_data_in_sensor(dev))
{
printf("This driver doesn't support to store data in sensor.\n");
goto out_close;
}
r = fp_delete_finger(dev, data);
fp_print_data_free(data);
if (r) {
printf("delete finger failed with error %d :(\n", r);
}
else
{
printf("sensor data deleted. now delete host data");
r = fp_print_data_delete(dev, RIGHT_INDEX);
if (r < 0) {
printf("Delete sensor data successfully but delete host data failed. %d :(\n", r);
}
}
out_close:
fp_dev_close(dev);
out:
fp_exit();
return r;
}
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ]
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture', 'delete' ]
foreach example: examples
executable(example,
example + '.c',
......
......@@ -42,6 +42,7 @@ enum {
VFS5011_ID = 19,
VFS0050_ID = 20,
ELAN_ID = 21,
SYNAPTICS_ID = 22,
};
#endif
/*
* Copyright (C) 2019 Synaptics 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 "bmkt_internal.h"
#include "bmkt_message.h"
#include "sensor.h"
struct bmkt_ctx
{
bmkt_sensor_t sensor;
};
bmkt_ctx_t g_ctx;
int bmkt_init(bmkt_ctx_t **ctx)
{
if (ctx == NULL)
{
return BMKT_INVALID_PARAM;
}
memset(&g_ctx, 0, sizeof(bmkt_ctx_t));
*ctx = &g_ctx;
bmkt_dbg_log("%s: context size: %ld", __func__, sizeof(bmkt_ctx_t));
return BMKT_SUCCESS;
}
void bmkt_exit(bmkt_ctx_t *ctx)
{
if (ctx == NULL)
{
return;
}
}
int bmkt_open(bmkt_ctx_t *ctx, bmkt_sensor_t **sensor,
bmkt_general_error_cb_t err_cb, void *err_cb_ctx, libusb_device_handle *usb_handle)
{
int ret;
if (ctx == NULL || sensor == NULL)
{
return BMKT_INVALID_PARAM;
}
*sensor = &ctx->sensor;
memset(*sensor, 0, sizeof(bmkt_sensor_t));
(*sensor)->usb_xport.handle = usb_handle;
ret = bmkt_sensor_open(*sensor, err_cb, err_cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
int bmkt_init_fps(bmkt_sensor_t *sensor)
{
int ret;
uint8_t *resp_buf;
int resp_len;
bmkt_response_t resp;
if (sensor->sensor_state != BMKT_SENSOR_STATE_UNINIT)
{
//sensor is already initialized
return BMKT_OPERATION_DENIED;
}
ret = bmkt_sensor_send_message_sync(sensor, BMKT_CMD_FPS_INIT, 0, NULL, &resp_buf, &resp_len, &resp);
if (ret != BMKT_SUCCESS)
{
return ret;
}
if (resp.result != BMKT_SUCCESS)
{
return resp.result;
}
return bmkt_sensor_init_fps(sensor);
}
int bmkt_close(bmkt_sensor_t *sensor)
{
if (sensor == NULL)
{
return BMKT_INVALID_PARAM;
}
return bmkt_sensor_close(sensor);
}
int bmkt_delete_enrolled_user(bmkt_sensor_t *sensor, uint8_t finger_id, const char *user_id, uint32_t user_id_len,
bmkt_resp_cb_t resp_cb, void *cb_ctx)
{
int ret;
uint8_t payload[BMKT_MAX_USER_ID_LEN + sizeof(finger_id)];
uint8_t payload_len;
if (sensor == NULL)
{
return BMKT_INVALID_PARAM;
}
if (user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_INVALID_PARAM;
}
memset(payload, 0, sizeof(payload));
payload_len = user_id_len + sizeof(finger_id);
payload[0] = finger_id;
memcpy(&payload[1], user_id, user_id_len);
ret = bmkt_sensor_send_message(sensor, BMKT_CMD_DEL_USER_FP, payload_len, payload, resp_cb, cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
int bmkt_enroll(bmkt_sensor_t *sensor, const uint8_t *user_id, uint32_t user_id_len,
uint8_t finger_id, bmkt_resp_cb_t resp_cb, void *cb_ctx)
{
int ret = BMKT_GENERAL_ERROR;
/* Payload data for enroll_user [1 byte<backup option> 1 byte<finger Id> maximum length: 100 bytes]*/
uint8_t payload[BMKT_MAX_USER_ID_LEN + 2];
uint8_t payload_len = 0;
/* Backup options is not supported for Prometheus. */
uint8_t backup_opt = 0;
if (sensor == NULL || user_id == NULL)
{
return BMKT_INVALID_PARAM;
}
if (user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_INVALID_PARAM;
}
payload_len = user_id_len + 2;
payload[0] = backup_opt;
payload[1] = finger_id;
memcpy(&payload[2], user_id, user_id_len);
ret = bmkt_sensor_send_message(sensor, BMKT_CMD_ENROLL_USER, payload_len, payload, resp_cb, cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
int bmkt_verify(bmkt_sensor_t *sensor, bmkt_user_id_t *user,
bmkt_resp_cb_t resp_cb, void *cb_ctx)
{
int ret;
uint8_t payload[BMKT_MAX_USER_ID_LEN + 1];
uint8_t payload_len;
if (sensor == NULL || user == NULL || user->user_id == NULL)
{
return BMKT_INVALID_PARAM;
}
if (user->user_id_len == 0 || user->user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_INVALID_PARAM;
}
payload_len = user->user_id_len;
memset(payload, 0, sizeof(payload));
memcpy(&payload[0], user->user_id, user->user_id_len);
ret = bmkt_sensor_send_message(sensor, BMKT_CMD_VERIFY_USER, payload_len, payload, resp_cb,
cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
void bmkt_op_set_state(bmkt_sensor_t* sensor, bmkt_op_state_t state)
{
sensor->op_state = state;
}
void bmkt_op_sm(bmkt_sensor_t *sensor)
{
int ret;
int len = 0;
bmkt_dbg_log("bmkt_op_sm state = %d", sensor->op_state);
switch(sensor->op_state)
{
case BMKT_OP_STATE_GET_RESP:
ret = usb_receive_resp_async(&sensor->usb_xport, &len);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("bmkt_op_sm: usb_receive_resp_async failed %d", ret);
}
break;
case BMKT_OP_STATE_WAIT_INTERRUPT:
ret = usb_check_interrupt(&sensor->usb_xport);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("bmkt_op_sm: check_interrupt failed %d", ret);
}
break;
case BMKT_OP_STATE_SEND_ASYNC:
ret = bmkt_sensor_send_async_read_command(sensor);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("bmkt_op_sm: bmkt_sensor_send_async_read_command failed %d", ret);
}
break;
case BMKT_OP_STATE_COMPLETE:
break;
default:
break;
}
}
void bmkt_op_next_state(bmkt_sensor_t* sensor)
{
if(sensor->op_state != BMKT_OP_STATE_COMPLETE)
sensor->op_state = (sensor->op_state + 1) % BMKT_OP_STATE_COMPLETE;
bmkt_op_sm(sensor);
}
This diff is collapsed.
/*
* Copyright (C) 2019 Synaptics 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
*/
#ifndef _BMKT_INTERNAL_H_
#define _BMKT_INTERNAL_H_
#include "bmkt.h"
#include "bmkt_message.h"
#include <time.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "fp_internal.h"
uint32_t extract32(const uint8_t *buf, int *offset);
uint16_t extract16(const uint8_t *buf, int *offset);
uint8_t extract8(const uint8_t *buf, int *offset);
void print_buffer(uint8_t *buf, int len);
#define bmkt_dbg_log fp_dbg
#define bmkt_info_log fp_info
#define bmkt_warn_log fp_warn
#define bmkt_err_log fp_err
void bmkt_op_next_state(bmkt_sensor_t *sensor);
#endif /* _BMKT_INTERNAL_H_ */
\ No newline at end of file
This diff is collapsed.
/*
* Copyright (C) 2019 Synaptics 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
*/
#ifndef BMKT_MESSAGE_H_
#define BMKT_MESSAGE_H_
#include "bmkt_internal.h"
#define BMKT_MESSAGE_HEADER_ID 0xFE
#define BMKT_MESSAGE_HEADER_LEN (4)
#define BMKT_MESSAGE_CRC32_LEN (4)
#define BMKT_MESSAGE_HEADER_ID_FIELD 0
#define BMKT_MESSAGE_SEQ_NUM_FIELD 1
#define BMKT_MESSAGE_ID_FIELD 2
#define BMKT_MESSAGE_PAYLOAD_LEN_FIELD 3
#define BMKT_MESSAGE_PAYLOAD_FIELD 4
// Command messages
#define BMKT_CMD_CONTINUOUS_IMAGE_CAPTURE 0x01
#define BMKT_CMD_CONTINUOUS_IMAGE_CAPTURE_STOP 0x04
#define BMKT_CMD_SENSOR_MODULE_TEST 0x06
#define BMKT_CMD_SENSOR_MODULE_TEST_START 0x08
#define BMKT_CMD_NEXT_TEST_REPORT_CHUNK 0x0B
#define BMKT_CMD_FPS_INIT 0x11
#define BMKT_CMD_GET_FPS_MODE 0x21
#define BMKT_CMD_SET_SECURITY_LEVEL 0x31
#define BMKT_CMD_GET_SECURITY_LEVEL 0x34
#define BMKT_CMD_CANCEL_OP 0x41
#define BMKT_CMD_ENROLL_USER 0x51
#define BMKT_CMD_ENROLL_PAUSE 0x52
#define BMKT_CMD_ENROLL_RESUME 0x53
#define BMKT_CMD_ID_USER 0x61
#define BMKT_CMD_VERIFY_USER 0x65
#define BMKT_CMD_GET_TEMPLATE_RECORDS 0x71
#define BMKT_CMD_GET_NEXT_QUERY_RESPONSE 0x72
#define BMKT_CMD_GET_ENROLLED_FINGERS 0x73
#define BMKT_CMD_GET_DATABASE_CAPACITY 0x74
#define BMKT_CMD_DEL_USER_FP 0x81
#define BMKT_CMD_DEL_FULL_DB 0x84
#define BMKT_CMD_REPEAT_LAST_RSP 0x92
#define BMKT_CMD_POWER_DOWN_NOTIFY 0xA1
#define BMKT_CMD_GET_VERSION 0xB1
#define BMKT_CMD_DISABLE_PAIRING 0xC2
#define BMKT_CMD_QUERY_PAIRING 0xC5
#define BMKT_CMD_SENSOR_STATUS 0xD1
#define BMKT_CMD_ID_USER_IN_ORDER 0xE1
#define BMKT_CMD_ID_NEXT_USER 0xE3
#define BMKT_CMD_VERIFY_USER_IN_ORDER 0xF1
#define BMKT_CMD_VERIFY_FINGERS_IN_ORDER 0xF2
#define BMKT_CMD_GET_FINAL_RESULT 0xE4
#define BMKT_EVT_FINGER_REPORT 0x91
#define BMKT_EVT_FINGER_STATE_NOT_ON_SENSOR 0x00
#define BMKT_EVT_FINGER_STATE_ON_SENSOR 0x01
typedef struct bmkt_msg_resp
{
uint8_t msg_id;
uint8_t seq_num;
uint8_t payload_len;
uint8_t *payload;
int result;
} bmkt_msg_resp_t;
typedef struct bmkt_session_ctx
{
uint8_t seq_num;
bmkt_resp_cb_t resp_cb;
void *cb_ctx;
} bmkt_session_ctx_t;
int bmkt_compose_message(uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num,
uint8_t payload_size, uint8_t *payload);
int bmkt_parse_message_header(uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp);
int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp);
#endif /* BMKT_MESSAGE_H_ */
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (C) 2019 Synaptics 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
*/
#ifndef _SENSOR_H_
#define _SENSOR_H_
#include "usb_transport.h"
#define BMKT_MAX_PENDING_SESSIONS 2
typedef enum bmkt_sensor_state
{
BMKT_SENSOR_STATE_UNINIT = 0,
BMKT_SENSOR_STATE_IDLE,
BMKT_SENSOR_STATE_INIT,
BMKT_SENSOR_STATE_EXIT,
} bmkt_sensor_state_t;
typedef struct bmkt_sensor_drv bmkt_sensor_drv_t;
typedef struct bmkt_sensor_version
{
uint32_t build_time;
uint32_t build_num;
uint8_t version_major;
uint8_t version_minor;
uint8_t target;
uint8_t product;
uint8_t silicon_rev;
uint8_t formal_release;
uint8_t platform;
uint8_t patch;
uint8_t serial_number[6];
uint16_t security;
uint8_t iface;
uint8_t device_type;
} bmkt_sensor_version_t;
typedef struct bmkt_sensor
{
bmkt_usb_transport_t usb_xport;
bmkt_sensor_version_t version;
bmkt_session_ctx_t pending_sessions[BMKT_MAX_PENDING_SESSIONS];
int empty_session_idx;
int flags;
int seq_num;
bmkt_sensor_state_t sensor_state;
bmkt_event_cb_t finger_event_cb;
void *finger_cb_ctx;
bmkt_general_error_cb_t gen_err_cb;
void *gen_err_cb_ctx;
bmkt_op_state_t op_state;
} bmkt_sensor_t;
int bmkt_sensor_open(bmkt_sensor_t *sensor,
bmkt_general_error_cb_t err_cb, void *err_cb_ctx);
int bmkt_sensor_close(bmkt_sensor_t *sensor);
int bmkt_sensor_init_fps(bmkt_sensor_t *sensor);
int bmkt_sensor_send_message(bmkt_sensor_t *sensor, uint8_t msg_id, uint8_t payload_size,
uint8_t *payload, bmkt_resp_cb_t resp_cb, void *resp_data);
int bmkt_sensor_send_message_sync(bmkt_sensor_t *sensor, uint8_t msg_id, uint8_t payload_size,
uint8_t *payload, uint8_t **resp_buf, int *resp_len, bmkt_response_t *resp);
int bmkt_sensor_handle_response(bmkt_sensor_t *sensor, uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp);
int bmkt_sensor_send_async_read_command(bmkt_sensor_t *sensor);
#endif /* _SENSOR_H_ */
\ No newline at end of file
This diff is collapsed.
/*
* Copyright (C) 2019 Synaptics 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
*/
#ifndef __synaptics_h__
#define __synaptics_h__
#define SYNAPTICS_VENDOR_ID 0x06cb
#define SYNAPTICS_PRODUCT_ID_A9 0x00a9
/* Number of enroll stages */
#define ENROLL_SAMPLES 12
#define SYNAPTICS_DRIVER_FULLNAME "Synaptics Sensors"
#include "bmkt.h"
#include "bmkt_response.h"
struct syna_enroll_resp_data
{
int progress;
};
typedef enum syna_state
{
SYNA_STATE_UNINIT = 0,
SYNA_STATE_IDLE ,
SYNA_STATE_ENROLL ,
SYNA_STATE_IDENTIFY ,
SYNA_STATE_IDENTIFY_DELAY_RESULT ,
SYNA_STATE_VERIFY ,
SYNA_STATE_VERIFY_DELAY_RESULT ,
SYNA_STATE_DELETE ,
} syna_state_t;
typedef struct synaptics_dev_s
{
bmkt_ctx_t *ctx;
bmkt_sensor_t *sensor;
struct syna_enroll_resp_data enroll_resp_data;
gboolean isFingerOnSensor;
syna_state_t state;
}synaptics_dev;
#endif //__synaptics_h__
/*
* Copyright (C) 2019 Synaptics 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 "bmkt_internal.h"
#include "sensor.h"
#include "drivers_api.h"
#define USB_ASYNC_MESSAGE_PENDING 0x4
static void usb_int_callback(struct libusb_transfer *transfer)
{
bmkt_usb_transport_t *usb_xport = (bmkt_usb_transport_t *)transfer->user_data;
#ifdef TRANSPORT_DEBUG
bmkt_dbg_log("INTERRUPT: (%d) ", transfer->actual_length);
print_buffer(transfer->buffer, transfer->actual_length);
#endif
if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING)
{
libusb_free_transfer(transfer);
bmkt_op_next_state(usb_xport->sensor);
}
else
libusb_submit_transfer(transfer);
}
int usb_check_interrupt(bmkt_usb_transport_t *usb_xport)
{
int ret;
struct libusb_transfer *interrupt_xfer;
interrupt_xfer = libusb_alloc_transfer(0);
if (interrupt_xfer == NULL)
{
return BMKT_GENERAL_ERROR;
}
libusb_fill_interrupt_transfer(interrupt_xfer, usb_xport->handle, USB_EP_INTERRUPT,
usb_xport->interrupt_data, sizeof(usb_xport->interrupt_data), usb_int_callback, usb_xport, 0);
ret = libusb_submit_transfer(interrupt_xfer);
if (ret != LIBUSB_SUCCESS)
{
libusb_free_transfer(interrupt_xfer);
if (ret == LIBUSB_ERROR_NO_DEVICE)
{
return BMKT_SENSOR_MALFUNCTION;
}
else
{
return BMKT_GENERAL_ERROR;
}
}
return BMKT_SUCCESS;
}
int usb_open(bmkt_usb_transport_t *usb_xport)
{
int ret;
struct libusb_config_descriptor *configDesc;
const struct libusb_interface *iface;
const struct libusb_interface_descriptor *ifaceDesc;
const struct libusb_endpoint_descriptor *endpointDesc;
int config;
int i;
usb_xport->device = libusb_get_device(usb_xport->handle);
ret = libusb_reset_device(usb_xport->handle);
if (ret)
{
bmkt_dbg_log("Failed to reset device\n");
}
ret = libusb_get_config_descriptor(usb_xport->device, USB_DEFAULT_CONFIGURATION, &configDesc);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
return ret;
}
ret = libusb_get_configuration(usb_xport->handle, &config);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
if (configDesc->bConfigurationValue != config)
{
ret = libusb_set_configuration(usb_xport->handle, config);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
}
ret = libusb_kernel_driver_active(usb_xport->handle, 0);
if (ret == 1)
{
bmkt_err_log("Failed to detect kernel driver\n");
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
ret = libusb_claim_interface(usb_xport->handle, USB_DEFAULT_INTERFACE);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
iface = configDesc->interface + USB_DEFAULT_INTERFACE;
ifaceDesc = iface->altsetting + USB_DEFAULT_ALT_SETTING;
endpointDesc = ifaceDesc->endpoint;
for (i = 0; i < ifaceDesc->bNumEndpoints; i++)
{
ret = libusb_clear_halt(usb_xport->handle, endpointDesc->bEndpointAddress);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
++endpointDesc;
}
free_config:
libusb_free_config_descriptor(configDesc);
return ret;
}
int usb_close(bmkt_usb_transport_t *usb_xport)
{
if (usb_xport->handle)
{
libusb_release_interface(usb_xport->handle, USB_DEFAULT_INTERFACE);
}
return BMKT_SUCCESS;
}
void usb_in_cb(struct libusb_transfer *transfer)
{
uint8_t *resp_buf;
int resp_len;
bmkt_msg_resp_t msg_resp;
bmkt_usb_transport_t *usb_xport = (bmkt_usb_transport_t *)transfer->user_data;
#ifdef TRANSPORT_DEBUG
bmkt_dbg_log("RX_ASYNC: (%d) ", transfer->actual_length);
print_buffer(transfer->buffer, transfer->actual_length);
#endif
resp_buf = transfer->buffer;
resp_len = transfer->actual_length;
bmkt_sensor_handle_response(usb_xport->sensor, resp_buf, resp_len, &msg_resp);
libusb_free_transfer(transfer);
bmkt_op_next_state(usb_xport->sensor);
}
void usb_out_cb(struct libusb_transfer *transfer)
{
bmkt_usb_transport_t *usb_xport = (bmkt_usb_transport_t *)transfer->user_data;
libusb_free_transfer(transfer);
bmkt_op_next_state(usb_xport->sensor);
}
static int bulk_transfer_async(bmkt_usb_transport_t *usb_xport, uint8_t *buf, int size, uint8_t endpoint,
int *transferred, uint32_t timeout, libusb_transfer_cb_fn callback)
{
int ret;
struct libusb_transfer *transfer;
#ifdef TRANSPORT_DEBUG
if (!(endpoint & 0x80))
{
bmkt_dbg_log("TX2: (%d) ", size);
print_buffer(buf, size);
}
#endif
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer( transfer, usb_xport->handle, endpoint,
buf, size, callback, usb_xport, 0);
ret = libusb_submit_transfer(transfer);
if (ret != LIBUSB_SUCCESS)
{
libusb_free_transfer(transfer);
if (ret == LIBUSB_ERROR_NO_DEVICE)
{
return BMKT_SENSOR_MALFUNCTION;
}
else
{
return BMKT_GENERAL_ERROR;
}
}
return BMKT_SUCCESS;
}
static int bulk_transfer(bmkt_usb_transport_t *usb_xport, uint8_t *buf, int size, uint8_t endpoint,
int *transferred, uint32_t timeout)
{
int ret;
#ifdef TRANSPORT_DEBUG
if (!(endpoint & 0x80))
{
bmkt_dbg_log("TX: (%d) ", size);
print_buffer(buf, size);
}
#endif
ret = libusb_bulk_transfer(usb_xport->handle, endpoint, buf, size, transferred, timeout);
if (ret)
{
bmkt_warn_log("libusb_bulk_transfer: bulk transfer failed: %d\n", ret);
if (ret == LIBUSB_ERROR_TIMEOUT)
{
return BMKT_OP_TIME_OUT;
}
else
{
return BMKT_SENSOR_MALFUNCTION;
}
}
bmkt_dbg_log("transferred: %d\n", *transferred);
#ifdef TRANSPORT_DEBUG
if (endpoint & 0x80)
{
bmkt_dbg_log("RX: (%d) ", *transferred);
print_buffer(buf, *transferred);
}
#endif
return BMKT_SUCCESS;
}
int usb_send_command(bmkt_usb_transport_t *usb_xport, int len)
{
int ret;
int tx_len = 0;
ret = bulk_transfer_async(usb_xport, usb_xport->transfer, len, USB_EP_REQUEST, &tx_len, 0, usb_out_cb);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
return BMKT_SUCCESS;
}
int usb_get_command_buffer(bmkt_usb_transport_t *usb_xport, uint8_t **cmd, int *len)
{
*len = BMKT_MAX_TRANSFER_LEN;
*cmd = usb_xport->transfer;
return BMKT_SUCCESS;
}
int usb_get_response_buffer(bmkt_usb_transport_t *usb_xport, uint8_t **resp, int *len)
{
*len = BMKT_MAX_TRANSFER_LEN;
*resp = usb_xport->transfer;
return BMKT_SUCCESS;
}
int usb_receive_resp_async(bmkt_usb_transport_t *usb_xport, int *len)
{
int ret;
*len = BMKT_MAX_TRANSFER_LEN;
/* Check to make sure the buffer is clear */
memset(usb_xport->transfer, 0, BMKT_MAX_TRANSFER_LEN);
ret = bulk_transfer_async(usb_xport, usb_xport->transfer, *len, USB_EP_REPLY, len, 0, usb_in_cb);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
return BMKT_SUCCESS;
}
int usb_receive_resp(bmkt_usb_transport_t *usb_xport, int *len)
{
int ret;
*len = BMKT_MAX_TRANSFER_LEN;
/* Check to make sure the buffer is clear */
memset(usb_xport->transfer, 0, BMKT_MAX_TRANSFER_LEN);
ret = bulk_transfer(usb_xport, usb_xport->transfer, *len, USB_EP_REPLY, len, 0);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
return BMKT_SUCCESS;
}
int usb_send_command_sync(bmkt_usb_transport_t *usb_xport, int len, uint8_t **resp_buf,
int *resp_len)
{
int ret;
int tx_len = 0;
ret = bulk_transfer(usb_xport, usb_xport->transfer, len, USB_EP_REQUEST, &tx_len, 0);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
/* Check to make sure the buffer is clear */
memset(usb_xport->transfer, 0, BMKT_MAX_TRANSFER_LEN);
ret = bulk_transfer(usb_xport, usb_xport->transfer, *resp_len, USB_EP_REPLY, resp_len, 0);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
*resp_buf = usb_xport->transfer;
return BMKT_SUCCESS;
}
int usb_reset(bmkt_usb_transport_t *usb_xport)
{
return BMKT_OPERATION_DENIED;
}
int usb_release_command_buffer(bmkt_usb_transport_t *usb_xport)
{
return BMKT_SUCCESS;
}
int usb_release_response_buffer(bmkt_usb_transport_t *usb_xport)
{
return BMKT_SUCCESS;
}
/*
* Copyright (C) 2019 Synaptics 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
*/
#ifndef _USB_TRANSPORT_H_
#define _USB_TRANSPORT_H_
#include "bmkt_internal.h"
#include "libusb-1.0/libusb.h"
#define BMKT_MAX_TRANSFER_LEN 263 + 1 /* SPI Header */ + 2 /* VCSFW header */
#define BMKT_XPORT_INT_NONE 0x0
#define BMKT_XPORT_INT_RESPONSE 0x1
#define BMKT_XPORT_INT_FINGER 0x2
#define BMKT_XPORT_INT_ASYNC 0x4
#define USB_DEFAULT_CONFIGURATION 0
#define USB_DEFAULT_INTERFACE 0
#define USB_DEFAULT_ALT_SETTING 0
#define USB_EP_REQUEST 0x01
#define USB_EP_REPLY 0x81
#define USB_EP_FINGERPRINT 0x82
#define USB_EP_INTERRUPT 0x83
#define USB_INTERRUPT_DATA_SIZE 7
typedef struct bmkt_usb_transport
{
libusb_context *ctx;
libusb_device *device;
libusb_device_handle *handle;
uint8_t interrupt_data[USB_INTERRUPT_DATA_SIZE];
bmkt_sensor_t *sensor;
uint8_t transfer[BMKT_MAX_TRANSFER_LEN];
} bmkt_usb_transport_t;
int usb_release_command_buffer(bmkt_usb_transport_t *xport);
int usb_release_response_buffer(bmkt_usb_transport_t *xport);
int usb_open(bmkt_usb_transport_t *xport);
int usb_close(bmkt_usb_transport_t *xport);
int usb_send_command(bmkt_usb_transport_t *xport, int len);
int usb_get_command_buffer(bmkt_usb_transport_t *xport, uint8_t **cmd, int *len);
int usb_get_response_buffer(bmkt_usb_transport_t *xport, uint8_t **resp, int *len);
int usb_receive_resp(bmkt_usb_transport_t *xport, int *len);
int usb_send_command_sync(bmkt_usb_transport_t *xport, int len, uint8_t **resp_buf,
int *resp_len);
int usb_receive_resp_async(bmkt_usb_transport_t *usb_xport, int *len);
int usb_check_interrupt(bmkt_usb_transport_t *usb_xport);
#endif /* _USB_TRANSPORT_H_ */
\ No newline at end of file
/*
* Copyright (C) 2019 Synaptics 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 "bmkt_internal.h"
#include "sensor.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-zero-length"
void print_buffer(uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++)
{
bmkt_dbg_log("0x%02x ", buf[i]);
if ((i % 16) == 15)
{
bmkt_dbg_log("");
}
}
bmkt_dbg_log("");
}
#pragma GCC diagnostic pop
uint32_t extract32(const uint8_t *buf, int *offset)
{
uint32_t ret = 0;
int off = 0;
if (offset)
{
off = *offset;
}
ret = GUINT32_FROM_LE(*(uint32_t*)(buf + off));
if (offset)
{
*offset += 4;
}
return ret;
}
uint16_t extract16(const uint8_t *buf, int *offset)
{
uint16_t ret = 0;
int off = 0;
if (offset)
{
off = *offset;
}
ret = GUINT16_FROM_LE(*(uint16_t*)(buf + off));
if (offset)
{
*offset += 2;
}
return ret;
}
uint8_t extract8(const uint8_t *buf, int *offset)
{
uint8_t ret = 0;
int off = 0;
if (offset)
{
off = *offset;
}
ret = *(buf + off);
if (offset)
{
*offset += 1;
}
return ret;
}
......@@ -77,6 +77,9 @@ enum fp_dev_state {
DEV_STATE_CAPTURING,
DEV_STATE_CAPTURE_DONE,
DEV_STATE_CAPTURE_STOPPING,
DEV_STATE_DELETING,
DEV_STATE_DELETE_DONE,
DEV_STATE_DELETE_STOPPING,
};
struct fp_dev {
......@@ -96,6 +99,9 @@ struct fp_dev {
/* read-only to drivers */
struct fp_print_data *verify_data;
struct fp_print_data *delete_data;
/* drivers should not mess with any of the below */
enum fp_dev_state state;
int __enroll_stage;
......@@ -123,6 +129,8 @@ struct fp_dev {
void *capture_cb_data;
fp_operation_stop_cb capture_stop_cb;
void *capture_stop_cb_data;
fp_delete_cb delete_cb;
void *delete_cb_data;
/* FIXME: better place to put this? */
struct fp_print_data **identify_gallery;
......
......@@ -680,3 +680,58 @@ API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
}
return r;
}
/**
* fp_async_delete_finger:
* @dev: the struct #fp_dev device
* @data: data to delete. Must have been previously enrolled.
* @callback: the callback to call when data deleted.
* @user_data: user data to pass to the callback
*
* Request to delete data in sensor.
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_delete_finger(struct fp_dev *dev,
struct fp_print_data *data, fp_delete_cb callback, void *user_data)
{
struct fp_driver *drv;
int r;
g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv;
G_DEBUG_HERE();
if (!drv->delete_finger)
return -ENOTSUP;
dev->state = DEV_STATE_DELETING;
dev->delete_cb = callback;
dev->delete_cb_data = user_data;
dev->delete_data = data;
r = drv->delete_finger(dev);
if (r < 0) {
dev->delete_cb = NULL;
dev->state = DEV_STATE_ERROR;
fp_err("failed to delete data, error %d", r);
}
return r;
}
/* Drivers call this when delete done */
void fpi_drvcb_delete_complete(struct fp_dev *dev, int status)
{
fp_dbg("status %d", status);
BUG_ON(dev->state != DEV_STATE_DELETING);
dev->state = (status) ? DEV_STATE_ERROR : DEV_STATE_DELETE_DONE;
if (dev->delete_cb)
dev->delete_cb(dev, status, dev->delete_cb_data);
}
......@@ -36,4 +36,7 @@ void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
struct fp_img *img);
void fpi_drvcb_verify_stopped(struct fp_dev *dev);
void fpi_drvcb_delete_complete(struct fp_dev *dev, int status);
#endif
......@@ -703,6 +703,21 @@ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
return dev->drv->identify_start != NULL;
}
/**
* fp_dev_supports_data_in_sensor:
* @dev: the struct #fp_dev device
*
* Determines if a device is capable of storing print data in sensor.
* Not all devices support this functionality.
*
* Returns: 1 if the device is capable of storing data in sensor, 0 otherwise.
*/
API_EXPORTED int fp_dev_supports_data_in_sensor(struct fp_dev *dev)
{
return dev->drv->delete_finger != NULL;
}
/**
* fp_dev_get_img_width:
* @dev: the struct #fp_dev device
......
......@@ -87,6 +87,7 @@ struct fp_driver {
int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
int (*capture_start)(struct fp_dev *dev);
int (*capture_stop)(struct fp_dev *dev);
int (*delete_finger)(struct fp_dev *dev);
};
/**
......
......@@ -148,3 +148,17 @@ fpi_dev_get_verify_data(struct fp_dev *dev)
{
return dev->verify_data;
}
/**
* fpi_dev_get_delete_data:
* @dev: a struct #fp_dev
*
* Returns the delete data associated with @dev.
* Returns: a struct #fp_print_data pointer or %NULL
*/
struct fp_print_data *
fpi_dev_get_delete_data(struct fp_dev *dev)
{
return dev->delete_data;
}
......@@ -43,5 +43,7 @@ libusb_device_handle *fpi_dev_get_usb_dev(struct fp_dev *dev);
void fpi_dev_set_nr_enroll_stages(struct fp_dev *dev,
int nr_enroll_stages);
struct fp_print_data *fpi_dev_get_verify_data(struct fp_dev *dev);
struct fp_print_data *fpi_dev_get_delete_data(struct fp_dev *dev);
#endif
......@@ -441,6 +441,72 @@ API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
return fp_verify_finger_img(dev, enrolled_print, NULL);
}
struct sync_delete_data {
gboolean populated;
int result;
};
static void sync_delete_cb(struct fp_dev *dev, int result, void *user_data)
{
struct sync_delete_data *ddata = user_data;
ddata->result = result;
ddata->populated = TRUE;
}
/**
* fp_delete_finger:
* @dev: the struct #fp_dev device to perform the operation.
* @enrolled_data: the id need to delete on sensor. This id is
* returned in previously enrolled with a MIS device.
*
* Perform a delete data operation on sensor. When print data is stored on sensor,
* this function is needed when host deletes enrolled finger.
*
* Returns: negative code on error, otherwise a code from #fp_delete_result
*/
API_EXPORTED int fp_delete_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_data)
{
struct sync_delete_data *ddata;
gboolean stopped = FALSE;
int r;
if (!enrolled_data) {
fp_err("no print given");
return -EINVAL;
}
if (!fp_dev_supports_print_data(dev, enrolled_data)) {
fp_err("print is not compatible with device");
return -EINVAL;
}
fp_dbg("to be handled by %s", dev->drv->name);
ddata = g_malloc0(sizeof(struct sync_delete_data));
r = fp_async_delete_finger(dev, enrolled_data, sync_delete_cb, ddata);
if (r < 0) {
fp_dbg("delete_finger error %d", r);
g_free(ddata);
return r;
}
while (!ddata->populated) {
r = fp_handle_events();
if (r < 0)
goto out;
}
r = ddata->result;
fp_dbg("delete_finger result %d", r);
out:
g_free(ddata);
return r;
}
struct sync_identify_data {
gboolean populated;
int result;
......
......@@ -267,12 +267,17 @@ int fp_verify_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_print);
int fp_dev_supports_identification(struct fp_dev *dev);
int fp_dev_supports_data_in_sensor(struct fp_dev *dev);
int fp_identify_finger_img(struct fp_dev *dev,
struct fp_print_data **print_gallery, size_t *match_offset,
struct fp_img **img);
int fp_identify_finger(struct fp_dev *dev,
struct fp_print_data **print_gallery, size_t *match_offset);
int fp_delete_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_print);
/* Data handling */
int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger,
struct fp_print_data **data) LIBFPRINT_DEPRECATED;
......@@ -451,6 +456,22 @@ int fp_async_capture_start(struct fp_dev *dev, int unconditional, fp_img_operati
int fp_async_capture_stop(struct fp_dev *dev, fp_operation_stop_cb callback, void *user_data);
/**
* fp_delete_result:
* @FP_DELETE_COMPLETE: Delete completed successfully.
* @FP_DELETE_FAIL: Delete failed
*
*/
enum fp_delete_result {
FP_DELETE_COMPLETE = 0,
FP_DELETE_FAIL = 1,
};
typedef void (*fp_delete_cb)(struct fp_dev *dev, int status, void *user_data);
int fp_async_delete_finger(struct fp_dev *dev, struct fp_print_data *data, fp_delete_cb callback, void *user_data);
#ifdef __cplusplus
}
#endif
......
......@@ -74,6 +74,7 @@ aesx660 = false
aes3k = false
drivers_sources = []
drivers_cflags = []
foreach driver: drivers
if driver == 'upekts'
drivers_sources += [ 'drivers/upekts.c' ]
......@@ -146,6 +147,16 @@ foreach driver: drivers
if driver == 'elan'
drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ]
endif
if driver == 'synaptics'
drivers_sources += [
'drivers/synaptics/synaptics.c',
'drivers/synaptics/bmkt.c',
'drivers/synaptics/util.c',
'drivers/synaptics/bmkt_message.c',
'drivers/synaptics/sensor.c',
'drivers/synaptics/usb_transport.c',
]
endif
endforeach
if aeslib
......@@ -180,6 +191,7 @@ libfprint_sources += configure_file(input: 'empty_file',
])
deps = [ mathlib_dep, glib_dep, libusb_dep, nss_dep, imaging_dep ]
libfprint = library('fprint',
libfprint_sources + drivers_sources + nbis_sources + other_sources,
soversion: soversion,
......
......@@ -45,8 +45,8 @@ mathlib_dep = cc.find_library('m', required: false)
# Drivers
drivers = get_option('drivers').split(',')
all_drivers = [ 'upekts', 'upektc', 'upeksonly', 'vcom5s', 'uru4000', 'aes1610', 'aes1660', 'aes2501', 'aes2550', 'aes2660', 'aes3500', 'aes4000', 'vfs101', 'vfs301', 'vfs5011', 'upektc_img', 'etes603', 'vfs0050', 'elan' ]
primitive_drivers = [ 'upekts' ]
all_drivers = [ 'upekts', 'upektc', 'upeksonly', 'vcom5s', 'uru4000', 'aes1610', 'aes1660', 'aes2501', 'aes2550', 'aes2660', 'aes3500', 'aes4000', 'vfs101', 'vfs301', 'vfs5011', 'upektc_img', 'etes603', 'vfs0050', 'elan', 'synaptics' ]
primitive_drivers = [ 'upekts', 'synaptics' ]
if drivers == [ 'all' ]
drivers = all_drivers
......