aesx660: Port aes1660 and aes2660 drivers to new API

This commit is contained in:
Benjamin Berg 2019-07-08 17:54:54 +02:00
parent 5e05afecf2
commit 0a47df7bb7
5 changed files with 470 additions and 461 deletions

View file

@ -27,6 +27,13 @@
#define FRAME_WIDTH 128 #define FRAME_WIDTH 128
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) #define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes1660 {
FpiDeviceAesX660 parent;
};
G_DECLARE_FINAL_TYPE(FpiDeviceAes1660, fpi_device_aes1660, FPI,
DEVICE_AES1660, FpiDeviceAesX660);
G_DEFINE_TYPE(FpiDeviceAes1660, fpi_device_aes1660, FPI_TYPE_DEVICE_AES_X660);
static struct fpi_frame_asmbl_ctx assembling_ctx = { static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH, .frame_width = FRAME_WIDTH,
.frame_height = AESX660_FRAME_HEIGHT, .frame_height = AESX660_FRAME_HEIGHT,
@ -34,79 +41,50 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = {
.get_pixel = aes_get_pixel, .get_pixel = aes_get_pixel,
}; };
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) static const FpIdEntry id_table [ ] = {
{ { .vid = 0x08ff, .pid = 0x1660, },
/* TODO check that device has endpoints we're using */ { .vid = 0x08ff, .pid = 0x1680, },
int r; { .vid = 0x08ff, .pid = 0x1681, },
struct aesX660_dev *aesdev; { .vid = 0x08ff, .pid = 0x1682, },
{ .vid = 0x08ff, .pid = 0x1683, },
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); { .vid = 0x08ff, .pid = 0x1684, },
if (r < 0) { { .vid = 0x08ff, .pid = 0x1685, },
fp_err("could not claim interface 0: %s", libusb_error_name(r)); { .vid = 0x08ff, .pid = 0x1686, },
return r; { .vid = 0x08ff, .pid = 0x1687, },
} { .vid = 0x08ff, .pid = 0x1688, },
{ .vid = 0x08ff, .pid = 0x1689, },
aesdev = g_malloc0(sizeof(struct aesX660_dev)); { .vid = 0x08ff, .pid = 0x168a, },
fp_dev_set_instance_data(FP_DEV(dev), aesdev); { .vid = 0x08ff, .pid = 0x168b, },
aesdev->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE); { .vid = 0x08ff, .pid = 0x168c, },
aesdev->init_seqs[0] = aes1660_init_1; { .vid = 0x08ff, .pid = 0x168d, },
aesdev->init_seqs_len[0] = G_N_ELEMENTS(aes1660_init_1); { .vid = 0x08ff, .pid = 0x168e, },
aesdev->init_seqs[1] = aes1660_init_2; { .vid = 0x08ff, .pid = 0x168f, },
aesdev->init_seqs_len[1] = G_N_ELEMENTS(aes1660_init_2); { .vid = 0, .pid = 0, .driver_data = 0 },
aesdev->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd;
aesdev->start_imaging_cmd_len = sizeof(aes1660_start_imaging_cmd);
aesdev->assembling_ctx = &assembling_ctx;
aesdev->extra_img_flags = FP_IMG_PARTIAL;
fpi_imgdev_open_complete(dev, 0);
return 0;
}
static void dev_deinit(struct fp_img_dev *dev)
{
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev->buffer);
g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}
static const struct usb_id id_table[] = {
{ .vendor = 0x08ff, .product = 0x1660 },
{ .vendor = 0x08ff, .product = 0x1680 },
{ .vendor = 0x08ff, .product = 0x1681 },
{ .vendor = 0x08ff, .product = 0x1682 },
{ .vendor = 0x08ff, .product = 0x1683 },
{ .vendor = 0x08ff, .product = 0x1684 },
{ .vendor = 0x08ff, .product = 0x1685 },
{ .vendor = 0x08ff, .product = 0x1686 },
{ .vendor = 0x08ff, .product = 0x1687 },
{ .vendor = 0x08ff, .product = 0x1688 },
{ .vendor = 0x08ff, .product = 0x1689 },
{ .vendor = 0x08ff, .product = 0x168a },
{ .vendor = 0x08ff, .product = 0x168b },
{ .vendor = 0x08ff, .product = 0x168c },
{ .vendor = 0x08ff, .product = 0x168d },
{ .vendor = 0x08ff, .product = 0x168e },
{ .vendor = 0x08ff, .product = 0x168f },
{ 0, 0, 0, },
}; };
struct fp_img_driver aes1660_driver = { static void fpi_device_aes1660_init(FpiDeviceAes1660 *self) {
.driver = { }
.id = AES1660_ID, static void fpi_device_aes1660_class_init(FpiDeviceAes1660Class *klass) {
.name = FP_COMPONENT, FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
.full_name = "AuthenTec AES1660", FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
.id_table = id_table, FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
.scan_type = FP_SCAN_TYPE_SWIPE,
},
.flags = 0,
.img_height = -1,
.img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
.bz3_threshold = 20,
.open = dev_init, dev_class->id = "aes1660";
.close = dev_deinit, dev_class->full_name = "AuthenTec AES1660";
.activate = aesX660_dev_activate, dev_class->type = FP_DEVICE_TYPE_USB;
.deactivate = aesX660_dev_deactivate, dev_class->id_table = id_table;
}; dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->bz3_threshold = 20;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
aes_class->init_seqs[0] = aes1660_init_1;
aes_class->init_seqs_len[0] = G_N_ELEMENTS(aes1660_init_1);
aes_class->init_seqs[1] = aes1660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS(aes1660_init_2);
aes_class->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof(aes1660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx;
}

View file

@ -27,6 +27,13 @@
#define FRAME_WIDTH 192 #define FRAME_WIDTH 192
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) #define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes2660 {
FpiDeviceAesX660 parent;
};
G_DECLARE_FINAL_TYPE(FpiDeviceAes2660, fpi_device_aes2660, FPI,
DEVICE_AES2660, FpiDeviceAesX660);
G_DEFINE_TYPE(FpiDeviceAes2660, fpi_device_aes2660, FPI_TYPE_DEVICE_AES_X660);
static struct fpi_frame_asmbl_ctx assembling_ctx = { static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH, .frame_width = FRAME_WIDTH,
.frame_height = AESX660_FRAME_HEIGHT, .frame_height = AESX660_FRAME_HEIGHT,
@ -34,81 +41,52 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = {
.get_pixel = aes_get_pixel, .get_pixel = aes_get_pixel,
}; };
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) static const FpIdEntry id_table [ ] = {
{ { .vid = 0x08ff, .pid = 0x2660, },
/* TODO check that device has endpoints we're using */ { .vid = 0x08ff, .pid = 0x2680, },
int r; { .vid = 0x08ff, .pid = 0x2681, },
struct aesX660_dev *aesdev; { .vid = 0x08ff, .pid = 0x2682, },
{ .vid = 0x08ff, .pid = 0x2683, },
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); { .vid = 0x08ff, .pid = 0x2684, },
if (r < 0) { { .vid = 0x08ff, .pid = 0x2685, },
fp_err("could not claim interface 0: %s", libusb_error_name(r)); { .vid = 0x08ff, .pid = 0x2686, },
return r; { .vid = 0x08ff, .pid = 0x2687, },
} { .vid = 0x08ff, .pid = 0x2688, },
{ .vid = 0x08ff, .pid = 0x2689, },
aesdev = g_malloc0(sizeof(struct aesX660_dev)); { .vid = 0x08ff, .pid = 0x268a, },
fp_dev_set_instance_data(FP_DEV(dev), aesdev); { .vid = 0x08ff, .pid = 0x268b, },
aesdev->buffer = g_malloc0(AES2660_FRAME_SIZE + AESX660_HEADER_SIZE); { .vid = 0x08ff, .pid = 0x268c, },
/* No scaling for AES2660 */ { .vid = 0x08ff, .pid = 0x268d, },
aesdev->init_seqs[0] = aes2660_init_1; { .vid = 0x08ff, .pid = 0x268e, },
aesdev->init_seqs_len[0] = G_N_ELEMENTS(aes2660_init_1); { .vid = 0x08ff, .pid = 0x268f, },
aesdev->init_seqs[1] = aes2660_init_2; { .vid = 0x08ff, .pid = 0x2691, },
aesdev->init_seqs_len[1] = G_N_ELEMENTS(aes2660_init_2); { .vid = 0, .pid = 0, .driver_data = 0 },
aesdev->start_imaging_cmd = (unsigned char *)aes2660_start_imaging_cmd;
aesdev->start_imaging_cmd_len = sizeof(aes2660_start_imaging_cmd);
aesdev->assembling_ctx = &assembling_ctx;
aesdev->extra_img_flags = FP_IMG_PARTIAL;
fpi_imgdev_open_complete(dev, 0);
return 0;
}
static void dev_deinit(struct fp_img_dev *dev)
{
struct aesX660_dev *aesdev;
aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev->buffer);
g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}
static const struct usb_id id_table[] = {
{ .vendor = 0x08ff, .product = 0x2660 },
{ .vendor = 0x08ff, .product = 0x2680 },
{ .vendor = 0x08ff, .product = 0x2681 },
{ .vendor = 0x08ff, .product = 0x2682 },
{ .vendor = 0x08ff, .product = 0x2683 },
{ .vendor = 0x08ff, .product = 0x2684 },
{ .vendor = 0x08ff, .product = 0x2685 },
{ .vendor = 0x08ff, .product = 0x2686 },
{ .vendor = 0x08ff, .product = 0x2687 },
{ .vendor = 0x08ff, .product = 0x2688 },
{ .vendor = 0x08ff, .product = 0x2689 },
{ .vendor = 0x08ff, .product = 0x268a },
{ .vendor = 0x08ff, .product = 0x268b },
{ .vendor = 0x08ff, .product = 0x268c },
{ .vendor = 0x08ff, .product = 0x268d },
{ .vendor = 0x08ff, .product = 0x268e },
{ .vendor = 0x08ff, .product = 0x268f },
{ .vendor = 0x08ff, .product = 0x2691 },
{ 0, 0, 0, },
}; };
struct fp_img_driver aes2660_driver = { static void fpi_device_aes2660_init(FpiDeviceAes2660 *self) {
.driver = { }
.id = AES2660_ID,
.name = FP_COMPONENT,
.full_name = "AuthenTec AES2660",
.id_table = id_table,
.scan_type = FP_SCAN_TYPE_SWIPE,
},
.flags = 0,
.img_height = -1,
.img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
.open = dev_init, static void fpi_device_aes2660_class_init(FpiDeviceAes2660Class *klass) {
.close = dev_deinit, FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
.activate = aesX660_dev_activate, FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
.deactivate = aesX660_dev_deactivate, FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
};
dev_class->id = "aes2660";
dev_class->full_name = "AuthenTec AES2660";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->bz3_threshold = 20;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
aes_class->init_seqs[0] = aes2660_init_1;
aes_class->init_seqs_len[0] = G_N_ELEMENTS(aes2660_init_1);
aes_class->init_seqs[1] = aes2660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS(aes2660_init_2);
aes_class->start_imaging_cmd = (unsigned char *)aes2660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof(aes2660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx;
}

View file

@ -27,11 +27,24 @@
#include "aeslib.h" #include "aeslib.h"
#include "aesx660.h" #include "aesx660.h"
static void start_capture(struct fp_img_dev *dev); typedef struct {
static void complete_deactivation(struct fp_img_dev *dev); GByteArray *stripe_packet;
GSList *strips;
size_t strips_len;
gboolean deactivating;
struct aesX660_cmd *init_seq;
size_t init_seq_len;
unsigned int init_cmd_idx;
unsigned int init_seq_idx;
} FpiDeviceAesX660Private;
#define EP_IN (1 | LIBUSB_ENDPOINT_IN) G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(FpiDeviceAesX660, fpi_device_aes_x660, FP_TYPE_IMAGE_DEVICE);
#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
static void start_capture(FpImageDevice *dev);
static void complete_deactivation(FpImageDevice *dev);
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
#define BULK_TIMEOUT 4000 #define BULK_TIMEOUT 4000
#define FRAME_HEIGHT AESX660_FRAME_HEIGHT #define FRAME_HEIGHT AESX660_FRAME_HEIGHT
@ -41,99 +54,84 @@ static void complete_deactivation(struct fp_img_dev *dev);
#define FINGER_DET_DATA_LEN 4 #define FINGER_DET_DATA_LEN 4
static void static void
aesX660_send_cmd_timeout(fpi_ssm *ssm, aesX660_send_cmd_timeout(FpiSsm *ssm,
struct fp_dev *_dev, FpDevice *_dev,
const unsigned char *cmd, const unsigned char *cmd,
size_t cmd_len, size_t cmd_len,
libusb_transfer_cb_fn callback, FpiUsbTransferCallback callback,
int timeout) int timeout)
{ {
struct fp_img_dev *dev = FP_IMG_DEV(_dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev);
struct libusb_transfer *transfer = fpi_usb_alloc();
int r;
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, (unsigned char *)cmd,
(unsigned char *)cmd, cmd_len, cmd_len, NULL);
callback, ssm, timeout); transfer->ssm = ssm;
r = libusb_submit_transfer(transfer); fpi_usb_transfer_submit(transfer, timeout, NULL, callback, NULL);
if (r < 0) { fpi_usb_transfer_unref(transfer);
fp_dbg("failed to submit transfer\n");
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
} }
static void static void
aesX660_send_cmd(fpi_ssm *ssm, aesX660_send_cmd(FpiSsm *ssm,
struct fp_dev *dev, FpDevice *dev,
const unsigned char *cmd, const unsigned char *cmd,
size_t cmd_len, size_t cmd_len,
libusb_transfer_cb_fn callback) FpiUsbTransferCallback callback)
{ {
return aesX660_send_cmd_timeout(ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT); return aesX660_send_cmd_timeout(ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT);
} }
static void static void
aesX660_read_response(fpi_ssm *ssm, aesX660_read_response(FpiSsm *ssm,
struct fp_dev *_dev, FpDevice *_dev,
gboolean short_is_error,
gboolean cancellable,
size_t buf_len, size_t buf_len,
libusb_transfer_cb_fn callback) FpiUsbTransferCallback callback)
{ {
struct fp_img_dev *dev = FP_IMG_DEV(_dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
int r; GCancellable *cancel = NULL;
if (cancellable)
cancel = fpi_device_get_cancellable (_dev);
data = g_malloc(buf_len); data = g_malloc(buf_len);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, fpi_usb_transfer_fill_bulk_full(transfer, EP_IN, data, buf_len, NULL);
data, buf_len, transfer->ssm = ssm;
callback, ssm, BULK_TIMEOUT); transfer->short_is_error = short_is_error;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, cancel, callback, NULL);
r = libusb_submit_transfer(transfer); fpi_usb_transfer_unref(transfer);
if (r < 0) {
fp_dbg("Failed to submit rx transfer: %d\n", r);
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
}
} }
static void aesX660_send_cmd_cb(struct libusb_transfer *transfer) static void aesX660_send_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{ {
fpi_ssm *ssm = transfer->user_data; if (!error) {
fpi_ssm_next_state(transfer->ssm);
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm);
} else { } else {
fp_dbg("tx transfer status: %d, actual_len: %.4x\n", fpi_ssm_mark_failed(transfer->ssm, error);
transfer->status, transfer->actual_length);
fpi_ssm_mark_failed(ssm, -EIO);
} }
libusb_free_transfer(transfer);
} }
static void aesX660_read_calibrate_data_cb(struct libusb_transfer *transfer) static void aesX660_read_calibrate_data_cb(FpiUsbTransfer *transfer,
FpDevice *device,
gpointer user_data, GError *error)
{ {
fpi_ssm *ssm = transfer->user_data;
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || if (error) {
(transfer->length != transfer->actual_length)) { fpi_ssm_mark_failed(transfer->ssm, error);
fpi_ssm_mark_failed(ssm, -EIO); return;
goto out;
} }
/* Calibrate response was read correctly? */ /* Calibrate response was read correctly? */
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) { if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) {
fp_dbg("Bogus calibrate response: %.2x\n", data[0]); fp_dbg("Bogus calibrate response: %.2x\n", data[0]);
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_failed(transfer->ssm,
goto out; fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus calibrate response"));
return;
} }
fpi_ssm_next_state(ssm); fpi_ssm_next_state(transfer->ssm);
out:
g_free(transfer->buffer);
libusb_free_transfer(transfer);
} }
/****** FINGER PRESENCE DETECTION ******/ /****** FINGER PRESENCE DETECTION ******/
@ -146,81 +144,78 @@ enum finger_det_states {
FINGER_DET_NUM_STATES, FINGER_DET_NUM_STATES,
}; };
static void finger_det_read_fd_data_cb(struct libusb_transfer *transfer) static void finger_det_read_fd_data_cb(FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data,
GError *error)
{ {
fpi_ssm *ssm = transfer->user_data; FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
aesdev->fd_data_transfer = NULL; if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
fpi_ssm_next_state(transfer->ssm);
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { return;
fp_dbg("Cancelling transfer...\n");
fpi_ssm_next_state(ssm);
goto out;
} }
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || if (error) {
(transfer->length != transfer->actual_length)) {
fp_dbg("Failed to read FD data\n"); fp_dbg("Failed to read FD data\n");
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_failed(transfer->ssm, error);
goto out; return;
} }
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) { if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) {
fp_dbg("Bogus FD response: %.2x\n", data[0]); fp_dbg("Bogus FD response: %.2x\n", data[0]);
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_failed(transfer->ssm,
goto out; fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus FD response"));
return;
} }
if (data[AESX660_FINGER_PRESENT_OFFSET] == AESX660_FINGER_PRESENT || aesdev->deactivating) { if (data[AESX660_FINGER_PRESENT_OFFSET] == AESX660_FINGER_PRESENT || priv->deactivating) {
/* Finger present or we're deactivating... */ /* Finger present or we're deactivating... */
fpi_ssm_next_state(ssm); fpi_ssm_next_state(transfer->ssm);
} else { } else {
fp_dbg("Wait for finger returned %.2x as result\n", fp_dbg("Wait for finger returned %.2x as result\n",
data[AESX660_FINGER_PRESENT_OFFSET]); data[AESX660_FINGER_PRESENT_OFFSET]);
fpi_ssm_jump_to_state(ssm, FINGER_DET_SEND_FD_CMD); fpi_ssm_jump_to_state(transfer->ssm, FINGER_DET_SEND_FD_CMD);
} }
out:
g_free(data);
libusb_free_transfer(transfer);
} }
static void finger_det_set_idle_cmd_cb(struct libusb_transfer *transfer) static void finger_det_set_idle_cmd_cb(FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data,
GError *error)
{ {
fpi_ssm *ssm = transfer->user_data; if (!error) {
fpi_ssm_mark_completed(transfer->ssm);
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_mark_completed(ssm);
} else { } else {
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_failed(transfer->ssm, error);
} }
libusb_free_transfer(transfer);
} }
static void finger_det_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void finger_det_sm_complete(FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error)
{ {
struct fp_img_dev *dev = user_data; FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
int err = fpi_ssm_get_error(ssm); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
fp_dbg("Finger detection completed"); fp_dbg("Finger detection completed");
fpi_imgdev_report_finger_status(dev, TRUE); fpi_image_device_report_finger_status(dev, TRUE);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
if (aesdev->deactivating) if (priv->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
else if (err) if (error)
fpi_imgdev_session_error(dev, err); g_error_free (error);
else { } else if (error) {
fpi_imgdev_report_finger_status(dev, TRUE); fpi_image_device_session_error(dev, error);
} else {
fpi_image_device_report_finger_status(dev, TRUE);
start_capture(dev); start_capture(dev);
} }
} }
static void finger_det_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void finger_det_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data)
{ {
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case FINGER_DET_SEND_LED_CMD: case FINGER_DET_SEND_LED_CMD:
@ -232,7 +227,7 @@ static void finger_det_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_da
aesX660_send_cmd_cb, 0); aesX660_send_cmd_cb, 0);
break; break;
case FINGER_DET_READ_FD_DATA: case FINGER_DET_READ_FD_DATA:
aesX660_read_response(ssm, dev, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb); aesX660_read_response(ssm, dev, TRUE, TRUE, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb);
break; break;
case FINGER_DET_SET_IDLE: case FINGER_DET_SET_IDLE:
aesX660_send_cmd(ssm, dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd(ssm, dev, set_idle_cmd, sizeof(set_idle_cmd),
@ -241,17 +236,19 @@ static void finger_det_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_da
} }
} }
static void start_finger_detection(struct fp_img_dev *dev) static void start_finger_detection(FpImageDevice *dev)
{ {
fpi_ssm *ssm; FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiSsm *ssm;
if (aesdev->deactivating) { if (priv->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEV(dev), finger_det_run_state, FINGER_DET_NUM_STATES, dev); ssm = fpi_ssm_new(FP_DEVICE(dev), finger_det_run_state,
FINGER_DET_NUM_STATES, dev);
fpi_ssm_start(ssm, finger_det_sm_complete); fpi_ssm_start(ssm, finger_det_sm_complete);
} }
@ -266,13 +263,22 @@ enum capture_states {
}; };
/* Returns number of processed bytes */ /* Returns number of processed bytes */
static int process_stripe_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned char *data) static int process_stripe_data(FpiSsm *ssm, FpiDeviceAesX660 *self,
unsigned char *data, gsize length)
{ {
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
struct fpi_frame *stripe; struct fpi_frame *stripe;
unsigned char *stripdata; unsigned char *stripdata;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
stripe = g_malloc(aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */ if (length < AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2) {
fp_warn ("Received stripe data is too short, got %zi expected %i bytes!",
length,
AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2);
return 0;
}
stripe = g_malloc(cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */
stripdata = stripe->data; stripdata = stripe->data;
fp_dbg("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET], fp_dbg("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET],
@ -283,10 +289,10 @@ static int process_stripe_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned ch
fp_dbg("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y); fp_dbg("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y);
if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK) { if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK) {
memcpy(stripdata, data + AESX660_IMAGE_OFFSET, aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2); memcpy(stripdata, data + AESX660_IMAGE_OFFSET, cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2);
aesdev->strips = g_slist_prepend(aesdev->strips, stripe); priv->strips = g_slist_prepend(priv->strips, stripe);
aesdev->strips_len++; priv->strips_len++;
return (data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT); return (data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT);
} }
@ -294,88 +300,101 @@ static int process_stripe_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned ch
return 0; return 0;
} }
static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer) static void capture_set_idle_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{ {
fpi_ssm *ssm = transfer->user_data; FpImageDevice *dev = FP_IMAGE_DEVICE (device);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && if (!error) {
(transfer->length == transfer->actual_length)) { FpImage *img;
struct fp_img *img;
aesdev->strips = g_slist_reverse(aesdev->strips); priv->strips = g_slist_reverse(priv->strips);
img = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips, aesdev->strips_len); img = fpi_assemble_frames(cls->assembling_ctx, priv->strips, priv->strips_len);
img->flags |= aesdev->extra_img_flags; g_slist_foreach(priv->strips, (GFunc) g_free, NULL);
g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); g_slist_free(priv->strips);
g_slist_free(aesdev->strips); priv->strips = NULL;
aesdev->strips = NULL; priv->strips_len = 0;
aesdev->strips_len = 0; fpi_image_device_image_captured(dev, img);
fpi_imgdev_image_captured(dev, img); fpi_image_device_report_finger_status(dev, FALSE);
fpi_imgdev_report_finger_status(dev, FALSE); fpi_ssm_mark_completed(transfer->ssm);
fpi_ssm_mark_completed(ssm);
} else { } else {
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_failed(transfer->ssm, error);
} }
libusb_free_transfer(transfer);
} }
static void capture_read_stripe_data_cb(struct libusb_transfer *transfer) static void capture_read_stripe_data_cb(FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data,
GError *error)
{ {
fpi_ssm *ssm = transfer->user_data; FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
int finger_missing = 0; int finger_missing = 0;
size_t copied, actual_len = transfer->actual_length; size_t actual_length = transfer->actual_length;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (error) {
fpi_ssm_mark_failed(ssm, -EIO); g_byte_array_set_size (priv->stripe_packet, 0);
goto out; fpi_ssm_mark_failed(transfer->ssm, error);
return;
} }
fp_dbg("Got %lu bytes of data", actual_len); fp_dbg("Got %lu bytes of data", actual_length);
do { while (actual_length) {
copied = MIN(aesdev->buffer_max - aesdev->buffer_size, actual_len); gssize payload_length;
memcpy(aesdev->buffer + aesdev->buffer_size, gssize still_needed_len;
data, gssize copy_len;
copied);
actual_len -= copied; still_needed_len = MAX (0, AESX660_HEADER_SIZE - (gssize) priv->stripe_packet->len);
data += copied; copy_len = MIN (actual_length, still_needed_len);
aesdev->buffer_size += copied; g_byte_array_append (priv->stripe_packet, data, copy_len);
fp_dbg("Copied %.4lx bytes into internal buffer", data += copy_len;
copied); actual_length -= copy_len;
if (aesdev->buffer_size == aesdev->buffer_max) {
if (aesdev->buffer_max == AESX660_HEADER_SIZE) { /* Do we have a full header? */
aesdev->buffer_max = aesdev->buffer[AESX660_RESPONSE_SIZE_LSB_OFFSET] + if (priv->stripe_packet->len < AESX660_HEADER_SIZE)
(aesdev->buffer[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8) + AESX660_HEADER_SIZE; break;
fp_dbg("Got frame, type %.2x size %.4lx",
aesdev->buffer[AESX660_RESPONSE_TYPE_OFFSET], payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] +
aesdev->buffer_max); (priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
continue; fp_dbg("Got frame, type %.2x payload of size %.4lx",
} else { priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
finger_missing |= process_stripe_data(ssm, dev, aesdev->buffer); payload_length);
aesdev->buffer_max = AESX660_HEADER_SIZE;
aesdev->buffer_size = 0; still_needed_len = MAX (0, AESX660_HEADER_SIZE + payload_length - (gssize) priv->stripe_packet->len);
copy_len = MIN (actual_length, still_needed_len);
g_byte_array_append (priv->stripe_packet, data, copy_len);
data += copy_len;
actual_length -= copy_len;
/* Do we have a full packet including the payload? */
if (priv->stripe_packet->len < payload_length + AESX660_HEADER_SIZE)
break;
finger_missing |= process_stripe_data(transfer->ssm,
self,
priv->stripe_packet->data,
priv->stripe_packet->len);
g_byte_array_set_size (priv->stripe_packet, 0);
} }
}
} while (actual_len);
fp_dbg("finger %s\n", finger_missing ? "missing" : "present"); fp_dbg("finger %s\n", finger_missing ? "missing" : "present");
if (finger_missing) { if (finger_missing) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(transfer->ssm);
} else { } else {
fpi_ssm_jump_to_state(ssm, CAPTURE_READ_STRIPE_DATA); fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_STRIPE_DATA);
} }
out:
g_free(transfer->buffer);
libusb_free_transfer(transfer);
} }
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data)
{ {
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_SEND_LED_CMD: case CAPTURE_SEND_LED_CMD:
@ -383,52 +402,56 @@ static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case CAPTURE_SEND_CAPTURE_CMD: case CAPTURE_SEND_CAPTURE_CMD:
aesdev->buffer_size = 0; g_byte_array_set_size (priv->stripe_packet, 0);
aesdev->buffer_max = AESX660_HEADER_SIZE; aesX660_send_cmd(ssm, _dev, cls->start_imaging_cmd,
aesX660_send_cmd(ssm, _dev, aesdev->start_imaging_cmd, cls->start_imaging_cmd_len,
aesdev->start_imaging_cmd_len,
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case CAPTURE_READ_STRIPE_DATA: case CAPTURE_READ_STRIPE_DATA:
aesX660_read_response(ssm, _dev, AESX660_BULK_TRANSFER_SIZE, aesX660_read_response(ssm, _dev, FALSE, FALSE, AESX660_BULK_TRANSFER_SIZE,
capture_read_stripe_data_cb); capture_read_stripe_data_cb);
break; break;
case CAPTURE_SET_IDLE: case CAPTURE_SET_IDLE:
fp_dbg("Got %lu frames\n", aesdev->strips_len); fp_dbg("Got %lu frames\n", priv->strips_len);
aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd),
capture_set_idle_cmd_cb); capture_set_idle_cmd_cb);
break; break;
} }
} }
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_sm_complete(FpiSsm *ssm, FpDevice *device, void *user_data,
GError *error)
{ {
struct fp_img_dev *dev = user_data; FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
int err = fpi_ssm_get_error(ssm);
fp_dbg("Capture completed"); fp_dbg("Capture completed");
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
if (aesdev->deactivating) if (priv->deactivating) {
complete_deactivation(dev); complete_deactivation(FP_IMAGE_DEVICE (device));
else if (err) if (error)
fpi_imgdev_session_error(dev, err); g_error_free (error);
else } else if (error) {
start_finger_detection(dev); fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
} else {
start_finger_detection(FP_IMAGE_DEVICE (device));
}
} }
static void start_capture(struct fp_img_dev *dev) static void start_capture(FpImageDevice *dev)
{ {
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
fpi_ssm *ssm; FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiSsm *ssm;
if (aesdev->deactivating) { if (priv->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state,
CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start(ssm, capture_sm_complete);
} }
@ -446,18 +469,18 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
static void activate_read_id_cb(struct libusb_transfer *transfer) static void activate_read_id_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{ {
fpi_ssm *ssm = transfer->user_data; FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || if (error) {
(transfer->length != transfer->actual_length)) {
fp_dbg("read_id cmd failed\n"); fp_dbg("read_id cmd failed\n");
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_failed(transfer->ssm, error);
goto out; return;
} }
/* ID was read correctly */ /* ID was read correctly */
if (data[0] == 0x07) { if (data[0] == 0x07) {
@ -465,83 +488,82 @@ static void activate_read_id_cb(struct libusb_transfer *transfer)
data[4], data[3], data[5], data[6], data[7]); data[4], data[3], data[5], data[6], data[7]);
} else { } else {
fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]); fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_failed(transfer->ssm,
goto out; fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read ID response"));
return;
} }
switch (aesdev->init_seq_idx) { switch (priv->init_seq_idx) {
case 0: case 0:
aesdev->init_seq = aesdev->init_seqs[0]; priv->init_seq = cls->init_seqs[0];
aesdev->init_seq_len = aesdev->init_seqs_len[0]; priv->init_seq_len = cls->init_seqs_len[0];
aesdev->init_seq_idx = 1; priv->init_seq_idx = 1;
aesdev->init_cmd_idx = 0; priv->init_cmd_idx = 0;
/* Do calibration only after 1st init sequence */ /* Do calibration only after 1st init sequence */
fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_INIT_CMD); fpi_ssm_jump_to_state(transfer->ssm, ACTIVATE_SEND_INIT_CMD);
break; break;
case 1: case 1:
aesdev->init_seq = aesdev->init_seqs[1]; priv->init_seq = cls->init_seqs[1];
aesdev->init_seq_len = aesdev->init_seqs_len[1]; priv->init_seq_len = cls->init_seqs_len[1];
aesdev->init_seq_idx = 2; priv->init_seq_idx = 2;
aesdev->init_cmd_idx = 0; priv->init_cmd_idx = 0;
fpi_ssm_next_state(ssm); fpi_ssm_next_state(transfer->ssm);
break; break;
default: default:
fp_dbg("Failed to init device! init status: %.2x\n", data[7]); fp_dbg("Failed to init device! init status: %.2x\n", data[7]);
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_failed(transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Failed to init device"));
break; break;
}
} }
out: static void activate_read_init_cb(FpiUsbTransfer *transfer, FpDevice *device,
g_free(transfer->buffer); gpointer user_data, GError *error)
libusb_free_transfer(transfer);
}
static void activate_read_init_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
fp_dbg("read_init_cb\n"); fp_dbg("read_init_cb\n");
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || if (error) {
(transfer->length != transfer->actual_length)) { fp_dbg("read_init transfer status: %s, actual_len: %d\n", error->message,
fp_dbg("read_init transfer status: %d, actual_len: %d\n", transfer->status, transfer->actual_length); (gint)transfer->actual_length);
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_failed(transfer->ssm, error);
goto out; return;
} }
/* ID was read correctly */ /* ID was read correctly */
if (data[0] != 0x42 || data[3] != 0x01) { if (data[0] != 0x42 || data[3] != 0x01) {
fp_dbg("Bogus read init response: %.2x %.2x\n", data[0], fp_dbg("Bogus read init response: %.2x %.2x\n", data[0],
data[3]); data[3]);
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_failed(transfer->ssm,
goto out; fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read init response"));
return;
} }
aesdev->init_cmd_idx++; priv->init_cmd_idx++;
if (aesdev->init_cmd_idx == aesdev->init_seq_len) { if (priv->init_cmd_idx == priv->init_seq_len) {
if (aesdev->init_seq_idx < 2) if (priv->init_seq_idx < 2)
fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_READ_ID_CMD); fpi_ssm_jump_to_state(transfer->ssm,
ACTIVATE_SEND_READ_ID_CMD);
else else
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(transfer->ssm);
goto out; return;
} }
fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_INIT_CMD); fpi_ssm_jump_to_state(transfer->ssm, ACTIVATE_SEND_INIT_CMD);
out:
g_free(transfer->buffer);
libusb_free_transfer(transfer);
} }
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data)
{ {
struct fp_img_dev *dev = user_data; FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case ACTIVATE_SET_IDLE: case ACTIVATE_SET_IDLE:
aesdev->init_seq_idx = 0; priv->init_seq_idx = 0;
fp_dbg("Activate: set idle\n"); fp_dbg("Activate: set idle\n");
aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd),
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
@ -552,69 +574,112 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_ID: case ACTIVATE_READ_ID:
aesX660_read_response(ssm, _dev, ID_LEN, activate_read_id_cb); aesX660_read_response(ssm, _dev, TRUE, FALSE, ID_LEN, activate_read_id_cb);
break; break;
case ACTIVATE_SEND_INIT_CMD: case ACTIVATE_SEND_INIT_CMD:
fp_dbg("Activate: send init seq #%d cmd #%d\n", fp_dbg("Activate: send init seq #%d cmd #%d\n",
aesdev->init_seq_idx, priv->init_seq_idx,
aesdev->init_cmd_idx); priv->init_cmd_idx);
aesX660_send_cmd(ssm, _dev, aesX660_send_cmd(ssm, _dev,
aesdev->init_seq[aesdev->init_cmd_idx].cmd, priv->init_seq[priv->init_cmd_idx].cmd,
aesdev->init_seq[aesdev->init_cmd_idx].len, priv->init_seq[priv->init_cmd_idx].len,
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_INIT_RESPONSE: case ACTIVATE_READ_INIT_RESPONSE:
fp_dbg("Activate: read init response\n"); fp_dbg("Activate: read init response\n");
aesX660_read_response(ssm, _dev, INIT_LEN, activate_read_init_cb); aesX660_read_response(ssm, _dev, TRUE, FALSE, INIT_LEN, activate_read_init_cb);
break; break;
case ACTIVATE_SEND_CALIBRATE_CMD: case ACTIVATE_SEND_CALIBRATE_CMD:
aesX660_send_cmd(ssm, _dev, calibrate_cmd, sizeof(calibrate_cmd), aesX660_send_cmd(ssm, _dev, calibrate_cmd, sizeof(calibrate_cmd),
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_CALIBRATE_DATA: case ACTIVATE_READ_CALIBRATE_DATA:
aesX660_read_response(ssm, _dev, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb); aesX660_read_response(ssm, _dev, TRUE, FALSE, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb);
break; break;
} }
} }
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_sm_complete(FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error)
{ {
struct fp_img_dev *dev = user_data; fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error);
int err = fpi_ssm_get_error(ssm);
fp_dbg("status %d", err);
fpi_imgdev_activate_complete(dev, err);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
if (!err) if (!error)
start_finger_detection(dev); start_finger_detection(FP_IMAGE_DEVICE (_dev));
} }
int aesX660_dev_activate(struct fp_img_dev *dev) static void aesX660_dev_activate(FpImageDevice *dev)
{ {
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start(ssm, activate_sm_complete);
return 0;
} }
void aesX660_dev_deactivate(struct fp_img_dev *dev) static void aesX660_dev_deactivate(FpImageDevice *dev)
{ {
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
if (aesdev->fd_data_transfer) priv->deactivating = TRUE;
libusb_cancel_transfer(aesdev->fd_data_transfer);
aesdev->deactivating = TRUE;
} }
static void complete_deactivation(struct fp_img_dev *dev) static void aesX660_dev_init(FpImageDevice *dev)
{ {
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
GError *error = NULL;
g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error);
priv->stripe_packet = g_byte_array_new ();
fpi_image_device_open_complete(dev, error);
}
static void aesX660_dev_deinit(FpImageDevice *dev)
{
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)),
0, 0, &error);
g_clear_pointer (&priv->stripe_packet, g_byte_array_unref);
fpi_image_device_close_complete(dev, error);
}
static void complete_deactivation(FpImageDevice *dev)
{
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
G_DEBUG_HERE(); G_DEBUG_HERE();
aesdev->deactivating = FALSE; priv->deactivating = FALSE;
g_slist_free(aesdev->strips); g_slist_free(priv->strips);
aesdev->strips = NULL; priv->strips = NULL;
aesdev->strips_len = 0; priv->strips_len = 0;
fpi_imgdev_deactivate_complete(dev); fpi_image_device_deactivate_complete(dev, NULL);
}
static void fpi_device_aes_x660_init(FpiDeviceAesX660 *self) {
}
static void fpi_device_aes_x660_class_init(FpiDeviceAesX660Class *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->img_open = aesX660_dev_init;
img_class->img_close = aesX660_dev_deinit;
img_class->activate = aesX660_dev_activate;
img_class->deactivate = aesX660_dev_deactivate;
/* Everything else is set by the subclasses. */
} }

