vfs301: Port driver to new API
This driver is synchronuous mostly, and the sync API is not well tested. It should work, but there has been some re-shuffling of buffers, etc.
This commit is contained in:
parent
fd64c46c74
commit
2e30572364
4 changed files with 295 additions and 284 deletions
|
@ -22,32 +22,30 @@
|
||||||
#define FP_COMPONENT "vfs301"
|
#define FP_COMPONENT "vfs301"
|
||||||
|
|
||||||
#include "drivers_api.h"
|
#include "drivers_api.h"
|
||||||
#include "vfs301_proto.h"
|
#include "vfs301.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (FpDeviceVfs301, fpi_device_vfs301, FP_TYPE_IMAGE_DEVICE)
|
||||||
|
|
||||||
/************************** GENERIC STUFF *************************************/
|
/************************** GENERIC STUFF *************************************/
|
||||||
|
|
||||||
/* Submit asynchronous sleep */
|
/* Submit asynchronous sleep */
|
||||||
static void
|
static void
|
||||||
async_sleep(unsigned int msec,
|
async_sleep(unsigned int msec,
|
||||||
fpi_ssm *ssm,
|
FpiSsm *ssm,
|
||||||
struct fp_img_dev *dev)
|
FpImageDevice *dev)
|
||||||
{
|
{
|
||||||
/* Add timeout */
|
/* Add timeout */
|
||||||
if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL) {
|
fpi_device_add_timeout(FP_DEVICE(dev), msec,
|
||||||
/* Failed to add timeout */
|
fpi_ssm_next_state_timeout_cb, ssm);
|
||||||
fp_err("failed to add timeout");
|
|
||||||
fpi_imgdev_session_error(dev, -ETIME);
|
|
||||||
fpi_ssm_mark_failed(ssm, -ETIME);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
submit_image(fpi_ssm *ssm,
|
submit_image(FpiSsm *ssm,
|
||||||
struct fp_img_dev *dev)
|
FpImageDevice *dev)
|
||||||
{
|
{
|
||||||
vfs301_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
|
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev);
|
||||||
int height;
|
int height;
|
||||||
struct fp_img *img;
|
FpImage *img;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* XXX: This is probably handled by libfprint automagically? */
|
/* XXX: This is probably handled by libfprint automagically? */
|
||||||
|
@ -57,22 +55,23 @@ submit_image(fpi_ssm *ssm,
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (img == NULL)
|
||||||
return 0;
|
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
|
/* TODO: how to detect flip? should the resulting image be
|
||||||
* oriented so that it is equal e.g. to a fingerprint on a paper,
|
* oriented so that it is equal e.g. to a fingerprint on a paper,
|
||||||
* or to the finger when I look at it?) */
|
* 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->width = VFS301_FP_OUTPUT_WIDTH;
|
||||||
img->height = height;
|
img->height = height;
|
||||||
|
|
||||||
img = fpi_img_realloc(img, img->height * img->width);
|
fpi_image_device_image_captured(dev, img);
|
||||||
fpi_imgdev_image_captured(dev, img);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -94,14 +93,14 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Exec loop sequential state machine */
|
/* 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;
|
FpImageDevice *dev = user_data;
|
||||||
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev);
|
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(_dev);
|
||||||
|
|
||||||
switch (fpi_ssm_get_cur_state(ssm)) {
|
switch (fpi_ssm_get_cur_state(ssm)) {
|
||||||
case M_REQUEST_PRINT:
|
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);
|
fpi_ssm_next_state(ssm);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -111,15 +110,15 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_CHECK_PRINT:
|
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);
|
fpi_ssm_jump_to_state(ssm, M_WAIT_PRINT);
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_READ_PRINT_START:
|
case M_READ_PRINT_START:
|
||||||
fpi_imgdev_report_finger_status(dev, TRUE);
|
fpi_image_device_report_finger_status(dev, TRUE);
|
||||||
vfs301_proto_process_event_start(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
|
vfs301_proto_process_event_start(self);
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
break;
|
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:
|
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);
|
g_assert(rv != VFS301_FAILURE);
|
||||||
if (rv == VFS301_ONGOING)
|
if (rv == VFS301_ONGOING)
|
||||||
fpi_ssm_jump_to_state(ssm, M_READ_PRINT_WAIT);
|
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)) {
|
if (submit_image(ssm, dev)) {
|
||||||
fpi_ssm_mark_completed(ssm);
|
fpi_ssm_mark_completed(ssm);
|
||||||
/* NOTE: finger off is expected only after submitting image... */
|
/* 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 {
|
} else {
|
||||||
fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT);
|
fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete loop sequential state machine */
|
/* 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 */
|
/* Free sequential state machine */
|
||||||
fpi_ssm_free(ssm);
|
fpi_ssm_free(ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exec init sequential state machine */
|
/* 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;
|
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(_dev);
|
||||||
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev);
|
|
||||||
|
|
||||||
g_assert(fpi_ssm_get_cur_state(ssm) == 0);
|
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);
|
fpi_ssm_mark_completed(ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete init sequential state machine */
|
/* 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;
|
FpiSsm *ssm_loop;
|
||||||
fpi_ssm *ssm_loop;
|
|
||||||
|
|
||||||
if (!fpi_ssm_get_error(ssm)) {
|
fpi_image_device_activate_complete(FP_IMAGE_DEVICE (dev), error);
|
||||||
|
if (!error) {
|
||||||
/* Notify activate complete */
|
/* Notify activate complete */
|
||||||
fpi_imgdev_activate_complete(dev, 0);
|
|
||||||
|
|
||||||
/* Start loop ssm */
|
/* 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);
|
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 */
|
/* 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 */
|
/* 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);
|
fpi_ssm_start(ssm, m_init_complete);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deactivate device */
|
/* 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));
|
self = FPI_DEVICE_VFS301(dev);
|
||||||
vfs301_proto_deinit(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
|
vfs301_proto_deinit(self);
|
||||||
fpi_imgdev_deactivate_complete(dev);
|
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;
|
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev);
|
||||||
int r;
|
GError *error = NULL;
|
||||||
|
|
||||||
/* Claim usb interface */
|
/* Claim usb interface */
|
||||||
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
|
g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error);
|
||||||
if (r < 0) {
|
|
||||||
/* Interface not claimed, return error */
|
|
||||||
fp_err("could not claim interface 0: %s", libusb_error_name(r));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize private structure */
|
/* Initialize private structure */
|
||||||
vdev = g_malloc0(sizeof(vfs301_dev_t));
|
self->scanline_count = 0;
|
||||||
fp_dev_set_instance_data(FP_DEV(dev), vdev);
|
|
||||||
|
|
||||||
vdev->scanline_buf = malloc(0);
|
|
||||||
vdev->scanline_count = 0;
|
|
||||||
|
|
||||||
/* Notify open complete */
|
/* Notify open complete */
|
||||||
fpi_imgdev_open_complete(dev, 0);
|
fpi_image_device_open_complete(dev, error);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 */
|
/* Release private structure */
|
||||||
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
|
g_clear_pointer (&self->scanline_buf, g_free);
|
||||||
free(vdev->scanline_buf);
|
|
||||||
g_free(vdev);
|
|
||||||
|
|
||||||
/* Release usb interface */
|
/* 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 */
|
/* Notify close complete */
|
||||||
fpi_imgdev_close_complete(dev);
|
fpi_image_device_close_complete(dev, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Usb id table of device */
|
/* Usb id table of device */
|
||||||
static const struct usb_id id_table[] =
|
static const FpIdEntry id_table [ ] = {
|
||||||
{
|
{ /* vfs301 */ .vid = 0x138a, .pid = 0x0005, },
|
||||||
{ .vendor = 0x138a, .product = 0x0005 /* vfs301 */ },
|
{ /* vfs300 */ .vid = 0x138a, .pid = 0x0008, },
|
||||||
{ .vendor = 0x138a, .product = 0x0008 /* vfs300 */ },
|
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||||
{ 0, 0, 0, },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Device driver definition */
|
static void fpi_device_vfs301_init(FpDeviceVfs301 *self) {
|
||||||
struct fp_img_driver vfs301_driver =
|
}
|
||||||
{
|
static void fpi_device_vfs301_class_init(FpDeviceVfs301Class *klass) {
|
||||||
/* Driver specification */
|
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
|
||||||
.driver =
|
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
|
||||||
{
|
|
||||||
.id = VFS301_ID,
|
|
||||||
.name = FP_COMPONENT,
|
|
||||||
.full_name = "Validity VFS301",
|
|
||||||
.id_table = id_table,
|
|
||||||
.scan_type = FP_SCAN_TYPE_SWIPE,
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Image specification */
|
dev_class->id = "vfs301";
|
||||||
.flags = 0,
|
dev_class->full_name = "Validity VFS301";
|
||||||
.img_width = VFS301_FP_WIDTH,
|
dev_class->type = FP_DEVICE_TYPE_USB;
|
||||||
.img_height = -1,
|
dev_class->id_table = id_table;
|
||||||
.bz3_threshold = 24,
|
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
|
||||||
|
|
||||||
/* Routine specification */
|
img_class->img_open = dev_open;
|
||||||
.open = dev_open,
|
img_class->img_close = dev_close;
|
||||||
.close = dev_close,
|
img_class->activate = dev_activate;
|
||||||
.activate = dev_activate,
|
img_class->deactivate = dev_deactivate;
|
||||||
.deactivate = dev_deactivate,
|
|
||||||
};
|
img_class->bz3_threshold = 24;
|
||||||
|
|
||||||
|
img_class->img_width = VFS301_FP_WIDTH;
|
||||||
|
img_class->img_height = -1;
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,11 @@
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
#include <libusb-1.0/libusb.h>
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fpi-usb-transfer.h"
|
||||||
|
#include "fpi-image-device.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VFS301_DEFAULT_WAIT_TIMEOUT = 300,
|
VFS301_DEFAULT_WAIT_TIMEOUT = 300,
|
||||||
|
@ -31,10 +35,8 @@ enum {
|
||||||
#define VFS301_FP_RECV_LEN_1 (84032)
|
#define VFS301_FP_RECV_LEN_1 (84032)
|
||||||
#define VFS301_FP_RECV_LEN_2 (84096)
|
#define VFS301_FP_RECV_LEN_2 (84096)
|
||||||
|
|
||||||
typedef struct {
|
struct _FpDeviceVfs301 {
|
||||||
/* buffer for received data */
|
FpImageDevice parent;
|
||||||
unsigned char recv_buf[0x20000];
|
|
||||||
int recv_len;
|
|
||||||
|
|
||||||
/* buffer to hold raw scanlines */
|
/* buffer to hold raw scanlines */
|
||||||
unsigned char *scanline_buf;
|
unsigned char *scanline_buf;
|
||||||
|
@ -46,7 +48,9 @@ typedef struct {
|
||||||
VFS301_FAILURE = -1
|
VFS301_FAILURE = -1
|
||||||
} recv_progress;
|
} recv_progress;
|
||||||
int recv_exp_amt;
|
int recv_exp_amt;
|
||||||
} vfs301_dev_t;
|
};
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpDeviceVfs301, fpi_device_vfs301, FPI, DEVICE_VFS301, FpImageDevice)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* Width of the scanned data in px */
|
/* Width of the scanned data in px */
|
||||||
|
@ -120,18 +124,14 @@ typedef struct {
|
||||||
unsigned char sum3[3];
|
unsigned char sum3[3];
|
||||||
} vfs301_line_t;
|
} vfs301_line_t;
|
||||||
|
|
||||||
void vfs301_proto_init(struct libusb_device_handle *devh, vfs301_dev_t *dev);
|
void vfs301_proto_init(FpDeviceVfs301 *dev);
|
||||||
void vfs301_proto_deinit(struct libusb_device_handle *devh, vfs301_dev_t *dev);
|
void vfs301_proto_deinit(FpDeviceVfs301 *dev);
|
||||||
|
|
||||||
void vfs301_proto_request_fingerprint(
|
void vfs301_proto_request_fingerprint(FpDeviceVfs301 *dev);
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *dev);
|
|
||||||
|
|
||||||
/** returns 0 if no event is ready, or 1 if there is one... */
|
/** returns 0 if no event is ready, or 1 if there is one... */
|
||||||
int vfs301_proto_peek_event(
|
int vfs301_proto_peek_event(FpDeviceVfs301 *dev);
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *dev);
|
void vfs301_proto_process_event_start(FpDeviceVfs301 *dev);
|
||||||
void vfs301_proto_process_event_start(
|
int vfs301_proto_process_event_poll(FpDeviceVfs301 *dev);
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *dev);
|
|
||||||
int vfs301_proto_process_event_poll(
|
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *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);
|
|
@ -34,16 +34,16 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include "fpi-usb.h"
|
#include "fpi-usb-transfer.h"
|
||||||
#include "vfs301_proto.h"
|
#include "vfs301.h"
|
||||||
#include "vfs301_proto_fragments.h"
|
#include "vfs301_proto_fragments.h"
|
||||||
|
|
||||||
/************************** USB STUFF *****************************************/
|
/************************** USB STUFF *****************************************/
|
||||||
|
|
||||||
#ifdef DEBUG
|
#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
|
#ifdef PRINT_VERBOSE
|
||||||
int i;
|
int i;
|
||||||
|
@ -61,60 +61,69 @@ static void usb_print_packet(int dir, int rv, const unsigned char *data, int len
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int usb_recv(
|
static void usb_recv(FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error)
|
||||||
vfs301_dev_t *dev,
|
|
||||||
struct libusb_device_handle *devh, unsigned char endpoint, int max_bytes)
|
|
||||||
{
|
{
|
||||||
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
|
#ifdef DEBUG
|
||||||
usb_print_packet(0, r, dev->recv_buf, dev->recv_len);
|
usb_print_packet(0, err, transfer->buffer, transfer->actual_length);
|
||||||
#endif
|
#endif
|
||||||
|
if (err) {
|
||||||
|
if (!error)
|
||||||
|
g_warning("Unhandled receive error: %s", err->message);
|
||||||
|
g_propagate_error (error, err);
|
||||||
|
}
|
||||||
|
|
||||||
if (r < 0)
|
if (out)
|
||||||
return r;
|
*out = g_steal_pointer (&transfer);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_send(
|
static void usb_send(FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error)
|
||||||
struct libusb_device_handle *devh, const unsigned char *data, int length)
|
|
||||||
{
|
{
|
||||||
int transferred = 0;
|
GError *err = NULL;
|
||||||
|
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||||
|
|
||||||
int r = libusb_bulk_transfer(
|
/* XXX: This function swallows any transfer errors, that is obviously
|
||||||
devh, VFS301_SEND_ENDPOINT,
|
* quite bad (it used to assert on no-error)! */
|
||||||
(unsigned char *)data, length, &transferred, VFS301_DEFAULT_WAIT_TIMEOUT
|
|
||||||
);
|
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
|
#ifdef DEBUG
|
||||||
usb_print_packet(1, r, data, length);
|
usb_print_packet(1, err, data, length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_assert(r == 0);
|
if (err) {
|
||||||
|
g_warning ("Error while sending data, continuing anyway: %s", err->message);
|
||||||
if (r < 0)
|
g_propagate_error (error, err);
|
||||||
return r;
|
}
|
||||||
if (transferred < length)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************** OUT MESSAGES GENERATION ***************************/
|
/************************** 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;
|
*data = 0x0B;
|
||||||
*len = 1;
|
*len = 1;
|
||||||
data++;
|
data++;
|
||||||
|
|
||||||
memset(data, 0, 39);
|
|
||||||
*len += 38;
|
*len += 38;
|
||||||
|
|
||||||
data[20] = subtype;
|
data[20] = subtype;
|
||||||
|
@ -125,40 +134,50 @@ static void vfs301_proto_generate_0B(int subtype, unsigned char *data, int *len)
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
data[34] = 0xAB;
|
data[34] = 0xAB;
|
||||||
len++;
|
/* NOTE: There was a len++ here, which could never do anything */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HEX_TO_INT(c) \
|
#define HEX_TO_INT(c) \
|
||||||
(((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10))
|
(((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;
|
const char *src;
|
||||||
unsigned char *dataOrig = data;
|
gssize src_len = 0;
|
||||||
|
|
||||||
while (*srcL != NULL) {
|
for (src_pos = srcL; *src_pos; src_pos++) {
|
||||||
src = *srcL;
|
gint tmp;
|
||||||
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))));
|
|
||||||
|
|
||||||
data++;
|
src = *src_pos;
|
||||||
src += 2;
|
tmp = strlen(src);
|
||||||
}
|
g_assert (tmp % 2 == 0);
|
||||||
|
src_len += tmp;
|
||||||
srcL++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*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) {
|
switch (type) {
|
||||||
case 0x01:
|
case 0x01:
|
||||||
|
@ -173,11 +192,15 @@ static void vfs301_proto_generate(int type, int subtype, unsigned char *data, in
|
||||||
case 0x17:
|
case 0x17:
|
||||||
case 0x19:
|
case 0x19:
|
||||||
case 0x1A:
|
case 0x1A:
|
||||||
*data = type;
|
{
|
||||||
*len = 1;
|
guint8 *data = g_malloc0 (1);
|
||||||
|
*data = type;
|
||||||
|
*len = 1;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0B:
|
case 0x0B:
|
||||||
vfs301_proto_generate_0B(subtype, data, len);
|
return vfs301_proto_generate_0B(subtype, len);
|
||||||
break;
|
break;
|
||||||
case 0x02D0:
|
case 0x02D0:
|
||||||
{
|
{
|
||||||
|
@ -190,49 +213,57 @@ static void vfs301_proto_generate(int type, int subtype, unsigned char *data, in
|
||||||
vfs301_02D0_06,
|
vfs301_02D0_06,
|
||||||
vfs301_02D0_07,
|
vfs301_02D0_07,
|
||||||
};
|
};
|
||||||
g_assert((int)subtype <= (int)(sizeof(dataLs) / sizeof(dataLs[0])));
|
g_assert((int)subtype <= G_N_ELEMENTS (dataLs));
|
||||||
translate_str(dataLs[subtype - 1], data, len);
|
return translate_str(dataLs[subtype - 1], len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0220:
|
case 0x0220:
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case 1:
|
case 1:
|
||||||
translate_str(vfs301_0220_01, data, len);
|
return translate_str(vfs301_0220_01, len);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
translate_str(vfs301_0220_02, data, len);
|
return translate_str(vfs301_0220_02, len);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
translate_str(vfs301_0220_03, data, len);
|
return translate_str(vfs301_0220_03, len);
|
||||||
break;
|
break;
|
||||||
case 0xFA00:
|
case 0xFA00:
|
||||||
case 0x2C01:
|
case 0x2C01:
|
||||||
case 0x5E01:
|
case 0x5E01: {
|
||||||
translate_str(vfs301_next_scan_template, data, len);
|
guint8 *data;
|
||||||
unsigned char *field = data + *len - (sizeof(S4_TAIL) - 1) / 2 - 4;
|
guint8 *field;
|
||||||
|
|
||||||
g_assert(*field == 0xDE);
|
data = translate_str(vfs301_next_scan_template, len);
|
||||||
g_assert(*(field + 1) == 0xAD);
|
field = data + *len - (sizeof(S4_TAIL) - 1) / 2 - 4;
|
||||||
g_assert(*(field + 2) == 0xDE);
|
|
||||||
g_assert(*(field + 3) == 0xAD);
|
|
||||||
|
|
||||||
*field = (unsigned char)((subtype >> 8) & 0xFF);
|
g_assert (field >= data && field < data + *len);
|
||||||
*(field + 1) = (unsigned char)(subtype & 0xFF);
|
g_assert(field[0] == 0xDE);
|
||||||
*(field + 2) = *field;
|
g_assert(field[1] == 0xAD);
|
||||||
*(field + 3) = *(field + 1);
|
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;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
g_assert(0);
|
g_assert_not_reached();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
g_assert_not_reached();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_assert_not_reached();
|
||||||
|
*len = 0;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************** SCAN IMAGE PROCESSING *****************************/
|
/************************** SCAN IMAGE PROCESSING *****************************/
|
||||||
|
@ -256,10 +287,10 @@ static int img_is_finished_scan(fp_line_t *lines, int no_lines)
|
||||||
}
|
}
|
||||||
#endif
|
#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 guint8 *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH;
|
||||||
const unsigned char *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH;
|
const guint8 *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH;
|
||||||
int i;
|
int i;
|
||||||
int diff;
|
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 */
|
/** Transform the input data to a normalized fingerprint scan */
|
||||||
void vfs301_extract_image(
|
void vfs301_extract_image(FpDeviceVfs301 *vfs, guint8 *output, int *output_height
|
||||||
vfs301_dev_t *vfs, unsigned char *output, int *output_height
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const unsigned char *scanlines = vfs->scanline_buf;
|
const guint8 *scanlines = vfs->scanline_buf;
|
||||||
int last_line;
|
int last_line;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -318,15 +348,13 @@ void vfs301_extract_image(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int img_process_data(
|
static int img_process_data(int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int len)
|
||||||
int first_block, vfs301_dev_t *dev, const unsigned char *buf, int len
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
vfs301_line_t *lines = (vfs301_line_t*)buf;
|
vfs301_line_t *lines = (vfs301_line_t*)buf;
|
||||||
int no_lines = len / sizeof(vfs301_line_t);
|
int no_lines = len / sizeof(vfs301_line_t);
|
||||||
int i;
|
int i;
|
||||||
/*int no_nonempty;*/
|
/*int no_nonempty;*/
|
||||||
unsigned char *cur_line;
|
guint8 *cur_line;
|
||||||
int last_img_height;
|
int last_img_height;
|
||||||
#ifdef SCAN_FINISH_DETECTION
|
#ifdef SCAN_FINISH_DETECTION
|
||||||
int finished_scan;
|
int finished_scan;
|
||||||
|
@ -340,8 +368,7 @@ static int img_process_data(
|
||||||
dev->scanline_count += no_lines;
|
dev->scanline_count += no_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->scanline_buf = realloc(dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH);
|
dev->scanline_buf = g_realloc(dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH);
|
||||||
g_assert(dev->scanline_buf != NULL);
|
|
||||||
|
|
||||||
for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0;
|
for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0;
|
||||||
i < no_lines;
|
i < no_lines;
|
||||||
|
@ -365,27 +392,24 @@ static int img_process_data(
|
||||||
|
|
||||||
/************************** PROTOCOL STUFF ************************************/
|
/************************** PROTOCOL STUFF ************************************/
|
||||||
|
|
||||||
static unsigned char usb_send_buf[0x2000];
|
|
||||||
|
|
||||||
#define USB_RECV(from, len) \
|
#define USB_RECV(from, len) \
|
||||||
usb_recv(dev, devh, from, len)
|
usb_recv(dev, from, len, NULL, NULL)
|
||||||
|
|
||||||
#define USB_SEND(type, subtype) \
|
#define USB_SEND(type, subtype) \
|
||||||
{ \
|
{ \
|
||||||
int len; \
|
const guint8 *data; \
|
||||||
vfs301_proto_generate(type, subtype, usb_send_buf, &len); \
|
gssize len; \
|
||||||
usb_send(devh, usb_send_buf, len); \
|
data = vfs301_proto_generate(type, subtype, &len); \
|
||||||
|
usb_send(dev, data, len, NULL); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RAW_DATA(x) x, sizeof(x)
|
#define RAW_DATA(x) x, sizeof(x)
|
||||||
|
|
||||||
#define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe))
|
#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;
|
int i;
|
||||||
const unsigned char *buf = dev->recv_buf;
|
|
||||||
int len = dev->recv_len;
|
|
||||||
|
|
||||||
if (first_block) {
|
if (first_block) {
|
||||||
g_assert(len >= VFS301_FP_FRAME_SIZE);
|
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);
|
return img_process_data(first_block, dev, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vfs301_proto_request_fingerprint(
|
void vfs301_proto_request_fingerprint(FpDeviceVfs301 *dev)
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *dev)
|
|
||||||
{
|
{
|
||||||
USB_SEND(0x0220, 0xFA00);
|
USB_SEND(0x0220, 0xFA00);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */
|
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */
|
||||||
}
|
}
|
||||||
|
|
||||||
int vfs301_proto_peek_event(
|
int vfs301_proto_peek_event(FpDeviceVfs301 *dev)
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *dev)
|
|
||||||
{
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||||
|
|
||||||
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
|
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
USB_SEND(0x17, -1);
|
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;
|
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;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
g_assert_not_reached();
|
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;\
|
g_autoptr(GError) error = NULL;\
|
||||||
b; \
|
usb_recv(dev, e1, l1, NULL, &error); \
|
||||||
if (_rv == -7) \
|
usb_recv(dev, e2, l2, NULL, NULL); \
|
||||||
a; \
|
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;
|
FpDeviceVfs301 *dev = user_data;
|
||||||
struct libusb_device_handle *devh = transfer->dev_handle;
|
|
||||||
|
|
||||||
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;
|
dev->recv_progress = VFS301_FAILURE;
|
||||||
goto end;
|
return;
|
||||||
} else if (transfer->actual_length < dev->recv_exp_amt) {
|
} else if (transfer->actual_length < transfer->length) {
|
||||||
/* TODO: process the data anyway? */
|
/* TODO: process the data anyway? */
|
||||||
dev->recv_progress = VFS301_ENDED;
|
dev->recv_progress = VFS301_ENDED;
|
||||||
goto end;
|
return;
|
||||||
} else {
|
} else {
|
||||||
dev->recv_len = transfer->actual_length;
|
FpiUsbTransfer *new;
|
||||||
if (!vfs301_proto_process_data(dev->recv_exp_amt == VFS301_FP_RECV_LEN_1, dev)) {
|
if (!vfs301_proto_process_data(dev,
|
||||||
|
transfer->length == VFS301_FP_RECV_LEN_1,
|
||||||
|
transfer->buffer,
|
||||||
|
transfer->actual_length)) {
|
||||||
dev->recv_progress = VFS301_ENDED;
|
dev->recv_progress = VFS301_ENDED;
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->recv_exp_amt = VFS301_FP_RECV_LEN_2;
|
new = fpi_usb_transfer_new (device);
|
||||||
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) {
|
fpi_usb_transfer_fill_bulk(new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2);
|
||||||
printf("cb::continue fail\n");
|
fpi_usb_transfer_submit(new, VFS301_FP_RECV_TIMEOUT, NULL,
|
||||||
dev->recv_progress = VFS301_FAILURE;
|
vfs301_proto_process_event_cb, NULL);
|
||||||
goto end;
|
fpi_usb_transfer_unref (new);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
libusb_free_transfer(transfer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vfs301_proto_process_event_start(
|
void vfs301_proto_process_event_start(FpDeviceVfs301 *dev)
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *dev)
|
|
||||||
{
|
{
|
||||||
struct libusb_transfer *transfer;
|
FpiUsbTransfer *transfer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notes:
|
* Notes:
|
||||||
|
@ -499,24 +529,16 @@ void vfs301_proto_process_event_start(
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64);
|
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64);
|
||||||
|
|
||||||
/* now read the fingerprint data, while there are some */
|
/* 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_progress = VFS301_ONGOING;
|
||||||
dev->recv_exp_amt = VFS301_FP_RECV_LEN_1;
|
|
||||||
|
|
||||||
libusb_fill_bulk_transfer(
|
fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1);
|
||||||
transfer, devh, VFS301_RECEIVE_ENDPOINT_DATA,
|
fpi_usb_transfer_submit(transfer, VFS301_FP_RECV_TIMEOUT, NULL,
|
||||||
dev->recv_buf, dev->recv_exp_amt,
|
vfs301_proto_process_event_cb, NULL);
|
||||||
vfs301_proto_process_event_cb, dev, VFS301_FP_RECV_TIMEOUT);
|
fpi_usb_transfer_unref(transfer);
|
||||||
|
|
||||||
if (libusb_submit_transfer(transfer) < 0) {
|
|
||||||
libusb_free_transfer(transfer);
|
|
||||||
dev->recv_progress = VFS301_FAILURE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int /* vfs301_dev_t::recv_progress */ vfs301_proto_process_event_poll(
|
int vfs301_proto_process_event_poll(FpDeviceVfs301 *dev)
|
||||||
struct libusb_device_handle *devh, vfs301_dev_t *dev)
|
|
||||||
{
|
{
|
||||||
if (dev->recv_progress != VFS301_ENDED)
|
if (dev->recv_progress != VFS301_ENDED)
|
||||||
return dev->recv_progress;
|
return dev->recv_progress;
|
||||||
|
@ -526,21 +548,21 @@ int /* vfs301_dev_t::recv_progress */ vfs301_proto_process_event_poll(
|
||||||
USB_SEND(0x04, -1);
|
USB_SEND(0x04, -1);
|
||||||
/* the following may come in random order, data may not come at all, don't
|
/* the following may come in random order, data may not come at all, don't
|
||||||
* try for too long... */
|
* try for too long... */
|
||||||
VARIABLE_ORDER(
|
PARALLEL_RECEIVE(
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2), /* 1204 */
|
VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 1204 */
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 16384)
|
VFS301_RECEIVE_ENDPOINT_DATA, 16384
|
||||||
);
|
);
|
||||||
|
|
||||||
USB_SEND(0x0220, 2);
|
USB_SEND(0x0220, 2);
|
||||||
VARIABLE_ORDER(
|
PARALLEL_RECEIVE(
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760), /* seems to always come */
|
VFS301_RECEIVE_ENDPOINT_DATA, 5760, /* seems to always come */
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2) /* 0000 */
|
VFS301_RECEIVE_ENDPOINT_CTRL, 2 /* 0000 */
|
||||||
);
|
);
|
||||||
|
|
||||||
return dev->recv_progress;
|
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_SEND(0x01, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38);
|
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_SEND(0x19, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 64);
|
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 64);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 4); /* 6BB4D0BC */
|
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_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
|
|
||||||
USB_SEND(0x01, -1);
|
USB_SEND(0x01, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38);
|
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38);
|
||||||
USB_SEND(0x1A, -1);
|
USB_SEND(0x1A, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
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_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
USB_SEND(0x0220, 1);
|
USB_SEND(0x0220, 1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
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_SEND(0x1A, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
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_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
|
|
||||||
USB_SEND(0x01, -1);
|
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_SEND(0x02D0, 7);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 832);
|
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_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
|
|
||||||
USB_SEND(0x1A, -1);
|
USB_SEND(0x1A, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
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_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
USB_SEND(0x0220, 2);
|
USB_SEND(0x0220, 2);
|
||||||
VARIABLE_ORDER(
|
PARALLEL_RECEIVE(
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2), /* 0000 */
|
VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 0000 */
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760)
|
VFS301_RECEIVE_ENDPOINT_DATA, 5760
|
||||||
);
|
);
|
||||||
|
|
||||||
USB_SEND(0x1A, -1);
|
USB_SEND(0x1A, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
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_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
|
|
||||||
USB_SEND(0x1A, -1);
|
USB_SEND(0x1A, -1);
|
||||||
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
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_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_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
|
||||||
|
|
||||||
USB_SEND(0x01, -1);
|
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);
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -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', '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
|
all_drivers = default_drivers + virtual_drivers
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue