Update for libusb API rework
This commit is contained in:
parent
81a5d6d966
commit
4e884807a7
9 changed files with 601 additions and 489 deletions
|
@ -46,22 +46,19 @@ static void continue_write_regv(struct write_regv_data *wdata);
|
||||||
|
|
||||||
/* libusb bulk callback for regv write completion transfer. continues the
|
/* libusb bulk callback for regv write completion transfer. continues the
|
||||||
* transaction */
|
* transaction */
|
||||||
static void write_regv_trf_complete(libusb_dev_handle *devh,
|
static void write_regv_trf_complete(struct libusb_transfer *transfer)
|
||||||
libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
|
||||||
unsigned char endpoint, int rqlength, unsigned char *data,
|
|
||||||
int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct write_regv_data *wdata = user_data;
|
struct write_regv_data *wdata = transfer->user_data;
|
||||||
|
|
||||||
g_free(data);
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
libusb_urb_handle_free(urbh);
|
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED)
|
|
||||||
wdata->callback(wdata->imgdev, -EIO, wdata->user_data);
|
wdata->callback(wdata->imgdev, -EIO, wdata->user_data);
|
||||||
else if (rqlength != actual_length)
|
else if (transfer->length != transfer->actual_length)
|
||||||
wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data);
|
wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data);
|
||||||
else
|
else
|
||||||
continue_write_regv(wdata);
|
continue_write_regv(wdata);
|
||||||
|
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write from wdata->offset to upper_bound (inclusive) of wdata->regs */
|
/* write from wdata->offset to upper_bound (inclusive) of wdata->regs */
|
||||||
|
@ -73,12 +70,13 @@ static int do_write_regv(struct write_regv_data *wdata, int upper_bound)
|
||||||
unsigned char *data = g_malloc(alloc_size);
|
unsigned char *data = g_malloc(alloc_size);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
size_t data_offset = 0;
|
size_t data_offset = 0;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
struct libusb_bulk_transfer msg = {
|
int r;
|
||||||
.endpoint = EP_OUT,
|
|
||||||
.data = data,
|
if (!transfer) {
|
||||||
.length = alloc_size,
|
g_free(data);
|
||||||
};
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = offset; i < offset + num; i++) {
|
for (i = offset; i < offset + num; i++) {
|
||||||
const struct aes_regwrite *regwrite = &wdata->regs[i];
|
const struct aes_regwrite *regwrite = &wdata->regs[i];
|
||||||
|
@ -86,14 +84,15 @@ static int do_write_regv(struct write_regv_data *wdata, int upper_bound)
|
||||||
data[data_offset++] = regwrite->value;
|
data[data_offset++] = regwrite->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
urbh = libusb_async_bulk_transfer(wdata->imgdev->udev, &msg,
|
libusb_fill_bulk_transfer(transfer, wdata->imgdev->udev, EP_OUT, data,
|
||||||
write_regv_trf_complete, wdata, BULK_TIMEOUT);
|
alloc_size, write_regv_trf_complete, wdata, BULK_TIMEOUT);
|
||||||
if (!urbh) {
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
g_free(data);
|
g_free(data);
|
||||||
return -EIO;
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write the next batch of registers to be written, or if there are no more,
|
/* write the next batch of registers to be written, or if there are no more,
|
||||||
|
|
|
@ -41,7 +41,7 @@ API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb cb,
|
||||||
{
|
{
|
||||||
struct fp_driver *drv = ddev->drv;
|
struct fp_driver *drv = ddev->drv;
|
||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
libusb_dev_handle *udevh;
|
libusb_device_handle *udevh;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
fp_dbg("");
|
fp_dbg("");
|
||||||
|
|
|
@ -352,11 +352,11 @@ static void register_drivers(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fp_driver *find_supporting_driver(libusb_dev *udev,
|
static struct fp_driver *find_supporting_driver(libusb_device *udev,
|
||||||
const struct usb_id **usb_id)
|
const struct usb_id **usb_id)
|
||||||
{
|
{
|
||||||
GSList *elem = registered_drivers;
|
GSList *elem = registered_drivers;
|
||||||
struct libusb_dev_descriptor *dsc = libusb_dev_get_descriptor(udev);
|
struct libusb_device_descriptor *dsc = libusb_get_device_descriptor(udev);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct fp_driver *drv = elem->data;
|
struct fp_driver *drv = elem->data;
|
||||||
|
@ -373,7 +373,7 @@ static struct fp_driver *find_supporting_driver(libusb_dev *udev,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fp_dscv_dev *discover_dev(libusb_dev *udev)
|
static struct fp_dscv_dev *discover_dev(libusb_device *udev)
|
||||||
{
|
{
|
||||||
const struct usb_id *usb_id;
|
const struct usb_id *usb_id;
|
||||||
struct fp_driver *drv = find_supporting_driver(udev, &usb_id);
|
struct fp_driver *drv = find_supporting_driver(udev, &usb_id);
|
||||||
|
@ -409,33 +409,40 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
||||||
{
|
{
|
||||||
GSList *tmplist = NULL;
|
GSList *tmplist = NULL;
|
||||||
struct fp_dscv_dev **list;
|
struct fp_dscv_dev **list;
|
||||||
struct libusb_dev *udev;
|
libusb_device *udev;
|
||||||
|
libusb_device **devs;
|
||||||
int dscv_count = 0;
|
int dscv_count = 0;
|
||||||
|
int r;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
if (registered_drivers == NULL)
|
if (registered_drivers == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
libusb_find_devices();
|
r = libusb_get_device_list(&devs);
|
||||||
|
if (r < 0) {
|
||||||
|
fp_err("couldn't enumerate USB devices, error %d", r);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check each device against each driver, temporarily storing successfully
|
/* Check each device against each driver, temporarily storing successfully
|
||||||
* discovered devices in a GSList.
|
* discovered devices in a GSList.
|
||||||
*
|
*
|
||||||
* Quite inefficient but excusable as we'll only be dealing with small
|
* Quite inefficient but excusable as we'll only be dealing with small
|
||||||
* sets of drivers against small sets of USB devices */
|
* sets of drivers against small sets of USB devices */
|
||||||
for (udev = libusb_get_devices(); udev; udev = libusb_dev_next(udev)) {
|
while ((udev = devs[i++]) != NULL) {
|
||||||
struct fp_dscv_dev *ddev = discover_dev(udev);
|
struct fp_dscv_dev *ddev = discover_dev(udev);
|
||||||
if (!ddev)
|
if (!ddev)
|
||||||
continue;
|
continue;
|
||||||
tmplist = g_slist_prepend(tmplist, (gpointer) ddev);
|
tmplist = g_slist_prepend(tmplist, (gpointer) ddev);
|
||||||
dscv_count++;
|
dscv_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert our temporary GSList into a standard NULL-terminated pointer
|
/* Convert our temporary GSList into a standard NULL-terminated pointer
|
||||||
* array. */
|
* array. */
|
||||||
list = g_malloc(sizeof(*list) * (dscv_count + 1));
|
list = g_malloc(sizeof(*list) * (dscv_count + 1));
|
||||||
if (dscv_count > 0) {
|
if (dscv_count > 0) {
|
||||||
GSList *elem = tmplist;
|
GSList *elem = tmplist;
|
||||||
int i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
list[i++] = elem->data;
|
list[i++] = elem->data;
|
||||||
} while ((elem = g_slist_next(elem)));
|
} while ((elem = g_slist_next(elem)));
|
||||||
|
|
|
@ -79,48 +79,53 @@ struct aes2501_read_regs {
|
||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void read_regs_data_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void read_regs_data_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct aes2501_read_regs *rdata = user_data;
|
struct aes2501_read_regs *rdata = transfer->user_data;
|
||||||
unsigned char *retdata = NULL;
|
unsigned char *retdata = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
} else if (rqlength != actual_length) {
|
} else if (transfer->length != transfer->actual_length) {
|
||||||
r = -EPROTO;
|
r = -EPROTO;
|
||||||
} else {
|
} else {
|
||||||
r = 0;
|
r = 0;
|
||||||
retdata = data;
|
retdata = transfer->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdata->callback(rdata->dev, r, retdata, rdata->user_data);
|
rdata->callback(rdata->dev, r, retdata, rdata->user_data);
|
||||||
libusb_urb_handle_free(urbh);
|
|
||||||
g_free(data);
|
|
||||||
g_free(rdata);
|
g_free(rdata);
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
|
static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
|
||||||
{
|
{
|
||||||
struct aes2501_read_regs *rdata = user_data;
|
struct aes2501_read_regs *rdata = user_data;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
struct libusb_bulk_transfer trf = {
|
unsigned char *data;
|
||||||
.endpoint = EP_IN,
|
int r;
|
||||||
.length = 126,
|
|
||||||
};
|
|
||||||
|
|
||||||
g_free(rdata->regwrite);
|
g_free(rdata->regwrite);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
trf.data = g_malloc(trf.length);
|
transfer = libusb_alloc_transfer();
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &trf, read_regs_data_cb,
|
if (!transfer) {
|
||||||
rdata, BULK_TIMEOUT);
|
result = -ENOMEM;
|
||||||
if (!urbh) {
|
goto err;
|
||||||
g_free(trf.data);
|
}
|
||||||
result = EIO;
|
|
||||||
|
data = g_malloc(126);
|
||||||
|
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 126,
|
||||||
|
read_regs_data_cb, rdata, BULK_TIMEOUT);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
result = -EIO;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,40 +184,43 @@ static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check that read succeeded but ignore all data */
|
/* check that read succeeded but ignore all data */
|
||||||
static void generic_ignore_data_cb(libusb_dev_handle *devh,
|
static void generic_ignore_data_cb(struct libusb_transfer *transfer)
|
||||||
libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
|
||||||
unsigned char endpoint, int rqlength, unsigned char *data,
|
|
||||||
int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
g_free(data);
|
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED)
|
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
else if (rqlength != actual_length)
|
else if (transfer->length != transfer->actual_length)
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
|
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read the specified number of bytes from the IN endpoint but throw them
|
/* read the specified number of bytes from the IN endpoint but throw them
|
||||||
* away, then increment the SSM */
|
* away, then increment the SSM */
|
||||||
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
|
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
struct libusb_bulk_transfer trf = {
|
unsigned char *data;
|
||||||
.endpoint = EP_IN,
|
int r;
|
||||||
.data = g_malloc(bytes),
|
|
||||||
.length = bytes,
|
|
||||||
};
|
|
||||||
|
|
||||||
urbh = libusb_async_bulk_transfer(ssm->dev->udev, &trf,
|
if (!transfer) {
|
||||||
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = g_malloc(bytes);
|
||||||
|
libusb_fill_bulk_transfer(transfer, ssm->dev->udev, EP_IN, data, bytes,
|
||||||
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
|
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
|
||||||
if (!urbh) {
|
|
||||||
g_free(trf.data);
|
r = libusb_submit_transfer(transfer);
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,19 +390,17 @@ static const struct aes_regwrite finger_det_reqs[] = {
|
||||||
|
|
||||||
static void start_finger_detection(struct fp_img_dev *dev);
|
static void start_finger_detection(struct fp_img_dev *dev);
|
||||||
|
|
||||||
static void finger_det_data_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void finger_det_data_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = user_data;
|
struct fp_img_dev *dev = transfer->user_data;
|
||||||
|
unsigned char *data = transfer->buffer;
|
||||||
int i;
|
int i;
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
if (status != FP_URB_COMPLETED) {
|
|
||||||
fpi_imgdev_session_error(dev, -EIO);
|
fpi_imgdev_session_error(dev, -EIO);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (rqlength != actual_length) {
|
} else if (transfer->length != transfer->actual_length) {
|
||||||
fpi_imgdev_session_error(dev, -EPROTO);
|
fpi_imgdev_session_error(dev, -EPROTO);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -413,28 +419,36 @@ static void finger_det_data_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
|
static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
struct libusb_bulk_transfer trf = {
|
unsigned char *data;
|
||||||
.endpoint = EP_IN,
|
int r;
|
||||||
.length = 20,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
fpi_imgdev_session_error(dev, result);
|
fpi_imgdev_session_error(dev, result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trf.data = g_malloc(trf.length);
|
transfer = libusb_alloc_transfer();
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &trf, finger_det_data_cb,
|
if (!transfer) {
|
||||||
dev, BULK_TIMEOUT);
|
fpi_imgdev_session_error(dev, -ENOMEM);
|
||||||
if (!urbh) {
|
return;
|
||||||
g_free(trf.data);
|
}
|
||||||
fpi_imgdev_session_error(dev, -EIO);
|
|
||||||
|
data = g_malloc(20);
|
||||||
|
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 20,
|
||||||
|
finger_det_data_cb, dev, BULK_TIMEOUT);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
fpi_imgdev_session_error(dev, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,23 +541,20 @@ enum capture_states {
|
||||||
CAPTURE_NUM_STATES,
|
CAPTURE_NUM_STATES,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void capture_read_strip_cb(libusb_dev_handle *devh,
|
static void capture_read_strip_cb(struct libusb_transfer *transfer)
|
||||||
libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
|
||||||
unsigned char endpoint, int rqlength, unsigned char *data,
|
|
||||||
int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
unsigned char *stripdata;
|
unsigned char *stripdata;
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct aes2501_dev *aesdev = dev->priv;
|
struct aes2501_dev *aesdev = dev->priv;
|
||||||
|
unsigned char *data = transfer->buffer;
|
||||||
int sum;
|
int sum;
|
||||||
int threshold;
|
int threshold;
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
if (status != FP_URB_COMPLETED) {
|
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (rqlength != actual_length) {
|
} else if (transfer->length != transfer->actual_length) {
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -587,12 +598,14 @@ static void capture_read_strip_cb(libusb_dev_handle *devh,
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void capture_run_state(struct fpi_ssm *ssm)
|
static void capture_run_state(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct aes2501_dev *aesdev = dev->priv;
|
struct aes2501_dev *aesdev = dev->priv;
|
||||||
|
int r;
|
||||||
|
|
||||||
switch (ssm->cur_state) {
|
switch (ssm->cur_state) {
|
||||||
case CAPTURE_WRITE_REQS_1:
|
case CAPTURE_WRITE_REQS_1:
|
||||||
|
@ -617,17 +630,23 @@ static void capture_run_state(struct fpi_ssm *ssm)
|
||||||
generic_write_regv_cb, ssm);
|
generic_write_regv_cb, ssm);
|
||||||
break;
|
break;
|
||||||
case CAPTURE_READ_STRIP: ;
|
case CAPTURE_READ_STRIP: ;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
struct libusb_bulk_transfer trf = {
|
unsigned char *data;
|
||||||
.endpoint = EP_IN,
|
|
||||||
.data = g_malloc(1705),
|
if (!transfer) {
|
||||||
.length = 1705,
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
};
|
break;
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &trf,
|
}
|
||||||
|
|
||||||
|
data = g_malloc(1705);
|
||||||
|
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 1705,
|
||||||
capture_read_strip_cb, ssm, BULK_TIMEOUT);
|
capture_read_strip_cb, ssm, BULK_TIMEOUT);
|
||||||
if (!urbh) {
|
|
||||||
g_free(trf.data);
|
r = libusb_submit_transfer(transfer);
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#define SUBARRAY_LEN 768
|
#define SUBARRAY_LEN 768
|
||||||
|
|
||||||
struct aes4k_dev {
|
struct aes4k_dev {
|
||||||
libusb_urb_handle *img_trf;
|
struct libusb_transfer *img_trf;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct aes_regwrite init_reqs[] = {
|
static const struct aes_regwrite init_reqs[] = {
|
||||||
|
@ -115,22 +115,20 @@ static const struct aes_regwrite init_reqs[] = {
|
||||||
|
|
||||||
static void do_capture(struct fp_img_dev *dev);
|
static void do_capture(struct fp_img_dev *dev);
|
||||||
|
|
||||||
static void img_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void img_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = user_data;
|
struct fp_img_dev *dev = transfer->user_data;
|
||||||
struct aes4k_dev *aesdev = dev->priv;
|
struct aes4k_dev *aesdev = dev->priv;
|
||||||
unsigned char *ptr = data;
|
unsigned char *ptr = transfer->buffer;
|
||||||
struct fp_img *img;
|
struct fp_img *img;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (status == FP_URB_CANCELLED) {
|
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
|
||||||
goto err;
|
goto err;
|
||||||
} else if (status != FP_URB_COMPLETED) {
|
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fpi_imgdev_session_error(dev, -EIO);
|
fpi_imgdev_session_error(dev, -EIO);
|
||||||
goto err;
|
goto err;
|
||||||
} else if (rqlength != actual_length) {
|
} else if (transfer->length != transfer->actual_length) {
|
||||||
fpi_imgdev_session_error(dev, -EPROTO);
|
fpi_imgdev_session_error(dev, -EPROTO);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -155,25 +153,33 @@ static void img_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
do_capture(dev);
|
do_capture(dev);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
g_free(data);
|
g_free(transfer->buffer);
|
||||||
aesdev->img_trf = NULL;
|
aesdev->img_trf = NULL;
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_capture(struct fp_img_dev *dev)
|
static void do_capture(struct fp_img_dev *dev)
|
||||||
{
|
{
|
||||||
struct aes4k_dev *aesdev = dev->priv;
|
struct aes4k_dev *aesdev = dev->priv;
|
||||||
struct libusb_bulk_transfer trf = {
|
unsigned char *data;
|
||||||
.endpoint = EP_IN,
|
int r;
|
||||||
.length = DATA_BUFLEN,
|
|
||||||
.data = g_malloc(DATA_BUFLEN),
|
|
||||||
};
|
|
||||||
|
|
||||||
aesdev->img_trf = libusb_async_bulk_transfer(dev->udev, &trf, img_cb, dev,
|
aesdev->img_trf = libusb_alloc_transfer();
|
||||||
0);
|
|
||||||
if (!aesdev->img_trf) {
|
if (!aesdev->img_trf) {
|
||||||
g_free(trf.data);
|
|
||||||
fpi_imgdev_session_error(dev, -EIO);
|
fpi_imgdev_session_error(dev, -EIO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = g_malloc(DATA_BUFLEN);
|
||||||
|
libusb_fill_bulk_transfer(aesdev->img_trf, dev->udev, EP_IN, data,
|
||||||
|
DATA_BUFLEN, img_cb, dev, 0);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(aesdev->img_trf);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(aesdev->img_trf);
|
||||||
|
aesdev->img_trf = NULL;
|
||||||
|
fpi_imgdev_session_error(dev, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +204,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
|
||||||
* from deactivation, otherwise app may legally exit before we've
|
* from deactivation, otherwise app may legally exit before we've
|
||||||
* cleaned up */
|
* cleaned up */
|
||||||
if (aesdev->img_trf)
|
if (aesdev->img_trf)
|
||||||
libusb_urb_handle_cancel(dev->udev, aesdev->img_trf);
|
libusb_cancel_transfer(aesdev->img_trf);
|
||||||
fpi_imgdev_deactivate_complete(dev);
|
fpi_imgdev_deactivate_complete(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,10 +133,11 @@ static uint16_t udf_crc(unsigned char *buffer, size_t size)
|
||||||
|
|
||||||
#define CMD_SEQ_INCREMENT 0x10
|
#define CMD_SEQ_INCREMENT 0x10
|
||||||
|
|
||||||
static void fill_send_cmd_urb(struct libusb_bulk_transfer *msg,
|
static struct libusb_transfer *alloc_send_cmd_transfer(struct fp_dev *dev,
|
||||||
unsigned char seq_a, unsigned char seq_b, const unsigned char *data,
|
unsigned char seq_a, unsigned char seq_b, const unsigned char *data,
|
||||||
uint16_t len)
|
uint16_t len, libusb_transfer_cb_fn callback, void *user_data)
|
||||||
{
|
{
|
||||||
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
uint16_t crc;
|
uint16_t crc;
|
||||||
|
|
||||||
/* 9 bytes extra for: 4 byte 'Ciao', 1 byte A, 1 byte B | lenHI,
|
/* 9 bytes extra for: 4 byte 'Ciao', 1 byte A, 1 byte B | lenHI,
|
||||||
|
@ -144,15 +145,15 @@ static void fill_send_cmd_urb(struct libusb_bulk_transfer *msg,
|
||||||
size_t urblen = len + 9;
|
size_t urblen = len + 9;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
|
|
||||||
|
if (!transfer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (!data && len > 0) {
|
if (!data && len > 0) {
|
||||||
fp_err("len>0 but no data?");
|
fp_err("len>0 but no data?");
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->endpoint = EP_OUT;
|
|
||||||
msg->length = urblen;
|
|
||||||
buf = g_malloc(urblen);
|
buf = g_malloc(urblen);
|
||||||
msg->data = buf;
|
|
||||||
|
|
||||||
/* Write header */
|
/* Write header */
|
||||||
strncpy(buf, "Ciao", 4);
|
strncpy(buf, "Ciao", 4);
|
||||||
|
@ -169,17 +170,22 @@ static void fill_send_cmd_urb(struct libusb_bulk_transfer *msg,
|
||||||
crc = GUINT16_TO_BE(udf_crc(buf + 4, urblen - 6));
|
crc = GUINT16_TO_BE(udf_crc(buf + 4, urblen - 6));
|
||||||
buf[urblen - 2] = crc >> 8;
|
buf[urblen - 2] = crc >> 8;
|
||||||
buf[urblen - 1] = crc & 0xff;
|
buf[urblen - 1] = crc & 0xff;
|
||||||
|
|
||||||
|
libusb_fill_bulk_transfer(transfer, dev->udev, EP_OUT, buf, urblen,
|
||||||
|
callback, user_data, TIMEOUT);
|
||||||
|
return transfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_send_cmd28_urb(struct fp_dev *dev,
|
static struct libusb_transfer *alloc_send_cmd28_transfer(struct fp_dev *dev,
|
||||||
struct libusb_bulk_transfer *msg, unsigned char subcmd,
|
unsigned char subcmd, const unsigned char *data, uint16_t innerlen,
|
||||||
const unsigned char *data, uint16_t innerlen)
|
libusb_transfer_cb_fn callback, void *user_data)
|
||||||
{
|
{
|
||||||
uint16_t _innerlen = innerlen;
|
uint16_t _innerlen = innerlen;
|
||||||
size_t len = innerlen + 6;
|
size_t len = innerlen + 6;
|
||||||
unsigned char *buf = g_malloc0(len);
|
unsigned char *buf = g_malloc0(len);
|
||||||
struct upekts_dev *upekdev = dev->priv;
|
struct upekts_dev *upekdev = dev->priv;
|
||||||
uint8_t seq = upekdev->seq + CMD_SEQ_INCREMENT;
|
uint8_t seq = upekdev->seq + CMD_SEQ_INCREMENT;
|
||||||
|
struct libusb_transfer *ret;
|
||||||
|
|
||||||
fp_dbg("seq=%02x subcmd=%02x with %d bytes of data", seq, subcmd, innerlen);
|
fp_dbg("seq=%02x subcmd=%02x with %d bytes of data", seq, subcmd, innerlen);
|
||||||
|
|
||||||
|
@ -190,17 +196,19 @@ static void fill_send_cmd28_urb(struct fp_dev *dev,
|
||||||
buf[5] = subcmd;
|
buf[5] = subcmd;
|
||||||
memcpy(buf + 6, data, innerlen);
|
memcpy(buf + 6, data, innerlen);
|
||||||
|
|
||||||
fill_send_cmd_urb(msg, 0, seq, buf, len);
|
ret = alloc_send_cmd_transfer(dev, 0, seq, buf, len, callback, user_data);
|
||||||
upekdev->seq = seq;
|
upekdev->seq = seq;
|
||||||
|
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_send_cmdresponse_urb(struct libusb_bulk_transfer *msg,
|
static struct libusb_transfer *alloc_send_cmdresponse_transfer(
|
||||||
unsigned char seq, const unsigned char *data, uint8_t len)
|
struct fp_dev *dev, unsigned char seq, const unsigned char *data,
|
||||||
|
uint8_t len, libusb_transfer_cb_fn callback, void *user_data)
|
||||||
{
|
{
|
||||||
fp_dbg("seq=%02x len=%d", seq, len);
|
fp_dbg("seq=%02x len=%d", seq, len);
|
||||||
fill_send_cmd_urb(msg, seq, 0, data, len);
|
return alloc_send_cmd_transfer(dev, seq, 0, data, len, callback, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum read_msg_status {
|
enum read_msg_status {
|
||||||
|
@ -224,12 +232,12 @@ static int __read_msg_async(struct read_msg_data *udata);
|
||||||
#define READ_MSG_DATA_CB_ERR(udata) (udata)->callback((udata)->dev, \
|
#define READ_MSG_DATA_CB_ERR(udata) (udata)->callback((udata)->dev, \
|
||||||
READ_MSG_ERROR, 0, 0, NULL, 0, (udata)->user_data)
|
READ_MSG_ERROR, 0, 0, NULL, 0, (udata)->user_data)
|
||||||
|
|
||||||
static void busy_ack_sent_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void busy_ack_sent_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
|
|
||||||
unsigned char *data, int actual_length, void *_data)
|
|
||||||
{
|
{
|
||||||
struct read_msg_data *udata = (struct read_msg_data *) _data;
|
struct read_msg_data *udata = transfer->user_data;
|
||||||
if (status != FP_URB_COMPLETED || rqlength != actual_length) {
|
|
||||||
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED ||
|
||||||
|
transfer->length != transfer->actual_length) {
|
||||||
READ_MSG_DATA_CB_ERR(udata);
|
READ_MSG_DATA_CB_ERR(udata);
|
||||||
g_free(udata);
|
g_free(udata);
|
||||||
} else {
|
} else {
|
||||||
|
@ -239,22 +247,25 @@ static void busy_ack_sent_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
g_free(udata);
|
g_free(udata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int busy_ack_retry_read(struct read_msg_data *udata)
|
static int busy_ack_retry_read(struct read_msg_data *udata)
|
||||||
{
|
{
|
||||||
struct libusb_bulk_transfer msg;
|
struct libusb_transfer *transfer;
|
||||||
libusb_urb_handle *urbh;
|
int r;
|
||||||
|
|
||||||
fill_send_cmdresponse_urb(&msg, 0x09, NULL, 0);
|
transfer = alloc_send_cmdresponse_transfer(udata->dev, 0x09, NULL, 0,
|
||||||
urbh = libusb_async_bulk_transfer(udata->dev->udev, &msg, busy_ack_sent_cb,
|
busy_ack_sent_cb, udata);
|
||||||
udata, TIMEOUT);
|
if (!transfer)
|
||||||
if (!urbh) {
|
return -ENOMEM;
|
||||||
g_free(msg.data);
|
|
||||||
return -EIO;
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 0 if message was handled, 1 if it was a device-busy message, and
|
/* Returns 0 if message was handled, 1 if it was a device-busy message, and
|
||||||
|
@ -333,20 +344,19 @@ static int __handle_incoming_msg(struct read_msg_data *udata,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_msg_extend_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void read_msg_extend_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint, int rqlength,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct read_msg_data *udata = user_data;
|
struct read_msg_data *udata = transfer->user_data;
|
||||||
unsigned char *buf = data - MSG_READ_BUF_SIZE;
|
unsigned char *buf = transfer->buffer - MSG_READ_BUF_SIZE;
|
||||||
int handle_result = 0;
|
int handle_result = 0;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fp_err("extended msg read failed, code %d", status);
|
fp_err("extended msg read failed, code %d", transfer->status);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (actual_length < rqlength) {
|
if (transfer->actual_length < transfer->length) {
|
||||||
fp_err("extended msg short read (%d/%d)", actual_length, rqlength);
|
fp_err("extended msg short read (%d/%d)", transfer->actual_length,
|
||||||
|
transfer->length);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,23 +371,22 @@ out:
|
||||||
if (handle_result != 1)
|
if (handle_result != 1)
|
||||||
g_free(udata);
|
g_free(udata);
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void read_msg_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct read_msg_data *udata = user_data;
|
struct read_msg_data *udata = transfer->user_data;
|
||||||
|
unsigned char *data = transfer->buffer;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
int handle_result = 0;
|
int handle_result = 0;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fp_err("async msg read failed, code %d", status);
|
fp_err("async msg read failed, code %d", transfer->status);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (actual_length < 9) {
|
if (transfer->actual_length < 9) {
|
||||||
fp_err("async msg read too short (%d)", actual_length);
|
fp_err("async msg read too short (%d)", transfer->actual_length);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,11 +396,12 @@ static void read_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
}
|
}
|
||||||
|
|
||||||
len = GUINT16_FROM_LE(((data[5] & 0xf) << 8) | data[6]);
|
len = GUINT16_FROM_LE(((data[5] & 0xf) << 8) | data[6]);
|
||||||
if (actual_length != MSG_READ_BUF_SIZE && (len + 9) > actual_length) {
|
if (transfer->actual_length != MSG_READ_BUF_SIZE
|
||||||
|
&& (len + 9) > transfer->actual_length) {
|
||||||
/* Check that the length claimed inside the message is in line with
|
/* Check that the length claimed inside the message is in line with
|
||||||
* the amount of data that was transferred over USB. */
|
* the amount of data that was transferred over USB. */
|
||||||
fp_err("msg didn't include enough data, expected=%d recv=%d",
|
fp_err("msg didn't include enough data, expected=%d recv=%d",
|
||||||
len + 9, actual_length);
|
len + 9, transfer->actual_length);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,22 +410,26 @@ static void read_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
* to read the remainder. This is handled below. */
|
* to read the remainder. This is handled below. */
|
||||||
if (len > MAX_DATA_IN_READ_BUF) {
|
if (len > MAX_DATA_IN_READ_BUF) {
|
||||||
int needed = len - MAX_DATA_IN_READ_BUF;
|
int needed = len - MAX_DATA_IN_READ_BUF;
|
||||||
libusb_urb_handle *eurbh;
|
struct libusb_transfer *etransfer = libusb_alloc_transfer();
|
||||||
struct libusb_bulk_transfer extend_msg = {
|
int r;
|
||||||
.endpoint = EP_IN,
|
|
||||||
.length = needed,
|
if (!transfer)
|
||||||
};
|
goto err;
|
||||||
|
|
||||||
fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed);
|
fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed);
|
||||||
data = g_realloc((gpointer) data, MSG_READ_BUF_SIZE + needed);
|
data = g_realloc((gpointer) data, MSG_READ_BUF_SIZE + needed);
|
||||||
extend_msg.data = data + MSG_READ_BUF_SIZE;
|
|
||||||
eurbh = libusb_async_bulk_transfer(udata->dev->udev, &extend_msg,
|
libusb_fill_bulk_transfer(etransfer, udata->dev->udev, EP_IN,
|
||||||
read_msg_extend_cb, udata, TIMEOUT);
|
data + MSG_READ_BUF_SIZE, needed, read_msg_extend_cb, udata,
|
||||||
if (!eurbh) {
|
TIMEOUT);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(etransfer);
|
||||||
|
if (r < 0) {
|
||||||
fp_err("extended read submission failed");
|
fp_err("extended read submission failed");
|
||||||
|
/* FIXME memory leak here? */
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +441,7 @@ static void read_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
err:
|
err:
|
||||||
READ_MSG_DATA_CB_ERR(udata);
|
READ_MSG_DATA_CB_ERR(udata);
|
||||||
out:
|
out:
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
if (handle_result != 1)
|
if (handle_result != 1)
|
||||||
g_free(udata);
|
g_free(udata);
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
@ -436,18 +450,23 @@ out:
|
||||||
static int __read_msg_async(struct read_msg_data *udata)
|
static int __read_msg_async(struct read_msg_data *udata)
|
||||||
{
|
{
|
||||||
unsigned char *buf = g_malloc(MSG_READ_BUF_SIZE);
|
unsigned char *buf = g_malloc(MSG_READ_BUF_SIZE);
|
||||||
struct libusb_bulk_transfer msg = {
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
.endpoint = EP_IN,
|
int r;
|
||||||
.data = buf,
|
|
||||||
.length = MSG_READ_BUF_SIZE,
|
if (!transfer) {
|
||||||
};
|
|
||||||
libusb_urb_handle *urbh = libusb_async_bulk_transfer(udata->dev->udev, &msg,
|
|
||||||
read_msg_cb, udata, TIMEOUT);
|
|
||||||
if (!urbh) {
|
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
return -EIO;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
libusb_fill_bulk_transfer(transfer, udata->dev->udev, EP_IN, buf,
|
||||||
|
MSG_READ_BUF_SIZE, read_msg_cb, udata, TIMEOUT);
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(buf);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_msg_async(struct fp_dev *dev, read_msg_cb_fn callback,
|
static int read_msg_async(struct fp_dev *dev, read_msg_cb_fn callback,
|
||||||
|
@ -613,16 +632,16 @@ static void read_msg03_cb(struct fp_dev *dev, enum read_msg_status status,
|
||||||
initsm_read_msg_cmd_cb((struct fpi_ssm *) user_data, status, 3, seq);
|
initsm_read_msg_cmd_cb((struct fpi_ssm *) user_data, status, 3, seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ctrl400_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void ctrl400_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, struct libusb_ctrl_setup *setup,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
if (status == FP_URB_COMPLETED)
|
/* FIXME check length? */
|
||||||
|
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
else
|
else
|
||||||
fpi_ssm_mark_aborted(ssm, -1);
|
fpi_ssm_mark_aborted(ssm, -1);
|
||||||
libusb_urb_handle_free(urbh);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initsm_read_msg_handler(struct fpi_ssm *ssm,
|
static void initsm_read_msg_handler(struct fpi_ssm *ssm,
|
||||||
|
@ -635,35 +654,40 @@ static void initsm_read_msg_handler(struct fpi_ssm *ssm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initsm_send_msg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void initsm_send_msg_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
if (status == FP_URB_COMPLETED && rqlength == actual_length) {
|
if (transfer->status == LIBUSB_TRANSFER_COMPLETED
|
||||||
|
&& transfer->length == transfer->actual_length) {
|
||||||
fp_dbg("state %d completed", ssm->cur_state);
|
fp_dbg("state %d completed", ssm->cur_state);
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
} else {
|
} else {
|
||||||
fp_err("failed, state=%d rqlength=%d actual_length=%d", ssm->cur_state,
|
fp_err("failed, state=%d rqlength=%d actual_length=%d", ssm->cur_state,
|
||||||
rqlength, actual_length);
|
transfer->length, transfer->actual_length);
|
||||||
fpi_ssm_mark_aborted(ssm, -1);
|
fpi_ssm_mark_aborted(ssm, -1);
|
||||||
}
|
}
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initsm_send_msg28_handler(struct fpi_ssm *ssm,
|
static void initsm_send_msg28_handler(struct fpi_ssm *ssm,
|
||||||
unsigned char subcmd, const unsigned char *data, uint16_t innerlen)
|
unsigned char subcmd, const unsigned char *data, uint16_t innerlen)
|
||||||
{
|
{
|
||||||
struct fp_dev *dev = ssm->dev;
|
struct fp_dev *dev = ssm->dev;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
struct libusb_bulk_transfer trf;
|
int r;
|
||||||
|
|
||||||
fill_send_cmd28_urb(dev, &trf, subcmd, data, innerlen);
|
transfer = alloc_send_cmd28_transfer(dev, subcmd, data, innerlen,
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &trf, initsm_send_msg_cb,
|
initsm_send_msg_cb, ssm);
|
||||||
ssm, TIMEOUT);
|
if (!transfer) {
|
||||||
if (!urbh) {
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
fp_err("urb submission failed in state %d", ssm->cur_state);
|
return;
|
||||||
g_free(trf.data);
|
}
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
fp_err("urb submission failed error %d in state %d", r, ssm->cur_state);
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -672,38 +696,48 @@ static void initsm_run_state(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_dev *dev = ssm->dev;
|
struct fp_dev *dev = ssm->dev;
|
||||||
struct upekts_dev *upekdev = dev->priv;
|
struct upekts_dev *upekdev = dev->priv;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer;
|
||||||
|
int r;
|
||||||
|
|
||||||
switch (ssm->cur_state) {
|
switch (ssm->cur_state) {
|
||||||
case WRITE_CTRL400: ;
|
case WRITE_CTRL400: ;
|
||||||
unsigned char dummy = 0x10;
|
unsigned char *data;
|
||||||
struct libusb_control_transfer ctrl400_trf = {
|
|
||||||
.requesttype = LIBUSB_TYPE_VENDOR | LIBUSB_RECIP_DEVICE,
|
|
||||||
.request = 0x0c,
|
|
||||||
.value = 0x0100,
|
|
||||||
.index = 0x0400,
|
|
||||||
.length = sizeof(dummy),
|
|
||||||
.data = &dummy,
|
|
||||||
};
|
|
||||||
|
|
||||||
urbh = libusb_async_control_transfer(ssm->dev->udev, &ctrl400_trf,
|
transfer = libusb_alloc_transfer();
|
||||||
|
if (!transfer) {
|
||||||
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
|
||||||
|
libusb_fill_control_setup(data,
|
||||||
|
LIBUSB_TYPE_VENDOR | LIBUSB_RECIP_DEVICE, 0x0c, 0x100, 0x0400, 1);
|
||||||
|
libusb_fill_control_transfer(transfer, ssm->dev->udev, data,
|
||||||
ctrl400_cb, ssm, TIMEOUT);
|
ctrl400_cb, ssm, TIMEOUT);
|
||||||
if (!urbh)
|
|
||||||
fpi_ssm_mark_aborted(ssm, -1);
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case READ_MSG03:
|
case READ_MSG03:
|
||||||
initsm_read_msg_handler(ssm, read_msg03_cb);
|
initsm_read_msg_handler(ssm, read_msg03_cb);
|
||||||
break;
|
break;
|
||||||
case SEND_RESP03: ;
|
case SEND_RESP03: ;
|
||||||
struct libusb_bulk_transfer resp03_trf;
|
transfer = alloc_send_cmdresponse_transfer(dev, ++upekdev->seq,
|
||||||
|
init_resp03, sizeof(init_resp03), initsm_send_msg_cb, ssm);
|
||||||
|
if (!transfer) {
|
||||||
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fill_send_cmdresponse_urb(&resp03_trf, ++upekdev->seq, init_resp03,
|
r = libusb_submit_transfer(transfer);
|
||||||
sizeof(init_resp03));
|
if (r < 0) {
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &resp03_trf,
|
g_free(transfer->buffer);
|
||||||
initsm_send_msg_cb, ssm, TIMEOUT);
|
libusb_free_transfer(transfer);
|
||||||
if (!urbh) {
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
g_free(resp03_trf.data);
|
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case READ_MSG05:
|
case READ_MSG05:
|
||||||
|
@ -756,18 +790,16 @@ enum deinitsm_states {
|
||||||
DEINITSM_NUM_STATES,
|
DEINITSM_NUM_STATES,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void send_resp07_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void send_resp07_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
if (status != FP_URB_COMPLETED)
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
else if (rqlength != actual_length)
|
else if (transfer->length != transfer->actual_length)
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_msg01_cb(struct fp_dev *dev, enum read_msg_status status,
|
static void read_msg01_cb(struct fp_dev *dev, enum read_msg_status status,
|
||||||
|
@ -798,23 +830,29 @@ static void read_msg01_cb(struct fp_dev *dev, enum read_msg_status status,
|
||||||
static void deinitsm_state_handler(struct fpi_ssm *ssm)
|
static void deinitsm_state_handler(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_dev *dev = ssm->dev;
|
struct fp_dev *dev = ssm->dev;
|
||||||
|
int r;
|
||||||
|
|
||||||
switch (ssm->cur_state) {
|
switch (ssm->cur_state) {
|
||||||
case SEND_RESP07: ;
|
case SEND_RESP07: ;
|
||||||
struct libusb_bulk_transfer msg;
|
struct libusb_transfer *transfer;
|
||||||
struct libusb_urb_handle *urbh;
|
|
||||||
unsigned char dummy = 0;
|
unsigned char dummy = 0;
|
||||||
|
|
||||||
fill_send_cmdresponse_urb(&msg, 0x07, &dummy, 1);
|
transfer = alloc_send_cmdresponse_transfer(dev, 0x07, &dummy, 1,
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &msg, send_resp07_cb, ssm,
|
send_resp07_cb, ssm);
|
||||||
TIMEOUT);
|
if (!transfer) {
|
||||||
if (!urbh) {
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
g_free(msg.data);
|
break;
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
}
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case READ_MSG01: ;
|
case READ_MSG01: ;
|
||||||
int r = read_msg_async(dev, read_msg01_cb, ssm);
|
r = read_msg_async(dev, read_msg01_cb, ssm);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
fpi_ssm_mark_aborted(ssm, r);
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
break;
|
break;
|
||||||
|
@ -882,19 +920,16 @@ static void enroll_start_sm_cb_initsm(struct fpi_ssm *initsm)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called when enroll init URB has completed */
|
/* called when enroll init URB has completed */
|
||||||
static void enroll_start_sm_cb_init(libusb_dev_handle *devh,
|
static void enroll_start_sm_cb_init(struct libusb_transfer *transfer)
|
||||||
libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
|
||||||
unsigned char endpoint, int rqlength, unsigned char *data,
|
|
||||||
int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
if (status != FP_URB_COMPLETED)
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
else if (rqlength != actual_length)
|
else if (transfer->length != transfer->actual_length)
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enroll_start_sm_cb_msg28(struct fp_dev *dev,
|
static void enroll_start_sm_cb_msg28(struct fp_dev *dev,
|
||||||
|
@ -923,6 +958,7 @@ static void enroll_start_sm_cb_msg28(struct fp_dev *dev,
|
||||||
static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
|
static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_dev *dev = ssm->dev;
|
struct fp_dev *dev = ssm->dev;
|
||||||
|
int r;
|
||||||
|
|
||||||
switch (ssm->cur_state) {
|
switch (ssm->cur_state) {
|
||||||
case RUN_INITSM: ;
|
case RUN_INITSM: ;
|
||||||
|
@ -931,14 +967,19 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
|
||||||
fpi_ssm_start(initsm, enroll_start_sm_cb_initsm);
|
fpi_ssm_start(initsm, enroll_start_sm_cb_initsm);
|
||||||
break;
|
break;
|
||||||
case ENROLL_INIT: ;
|
case ENROLL_INIT: ;
|
||||||
struct libusb_bulk_transfer msg;
|
struct libusb_transfer *transfer;
|
||||||
struct libusb_urb_handle *urbh;
|
transfer = alloc_send_cmd28_transfer(dev, 0x02, enroll_init,
|
||||||
fill_send_cmd28_urb(dev, &msg, 0x02, enroll_init, sizeof(enroll_init));
|
sizeof(enroll_init), enroll_start_sm_cb_init, ssm);
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &msg,
|
if (!transfer) {
|
||||||
enroll_start_sm_cb_init, ssm, TIMEOUT);
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
if (!urbh) {
|
break;
|
||||||
g_free(msg.data);
|
}
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case READ_ENROLL_MSG28: ;
|
case READ_ENROLL_MSG28: ;
|
||||||
|
@ -946,7 +987,7 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
|
||||||
* to subcmd 0 after submitting subcmd 2? */
|
* to subcmd 0 after submitting subcmd 2? */
|
||||||
/* actually this is probably a poll response? does the above cmd
|
/* actually this is probably a poll response? does the above cmd
|
||||||
* include a 30 01 poll somewhere? */
|
* include a 30 01 poll somewhere? */
|
||||||
int r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm);
|
r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
fpi_ssm_mark_aborted(ssm, r);
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
break;
|
break;
|
||||||
|
@ -1069,35 +1110,37 @@ static void enroll_iterate_msg_cb(struct fp_dev *dev,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enroll_iterate_cmd_cb(libusb_dev_handle *devh,
|
static void enroll_iterate_cmd_cb(struct libusb_transfer *transfer)
|
||||||
libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
|
|
||||||
unsigned char endpoint, int rqlength, unsigned char *data,
|
|
||||||
int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fp_dev *dev = user_data;
|
struct fp_dev *dev = transfer->user_data;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL);
|
fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL);
|
||||||
} else if (rqlength != actual_length) {
|
} else if (transfer->length != transfer->actual_length) {
|
||||||
fpi_drvcb_enroll_stage_completed(dev, -EPROTO, NULL, NULL);
|
fpi_drvcb_enroll_stage_completed(dev, -EPROTO, NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
int r = read_msg_async(dev, enroll_iterate_msg_cb, NULL);
|
int r = read_msg_async(dev, enroll_iterate_msg_cb, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
fpi_drvcb_enroll_stage_completed(dev, r, NULL, NULL);
|
fpi_drvcb_enroll_stage_completed(dev, r, NULL, NULL);
|
||||||
}
|
}
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enroll_iterate(struct fp_dev *dev)
|
static void enroll_iterate(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
struct libusb_bulk_transfer msg;
|
int r;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = alloc_send_cmd28_transfer(dev, 0x00,
|
||||||
|
poll_data, sizeof(poll_data), enroll_iterate_cmd_cb, dev);
|
||||||
|
|
||||||
fill_send_cmd28_urb(dev, &msg, 0x00, poll_data, sizeof(poll_data));
|
if (!transfer) {
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &msg, enroll_iterate_cmd_cb,
|
fpi_drvcb_enroll_stage_completed(dev, -ENOMEM, NULL, NULL);
|
||||||
dev, TIMEOUT);
|
return;
|
||||||
if (!urbh) {
|
}
|
||||||
g_free(msg.data);
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL);
|
fpi_drvcb_enroll_stage_completed(dev, -EIO, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1176,23 +1219,22 @@ static void verify_start_sm_cb_initsm(struct fpi_ssm *initsm)
|
||||||
fpi_ssm_free(initsm);
|
fpi_ssm_free(initsm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_init_2803_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void verify_init_2803_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
if (status != FP_URB_COMPLETED)
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
else if (rqlength != actual_length)
|
else if (transfer->length != transfer->actual_length)
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_start_sm_run_state(struct fpi_ssm *ssm)
|
static void verify_start_sm_run_state(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_dev *dev = ssm->dev;
|
struct fp_dev *dev = ssm->dev;
|
||||||
|
int r;
|
||||||
|
|
||||||
switch (ssm->cur_state) {
|
switch (ssm->cur_state) {
|
||||||
case VERIFY_RUN_INITSM: ;
|
case VERIFY_RUN_INITSM: ;
|
||||||
|
@ -1204,18 +1246,22 @@ static void verify_start_sm_run_state(struct fpi_ssm *ssm)
|
||||||
struct fp_print_data *print = dev->verify_data;
|
struct fp_print_data *print = dev->verify_data;
|
||||||
size_t data_len = sizeof(verify_hdr) + print->length;
|
size_t data_len = sizeof(verify_hdr) + print->length;
|
||||||
unsigned char *data = g_malloc(data_len);
|
unsigned char *data = g_malloc(data_len);
|
||||||
struct libusb_bulk_transfer msg;
|
struct libusb_transfer *transfer;
|
||||||
struct libusb_urb_handle *urbh;
|
|
||||||
|
|
||||||
memcpy(data, verify_hdr, sizeof(verify_hdr));
|
memcpy(data, verify_hdr, sizeof(verify_hdr));
|
||||||
memcpy(data + sizeof(verify_hdr), print->data, print->length);
|
memcpy(data + sizeof(verify_hdr), print->data, print->length);
|
||||||
fill_send_cmd28_urb(dev, &msg, 0x03, data, data_len);
|
transfer = alloc_send_cmd28_transfer(dev, 0x03, data, data_len,
|
||||||
|
verify_init_2803_cb, ssm);
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
if (!transfer) {
|
||||||
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &msg,
|
r = libusb_submit_transfer(transfer);
|
||||||
verify_init_2803_cb, ssm, TIMEOUT);
|
if (r < 0) {
|
||||||
if (!urbh) {
|
g_free(transfer->buffer);
|
||||||
g_free(msg.data);
|
libusb_free_transfer(transfer);
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1323,28 +1369,25 @@ static void verify_rd2800_cb(struct fp_dev *dev, enum read_msg_status msgstat,
|
||||||
fpi_drvcb_report_verify_result(dev, -EPROTO, NULL);
|
fpi_drvcb_report_verify_result(dev, -EPROTO, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_wr2800_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void verify_wr2800_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fp_dev *dev = user_data;
|
struct fp_dev *dev = transfer->user_data;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
|
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
|
||||||
} else if (rqlength != actual_length) {
|
} else if (transfer->length != transfer->actual_length) {
|
||||||
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
|
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
|
||||||
} else {
|
} else {
|
||||||
int r = read_msg_async(dev, verify_rd2800_cb, NULL);
|
int r = read_msg_async(dev, verify_rd2800_cb, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
fpi_drvcb_report_verify_result(dev, r, NULL);
|
fpi_drvcb_report_verify_result(dev, r, NULL);
|
||||||
}
|
}
|
||||||
libusb_urb_handle_free(urbh);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify_iterate(struct fp_dev *dev)
|
static void verify_iterate(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
struct upekts_dev *upekdev = dev->priv;
|
struct upekts_dev *upekdev = dev->priv;
|
||||||
struct libusb_bulk_transfer msg;
|
|
||||||
|
|
||||||
if (upekdev->stop_verify) {
|
if (upekdev->stop_verify) {
|
||||||
do_verify_stop(dev);
|
do_verify_stop(dev);
|
||||||
|
@ -1359,12 +1402,19 @@ static void verify_iterate(struct fp_dev *dev)
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
fpi_drvcb_report_verify_result(dev, r, NULL);
|
fpi_drvcb_report_verify_result(dev, r, NULL);
|
||||||
} else {
|
} else {
|
||||||
struct libusb_urb_handle *urbh;
|
int r;
|
||||||
fill_send_cmd28_urb(dev, &msg, 0x00, poll_data, sizeof(poll_data));
|
struct libusb_transfer *transfer = alloc_send_cmd28_transfer(dev,
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &msg, verify_wr2800_cb,
|
0x00, poll_data, sizeof(poll_data), verify_wr2800_cb, dev);
|
||||||
dev, TIMEOUT);
|
|
||||||
if (!urbh) {
|
if (!transfer) {
|
||||||
g_free(msg.data);
|
fpi_drvcb_report_verify_result(dev, -ENOMEM, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
|
fpi_drvcb_report_verify_result(dev, -EIO, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,8 +122,8 @@ struct uru4k_dev {
|
||||||
enum fp_imgdev_state activate_state;
|
enum fp_imgdev_state activate_state;
|
||||||
unsigned char last_hwstat_rd;
|
unsigned char last_hwstat_rd;
|
||||||
|
|
||||||
libusb_urb_handle *irq_transfer;
|
struct libusb_transfer *irq_transfer;
|
||||||
libusb_urb_handle *img_transfer;
|
struct libusb_transfer *img_transfer;
|
||||||
|
|
||||||
irq_cb_fn irq_cb;
|
irq_cb_fn irq_cb;
|
||||||
void *irq_cb_data;
|
void *irq_cb_data;
|
||||||
|
@ -154,19 +154,18 @@ struct set_reg_data {
|
||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void set_reg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void set_reg_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, struct libusb_ctrl_setup *setup,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct set_reg_data *srdata = user_data;
|
struct set_reg_data *srdata = transfer->user_data;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED)
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
else if (setup->wLength != actual_length)
|
else if (transfer->actual_length != 1)
|
||||||
r = -EPROTO;
|
r = -EPROTO;
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
srdata->callback(srdata->dev, r, srdata->user_data);
|
srdata->callback(srdata->dev, r, srdata->user_data);
|
||||||
g_free(srdata);
|
g_free(srdata);
|
||||||
}
|
}
|
||||||
|
@ -174,29 +173,32 @@ static void set_reg_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
static int set_reg(struct fp_img_dev *dev, unsigned char reg,
|
static int set_reg(struct fp_img_dev *dev, unsigned char reg,
|
||||||
unsigned char value, set_reg_cb_fn callback, void *user_data)
|
unsigned char value, set_reg_cb_fn callback, void *user_data)
|
||||||
{
|
{
|
||||||
struct set_reg_data *srdata = g_malloc(sizeof(*srdata));
|
struct set_reg_data *srdata;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
struct libusb_control_transfer trf = {
|
unsigned char *data;
|
||||||
.requesttype = CTRL_OUT,
|
int r;
|
||||||
.request = USB_RQ,
|
|
||||||
.value = reg,
|
|
||||||
.index = 0,
|
|
||||||
.length = 1,
|
|
||||||
.data = &value,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if (!transfer)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
srdata = g_malloc(sizeof(*srdata));
|
||||||
srdata->dev = dev;
|
srdata->dev = dev;
|
||||||
srdata->callback = callback;
|
srdata->callback = callback;
|
||||||
srdata->user_data = user_data;
|
srdata->user_data = user_data;
|
||||||
|
|
||||||
trf.data[0] = value;
|
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
|
||||||
urbh = libusb_async_control_transfer(dev->udev, &trf, set_reg_cb, srdata,
|
data[LIBUSB_CONTROL_SETUP_SIZE] = value;
|
||||||
CTRL_TIMEOUT);
|
libusb_fill_control_setup(data, CTRL_OUT, USB_RQ, reg, 0, 1);
|
||||||
if (!urbh) {
|
libusb_fill_control_transfer(transfer, dev->udev, data, set_reg_cb,
|
||||||
|
srdata, CTRL_TIMEOUT);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
g_free(srdata);
|
g_free(srdata);
|
||||||
return -EIO;
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -233,59 +235,65 @@ struct c_r_data {
|
||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void response_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void response_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, struct libusb_ctrl_setup *setup,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct c_r_data *crdata = user_data;
|
struct c_r_data *crdata = transfer->user_data;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (status == FP_URB_COMPLETED)
|
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
else if (actual_length != setup->wLength)
|
else if (transfer->actual_length != CR_LENGTH)
|
||||||
r = -EPROTO;
|
r = -EPROTO;
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
crdata->callback(crdata->dev, r, crdata->user_data);
|
crdata->callback(crdata->dev, r, crdata->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void challenge_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void challenge_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, struct libusb_ctrl_setup *setup,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct c_r_data *crdata = user_data;
|
struct c_r_data *crdata = transfer->user_data;
|
||||||
struct fp_img_dev *dev = crdata->dev;
|
struct fp_img_dev *dev = crdata->dev;
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
unsigned char respdata[CR_LENGTH];
|
struct libusb_transfer *resp_transfer;
|
||||||
|
unsigned char *respdata;
|
||||||
|
int r;
|
||||||
|
|
||||||
struct libusb_urb_handle *resp_urbh;
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
struct libusb_control_transfer trf_write_response = {
|
|
||||||
.requesttype = CTRL_OUT,
|
|
||||||
.request = USB_RQ,
|
|
||||||
.value = REG_RESPONSE,
|
|
||||||
.index = 0,
|
|
||||||
.data = respdata,
|
|
||||||
.length = sizeof(respdata),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
|
||||||
crdata->callback(crdata->dev, -EIO, crdata->user_data);
|
crdata->callback(crdata->dev, -EIO, crdata->user_data);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (setup->wLength != actual_length) {
|
} else if (transfer->actual_length != CR_LENGTH) {
|
||||||
crdata->callback(crdata->dev, -EPROTO, crdata->user_data);
|
crdata->callback(crdata->dev, -EPROTO, crdata->user_data);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* produce response from challenge */
|
|
||||||
AES_encrypt(data, respdata, &urudev->aeskey);
|
|
||||||
|
|
||||||
/* submit response */
|
/* submit response */
|
||||||
resp_urbh = libusb_async_control_transfer(dev->udev, &trf_write_response,
|
resp_transfer = libusb_alloc_transfer();
|
||||||
response_cb, crdata, CTRL_TIMEOUT);
|
if (!resp_transfer) {
|
||||||
if (!resp_urbh)
|
crdata->callback(crdata->dev, -ENOMEM, crdata->user_data);
|
||||||
crdata->callback(crdata->dev, -EIO, crdata->user_data);
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
respdata = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + CR_LENGTH);
|
||||||
|
libusb_fill_control_setup(respdata, CTRL_OUT, USB_RQ, REG_RESPONSE, 0,
|
||||||
|
CR_LENGTH);
|
||||||
|
libusb_fill_control_transfer(transfer, dev->udev, respdata, response_cb,
|
||||||
|
crdata, CTRL_TIMEOUT);
|
||||||
|
|
||||||
|
/* produce response from challenge */
|
||||||
|
AES_encrypt(libusb_control_transfer_get_data(transfer),
|
||||||
|
respdata + LIBUSB_CONTROL_SETUP_SIZE, &urudev->aeskey);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(resp_transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(respdata);
|
||||||
|
libusb_free_transfer(resp_transfer);
|
||||||
|
crdata->callback(crdata->dev, r, crdata->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
libusb_urb_handle_free(urbh);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -296,28 +304,33 @@ out:
|
||||||
static int do_challenge_response(struct fp_img_dev *dev,
|
static int do_challenge_response(struct fp_img_dev *dev,
|
||||||
challenge_response_cb callback, void *user_data)
|
challenge_response_cb callback, void *user_data)
|
||||||
{
|
{
|
||||||
struct c_r_data *crdata = g_malloc(sizeof(*crdata));
|
struct libusb_transfer *transfer = libusb_alloc_transfer();;
|
||||||
struct libusb_urb_handle *urbh;
|
struct c_r_data *crdata;
|
||||||
struct libusb_control_transfer trf_read_challenge = {
|
unsigned char *data;
|
||||||
.requesttype = CTRL_IN,
|
int r;
|
||||||
.request = USB_RQ,
|
|
||||||
.value = REG_CHALLENGE,
|
|
||||||
.index = 0,
|
|
||||||
.length = CR_LENGTH,
|
|
||||||
};
|
|
||||||
|
|
||||||
fp_dbg("");
|
fp_dbg("");
|
||||||
|
if (!transfer)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
crdata = g_malloc(sizeof(*crdata));
|
||||||
crdata->dev = dev;
|
crdata->dev = dev;
|
||||||
crdata->callback = callback;
|
crdata->callback = callback;
|
||||||
crdata->user_data = user_data;
|
crdata->user_data = user_data;
|
||||||
|
|
||||||
urbh = libusb_async_control_transfer(dev->udev, &trf_read_challenge,
|
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + CR_LENGTH);
|
||||||
challenge_cb, crdata, CTRL_TIMEOUT);
|
libusb_fill_control_setup(data, CTRL_IN, USB_RQ, REG_CHALLENGE, 0,
|
||||||
if (!urbh) {
|
CR_LENGTH);
|
||||||
|
libusb_fill_control_transfer(transfer, dev->udev, data, challenge_cb,
|
||||||
|
crdata, CTRL_TIMEOUT);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
g_free(crdata);
|
g_free(crdata);
|
||||||
return -EIO;
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** INTERRUPT HANDLING *****/
|
/***** INTERRUPT HANDLING *****/
|
||||||
|
@ -326,35 +339,33 @@ static int do_challenge_response(struct fp_img_dev *dev,
|
||||||
|
|
||||||
static int start_irq_handler(struct fp_img_dev *dev);
|
static int start_irq_handler(struct fp_img_dev *dev);
|
||||||
|
|
||||||
static void irq_handler(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void irq_handler(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = user_data;
|
struct fp_img_dev *dev = transfer->user_data;
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
|
unsigned char *data = transfer->buffer;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
|
||||||
|
|
||||||
if (status == FP_URB_CANCELLED) {
|
|
||||||
fp_dbg("cancelled");
|
fp_dbg("cancelled");
|
||||||
if (urudev->irqs_stopped_cb)
|
if (urudev->irqs_stopped_cb)
|
||||||
urudev->irqs_stopped_cb(dev);
|
urudev->irqs_stopped_cb(dev);
|
||||||
urudev->irqs_stopped_cb = NULL;
|
urudev->irqs_stopped_cb = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
} else if (status != FP_URB_COMPLETED) {
|
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
goto err;
|
goto err;
|
||||||
} else if (actual_length != rqlength) {
|
} else if (transfer->actual_length != transfer->length) {
|
||||||
fp_err("short interrupt read? %d", actual_length);
|
fp_err("short interrupt read? %d", transfer->actual_length);
|
||||||
r = -EPROTO;
|
r = -EPROTO;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = GUINT16_FROM_BE(*((uint16_t *) data));
|
type = GUINT16_FROM_BE(*((uint16_t *) data));
|
||||||
g_free(data);
|
|
||||||
fp_dbg("recv irq type %04x", type);
|
fp_dbg("recv irq type %04x", type);
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
|
||||||
/* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer)
|
/* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer)
|
||||||
* of the next scan. It still appears on occasion. */
|
* of the next scan. It still appears on occasion. */
|
||||||
|
@ -370,41 +381,47 @@ static void irq_handler(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
transfer = NULL;
|
||||||
data = NULL;
|
data = NULL;
|
||||||
err:
|
err:
|
||||||
if (urudev->irq_cb)
|
if (urudev->irq_cb)
|
||||||
urudev->irq_cb(dev, r, 0, urudev->irq_cb_data);
|
urudev->irq_cb(dev, r, 0, urudev->irq_cb_data);
|
||||||
out:
|
out:
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
urudev->irq_transfer = NULL;
|
urudev->irq_transfer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start_irq_handler(struct fp_img_dev *dev)
|
static int start_irq_handler(struct fp_img_dev *dev)
|
||||||
{
|
{
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
struct libusb_bulk_transfer trf = {
|
unsigned char *data;
|
||||||
.endpoint = EP_INTR,
|
int r;
|
||||||
.length = IRQ_LENGTH,
|
|
||||||
.data = g_malloc(IRQ_LENGTH),
|
|
||||||
};
|
|
||||||
|
|
||||||
urbh = libusb_async_interrupt_transfer(dev->udev, &trf, irq_handler, dev,
|
if (!transfer)
|
||||||
0);
|
return -ENOMEM;
|
||||||
urudev->irq_transfer = urbh;
|
|
||||||
if (!urbh) {
|
data = g_malloc(IRQ_LENGTH);
|
||||||
g_free(trf.data);
|
libusb_fill_bulk_transfer(transfer, dev->udev, EP_INTR, data, IRQ_LENGTH,
|
||||||
return -EIO;
|
irq_handler, dev, 0);
|
||||||
|
|
||||||
|
urudev->irq_transfer = transfer;
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
urudev->irq_transfer = NULL;
|
||||||
}
|
}
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb)
|
static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb)
|
||||||
{
|
{
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
struct libusb_urb_handle *urbh = urudev->irq_transfer;
|
struct libusb_transfer *transfer = urudev->irq_transfer;
|
||||||
if (urbh) {
|
if (transfer) {
|
||||||
libusb_urb_handle_cancel(dev->udev, urbh);
|
libusb_cancel_transfer(transfer);
|
||||||
urudev->irqs_stopped_cb = cb;
|
urudev->irqs_stopped_cb = cb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,46 +430,45 @@ static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb)
|
||||||
|
|
||||||
static int start_imaging_loop(struct fp_img_dev *dev);
|
static int start_imaging_loop(struct fp_img_dev *dev);
|
||||||
|
|
||||||
static void image_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void image_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, unsigned char endpoint,
|
|
||||||
int rqlength, unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = user_data;
|
struct fp_img_dev *dev = transfer->user_data;
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
int hdr_skip = CAPTURE_HDRLEN;
|
int hdr_skip = CAPTURE_HDRLEN;
|
||||||
int image_size = DATABLK_EXPECT - CAPTURE_HDRLEN;
|
int image_size = DATABLK_EXPECT - CAPTURE_HDRLEN;
|
||||||
struct fp_img *img;
|
struct fp_img *img;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
libusb_urb_handle_free(urbh);
|
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
|
||||||
if (status == FP_URB_CANCELLED) {
|
|
||||||
fp_dbg("cancelled");
|
fp_dbg("cancelled");
|
||||||
urudev->img_transfer = NULL;
|
urudev->img_transfer = NULL;
|
||||||
g_free(data);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
return;
|
return;
|
||||||
} else if (status != FP_URB_COMPLETED) {
|
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual_length == image_size) {
|
if (transfer->actual_length == image_size) {
|
||||||
/* no header! this is rather odd, but it happens sometimes with my MS
|
/* no header! this is rather odd, but it happens sometimes with my MS
|
||||||
* keyboard */
|
* keyboard */
|
||||||
fp_dbg("got image with no header!");
|
fp_dbg("got image with no header!");
|
||||||
hdr_skip = 0;
|
hdr_skip = 0;
|
||||||
} else if (actual_length != DATABLK_EXPECT) {
|
} else if (transfer->actual_length != DATABLK_EXPECT) {
|
||||||
fp_err("unexpected image capture size (%d)", actual_length);
|
fp_err("unexpected image capture size (%d)", transfer->actual_length);
|
||||||
r = -EPROTO;
|
r = -EPROTO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
img = fpi_img_new(image_size);
|
img = fpi_img_new(image_size);
|
||||||
memcpy(img->data, data + hdr_skip, image_size);
|
memcpy(img->data, transfer->buffer + hdr_skip, image_size);
|
||||||
img->flags = FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED | FP_IMG_COLORS_INVERTED;
|
img->flags = FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED | FP_IMG_COLORS_INVERTED;
|
||||||
fpi_imgdev_image_captured(dev, img);
|
fpi_imgdev_image_captured(dev, img);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
g_free(data);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = start_imaging_loop(dev);
|
r = start_imaging_loop(dev);
|
||||||
|
|
||||||
|
@ -463,29 +479,33 @@ out:
|
||||||
static int start_imaging_loop(struct fp_img_dev *dev)
|
static int start_imaging_loop(struct fp_img_dev *dev)
|
||||||
{
|
{
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
struct libusb_bulk_transfer trf = {
|
unsigned char *data;
|
||||||
.endpoint = EP_DATA,
|
int r;
|
||||||
.length = DATABLK_RQLEN,
|
|
||||||
.data = g_malloc(DATABLK_RQLEN),
|
|
||||||
};
|
|
||||||
|
|
||||||
urbh = libusb_async_bulk_transfer(dev->udev, &trf, image_cb, dev, 0);
|
if (!transfer)
|
||||||
urudev->img_transfer = urbh;
|
return -ENOMEM;
|
||||||
if (!urbh) {
|
|
||||||
g_free(trf.data);
|
data = g_malloc(DATABLK_RQLEN);
|
||||||
return -EIO;
|
libusb_fill_bulk_transfer(transfer, dev->udev, EP_DATA, data,
|
||||||
|
DATABLK_RQLEN, image_cb, dev, 0);
|
||||||
|
|
||||||
|
urudev->img_transfer = transfer;
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stop_imaging_loop(struct fp_img_dev *dev)
|
static void stop_imaging_loop(struct fp_img_dev *dev)
|
||||||
{
|
{
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
libusb_urb_handle *urbh = urudev->img_transfer;
|
struct libusb_transfer *transfer = urudev->img_transfer;
|
||||||
if (urbh)
|
if (transfer)
|
||||||
libusb_urb_handle_cancel(dev->udev, urbh);
|
libusb_cancel_transfer(transfer);
|
||||||
/* FIXME: should probably wait for cancellation to complete */
|
/* FIXME: should probably wait for cancellation to complete */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,68 +597,72 @@ static void sm_set_hwstat(struct fpi_ssm *ssm, unsigned char value)
|
||||||
sm_set_reg(ssm, REG_HWSTAT, value);
|
sm_set_reg(ssm, REG_HWSTAT, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sm_get_hwstat_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void sm_get_hwstat_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, struct libusb_ctrl_setup *setup,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
} else if (setup->wLength != actual_length) {
|
} else if (transfer->actual_length != 1) {
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
||||||
} else {
|
} else {
|
||||||
urudev->last_hwstat_rd = *data;
|
urudev->last_hwstat_rd = libusb_control_transfer_get_data(transfer)[0];
|
||||||
fp_dbg("value %02x", urudev->last_hwstat_rd);
|
fp_dbg("value %02x", urudev->last_hwstat_rd);
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
}
|
}
|
||||||
libusb_urb_handle_free(urbh);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sm_get_hwstat(struct fpi_ssm *ssm)
|
static void sm_get_hwstat(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct libusb_urb_handle *urbh;
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
|
unsigned char *data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!transfer) {
|
||||||
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
|
||||||
|
|
||||||
/* The windows driver uses a request of 0x0c here. We use 0x04 to be
|
/* The windows driver uses a request of 0x0c here. We use 0x04 to be
|
||||||
* consistent with every other command we know about. */
|
* consistent with every other command we know about. */
|
||||||
/* FIXME is the above comment still true? */
|
/* FIXME is the above comment still true? */
|
||||||
struct libusb_control_transfer trf = {
|
libusb_fill_control_setup(data, CTRL_IN, USB_RQ, REG_HWSTAT, 0, 1);
|
||||||
.requesttype = CTRL_IN,
|
libusb_fill_control_transfer(transfer, dev->udev, data, sm_get_hwstat_cb,
|
||||||
.request = USB_RQ,
|
|
||||||
.value = REG_HWSTAT,
|
|
||||||
.index = 0,
|
|
||||||
.length = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
urbh = libusb_async_control_transfer(dev->udev, &trf, sm_get_hwstat_cb,
|
|
||||||
ssm, CTRL_TIMEOUT);
|
ssm, CTRL_TIMEOUT);
|
||||||
if (!urbh)
|
|
||||||
|
r = libusb_submit_transfer(transfer);
|
||||||
|
if (r < 0) {
|
||||||
|
g_free(data);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sm_fix_fw_read_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
static void sm_fix_fw_read_cb(struct libusb_transfer *transfer)
|
||||||
enum libusb_urb_cb_status status, struct libusb_ctrl_setup *setup,
|
|
||||||
unsigned char *data, int actual_length, void *user_data)
|
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
struct fpi_ssm *ssm = transfer->user_data;
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
unsigned char new;
|
unsigned char new;
|
||||||
unsigned char fwenc;
|
unsigned char fwenc;
|
||||||
uint32_t enc_addr = FIRMWARE_START + urudev->profile->fw_enc_offset;
|
uint32_t enc_addr = FIRMWARE_START + urudev->profile->fw_enc_offset;
|
||||||
|
|
||||||
if (status != FP_URB_COMPLETED) {
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_aborted(ssm, -EIO);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (actual_length != setup->wLength) {
|
} else if (transfer->actual_length != 1) {
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
fwenc = data[0];
|
fwenc = libusb_control_transfer_get_data(transfer)[0];
|
||||||
fp_dbg("firmware encryption byte at %x reads %02x", enc_addr, fwenc);
|
fp_dbg("firmware encryption byte at %x reads %02x", enc_addr, fwenc);
|
||||||
if (fwenc != 0x07 && fwenc != 0x17)
|
if (fwenc != 0x07 && fwenc != 0x17)
|
||||||
fp_dbg("strange encryption byte value, please report this");
|
fp_dbg("strange encryption byte value, please report this");
|
||||||
|
@ -652,7 +676,8 @@ static void sm_fix_fw_read_cb(libusb_dev_handle *devh, libusb_urb_handle *urbh,
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
libusb_urb_handle_free(urbh);
|
g_free(transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sm_fix_firmware(struct fpi_ssm *ssm)
|
static void sm_fix_firmware(struct fpi_ssm *ssm)
|
||||||
|
@ -660,20 +685,26 @@ static void sm_fix_firmware(struct fpi_ssm *ssm)
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct uru4k_dev *urudev = dev->priv;
|
struct uru4k_dev *urudev = dev->priv;
|
||||||
uint32_t enc_addr = FIRMWARE_START + urudev->profile->fw_enc_offset;
|
uint32_t enc_addr = FIRMWARE_START + urudev->profile->fw_enc_offset;
|
||||||
|
struct libusb_transfer *transfer = libusb_alloc_transfer();
|
||||||
|
unsigned char *data;
|
||||||
|
int r;
|
||||||
|
|
||||||
struct libusb_urb_handle *urbh;
|
if (!transfer) {
|
||||||
struct libusb_control_transfer trf_read_fw = {
|
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
||||||
.requesttype = 0xc0,
|
return;
|
||||||
.request = 0x0c,
|
}
|
||||||
.value = enc_addr,
|
|
||||||
.index = 0,
|
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
|
||||||
.length = 1,
|
libusb_fill_control_setup(data, 0xc0, 0x0c, enc_addr, 0, 1);
|
||||||
};
|
libusb_fill_control_transfer(transfer, dev->udev, data, sm_fix_fw_read_cb,
|
||||||
|
ssm, CTRL_TIMEOUT);
|
||||||
|
|
||||||
urbh = libusb_async_control_transfer(dev->udev, &trf_read_fw,
|
r = libusb_submit_transfer(transfer);
|
||||||
sm_fix_fw_read_cb, ssm, CTRL_TIMEOUT);
|
if (r < 0) {
|
||||||
if (!urbh)
|
g_free(data);
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
libusb_free_transfer(transfer);
|
||||||
|
fpi_ssm_mark_aborted(ssm, r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** INITIALIZATION *****/
|
/***** INITIALIZATION *****/
|
||||||
|
@ -1070,7 +1101,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Find fingerprint interface */
|
/* Find fingerprint interface */
|
||||||
config = libusb_dev_get_config(libusb_devh_get_dev(dev->udev));
|
config = libusb_get_config_descriptor(libusb_get_device(dev->udev));
|
||||||
for (i = 0; i < config->bNumInterfaces; i++) {
|
for (i = 0; i < config->bNumInterfaces; i++) {
|
||||||
struct libusb_interface *cur_iface = &config->interface[i];
|
struct libusb_interface *cur_iface = &config->interface[i];
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ enum fp_dev_state {
|
||||||
|
|
||||||
struct fp_dev {
|
struct fp_dev {
|
||||||
struct fp_driver *drv;
|
struct fp_driver *drv;
|
||||||
libusb_dev_handle *udev;
|
libusb_device_handle *udev;
|
||||||
uint32_t devtype;
|
uint32_t devtype;
|
||||||
void *priv;
|
void *priv;
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ enum fp_imgdev_verify_state {
|
||||||
|
|
||||||
struct fp_img_dev {
|
struct fp_img_dev {
|
||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
libusb_dev_handle *udev;
|
libusb_device_handle *udev;
|
||||||
enum fp_imgdev_action action;
|
enum fp_imgdev_action action;
|
||||||
int action_state;
|
int action_state;
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ void fpi_img_driver_setup(struct fp_img_driver *idriver);
|
||||||
container_of((drv), struct fp_img_driver, driver)
|
container_of((drv), struct fp_img_driver, driver)
|
||||||
|
|
||||||
struct fp_dscv_dev {
|
struct fp_dscv_dev {
|
||||||
libusb_dev *udev;
|
struct libusb_device *udev;
|
||||||
struct fp_driver *drv;
|
struct fp_driver *drv;
|
||||||
unsigned long driver_data;
|
unsigned long driver_data;
|
||||||
uint32_t devtype;
|
uint32_t devtype;
|
||||||
|
|
|
@ -180,7 +180,7 @@ API_EXPORTED int fp_enroll_finger_img(struct fp_dev *dev,
|
||||||
int stage = dev->__enroll_stage;
|
int stage = dev->__enroll_stage;
|
||||||
gboolean final = FALSE;
|
gboolean final = FALSE;
|
||||||
gboolean stopped = FALSE;
|
gboolean stopped = FALSE;
|
||||||
struct sync_enroll_data *edata;
|
struct sync_enroll_data *edata = NULL;
|
||||||
int r;
|
int r;
|
||||||
fp_dbg("");
|
fp_dbg("");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue