From 57866c45cd037ce12379f47c3fc9b238a89e81bc Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 9 Jul 2019 21:44:02 +0200 Subject: [PATCH] vcom5s: Port vcom5s to new API --- libfprint/drivers/vcom5s.c | 306 ++++++++++++++++++------------------- meson.build | 2 +- 2 files changed, 147 insertions(+), 161 deletions(-) diff --git a/libfprint/drivers/vcom5s.c b/libfprint/drivers/vcom5s.c index b0c6c45..c97c419 100644 --- a/libfprint/drivers/vcom5s.c +++ b/libfprint/drivers/vcom5s.c @@ -28,10 +28,8 @@ * powerdown? does windows do anything special on exit? */ -#define CTRL_IN 0xc0 -#define CTRL_OUT 0x40 #define CTRL_TIMEOUT 1000 -#define EP_IN (1 | LIBUSB_ENDPOINT_IN) +#define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define IMG_WIDTH 300 #define IMG_HEIGHT 288 @@ -40,12 +38,17 @@ #define RQ_SIZE (IMG_WIDTH * ROWS_PER_RQ) #define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT) -struct v5s_dev { +struct _FpDeviceVcom5s { + FpImageDevice parent; + int capture_iteration; - struct fp_img *capture_img; + FpImage *capture_img; gboolean loop_running; gboolean deactivating; }; +G_DECLARE_FINAL_TYPE(FpDeviceVcom5s, fpi_device_vcom5s, FPI, DEVICE_VCOM5S, + FpImageDevice); +G_DEFINE_TYPE(FpDeviceVcom5s, fpi_device_vcom5s, FP_TYPE_IMAGE_DEVICE); enum v5s_regs { /* when using gain 0x29: @@ -72,76 +75,62 @@ enum v5s_cmd { /***** REGISTER I/O *****/ -static void sm_write_reg_cb(struct libusb_transfer *transfer) +static void sm_write_reg_cb(FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); + if (error) + fpi_ssm_mark_failed(transfer->ssm, error); else - fpi_ssm_next_state(ssm); - - g_free(transfer->buffer); - libusb_free_transfer(transfer); + fpi_ssm_next_state(transfer->ssm); } static void -sm_write_reg(fpi_ssm *ssm, - struct fp_img_dev *dev, +sm_write_reg(FpiSsm *ssm, + FpDevice *dev, unsigned char reg, unsigned char value) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; - + FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); + fp_dbg("set %02x=%02x", reg, value); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE); - libusb_fill_control_setup(data, CTRL_OUT, reg, value, 0, 0); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, sm_write_reg_cb, - ssm, CTRL_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } + fpi_usb_transfer_fill_control(transfer, + G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + reg, value, 0, 0); + transfer->ssm = ssm; + fpi_usb_transfer_submit(transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, + NULL); + fpi_usb_transfer_unref(transfer); } -static void sm_exec_cmd_cb(struct libusb_transfer *transfer) +static void sm_exec_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device, + gpointer user_data, GError *error) { - fpi_ssm *ssm = transfer->user_data; - - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) - fpi_ssm_mark_failed(ssm, -EIO); + if (error) + fpi_ssm_mark_failed(transfer->ssm, error); else - fpi_ssm_next_state(ssm); - - g_free(transfer->buffer); - libusb_free_transfer(transfer); + fpi_ssm_next_state(transfer->ssm); } static void -sm_exec_cmd(fpi_ssm *ssm, - struct fp_img_dev *dev, +sm_exec_cmd(FpiSsm *ssm, + FpDevice *dev, unsigned char cmd, unsigned char param) { - struct libusb_transfer *transfer = fpi_usb_alloc(); - unsigned char *data; - int r; + FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); fp_dbg("cmd %02x param %02x", cmd, param); - data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE); - libusb_fill_control_setup(data, CTRL_IN, cmd, param, 0, 0); - libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, sm_exec_cmd_cb, - ssm, CTRL_TIMEOUT); - r = libusb_submit_transfer(transfer); - if (r < 0) { - g_free(data); - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } + fpi_usb_transfer_fill_control(transfer, + G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST, + G_USB_DEVICE_REQUEST_TYPE_VENDOR, + G_USB_DEVICE_RECIPIENT_DEVICE, + cmd, param, 0, 0); + transfer->ssm = ssm; + fpi_usb_transfer_submit(transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb, + NULL); + fpi_usb_transfer_unref(transfer); } /***** FINGER DETECTION *****/ @@ -159,11 +148,11 @@ sm_exec_cmd(fpi_ssm *ssm, static gboolean finger_is_present(unsigned char *data) { int row; - uint16_t imgavg = 0; + guint16 imgavg = 0; for (row = DETBOX_ROW_START; row < DETBOX_ROW_END; row++) { unsigned char *rowdata = data + (row * IMG_WIDTH); - uint16_t rowavg = 0; + guint16 rowavg = 0; int col; for (col = DETBOX_COL_START; col < DETBOX_COL_END; col++) @@ -181,67 +170,66 @@ static gboolean finger_is_present(unsigned char *data) /***** IMAGE ACQUISITION *****/ -static void capture_iterate(fpi_ssm *ssm, struct fp_img_dev *dev); +static void capture_iterate(FpiSsm *ssm, FpDevice *dev); -static void capture_cb(struct libusb_transfer *transfer) +static void capture_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 v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpImageDevice *imgdev = FP_IMAGE_DEVICE(device); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(device); - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { - fpi_ssm_mark_failed(ssm, -EIO); - goto out; + if (error) { + fpi_ssm_mark_failed(transfer->ssm, error); + return; } - if (++vdev->capture_iteration == NR_REQS) { - struct fp_img *img = vdev->capture_img; + if (++self->capture_iteration == NR_REQS) { + FpImage *img = self->capture_img; /* must clear this early, otherwise the call chain takes us into * loopsm_complete where we would free it, when in fact we are * supposed to be handing off this image */ - vdev->capture_img = NULL; + self->capture_img = NULL; - fpi_imgdev_report_finger_status(dev, finger_is_present(img->data)); - fpi_imgdev_image_captured(dev, img); - fpi_ssm_next_state(ssm); + fpi_image_device_report_finger_status(imgdev, + finger_is_present(img->data)); + fpi_image_device_image_captured(imgdev, img); + fpi_ssm_next_state(transfer->ssm); } else { - capture_iterate(ssm, dev); + capture_iterate(transfer->ssm, device); } - -out: - libusb_free_transfer(transfer); } static void -capture_iterate(fpi_ssm *ssm, - struct fp_img_dev *dev) +capture_iterate(FpiSsm *ssm, + FpDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - int iteration = vdev->capture_iteration; - struct libusb_transfer *transfer = fpi_usb_alloc(); - int r; + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); + int iteration = self->capture_iteration; + FpiUsbTransfer *transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); - libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, - vdev->capture_img->data + (RQ_SIZE * iteration), RQ_SIZE, - capture_cb, ssm, CTRL_TIMEOUT); - transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK; - r = libusb_submit_transfer(transfer); - if (r < 0) { - libusb_free_transfer(transfer); - fpi_ssm_mark_failed(ssm, r); - } + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk_full (transfer, + EP_IN, + self->capture_img->data + (RQ_SIZE * iteration), + RQ_SIZE, + NULL); + + fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, capture_cb, NULL); + fpi_usb_transfer_unref (transfer); } static void -sm_do_capture(fpi_ssm *ssm, - struct fp_img_dev *dev) +sm_do_capture(FpiSsm *ssm, + FpDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); + FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (dev); G_DEBUG_HERE(); - vdev->capture_img = fpi_img_new_for_imgdev(dev); - vdev->capture_iteration = 0; + self->capture_img = fp_image_new (cls->img_width, cls->img_height); + self->capture_iteration = 0; capture_iterate(ssm, dev); } @@ -256,10 +244,9 @@ enum loop_states { LOOP_NUM_STATES, }; -static void loop_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void loop_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data) { - struct fp_img_dev *dev = user_data; - struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); switch (fpi_ssm_get_cur_state(ssm)) { case LOOP_SET_CONTRAST: @@ -269,7 +256,7 @@ static void loop_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) sm_write_reg(ssm, dev, REG_GAIN, 0x29); break; case LOOP_CMD_SCAN: - if (vdev->deactivating) { + if (self->deactivating) { fp_dbg("deactivating, marking completed"); fpi_ssm_mark_completed(ssm); } else @@ -281,95 +268,94 @@ static void loop_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) case LOOP_CAPTURE_DONE: fpi_ssm_jump_to_state(ssm, LOOP_CMD_SCAN); break; + default: + g_assert_not_reached (); } } -static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void loopsm_complete(FpiSsm *ssm, FpDevice *dev, void *user_data, + GError *error) { - struct fp_img_dev *dev = user_data; - struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev); - int r = fpi_ssm_get_error(ssm); + FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev); + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); fpi_ssm_free(ssm); - fp_img_free(vdev->capture_img); - vdev->capture_img = NULL; - vdev->loop_running = FALSE; + g_object_unref (self->capture_img); + self->capture_img = NULL; + self->loop_running = FALSE; - if (r) - fpi_imgdev_session_error(dev, r); + if (error && !self->deactivating) + fpi_image_device_session_error(imgdev, error); + else if (error) + g_error_free (error); - if (vdev->deactivating) - fpi_imgdev_deactivate_complete(dev); + if (self->deactivating) + fpi_image_device_deactivate_complete(imgdev, NULL); } -static int dev_activate(struct fp_img_dev *dev) +static void dev_activate(FpImageDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), loop_run_state, - LOOP_NUM_STATES, dev); - vdev->deactivating = FALSE; + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); + FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), loop_run_state, + LOOP_NUM_STATES, dev); + self->deactivating = FALSE; fpi_ssm_start(ssm, loopsm_complete); - vdev->loop_running = TRUE; - fpi_imgdev_activate_complete(dev, 0); - return 0; + self->loop_running = TRUE; + fpi_image_device_activate_complete(dev, NULL); } -static void dev_deactivate(struct fp_img_dev *dev) +static void dev_deactivate(FpImageDevice *dev) { - struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - if (vdev->loop_running) - vdev->deactivating = TRUE; + FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); + if (self->loop_running) + self->deactivating = TRUE; else - fpi_imgdev_deactivate_complete(dev); + fpi_image_device_deactivate_complete(dev, NULL); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void dev_init(FpImageDevice *dev) { - int r; - struct v5s_dev *v5s_dev; + GError *error = NULL; - v5s_dev = g_malloc0(sizeof(struct v5s_dev)); - fp_dev_set_instance_data(FP_DEV(dev), v5s_dev); + g_usb_device_claim_interface (fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error); - 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)); - - if (r == 0) - fpi_imgdev_open_complete(dev, 0); - - return r; + fpi_image_device_open_complete(dev, error); } -static void dev_deinit(struct fp_img_dev *dev) +static void dev_deinit(FpImageDevice *dev) { - struct v5s_dev *v5s_dev; - v5s_dev = FP_INSTANCE_DATA(FP_DEV(dev)); - g_free(v5s_dev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + GError *error = NULL; + + g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), + 0, 0, &error); + + fpi_image_device_close_complete(dev, error); } -static const struct usb_id id_table[] = { - { .vendor = 0x061a, .product = 0x0110 }, - { 0, 0, 0, }, +static const FpIdEntry id_table [ ] = { + { .vid = 0x061a, .pid = 0x0110, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -struct fp_img_driver vcom5s_driver = { - .driver = { - .id = VCOM5S_ID, - .name = FP_COMPONENT, - .full_name = "Veridicom 5thSense", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_PRESS, - }, - .flags = 0, - .img_height = IMG_HEIGHT, - .img_width = IMG_WIDTH, +static void fpi_device_vcom5s_init(FpDeviceVcom5s *self) { +} - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; +static void fpi_device_vcom5s_class_init(FpDeviceVcom5sClass *klass) { + FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass); + + dev_class->id = "vcom5s"; + dev_class->full_name = "Veridicom 5thSense"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_PRESS; + + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->img_width = IMG_WIDTH; + img_class->img_height = IMG_HEIGHT; +} diff --git a/meson.build b/meson.build index cff9c49..8481073 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', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301', 'vfs0050', 'etes603' ] +default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301', 'vfs0050', 'etes603', 'vcom5s' ] all_drivers = default_drivers + virtual_drivers