diff --git a/libfprint/drivers/vfs301.c b/libfprint/drivers/vfs301.c index 94837de..2339c2f 100644 --- a/libfprint/drivers/vfs301.c +++ b/libfprint/drivers/vfs301.c @@ -22,32 +22,30 @@ #define FP_COMPONENT "vfs301" #include "drivers_api.h" -#include "vfs301_proto.h" +#include "vfs301.h" + +G_DEFINE_TYPE (FpDeviceVfs301, fpi_device_vfs301, FP_TYPE_IMAGE_DEVICE) /************************** GENERIC STUFF *************************************/ /* Submit asynchronous sleep */ static void async_sleep(unsigned int msec, - fpi_ssm *ssm, - struct fp_img_dev *dev) + FpiSsm *ssm, + FpImageDevice *dev) { /* Add timeout */ - if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL) { - /* Failed to add timeout */ - fp_err("failed to add timeout"); - fpi_imgdev_session_error(dev, -ETIME); - fpi_ssm_mark_failed(ssm, -ETIME); - } + fpi_device_add_timeout(FP_DEVICE(dev), msec, + fpi_ssm_next_state_timeout_cb, ssm); } static int -submit_image(fpi_ssm *ssm, - struct fp_img_dev *dev) +submit_image(FpiSsm *ssm, + FpImageDevice *dev) { - vfs301_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev); int height; - struct fp_img *img; + FpImage *img; #if 0 /* XXX: This is probably handled by libfprint automagically? */ @@ -57,22 +55,23 @@ submit_image(fpi_ssm *ssm, } #endif - img = fpi_img_new(VFS301_FP_OUTPUT_WIDTH * vdev->scanline_count); + img = fp_image_new(VFS301_FP_OUTPUT_WIDTH, self->scanline_count); if (img == NULL) return 0; - vfs301_extract_image(vdev, img->data, &height); + vfs301_extract_image(self, img->data, &height); /* TODO: how to detect flip? should the resulting image be * oriented so that it is equal e.g. to a fingerprint on a paper, * or to the finger when I look at it?) */ - img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED; + img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED; + /* The image buffer is larger at this point, but that does not + * matter. */ img->width = VFS301_FP_OUTPUT_WIDTH; img->height = height; - img = fpi_img_realloc(img, img->height * img->width); - fpi_imgdev_image_captured(dev, img); + fpi_image_device_image_captured(dev, img); return 1; } @@ -94,14 +93,14 @@ enum }; /* Exec loop sequential state machine */ -static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void m_loop_state(FpiSsm *ssm, FpDevice *_dev, void *user_data) { - struct fp_img_dev *dev = user_data; - vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = user_data; + FpDeviceVfs301 *self = FPI_DEVICE_VFS301(_dev); switch (fpi_ssm_get_cur_state(ssm)) { case M_REQUEST_PRINT: - vfs301_proto_request_fingerprint(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); + vfs301_proto_request_fingerprint(self); fpi_ssm_next_state(ssm); break; @@ -111,15 +110,15 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) break; case M_CHECK_PRINT: - if (!vfs301_proto_peek_event(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev)) + if (!vfs301_proto_peek_event(self)) fpi_ssm_jump_to_state(ssm, M_WAIT_PRINT); else fpi_ssm_next_state(ssm); break; case M_READ_PRINT_START: - fpi_imgdev_report_finger_status(dev, TRUE); - vfs301_proto_process_event_start(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); + fpi_image_device_report_finger_status(dev, TRUE); + vfs301_proto_process_event_start(self); fpi_ssm_next_state(ssm); break; @@ -130,7 +129,7 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) case M_READ_PRINT_POLL: { - int rv = vfs301_proto_process_event_poll(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); + int rv = vfs301_proto_process_event_poll(self); g_assert(rv != VFS301_FAILURE); if (rv == VFS301_ONGOING) fpi_ssm_jump_to_state(ssm, M_READ_PRINT_WAIT); @@ -143,46 +142,53 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) if (submit_image(ssm, dev)) { fpi_ssm_mark_completed(ssm); /* NOTE: finger off is expected only after submitting image... */ - fpi_imgdev_report_finger_status(dev, FALSE); + fpi_image_device_report_finger_status(dev, FALSE); } else { fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT); } break; + default: + g_assert_not_reached (); } } /* Complete loop sequential state machine */ -static void m_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void m_loop_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data, + GError *error) { + if (error) { + g_warning ("State machine completed with an error: %s", error->message); + g_error_free (error); + } /* Free sequential state machine */ fpi_ssm_free(ssm); } /* Exec init sequential state machine */ -static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void m_init_state(FpiSsm *ssm, FpDevice *_dev, void *user_data) { - struct fp_img_dev *dev = user_data; - vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev); + FpDeviceVfs301 *self = FPI_DEVICE_VFS301(_dev); g_assert(fpi_ssm_get_cur_state(ssm) == 0); - vfs301_proto_init(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); + vfs301_proto_init(self); fpi_ssm_mark_completed(ssm); } /* Complete init sequential state machine */ -static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void m_init_complete(FpiSsm *ssm, FpDevice *dev, void *user_data, + GError *error) { - struct fp_img_dev *dev = user_data; - fpi_ssm *ssm_loop; + FpiSsm *ssm_loop; - if (!fpi_ssm_get_error(ssm)) { + fpi_image_device_activate_complete(FP_IMAGE_DEVICE (dev), error); + if (!error) { /* Notify activate complete */ - fpi_imgdev_activate_complete(dev, 0); /* Start loop ssm */ - ssm_loop = fpi_ssm_new(FP_DEV(dev), m_loop_state, M_LOOP_NUM_STATES, dev); + ssm_loop = fpi_ssm_new(dev, m_loop_state, + M_LOOP_NUM_STATES, dev); fpi_ssm_start(ssm_loop, m_loop_complete); } @@ -191,99 +197,82 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) } /* Activate device */ -static int dev_activate(struct fp_img_dev *dev) +static void dev_activate(FpImageDevice *dev) { - fpi_ssm *ssm; + FpiSsm *ssm; /* Start init ssm */ - ssm = fpi_ssm_new(FP_DEV(dev), m_init_state, 1, dev); + ssm = fpi_ssm_new(FP_DEVICE(dev), m_init_state, 1, dev); fpi_ssm_start(ssm, m_init_complete); - - return 0; } /* Deactivate device */ -static void dev_deactivate(struct fp_img_dev *dev) +static void dev_deactivate(FpImageDevice *dev) { - vfs301_dev_t *vdev; + FpDeviceVfs301 *self; - vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - vfs301_proto_deinit(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); - fpi_imgdev_deactivate_complete(dev); + self = FPI_DEVICE_VFS301(dev); + vfs301_proto_deinit(self); + fpi_image_device_deactivate_complete(dev, NULL); } -static int dev_open(struct fp_img_dev *dev, unsigned long driver_data) +static void dev_open(FpImageDevice *dev) { - vfs301_dev_t *vdev = NULL; - int r; + FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev); + GError *error = NULL; /* Claim usb interface */ - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - /* Interface not claimed, return error */ - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; - } + g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error); /* Initialize private structure */ - vdev = g_malloc0(sizeof(vfs301_dev_t)); - fp_dev_set_instance_data(FP_DEV(dev), vdev); - - vdev->scanline_buf = malloc(0); - vdev->scanline_count = 0; + self->scanline_count = 0; /* Notify open complete */ - fpi_imgdev_open_complete(dev, 0); - - return 0; + fpi_image_device_open_complete(dev, error); } -static void dev_close(struct fp_img_dev *dev) +static void dev_close(FpImageDevice *dev) { - vfs301_dev_t *vdev; + FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev); + GError *error = NULL; /* Release private structure */ - vdev = FP_INSTANCE_DATA(FP_DEV(dev)); - free(vdev->scanline_buf); - g_free(vdev); + g_clear_pointer (&self->scanline_buf, g_free); /* Release usb interface */ - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); + g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), + 0, 0, &error); /* Notify close complete */ - fpi_imgdev_close_complete(dev); + fpi_image_device_close_complete(dev, error); } /* Usb id table of device */ -static const struct usb_id id_table[] = -{ - { .vendor = 0x138a, .product = 0x0005 /* vfs301 */ }, - { .vendor = 0x138a, .product = 0x0008 /* vfs300 */ }, - { 0, 0, 0, }, +static const FpIdEntry id_table [ ] = { + { /* vfs301 */ .vid = 0x138a, .pid = 0x0005, }, + { /* vfs300 */ .vid = 0x138a, .pid = 0x0008, }, + { .vid = 0, .pid = 0, .driver_data = 0 }, }; -/* Device driver definition */ -struct fp_img_driver vfs301_driver = -{ - /* Driver specification */ - .driver = - { - .id = VFS301_ID, - .name = FP_COMPONENT, - .full_name = "Validity VFS301", - .id_table = id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, +static void fpi_device_vfs301_init(FpDeviceVfs301 *self) { +} +static void fpi_device_vfs301_class_init(FpDeviceVfs301Class *klass) { + FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass); - /* Image specification */ - .flags = 0, - .img_width = VFS301_FP_WIDTH, - .img_height = -1, - .bz3_threshold = 24, + dev_class->id = "vfs301"; + dev_class->full_name = "Validity VFS301"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; - /* Routine specification */ - .open = dev_open, - .close = dev_close, - .activate = dev_activate, - .deactivate = dev_deactivate, -}; + img_class->img_open = dev_open; + img_class->img_close = dev_close; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + + img_class->bz3_threshold = 24; + + img_class->img_width = VFS301_FP_WIDTH; + img_class->img_height = -1; +} diff --git a/libfprint/drivers/vfs301_proto.h b/libfprint/drivers/vfs301.h similarity index 80% rename from libfprint/drivers/vfs301_proto.h rename to libfprint/drivers/vfs301.h index 2ae587a..dfbbc7e 100644 --- a/libfprint/drivers/vfs301_proto.h +++ b/libfprint/drivers/vfs301.h @@ -18,7 +18,11 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include + +#pragma once + +#include "fpi-usb-transfer.h" +#include "fpi-image-device.h" enum { VFS301_DEFAULT_WAIT_TIMEOUT = 300, @@ -31,10 +35,8 @@ enum { #define VFS301_FP_RECV_LEN_1 (84032) #define VFS301_FP_RECV_LEN_2 (84096) -typedef struct { - /* buffer for received data */ - unsigned char recv_buf[0x20000]; - int recv_len; +struct _FpDeviceVfs301 { + FpImageDevice parent; /* buffer to hold raw scanlines */ unsigned char *scanline_buf; @@ -46,7 +48,9 @@ typedef struct { VFS301_FAILURE = -1 } recv_progress; int recv_exp_amt; -} vfs301_dev_t; +}; + +G_DECLARE_FINAL_TYPE (FpDeviceVfs301, fpi_device_vfs301, FPI, DEVICE_VFS301, FpImageDevice) enum { /* Width of the scanned data in px */ @@ -120,18 +124,14 @@ typedef struct { unsigned char sum3[3]; } vfs301_line_t; -void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev); -void vfs301_proto_deinit(struct libusb_device_handle *devh, vfs301_dev_t *dev); +void vfs301_proto_init(FpDeviceVfs301 *dev); +void vfs301_proto_deinit(FpDeviceVfs301 *dev); -void vfs301_proto_request_fingerprint( - struct libusb_device_handle *devh, vfs301_dev_t *dev); +void vfs301_proto_request_fingerprint(FpDeviceVfs301 *dev); /** returns 0 if no event is ready, or 1 if there is one... */ -int vfs301_proto_peek_event( - struct libusb_device_handle *devh, vfs301_dev_t *dev); -void vfs301_proto_process_event_start( - struct libusb_device_handle *devh, vfs301_dev_t *dev); -int vfs301_proto_process_event_poll( - struct libusb_device_handle *devh, vfs301_dev_t *dev); +int vfs301_proto_peek_event(FpDeviceVfs301 *dev); +void vfs301_proto_process_event_start(FpDeviceVfs301 *dev); +int vfs301_proto_process_event_poll(FpDeviceVfs301 *dev); -void vfs301_extract_image(vfs301_dev_t *vfs, unsigned char *output, int *output_height); +void vfs301_extract_image(FpDeviceVfs301 *vfs, unsigned char *output, int *output_height); diff --git a/libfprint/drivers/vfs301_proto.c b/libfprint/drivers/vfs301_proto.c index 7564f56..17129f1 100644 --- a/libfprint/drivers/vfs301_proto.c +++ b/libfprint/drivers/vfs301_proto.c @@ -34,16 +34,16 @@ #include #include -#include "fpi-usb.h" -#include "vfs301_proto.h" +#include "fpi-usb-transfer.h" +#include "vfs301.h" #include "vfs301_proto_fragments.h" /************************** USB STUFF *****************************************/ #ifdef DEBUG -static void usb_print_packet(int dir, int rv, const unsigned char *data, int length) +static void usb_print_packet(int dir, GError *error, const guint8 *data, int length) { - fprintf(stderr, "%s, rv %d, len %d\n", dir ? "send" : "recv", rv, length); + fprintf(stderr, "%s, error %s, len %d\n", dir ? "send" : "recv", error ? error->message : "-", length); #ifdef PRINT_VERBOSE int i; @@ -61,60 +61,69 @@ static void usb_print_packet(int dir, int rv, const unsigned char *data, int len } #endif -static int usb_recv( - vfs301_dev_t *dev, - struct libusb_device_handle *devh, unsigned char endpoint, int max_bytes) +static void usb_recv(FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error) { - g_assert(max_bytes <= sizeof(dev->recv_buf)); + GError *err = NULL; + g_autoptr(FpiUsbTransfer) transfer = NULL; + + /* XXX: This function swallows any transfer errors, that is obviously + * quite bad (it used to assert on no-error)! */ + + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk (transfer, endpoint, max_bytes); + + fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err); - int r = libusb_bulk_transfer( - devh, endpoint, - dev->recv_buf, max_bytes, - &dev->recv_len, VFS301_DEFAULT_WAIT_TIMEOUT - ); #ifdef DEBUG - usb_print_packet(0, r, dev->recv_buf, dev->recv_len); + usb_print_packet(0, err, transfer->buffer, transfer->actual_length); #endif + if (err) { + if (!error) + g_warning("Unhandled receive error: %s", err->message); + g_propagate_error (error, err); + } - if (r < 0) - return r; - return 0; + if (out) + *out = g_steal_pointer (&transfer); } -static int usb_send( - struct libusb_device_handle *devh, const unsigned char *data, int length) +static void usb_send(FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error) { - int transferred = 0; + GError *err = NULL; + g_autoptr(FpiUsbTransfer) transfer = NULL; - int r = libusb_bulk_transfer( - devh, VFS301_SEND_ENDPOINT, - (unsigned char *)data, length, &transferred, VFS301_DEFAULT_WAIT_TIMEOUT - ); + /* XXX: This function swallows any transfer errors, that is obviously + * quite bad (it used to assert on no-error)! */ + + transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); + transfer->short_is_error = TRUE; + fpi_usb_transfer_fill_bulk_full (transfer, VFS301_SEND_ENDPOINT, (guint8*) data, length, g_free); + + fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err); #ifdef DEBUG - usb_print_packet(1, r, data, length); + usb_print_packet(1, err, data, length); #endif - g_assert(r == 0); - - if (r < 0) - return r; - if (transferred < length) - return r; - - return 0; + if (err) { + g_warning ("Error while sending data, continuing anyway: %s", err->message); + g_propagate_error (error, err); + } } /************************** OUT MESSAGES GENERATION ***************************/ -static void vfs301_proto_generate_0B(int subtype, unsigned char *data, int *len) +static guint8 * vfs301_proto_generate_0B(int subtype, gssize *len) { + guint8 *res = g_malloc0 (39); + guint8 *data = res; + *data = 0x0B; *len = 1; data++; - memset(data, 0, 39); *len += 38; data[20] = subtype; @@ -125,40 +134,50 @@ static void vfs301_proto_generate_0B(int subtype, unsigned char *data, int *len) break; case 0x05: data[34] = 0xAB; - len++; + /* NOTE: There was a len++ here, which could never do anything */ break; default: g_assert_not_reached(); break; } + + return res; } #define HEX_TO_INT(c) \ (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10)) -static void translate_str(const char **srcL, unsigned char *data, int *len) +static guint8 * translate_str(const char **srcL, gssize *len) { + guint8 *res = NULL; + guint8 *dst; + const char **src_pos; const char *src; - unsigned char *dataOrig = data; + gssize src_len = 0; - while (*srcL != NULL) { - src = *srcL; - while (*src != '\0') { - g_assert(*src != '\0'); - g_assert(*(src +1) != '\0'); - *data = (unsigned char)((HEX_TO_INT(*src) << 4) | (HEX_TO_INT(*(src + 1)))); + for (src_pos = srcL; *src_pos; src_pos++) { + gint tmp; - data++; - src += 2; - } - - srcL++; + src = *src_pos; + tmp = strlen(src); + g_assert (tmp % 2 == 0); + src_len += tmp; } - *len = data - dataOrig; + *len = src_len / 2; + res = g_malloc0 (*len); + dst = res; + + for (src_pos = srcL; *src_pos; src_pos++) { + for (src = *src_pos; *src; src += 2, dst += 1) { + *dst = (guint8) ((HEX_TO_INT (src[0]) << 4) | (HEX_TO_INT (src[1]))); + } + } + + return res; } -static void vfs301_proto_generate(int type, int subtype, unsigned char *data, int *len) +static guint8 *vfs301_proto_generate(int type, int subtype, gssize *len) { switch (type) { case 0x01: @@ -173,11 +192,15 @@ static void vfs301_proto_generate(int type, int subtype, unsigned char *data, in case 0x17: case 0x19: case 0x1A: - *data = type; - *len = 1; + { + guint8 *data = g_malloc0 (1); + *data = type; + *len = 1; + return data; + } break; case 0x0B: - vfs301_proto_generate_0B(subtype, data, len); + return vfs301_proto_generate_0B(subtype, len); break; case 0x02D0: { @@ -190,49 +213,57 @@ static void vfs301_proto_generate(int type, int subtype, unsigned char *data, in vfs301_02D0_06, vfs301_02D0_07, }; - g_assert((int)subtype <= (int)(sizeof(dataLs) / sizeof(dataLs[0]))); - translate_str(dataLs[subtype - 1], data, len); + g_assert((int)subtype <= G_N_ELEMENTS (dataLs)); + return translate_str(dataLs[subtype - 1], len); } break; case 0x0220: switch (subtype) { case 1: - translate_str(vfs301_0220_01, data, len); + return translate_str(vfs301_0220_01, len); break; case 2: - translate_str(vfs301_0220_02, data, len); + return translate_str(vfs301_0220_02, len); break; case 3: - translate_str(vfs301_0220_03, data, len); + return translate_str(vfs301_0220_03, len); break; case 0xFA00: case 0x2C01: - case 0x5E01: - translate_str(vfs301_next_scan_template, data, len); - unsigned char *field = data + *len - (sizeof(S4_TAIL) - 1) / 2 - 4; + case 0x5E01: { + guint8 *data; + guint8 *field; - g_assert(*field == 0xDE); - g_assert(*(field + 1) == 0xAD); - g_assert(*(field + 2) == 0xDE); - g_assert(*(field + 3) == 0xAD); + data = translate_str(vfs301_next_scan_template, len); + field = data + *len - (sizeof(S4_TAIL) - 1) / 2 - 4; - *field = (unsigned char)((subtype >> 8) & 0xFF); - *(field + 1) = (unsigned char)(subtype & 0xFF); - *(field + 2) = *field; - *(field + 3) = *(field + 1); + g_assert (field >= data && field < data + *len); + g_assert(field[0] == 0xDE); + g_assert(field[1] == 0xAD); + g_assert(field[2] == 0xDE); + g_assert(field[3] == 0xAD); + + field[0] = (guint8)((subtype >> 8) & 0xFF); + field[1] = (guint8)(subtype & 0xFF); + field[2] = field[0]; + field[3] = field[1]; + + return data; break; + } default: - g_assert(0); + g_assert_not_reached(); break; } break; case 0x06: - g_assert_not_reached(); - break; default: - g_assert_not_reached(); break; } + + g_assert_not_reached(); + *len = 0; + return NULL; } /************************** SCAN IMAGE PROCESSING *****************************/ @@ -256,10 +287,10 @@ static int img_is_finished_scan(fp_line_t *lines, int no_lines) } #endif -static int scanline_diff(const unsigned char *scanlines, int prev, int cur) +static int scanline_diff(const guint8 *scanlines, int prev, int cur) { - const unsigned char *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH; - const unsigned char *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH; + const guint8 *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH; + const guint8 *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH; int i; int diff; @@ -285,11 +316,10 @@ static int scanline_diff(const unsigned char *scanlines, int prev, int cur) } /** Transform the input data to a normalized fingerprint scan */ -void vfs301_extract_image( - vfs301_dev_t *vfs, unsigned char *output, int *output_height +void vfs301_extract_image(FpDeviceVfs301 *vfs, guint8 *output, int *output_height ) { - const unsigned char *scanlines = vfs->scanline_buf; + const guint8 *scanlines = vfs->scanline_buf; int last_line; int i; @@ -318,15 +348,13 @@ void vfs301_extract_image( } } -static int img_process_data( - int first_block, vfs301_dev_t *dev, const unsigned char *buf, int len -) +static int img_process_data(int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int len) { vfs301_line_t *lines = (vfs301_line_t*)buf; int no_lines = len / sizeof(vfs301_line_t); int i; /*int no_nonempty;*/ - unsigned char *cur_line; + guint8 *cur_line; int last_img_height; #ifdef SCAN_FINISH_DETECTION int finished_scan; @@ -340,8 +368,7 @@ static int img_process_data( dev->scanline_count += no_lines; } - dev->scanline_buf = realloc(dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH); - g_assert(dev->scanline_buf != NULL); + dev->scanline_buf = g_realloc(dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH); for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0; i < no_lines; @@ -365,27 +392,24 @@ static int img_process_data( /************************** PROTOCOL STUFF ************************************/ -static unsigned char usb_send_buf[0x2000]; - #define USB_RECV(from, len) \ - usb_recv(dev, devh, from, len) + usb_recv(dev, from, len, NULL, NULL) #define USB_SEND(type, subtype) \ { \ - int len; \ - vfs301_proto_generate(type, subtype, usb_send_buf, &len); \ - usb_send(devh, usb_send_buf, len); \ + const guint8 *data; \ + gssize len; \ + data = vfs301_proto_generate(type, subtype, &len); \ + usb_send(dev, data, len, NULL); \ } #define RAW_DATA(x) x, sizeof(x) #define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe)) -static int vfs301_proto_process_data(int first_block, vfs301_dev_t *dev) +static int vfs301_proto_process_data(FpDeviceVfs301 *dev, int first_block, const guint8 *buf, gint len) { int i; - const unsigned char *buf = dev->recv_buf; - int len = dev->recv_len; if (first_block) { g_assert(len >= VFS301_FP_FRAME_SIZE); @@ -400,80 +424,86 @@ static int vfs301_proto_process_data(int first_block, vfs301_dev_t *dev) return img_process_data(first_block, dev, buf, len); } -void vfs301_proto_request_fingerprint( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +void vfs301_proto_request_fingerprint(FpDeviceVfs301 *dev) { USB_SEND(0x0220, 0xFA00); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */ } -int vfs301_proto_peek_event( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +int vfs301_proto_peek_event(FpDeviceVfs301 *dev) { + g_autoptr(GError) error = NULL; + g_autoptr(FpiUsbTransfer) transfer = NULL; + const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; USB_SEND(0x17, -1); - g_assert(USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 7) == 0); + usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, &error); - if (memcmp(dev->recv_buf, no_event, sizeof(no_event)) == 0) { + /* XXX: This is obviously not a sane error handling! */ + g_assert (!error); + + if (memcmp(transfer->buffer, no_event, sizeof(no_event)) == 0) { return 0; - } else if (memcmp(dev->recv_buf, got_event, sizeof(no_event)) == 0) { + } else if (memcmp(transfer->buffer, got_event, sizeof(no_event)) == 0) { return 1; } else { g_assert_not_reached(); } } -#define VARIABLE_ORDER(a, b) \ +/* XXX: We sometimes need to receive data on from two endpoints at the same + * time. However, as this driver is currently all synchronous (yikes), + * we will run into timeouts randomly and need to then try again. + */ +#define PARALLEL_RECEIVE(e1, l1, e2, l2) \ { \ - int _rv = a;\ - b; \ - if (_rv == -7) \ - a; \ + g_autoptr(GError) error = NULL;\ + usb_recv(dev, e1, l1, NULL, &error); \ + usb_recv(dev, e2, l2, NULL, NULL); \ + if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \ + usb_recv(dev, e1, l1, NULL, NULL); \ } -static void vfs301_proto_process_event_cb(struct libusb_transfer *transfer) +static void vfs301_proto_process_event_cb(FpiUsbTransfer *transfer, + FpDevice *device, + gpointer user_data, GError *error) { - vfs301_dev_t *dev = transfer->user_data; - struct libusb_device_handle *devh = transfer->dev_handle; + FpDeviceVfs301 *dev = user_data; - if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { + if (error) { + g_warning ("Error receiving data: %s", error->message); + g_error_free (error); dev->recv_progress = VFS301_FAILURE; - goto end; - } else if (transfer->actual_length < dev->recv_exp_amt) { + return; + } else if (transfer->actual_length < transfer->length) { /* TODO: process the data anyway? */ dev->recv_progress = VFS301_ENDED; - goto end; + return; } else { - dev->recv_len = transfer->actual_length; - if (!vfs301_proto_process_data(dev->recv_exp_amt == VFS301_FP_RECV_LEN_1, dev)) { + FpiUsbTransfer *new; + if (!vfs301_proto_process_data(dev, + transfer->length == VFS301_FP_RECV_LEN_1, + transfer->buffer, + transfer->actual_length)) { dev->recv_progress = VFS301_ENDED; - goto end; + return; } - dev->recv_exp_amt = VFS301_FP_RECV_LEN_2; - libusb_fill_bulk_transfer( - transfer, devh, VFS301_RECEIVE_ENDPOINT_DATA, - dev->recv_buf, dev->recv_exp_amt, - vfs301_proto_process_event_cb, dev, VFS301_FP_RECV_TIMEOUT); + new = fpi_usb_transfer_new (device); - if (libusb_submit_transfer(transfer) < 0) { - printf("cb::continue fail\n"); - dev->recv_progress = VFS301_FAILURE; - goto end; - } + fpi_usb_transfer_fill_bulk(new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2); + fpi_usb_transfer_submit(new, VFS301_FP_RECV_TIMEOUT, NULL, + vfs301_proto_process_event_cb, NULL); + fpi_usb_transfer_unref (new); return; } - -end: - libusb_free_transfer(transfer); } -void vfs301_proto_process_event_start( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +void vfs301_proto_process_event_start(FpDeviceVfs301 *dev) { - struct libusb_transfer *transfer; + FpiUsbTransfer *transfer; /* * Notes: @@ -499,24 +529,16 @@ void vfs301_proto_process_event_start( USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64); /* now read the fingerprint data, while there are some */ - transfer = fpi_usb_alloc(); + transfer = fpi_usb_transfer_new(FP_DEVICE (dev)); dev->recv_progress = VFS301_ONGOING; - dev->recv_exp_amt = VFS301_FP_RECV_LEN_1; - libusb_fill_bulk_transfer( - transfer, devh, VFS301_RECEIVE_ENDPOINT_DATA, - dev->recv_buf, dev->recv_exp_amt, - vfs301_proto_process_event_cb, dev, VFS301_FP_RECV_TIMEOUT); - - if (libusb_submit_transfer(transfer) < 0) { - libusb_free_transfer(transfer); - dev->recv_progress = VFS301_FAILURE; - return; - } + fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1); + fpi_usb_transfer_submit(transfer, VFS301_FP_RECV_TIMEOUT, NULL, + vfs301_proto_process_event_cb, NULL); + fpi_usb_transfer_unref(transfer); } -int /* vfs301_dev_t::recv_progress */ vfs301_proto_process_event_poll( - struct libusb_device_handle *devh, vfs301_dev_t *dev) +int vfs301_proto_process_event_poll(FpDeviceVfs301 *dev) { if (dev->recv_progress != VFS301_ENDED) return dev->recv_progress; @@ -526,21 +548,21 @@ int /* vfs301_dev_t::recv_progress */ vfs301_proto_process_event_poll( USB_SEND(0x04, -1); /* the following may come in random order, data may not come at all, don't * try for too long... */ - VARIABLE_ORDER( - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2), /* 1204 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 16384) + PARALLEL_RECEIVE( + VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 1204 */ + VFS301_RECEIVE_ENDPOINT_DATA, 16384 ); USB_SEND(0x0220, 2); - VARIABLE_ORDER( - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760), /* seems to always come */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2) /* 0000 */ + PARALLEL_RECEIVE( + VFS301_RECEIVE_ENDPOINT_DATA, 5760, /* seems to always come */ + VFS301_RECEIVE_ENDPOINT_CTRL, 2 /* 0000 */ ); return dev->recv_progress; } -void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev) +void vfs301_proto_init(FpDeviceVfs301 *dev) { USB_SEND(0x01, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); @@ -551,14 +573,14 @@ void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev) USB_SEND(0x19, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 64); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 4); /* 6BB4D0BC */ - usb_send(devh, RAW_DATA(vfs301_06_1)); + usb_send(dev, RAW_DATA(vfs301_06_1), NULL); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_SEND(0x01, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); USB_SEND(0x1A, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_2)); + usb_send(dev, RAW_DATA(vfs301_06_2), NULL); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_SEND(0x0220, 1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ @@ -567,7 +589,7 @@ void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev) USB_SEND(0x1A, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_3)); + usb_send(dev, RAW_DATA(vfs301_06_3), NULL); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_SEND(0x01, -1); @@ -593,29 +615,29 @@ void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev) USB_SEND(0x02D0, 7); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 832); - usb_send(devh, RAW_DATA(vfs301_12)); + usb_send(dev, RAW_DATA(vfs301_12), NULL); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_SEND(0x1A, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_2)); + usb_send(dev, RAW_DATA(vfs301_06_2), NULL); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_SEND(0x0220, 2); - VARIABLE_ORDER( - USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2), /* 0000 */ - USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760) + PARALLEL_RECEIVE( + VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 0000 */ + VFS301_RECEIVE_ENDPOINT_DATA, 5760 ); USB_SEND(0x1A, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_1)); + usb_send(dev, RAW_DATA(vfs301_06_1), NULL); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_SEND(0x1A, -1); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_06_4)); + usb_send(dev, RAW_DATA(vfs301_06_4), NULL); USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ - usb_send(devh, RAW_DATA(vfs301_24)); /* turns on white */ + usb_send(dev, RAW_DATA(vfs301_24), NULL); /* turns on white */ USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_SEND(0x01, -1); @@ -626,6 +648,6 @@ void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev) USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760); } -void vfs301_proto_deinit(struct libusb_device_handle *devh, vfs301_dev_t *dev) +void vfs301_proto_deinit(FpDeviceVfs301 *dev) { } diff --git a/meson.build b/meson.build index f963fc8..afc6b81 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' ] +default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301' ] all_drivers = default_drivers + virtual_drivers