View file

@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __AESX660_H #pragma once
#define __AESX660_H
#define AESX660_HEADER_SIZE 3 #define AESX660_HEADER_SIZE 3
#define AESX660_RESPONSE_TYPE_OFFSET 0x00 #define AESX660_RESPONSE_TYPE_OFFSET 0x00
@ -43,37 +42,30 @@
#define AESX660_FRAME_HEIGHT 8 #define AESX660_FRAME_HEIGHT 8
struct aesX660_dev { G_DECLARE_DERIVABLE_TYPE(FpiDeviceAesX660, fpi_device_aes_x660, FPI,
GSList *strips; DEVICE_AES_X660, FpImageDevice)
size_t strips_len;
gboolean deactivating; #define FPI_TYPE_DEVICE_AES_X660 (fpi_device_aes_x660_get_type ())
struct aesX660_cmd *init_seq;
size_t init_seq_len; struct _FpiDeviceAesX660Class {
unsigned int init_cmd_idx; FpImageDeviceClass parent;
unsigned int init_seq_idx;
struct libusb_transfer *fd_data_transfer;
unsigned char *buffer;
size_t buffer_size;
size_t buffer_max;
/* Device-specific stuff */
struct aesX660_cmd *init_seqs[2]; struct aesX660_cmd *init_seqs[2];
size_t init_seqs_len[2]; gsize init_seqs_len[2];
unsigned char *start_imaging_cmd; guint8 *start_imaging_cmd;
size_t start_imaging_cmd_len; gsize start_imaging_cmd_len;
struct fpi_frame_asmbl_ctx *assembling_ctx; struct fpi_frame_asmbl_ctx *assembling_ctx;
uint16_t extra_img_flags;
}; };
struct aesX660_cmd { struct aesX660_cmd {
const unsigned char *cmd; const guint8 *cmd;
size_t len; gsize len;
}; };
/* 0x77 cmd seems to control LED, this sequence /* 0x77 cmd seems to control LED, this sequence
* makes LED blink * makes LED blink
*/ */
static const unsigned char led_blink_cmd[] = { static const guint8 led_blink_cmd[] = {
0x77, 0x18, 0x00, 0x77, 0x18, 0x00,
0x00, 0x3f, 0x00, 0xff, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00,
@ -83,40 +75,36 @@ static const unsigned char led_blink_cmd[] = {
/* This sequence makes LED light solid /* This sequence makes LED light solid
*/ */
static const unsigned char led_solid_cmd[] = { static const guint8 led_solid_cmd[] = {
0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00, 0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f 0x00, 0x00, 0x7f
}; };
static const unsigned char wait_for_finger_cmd[] = { static const guint8 wait_for_finger_cmd[] = {
0x20, 0x20,
0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32 0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32
}; };
/* 0x40 cmd response /* 0x40 cmd response
* *
static const unsigned char pkt1371[] = { static const guint8 pkt1371[] = {
0x40, 0x01, 0x00, 0x01 0x40, 0x01, 0x00, 0x01
}; };
*/ */
static const unsigned char set_idle_cmd[] = { static const guint8 set_idle_cmd[] = {
0x0d, /* Reset or "set idle"? */ 0x0d, /* Reset or "set idle"? */
}; };
static const unsigned char read_id_cmd[] = { static const guint8 read_id_cmd[] = {
0x44, 0x02, 0x00, 0x08, 0x00, /* Max transfer size is 8 */ 0x44, 0x02, 0x00, 0x08, 0x00, /* Max transfer size is 8 */
0x07, /* Read ID? */ 0x07, /* Read ID? */
}; };
static const unsigned char calibrate_cmd[] = { static const guint8 calibrate_cmd[] = {
0x44, 0x02, 0x00, 0x04, 0x00, 0x44, 0x02, 0x00, 0x04, 0x00,
0x06, 0x06,
}; };
int aesX660_dev_activate(struct fp_img_dev *dev);
void aesX660_dev_deactivate(struct fp_img_dev *dev);
#endif

View file

@ -51,7 +51,7 @@ mathlib_dep = cc.find_library('m', required: false)
drivers = get_option('drivers').split(',') drivers = get_option('drivers').split(',')
virtual_drivers = [ 'virtual_image' ] virtual_drivers = [ 'virtual_image' ]
#default_drivers = [ 'upekts', 'upektc', 'upeksonly', 'vcom5s', 'uru4000', 'aes1610', 'aes1660', 'aes2501', 'aes2550', 'aes2660', 'aes3500', 'aes4000', 'vfs101', 'vfs301', 'vfs5011', 'upektc_img', 'etes603', 'vfs0050', 'elan' ] #default_drivers = [ 'upekts', 'upektc', 'upeksonly', 'vcom5s', 'uru4000', 'aes1610', 'aes1660', 'aes2501', 'aes2550', 'aes2660', 'aes3500', 'aes4000', 'vfs101', 'vfs301', 'vfs5011', 'upektc_img', 'etes603', 'vfs0050', 'elan' ]
default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610' ] default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660' ]
all_drivers = default_drivers + virtual_drivers all_drivers = default_drivers + virtual_drivers