From 0a47df7bb7c512618d83cde88c4aa7463a774f0b Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 8 Jul 2019 17:54:54 +0200 Subject: [PATCH] aesx660: Port aes1660 and aes2660 drivers to new API --- libfprint/drivers/aes1660.c | 124 +++---- libfprint/drivers/aes2660.c | 128 +++----- libfprint/drivers/aesx660.c | 621 ++++++++++++++++++++---------------- libfprint/drivers/aesx660.h | 56 ++-- meson.build | 2 +- 5 files changed, 470 insertions(+), 461 deletions(-) diff --git a/libfprint/drivers/aes1660.c b/libfprint/drivers/aes1660.c index f27b9bf..cde7b48 100644 --- a/libfprint/drivers/aes1660.c +++ b/libfprint/drivers/aes1660.c @@ -27,6 +27,13 @@ #define FRAME_WIDTH 128 #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 = { .frame_width = FRAME_WIDTH, .frame_height = AESX660_FRAME_HEIGHT, @@ -34,79 +41,50 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = { .get_pixel = aes_get_pixel, }; -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) -{ - /* TODO check that device has endpoints we're using */ - int r; - struct aesX660_dev *aesdev; - - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } - - aesdev = g_malloc0(sizeof(struct aesX660_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aesdev); - aesdev->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE); - aesdev->init_seqs[0] = aes1660_init_1; - aesdev->init_seqs_len[0] = G_N_ELEMENTS(aes1660_init_1); - aesdev->init_seqs[1] = aes1660_init_2; - aesdev->init_seqs_len[1] = G_N_ELEMENTS(aes1660_init_2); - 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, }, +static const FpIdEntry id_table [ ] = { + { .vid = 0x08ff, .pid = 0x1660, }, + { .vid = 0x08ff, .pid = 0x1680, }, + { .vid = 0x08ff, .pid = 0x1681, }, + { .vid = 0x08ff, .pid = 0x1682, }, + { .vid = 0x08ff, .pid = 0x1683, }, + { .vid = 0x08ff, .pid = 0x1684, }, + { .vid = 0x08ff, .pid = 0x1685, }, + { .vid = 0x08ff, .pid = 0x1686, }, + { .vid = 0x08ff, .pid = 0x1687, }, + { .vid = 0x08ff, .pid = 0x1688, }, + { .vid = 0x08ff, .pid = 0x1689, }, + { .vid = 0x08ff, .pid = 0x168a, }, + { .vid = 0x08ff, .pid = 0x168b, }, + { .vid = 0x08ff, .pid = 0x168c, }, + { .vid = 0x08ff, .pid = 0x168d, }, + { .vid = 0x08ff, .pid = 0x168e, }, + { .vid = 0x08ff, .pid = 0x168f, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver aes1660_driver = { - .driver = { - .id = AES1660_ID, - .name = FP_COMPONENT, - .full_name = "AuthenTec AES1660", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, - .img_height = -1, - .img_width = FRAME_WIDTH + FRAME_WIDTH / 2, - .bz3_threshold = 20, +static void fpi_device_aes1660_init(FpiDeviceAes1660 *self) { +} +static void fpi_device_aes1660_class_init(FpiDeviceAes1660Class *klass) { + FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass); + FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass); - .open = dev_init, - .close = dev_deinit, - .activate = aesX660_dev_activate, - .deactivate = aesX660_dev_deactivate, -}; + dev_class->id = "aes1660"; + dev_class->full_name = "AuthenTec AES1660"; + 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] = 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; +} diff --git a/libfprint/drivers/aes2660.c b/libfprint/drivers/aes2660.c index de380e7..3b05464 100644 --- a/libfprint/drivers/aes2660.c +++ b/libfprint/drivers/aes2660.c @@ -27,6 +27,13 @@ #define FRAME_WIDTH 192 #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 = { .frame_width = FRAME_WIDTH, .frame_height = AESX660_FRAME_HEIGHT, @@ -34,81 +41,52 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = { .get_pixel = aes_get_pixel, }; -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) -{ - /* TODO check that device has endpoints we're using */ - int r; - struct aesX660_dev *aesdev; - - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } - - aesdev = g_malloc0(sizeof(struct aesX660_dev)); - fp_dev_set_instance_data(FP_DEV(dev), aesdev); - aesdev->buffer = g_malloc0(AES2660_FRAME_SIZE + AESX660_HEADER_SIZE); - /* No scaling for AES2660 */ - aesdev->init_seqs[0] = aes2660_init_1; - aesdev->init_seqs_len[0] = G_N_ELEMENTS(aes2660_init_1); - aesdev->init_seqs[1] = aes2660_init_2; - aesdev->init_seqs_len[1] = G_N_ELEMENTS(aes2660_init_2); - 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, }, +static const FpIdEntry id_table [ ] = { + { .vid = 0x08ff, .pid = 0x2660, }, + { .vid = 0x08ff, .pid = 0x2680, }, + { .vid = 0x08ff, .pid = 0x2681, }, + { .vid = 0x08ff, .pid = 0x2682, }, + { .vid = 0x08ff, .pid = 0x2683, }, + { .vid = 0x08ff, .pid = 0x2684, }, + { .vid = 0x08ff, .pid = 0x2685, }, + { .vid = 0x08ff, .pid = 0x2686, }, + { .vid = 0x08ff, .pid = 0x2687, }, + { .vid = 0x08ff, .pid = 0x2688, }, + { .vid = 0x08ff, .pid = 0x2689, }, + { .vid = 0x08ff, .pid = 0x268a, }, + { .vid = 0x08ff, .pid = 0x268b, }, + { .vid = 0x08ff, .pid = 0x268c, }, + { .vid = 0x08ff, .pid = 0x268d, }, + { .vid = 0x08ff, .pid = 0x268e, }, + { .vid = 0x08ff, .pid = 0x268f, }, + { .vid = 0x08ff, .pid = 0x2691, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver aes2660_driver = { - .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, +static void fpi_device_aes2660_init(FpiDeviceAes2660 *self) { +} - .open = dev_init, - .close = dev_deinit, - .activate = aesX660_dev_activate, - .deactivate = aesX660_dev_deactivate, -}; +static void fpi_device_aes2660_class_init(FpiDeviceAes2660Class *klass) { + FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass); + 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; +} diff --git a/libfprint/drivers/aesx660.c b/libfprint/drivers/aesx660.c index 47da51f..5ea4cae 100644 --- a/libfprint/drivers/aesx660.c +++ b/libfprint/drivers/aesx660.c @@ -27,11 +27,24 @@ #include "aeslib.h" #include "aesx660.h" -static void start_capture(struct fp_img_dev *dev); -static void complete_deactivation(struct fp_img_dev *dev); +typedef struct { + 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) -#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(FpiDeviceAesX660, fpi_device_aes_x660, FP_TYPE_IMAGE_DEVICE); + +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 FRAME_HEIGHT AESX660_FRAME_HEIGHT @@ -41,99 +54,84 @@ static void complete_deactivation(struct fp_img_dev *dev); #define FINGER_DET_DATA_LEN 4 static void -aesX660_send_cmd_timeout(fpi_ssm *ssm, - struct fp_dev *_dev, +aesX660_send_cmd_timeout(FpiSsm *ssm, + FpDevice *_dev, const unsigned char *cmd, size_t cmd_len, - libusb_transfer_cb_fn callback, + FpiUsbTransferCallback callback, int timeout) { - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - struct libusb_transfer *transfer = fpi_usb_alloc(); - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, - (unsigned char *)cmd, cmd_len, - callback, ssm, timeout); - r = libusb_submit_transfer(transfer); - if (r < 0) { - fp_dbg("failed to submit transfer\n"); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, -ENOMEM); - } + fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, (unsigned char *)cmd, + cmd_len, NULL); + transfer->ssm = ssm; + fpi_usb_transfer_submit(transfer, timeout, NULL, callback, NULL); + fpi_usb_transfer_unref(transfer); } static void -aesX660_send_cmd(fpi_ssm *ssm, - struct fp_dev *dev, +aesX660_send_cmd(FpiSsm *ssm, + FpDevice *dev, const unsigned char *cmd, size_t cmd_len, - libusb_transfer_cb_fn callback) + FpiUsbTransferCallback callback) { return aesX660_send_cmd_timeout(ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT); } static void -aesX660_read_response(fpi_ssm *ssm, - struct fp_dev *_dev, +aesX660_read_response(FpiSsm *ssm, + FpDevice *_dev, + gboolean short_is_error, + gboolean cancellable, size_t buf_len, - libusb_transfer_cb_fn callback) + FpiUsbTransferCallback callback) { - struct fp_img_dev *dev = FP_IMG_DEV(_dev); - struct libusb_transfer *transfer = fpi_usb_alloc(); + FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev); unsigned char *data; - int r; + GCancellable *cancel = NULL; + if (cancellable) + cancel = fpi_device_get_cancellable (_dev); data = g_malloc(buf_len); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, - data, buf_len, - callback, ssm, BULK_TIMEOUT); - - r = libusb_submit_transfer(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); - } + fpi_usb_transfer_fill_bulk_full(transfer, EP_IN, data, buf_len, NULL); + transfer->ssm = ssm; + transfer->short_is_error = short_is_error; + fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, cancel, callback, NULL); + fpi_usb_transfer_unref(transfer); } -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 ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_next_state(ssm); + if (!error) { + fpi_ssm_next_state(transfer->ssm); } else { - fp_dbg("tx transfer status: %d, actual_len: %.4x\n", - transfer->status, transfer->actual_length); - fpi_ssm_mark_failed(ssm, -EIO); + fpi_ssm_mark_failed(transfer->ssm, error); } - 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; - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { - fpi_ssm_mark_failed(ssm, -EIO); - goto out; + if (error) { + fpi_ssm_mark_failed(transfer->ssm, error); + return; } /* Calibrate response was read correctly? */ if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) { fp_dbg("Bogus calibrate response: %.2x\n", data[0]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; + fpi_ssm_mark_failed(transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Bogus calibrate response")); + return; } - fpi_ssm_next_state(ssm); -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + fpi_ssm_next_state(transfer->ssm); } /****** FINGER PRESENCE DETECTION ******/ @@ -146,81 +144,78 @@ enum finger_det_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; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); unsigned char *data = transfer->buffer; - aesdev->fd_data_transfer = NULL; - - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - fp_dbg("Cancelling transfer...\n"); - fpi_ssm_next_state(ssm); - goto out; + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + fpi_ssm_next_state(transfer->ssm); + return; } - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { + if (error) { fp_dbg("Failed to read FD data\n"); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; + fpi_ssm_mark_failed(transfer->ssm, error); + return; } if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) { fp_dbg("Bogus FD response: %.2x\n", data[0]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; + fpi_ssm_mark_failed(transfer->ssm, + 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... */ - fpi_ssm_next_state(ssm); + fpi_ssm_next_state(transfer->ssm); } else { fp_dbg("Wait for finger returned %.2x as result\n", 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 ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && - (transfer->length == transfer->actual_length)) { - fpi_ssm_mark_completed(ssm); + if (!error) { + fpi_ssm_mark_completed(transfer->ssm); } 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; - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); - int err = fpi_ssm_get_error(ssm); + FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); fp_dbg("Finger detection completed"); - fpi_imgdev_report_finger_status(dev, TRUE); + fpi_image_device_report_finger_status(dev, TRUE); fpi_ssm_free(ssm); - if (aesdev->deactivating) + if (priv->deactivating) { complete_deactivation(dev); - else if (err) - fpi_imgdev_session_error(dev, err); - else { - fpi_imgdev_report_finger_status(dev, TRUE); + if (error) + g_error_free (error); + } else if (error) { + fpi_image_device_session_error(dev, error); + } else { + fpi_image_device_report_finger_status(dev, TRUE); 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)) { 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); break; 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; case FINGER_DET_SET_IDLE: 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; - 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); + FpiSsm *ssm; - if (aesdev->deactivating) { + if (priv->deactivating) { complete_deactivation(dev); 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); } @@ -266,13 +263,22 @@ enum capture_states { }; /* 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; 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; 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); 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); - aesdev->strips_len++; + priv->strips = g_slist_prepend(priv->strips, stripe); + priv->strips_len++; 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; } -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; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + 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) && - (transfer->length == transfer->actual_length)) { - struct fp_img *img; + if (!error) { + FpImage *img; - aesdev->strips = g_slist_reverse(aesdev->strips); - img = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips, aesdev->strips_len); - img->flags |= aesdev->extra_img_flags; - g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_image_captured(dev, img); - fpi_imgdev_report_finger_status(dev, FALSE); - fpi_ssm_mark_completed(ssm); + priv->strips = g_slist_reverse(priv->strips); + img = fpi_assemble_frames(cls->assembling_ctx, priv->strips, priv->strips_len); + g_slist_foreach(priv->strips, (GFunc) g_free, NULL); + g_slist_free(priv->strips); + priv->strips = NULL; + priv->strips_len = 0; + fpi_image_device_image_captured(dev, img); + fpi_image_device_report_finger_status(dev, FALSE); + fpi_ssm_mark_completed(transfer->ssm); } 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; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); unsigned char *data = transfer->buffer; 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) { - fpi_ssm_mark_failed(ssm, -EIO); - goto out; + if (error) { + g_byte_array_set_size (priv->stripe_packet, 0); + fpi_ssm_mark_failed(transfer->ssm, error); + return; } - fp_dbg("Got %lu bytes of data", actual_len); - do { - copied = MIN(aesdev->buffer_max - aesdev->buffer_size, actual_len); - memcpy(aesdev->buffer + aesdev->buffer_size, - data, - copied); - actual_len -= copied; - data += copied; - aesdev->buffer_size += copied; - fp_dbg("Copied %.4lx bytes into internal buffer", - copied); - if (aesdev->buffer_size == aesdev->buffer_max) { - if (aesdev->buffer_max == AESX660_HEADER_SIZE) { - aesdev->buffer_max = aesdev->buffer[AESX660_RESPONSE_SIZE_LSB_OFFSET] + - (aesdev->buffer[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8) + AESX660_HEADER_SIZE; - fp_dbg("Got frame, type %.2x size %.4lx", - aesdev->buffer[AESX660_RESPONSE_TYPE_OFFSET], - aesdev->buffer_max); - continue; - } else { - finger_missing |= process_stripe_data(ssm, dev, aesdev->buffer); - aesdev->buffer_max = AESX660_HEADER_SIZE; - aesdev->buffer_size = 0; - } - } - } while (actual_len); + fp_dbg("Got %lu bytes of data", actual_length); + while (actual_length) { + gssize payload_length; + gssize still_needed_len; + gssize copy_len; + + still_needed_len = MAX (0, AESX660_HEADER_SIZE - (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 header? */ + if (priv->stripe_packet->len < AESX660_HEADER_SIZE) + break; + + payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] + + (priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8); + fp_dbg("Got frame, type %.2x payload of size %.4lx", + priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET], + payload_length); + + 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); + } fp_dbg("finger %s\n", finger_missing ? "missing" : "present"); if (finger_missing) { - fpi_ssm_next_state(ssm); + fpi_ssm_next_state(transfer->ssm); } 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)) { 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); break; case CAPTURE_SEND_CAPTURE_CMD: - aesdev->buffer_size = 0; - aesdev->buffer_max = AESX660_HEADER_SIZE; - aesX660_send_cmd(ssm, _dev, aesdev->start_imaging_cmd, - aesdev->start_imaging_cmd_len, + g_byte_array_set_size (priv->stripe_packet, 0); + aesX660_send_cmd(ssm, _dev, cls->start_imaging_cmd, + cls->start_imaging_cmd_len, aesX660_send_cmd_cb); break; 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); break; 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), capture_set_idle_cmd_cb); 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; - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); - int err = fpi_ssm_get_error(ssm); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); fp_dbg("Capture completed"); fpi_ssm_free(ssm); - if (aesdev->deactivating) - complete_deactivation(dev); - else if (err) - fpi_imgdev_session_error(dev, err); - else - start_finger_detection(dev); + if (priv->deactivating) { + complete_deactivation(FP_IMAGE_DEVICE (device)); + if (error) + g_error_free (error); + } else if (error) { + 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)); - fpi_ssm *ssm; + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiSsm *ssm; - if (aesdev->deactivating) { + if (priv->deactivating) { complete_deactivation(dev); 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(); fpi_ssm_start(ssm, capture_sm_complete); } @@ -446,18 +469,18 @@ enum activate_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; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); + FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); unsigned char *data = transfer->buffer; - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { + if (error) { fp_dbg("read_id cmd failed\n"); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; + fpi_ssm_mark_failed(transfer->ssm, error); + return; } /* ID was read correctly */ 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]); } else { fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; + fpi_ssm_mark_failed(transfer->ssm, + 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: - aesdev->init_seq = aesdev->init_seqs[0]; - aesdev->init_seq_len = aesdev->init_seqs_len[0]; - aesdev->init_seq_idx = 1; - aesdev->init_cmd_idx = 0; + priv->init_seq = cls->init_seqs[0]; + priv->init_seq_len = cls->init_seqs_len[0]; + priv->init_seq_idx = 1; + priv->init_cmd_idx = 0; /* 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; case 1: - aesdev->init_seq = aesdev->init_seqs[1]; - aesdev->init_seq_len = aesdev->init_seqs_len[1]; - aesdev->init_seq_idx = 2; - aesdev->init_cmd_idx = 0; - fpi_ssm_next_state(ssm); + priv->init_seq = cls->init_seqs[1]; + priv->init_seq_len = cls->init_seqs_len[1]; + priv->init_seq_idx = 2; + priv->init_cmd_idx = 0; + fpi_ssm_next_state(transfer->ssm); break; default: 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; - } - -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); } -static void activate_read_init_cb(struct libusb_transfer *transfer) +static void activate_read_init_cb(FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); - struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); + FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); unsigned char *data = transfer->buffer; fp_dbg("read_init_cb\n"); - if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || - (transfer->length != transfer->actual_length)) { - fp_dbg("read_init transfer status: %d, actual_len: %d\n", transfer->status, transfer->actual_length); - fpi_ssm_mark_failed(ssm, -EIO); - goto out; + if (error) { + fp_dbg("read_init transfer status: %s, actual_len: %d\n", error->message, + (gint)transfer->actual_length); + fpi_ssm_mark_failed(transfer->ssm, error); + return; } /* ID was read correctly */ if (data[0] != 0x42 || data[3] != 0x01) { fp_dbg("Bogus read init response: %.2x %.2x\n", data[0], data[3]); - fpi_ssm_mark_failed(ssm, -EPROTO); - goto out; + fpi_ssm_mark_failed(transfer->ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, + "Bogus read init response")); + return; } - aesdev->init_cmd_idx++; - if (aesdev->init_cmd_idx == aesdev->init_seq_len) { - if (aesdev->init_seq_idx < 2) - fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_READ_ID_CMD); + priv->init_cmd_idx++; + if (priv->init_cmd_idx == priv->init_seq_len) { + if (priv->init_seq_idx < 2) + fpi_ssm_jump_to_state(transfer->ssm, + ACTIVATE_SEND_READ_ID_CMD); else - fpi_ssm_mark_completed(ssm); - goto out; + fpi_ssm_mark_completed(transfer->ssm); + return; } - fpi_ssm_jump_to_state(ssm, ACTIVATE_SEND_INIT_CMD); -out: - g_free(transfer->buffer); - libusb_free_transfer(transfer); + fpi_ssm_jump_to_state(transfer->ssm, ACTIVATE_SEND_INIT_CMD); } -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; - 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); switch (fpi_ssm_get_cur_state(ssm)) { case ACTIVATE_SET_IDLE: - aesdev->init_seq_idx = 0; + priv->init_seq_idx = 0; fp_dbg("Activate: set idle\n"); aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd), 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); break; 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; case ACTIVATE_SEND_INIT_CMD: fp_dbg("Activate: send init seq #%d cmd #%d\n", - aesdev->init_seq_idx, - aesdev->init_cmd_idx); + priv->init_seq_idx, + priv->init_cmd_idx); aesX660_send_cmd(ssm, _dev, - aesdev->init_seq[aesdev->init_cmd_idx].cmd, - aesdev->init_seq[aesdev->init_cmd_idx].len, + priv->init_seq[priv->init_cmd_idx].cmd, + priv->init_seq[priv->init_cmd_idx].len, aesX660_send_cmd_cb); break; case ACTIVATE_READ_INIT_RESPONSE: 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; case ACTIVATE_SEND_CALIBRATE_CMD: aesX660_send_cmd(ssm, _dev, calibrate_cmd, sizeof(calibrate_cmd), aesX660_send_cmd_cb); break; 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; } } -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; - int err = fpi_ssm_get_error(ssm); - fp_dbg("status %d", err); - fpi_imgdev_activate_complete(dev, err); + fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error); fpi_ssm_free(ssm); - if (!err) - start_finger_detection(dev); + if (!error) + 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, - ACTIVATE_NUM_STATES, dev); + FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state, + ACTIVATE_NUM_STATES, dev); 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) - libusb_cancel_transfer(aesdev->fd_data_transfer); - - aesdev->deactivating = TRUE; + priv->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(); - aesdev->deactivating = FALSE; - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - fpi_imgdev_deactivate_complete(dev); + priv->deactivating = FALSE; + g_slist_free(priv->strips); + priv->strips = NULL; + priv->strips_len = 0; + 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. */ } diff --git a/libfprint/drivers/aesx660.h b/libfprint/drivers/aesx660.h index 8d8f350..4d6faf5 100644 --- a/libfprint/drivers/aesx660.h +++ b/libfprint/drivers/aesx660.h @@ -17,8 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __AESX660_H -#define __AESX660_H +#pragma once #define AESX660_HEADER_SIZE 3 #define AESX660_RESPONSE_TYPE_OFFSET 0x00 @@ -43,37 +42,30 @@ #define AESX660_FRAME_HEIGHT 8 -struct aesX660_dev { - 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; - struct libusb_transfer *fd_data_transfer; - unsigned char *buffer; - size_t buffer_size; - size_t buffer_max; +G_DECLARE_DERIVABLE_TYPE(FpiDeviceAesX660, fpi_device_aes_x660, FPI, + DEVICE_AES_X660, FpImageDevice) - /* Device-specific stuff */ - struct aesX660_cmd *init_seqs[2]; - size_t init_seqs_len[2]; - unsigned char *start_imaging_cmd; - size_t start_imaging_cmd_len; - struct fpi_frame_asmbl_ctx *assembling_ctx; - uint16_t extra_img_flags; +#define FPI_TYPE_DEVICE_AES_X660 (fpi_device_aes_x660_get_type ()) + +struct _FpiDeviceAesX660Class { + FpImageDeviceClass parent; + + struct aesX660_cmd *init_seqs[2]; + gsize init_seqs_len[2]; + guint8 *start_imaging_cmd; + gsize start_imaging_cmd_len; + struct fpi_frame_asmbl_ctx *assembling_ctx; }; struct aesX660_cmd { - const unsigned char *cmd; - size_t len; + const guint8 *cmd; + gsize len; }; /* 0x77 cmd seems to control LED, this sequence * makes LED blink */ -static const unsigned char led_blink_cmd[] = { +static const guint8 led_blink_cmd[] = { 0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 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 */ -static const unsigned char led_solid_cmd[] = { +static const guint8 led_solid_cmd[] = { 0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f }; -static const unsigned char wait_for_finger_cmd[] = { +static const guint8 wait_for_finger_cmd[] = { 0x20, 0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32 }; /* 0x40 cmd response * -static const unsigned char pkt1371[] = { +static const guint8 pkt1371[] = { 0x40, 0x01, 0x00, 0x01 }; */ -static const unsigned char set_idle_cmd[] = { +static const guint8 set_idle_cmd[] = { 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 */ 0x07, /* Read ID? */ }; -static const unsigned char calibrate_cmd[] = { +static const guint8 calibrate_cmd[] = { 0x44, 0x02, 0x00, 0x04, 0x00, 0x06, }; -int aesX660_dev_activate(struct fp_img_dev *dev); -void aesX660_dev_deactivate(struct fp_img_dev *dev); - -#endif diff --git a/meson.build b/meson.build index f459711..d382ae8 100644 --- a/meson.build +++ b/meson.build @@ -51,7 +51,7 @@ mathlib_dep = cc.find_library('m', required: false) drivers = get_option('drivers').split(',') 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 = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610' ] +default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660' ] all_drivers = default_drivers + virtual_drivers