Compare commits

..

17 Commits

Author SHA1 Message Date
Benjamin Berg
615c370842 vfs301: Fix device pointer handling in callback
When porting the driver to the new libfprint 1.90.0 a mistake was made
where the device was not passed through user_data anymore but it was
still read from there. Stop using user_data in the callback to fix this.

Closes: #320
2020-10-23 18:48:17 +02:00
Vincent Huang
31319d9c6f synaptics: add support to pid 0xF9, 0xFC, 0xC2 2020-10-15 12:25:34 +08:00
Vincent Huang
e27b65c930 synaptics: add identify function 2020-10-14 18:48:09 +08:00
Benjamin Berg
b03f9a502a tests: Remove old README-umockdev file
It has been superseeded by README.md.
2020-10-14 12:39:10 +02:00
Benjamin Berg
44ef20d5ac aesx660: Use convenience API to allocate USB receive buffer
This also fixes a memory leak of the data as the g_free was missing and
none of the callback handlers free the data either.
2020-10-07 13:38:59 +02:00
Benjamin Berg
4719b30f16 aes1610: Use convenience API to allocate USB receive buffer 2020-10-07 13:38:59 +02:00
Benjamin Berg
7eb361087a drivers: Add access annotations to USB helpers
Mostly for completeness sake, doing this did not find any errors (but
might catch some issues with fixed buffer lengths).
2020-10-07 13:38:59 +02:00
Benjamin Berg
33d50e4e30 usb: Annotate access to USB buffers
Annotate the USB transfer creation functions with the correct buffer
access attribute. Note that we only annotate them as read_only as the
functions may be used for sending and receiving.

Hopefully this will catch buffer overflows in drivers in the future.
2020-10-07 13:22:18 +02:00
Benjamin Berg
994690cfa3 virtual-image: Only read socket when active
Doing this avoids race conditions in testing code where the code might
try to submit errors/images before the device has been activated. This
would then (sometimes) trigger assertions in the image driver code.
2020-10-07 09:44:49 +00:00
Benjamin Berg
52b2d10887 image-device: Delay task completion until device is deactivated
The earlier image device code tried to hide deactivation from the
surrounding library. However, this does not make any sense anymore with
the early reporting feature present.

This changes the operation to complete only once the device is
deactivated. Also changed that in most cases (except for cancellation)
we wait for the finger to be removed before deactivating the device.
2020-10-07 09:44:49 +00:00
Benjamin Berg
81e0f4dfe5 aes3k: Re-send some commands for each capture
The driver seems to have relied on the device to be fully
deactivated and activated again for each capture. This is not the case
during enroll, and as such in can cause issues.

Try fixing this by splitting out the last few commands send to the
device and assuming that this starts the capture.

Fixes: #306
2020-10-07 11:34:12 +02:00
Benjamin Berg
c7cab77fc1 usb-transfer: Work around libgusb cancellation issue
We have plenty of code paths where a transfer may be cancelled before it
is submitted. Unfortunately, libgusb up to and including version 0.3.6
are not handling that case correctly (due to libusb ignoring
cancellation on transfers that are not yet submitted).

Work around this, but do so in a somewhat lazy fashion that is not
entirely race free.

Closes: #306
2020-10-01 00:19:35 +02:00
Benjamin Berg
a63dcc96d5 virtual_image: Open a window for race conditions during open/close
Delay the open/close callbacks by 100ms so that we have a window of
opportunity for race conditions. This is needed to test certain
conditiosn in fprintd.
2020-09-29 12:02:19 +00:00
Benjamin Berg
fab349f356 Remove trailing \n where they are not necessary
Adding a trailing \n to g_message, g_debug, g_warning and g_error is not
neccessary, as a newline will be added automatically by the logging
infrastructure.
2020-09-29 10:42:03 +02:00
Benjamin Berg
62edf93958 tests: Add AES3500 test case
Thanks for Federico Cupellini for providing test samples.
2020-09-29 10:35:48 +02:00
Benjamin Berg
8c4ff253cb aes3k: Fix transfer error path and cancellable lifetime
The cancellable needs to be free'ed at deactivation. Also free it if we
run into a fatal error, which then in turn indicates that the device is
deactivated already.
2020-09-29 10:35:25 +02:00
Benjamin Berg
3ce6a15547 image-device: Don't deactivate if deactivation was already started
The test only prevent deactivation after it completed. Also guard
against trying to deactivate a second time.
2020-09-28 19:12:28 +02:00
29 changed files with 1070 additions and 283 deletions

View File

@@ -57,7 +57,7 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s\n", error->message);
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (enroll_data->loop);
}
@@ -89,7 +89,7 @@ on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
}
else
{
g_warning ("Enroll failed with error %s\n", error->message);
g_warning ("Enroll failed with error %s", error->message);
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,

View File

@@ -58,7 +58,7 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s\n", error->message);
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (capture_data->loop);
}

View File

@@ -54,7 +54,7 @@ on_device_closed (FpDevice *dev,
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s\n", error->message);
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (list_data->loop);
}
@@ -86,7 +86,7 @@ delete_next_print (FpDevice *dev,
g_assert_nonnull (list_data->to_delete);
print = list_data->to_delete->data;
g_debug ("Deleting print %s\n", fp_print_get_description (print));
g_debug ("Deleting print %s", fp_print_get_description (print));
fp_device_delete_print (dev, print, NULL,
(GAsyncReadyCallback) on_print_deleted, list_data);
}

View File

@@ -57,7 +57,7 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s\n", error->message);
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (verify_data->loop);
}

View File

@@ -135,10 +135,8 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
size_t bytes)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
unsigned char *data;
data = g_malloc (bytes);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, g_free);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,

View File

@@ -197,12 +197,12 @@ process_strip_data (FpiSsm *ssm, FpImageDevice *dev,
if (data[0] != AES2550_EDATA_MAGIC)
{
fp_dbg ("Bogus magic: %.2x\n", (int) (data[0]));
fp_dbg ("Bogus magic: %.2x", (int) (data[0]));
return FALSE;
}
len = data[1] * 256 + data[2];
if (len != (AES2550_STRIP_SIZE - 3))
fp_dbg ("Bogus frame len: %.4x\n", len);
fp_dbg ("Bogus frame len: %.4x", len);
stripe = g_malloc0 (FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); /* 4 bits per pixel */
stripe->delta_x = (int8_t) data[6];
stripe->delta_y = -(int8_t) data[7];

View File

@@ -106,7 +106,9 @@ static struct aes_regwrite init_reqs[] = {
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
};
static struct aes_regwrite capture_reqs[] = {
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
@@ -155,4 +157,6 @@ fpi_device_aes3500_class_init (FpiDeviceAes3500Class *klass)
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
aes_class->capture_reqs = capture_reqs;
aes_class->capture_reqs_len = G_N_ELEMENTS (capture_reqs);
}

View File

@@ -42,7 +42,10 @@
typedef struct
{
GCancellable *img_trf_cancel;
/* This is used both as a flag that we are in a capture operation
* and for cancellation.
*/
GCancellable *img_capture_cancel;
} FpiDeviceAes3kPrivate;
#define CTRL_TIMEOUT 1000
@@ -76,12 +79,16 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
{
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (device);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
unsigned char *ptr = transfer->buffer;
FpImage *tmp;
FpImage *img;
int i;
/* Image capture operation is finished (error/completed) */
g_clear_object (&priv->img_capture_cancel);
if (error)
{
if (g_error_matches (error,
@@ -95,6 +102,7 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
}
fpi_image_device_session_error (dev, error);
return;
}
fpi_image_device_report_finger_status (dev, TRUE);
@@ -118,11 +126,10 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_image_device_image_captured (dev, img);
/* FIXME: rather than assuming finger has gone, we should poll regs until
* it really has, then restart the capture */
* it really has. */
fpi_image_device_report_finger_status (dev, FALSE);
/* Note: We always restart the transfer, it may already be cancelled though. */
do_capture (dev);
/* Note: The transfer is re-started when we switch to the AWAIT_FINGER_ON state. */
}
static void
@@ -137,27 +144,51 @@ do_capture (FpImageDevice *dev)
fpi_usb_transfer_fill_bulk (img_trf, EP_IN, cls->data_buflen);
img_trf->short_is_error = TRUE;
fpi_usb_transfer_submit (g_steal_pointer (&img_trf), 0,
priv->img_trf_cancel,
priv->img_capture_cancel,
img_cb, NULL);
}
static void
capture_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
if (result)
{
g_clear_object (&priv->img_capture_cancel);
fpi_image_device_session_error (dev, result);
return;
}
/* FIXME: we never cancel a pending capture. So we are likely leaving the
* hardware in a bad state should we abort the capture operation and the
* user does not touch the device.
* But, we don't know how we might cancel, so just leave it as is. */
do_capture (dev);
}
static void
do_capture_start (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
aes_write_regv (dev, cls->capture_reqs, cls->capture_reqs_len, capture_reqs_cb, NULL);
}
static void
init_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
{
fpi_image_device_activate_complete (dev, result);
if (!result)
do_capture (dev);
}
static void
aes3k_dev_activate (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
g_assert (!priv->img_trf_cancel);
priv->img_trf_cancel = g_cancellable_new ();
aes_write_regv (dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL);
}
@@ -167,8 +198,26 @@ aes3k_dev_deactivate (FpImageDevice *dev)
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
/* Deactivation always finishes from the cancellation handler */
g_cancellable_cancel (priv->img_trf_cancel);
/* If a capture is running, then deactivation finishes from the cancellation handler */
if (priv->img_capture_cancel)
g_cancellable_cancel (priv->img_capture_cancel);
else
fpi_image_device_deactivate_complete (dev, NULL);
}
static void
aes3k_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
g_assert (!priv->img_capture_cancel);
priv->img_capture_cancel = g_cancellable_new ();
do_capture_start (dev);
}
}
static void
@@ -213,6 +262,7 @@ fpi_device_aes3k_class_init (FpiDeviceAes3kClass *klass)
img_class->img_open = aes3k_dev_init;
img_class->img_close = aes3k_dev_deinit;
img_class->activate = aes3k_dev_activate;
img_class->change_state = aes3k_dev_change_state;
img_class->deactivate = aes3k_dev_deactivate;
/* Extremely low due to low image quality. */

View File

@@ -57,4 +57,6 @@ struct _FpiDeviceAes3kClass
gsize data_buflen; /* buffer length of usb bulk transfer */
struct aes_regwrite *init_reqs; /* initial values sent to device */
gsize init_reqs_len;
struct aes_regwrite *capture_reqs; /* capture values sent to device */
gsize capture_reqs_len;
};

View File

@@ -103,7 +103,9 @@ static struct aes_regwrite init_reqs[] = {
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
};
static struct aes_regwrite capture_reqs[] = {
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
@@ -152,4 +154,6 @@ fpi_device_aes4000_class_init (FpiDeviceAes4000Class *klass)
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
aes_class->capture_reqs = capture_reqs;
aes_class->capture_reqs_len = G_N_ELEMENTS (capture_reqs);
}

View File

@@ -54,6 +54,7 @@ static void complete_deactivation (FpImageDevice *dev);
#define CALIBRATE_DATA_LEN 4
#define FINGER_DET_DATA_LEN 4
FP_GNUC_ACCESS (read_only, 3, 4)
static void
aesX660_send_cmd_timeout (FpiSsm *ssm,
FpDevice *_dev,
@@ -70,6 +71,7 @@ aesX660_send_cmd_timeout (FpiSsm *ssm,
fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
}
FP_GNUC_ACCESS (read_only, 3, 4)
static void
aesX660_send_cmd (FpiSsm *ssm,
FpDevice *dev,
@@ -89,13 +91,12 @@ aesX660_read_response (FpiSsm *ssm,
FpiUsbTransferCallback callback)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
unsigned char *data;
GCancellable *cancel = NULL;
if (cancellable)
cancel = fpi_device_get_cancellable (_dev);
data = g_malloc (buf_len);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, buf_len, NULL);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, buf_len);
transfer->ssm = ssm;
transfer->short_is_error = short_is_error;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL);
@@ -116,7 +117,7 @@ aesX660_read_calibrate_data_cb (FpiUsbTransfer *transfer,
/* Calibrate response was read correctly? */
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE)
{
fp_dbg ("Bogus calibrate response: %.2x\n", data[0]);
fp_dbg ("Bogus calibrate response: %.2x", data[0]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus calibrate "
@@ -155,14 +156,14 @@ finger_det_read_fd_data_cb (FpiUsbTransfer *transfer,
if (error)
{
fp_dbg ("Failed to read FD data\n");
fp_dbg ("Failed to read FD data");
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE)
{
fp_dbg ("Bogus FD response: %.2x\n", data[0]);
fp_dbg ("Bogus FD response: %.2x", data[0]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus FD response %.2x",
@@ -177,7 +178,7 @@ finger_det_read_fd_data_cb (FpiUsbTransfer *transfer,
}
else
{
fp_dbg ("Wait for finger returned %.2x as result\n",
fp_dbg ("Wait for finger returned %.2x as result",
data[AESX660_FINGER_PRESENT_OFFSET]);
fpi_ssm_jump_to_state (transfer->ssm, FINGER_DET_SEND_FD_CMD);
}
@@ -405,7 +406,7 @@ capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
g_byte_array_set_size (priv->stripe_packet, 0);
}
fp_dbg ("finger %s\n", finger_missing ? "missing" : "present");
fp_dbg ("finger %s", finger_missing ? "missing" : "present");
if (finger_missing)
fpi_ssm_next_state (transfer->ssm);
@@ -440,7 +441,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
break;
case CAPTURE_SET_IDLE:
fp_dbg ("Got %lu frames\n", priv->strips_len);
fp_dbg ("Got %lu frames", priv->strips_len);
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
capture_set_idle_cmd_cb);
break;
@@ -513,19 +514,19 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
if (error)
{
fp_dbg ("read_id cmd failed\n");
fp_dbg ("read_id cmd failed");
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
/* ID was read correctly */
if (data[0] == 0x07)
{
fp_dbg ("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x\n",
fp_dbg ("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x",
data[4], data[3], data[5], data[6], data[7]);
}
else
{
fp_dbg ("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
fp_dbg ("Bogus read ID response: %.2x", data[AESX660_RESPONSE_TYPE_OFFSET]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read ID response %.2x",
@@ -553,7 +554,7 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
break;
default:
fp_dbg ("Failed to init device! init status: %.2x\n", data[7]);
fp_dbg ("Failed to init device! init status: %.2x", data[7]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Failed to init device %.2x",
@@ -570,11 +571,11 @@ activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
unsigned char *data = transfer->buffer;
fp_dbg ("read_init_cb\n");
fp_dbg ("read_init_cb");
if (error)
{
fp_dbg ("read_init transfer status: %s, actual_len: %d\n", error->message,
fp_dbg ("read_init transfer status: %s, actual_len: %d", error->message,
(gint) transfer->actual_length);
fpi_ssm_mark_failed (transfer->ssm, error);
return;
@@ -582,7 +583,7 @@ activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
/* ID was read correctly */
if (data[0] != 0x42 || data[3] != 0x01)
{
fp_dbg ("Bogus read init response: %.2x %.2x\n", data[0],
fp_dbg ("Bogus read init response: %.2x %.2x", data[0],
data[3]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -614,13 +615,13 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
{
case ACTIVATE_SET_IDLE:
priv->init_seq_idx = 0;
fp_dbg ("Activate: set idle\n");
fp_dbg ("Activate: set idle");
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
fpi_ssm_usb_transfer_cb);
break;
case ACTIVATE_SEND_READ_ID_CMD:
fp_dbg ("Activate: read ID\n");
fp_dbg ("Activate: read ID");
aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd),
fpi_ssm_usb_transfer_cb);
break;
@@ -630,7 +631,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
break;
case ACTIVATE_SEND_INIT_CMD:
fp_dbg ("Activate: send init seq #%d cmd #%d\n",
fp_dbg ("Activate: send init seq #%d cmd #%d",
priv->init_seq_idx,
priv->init_cmd_idx);
aesX660_send_cmd (ssm, _dev,
@@ -640,7 +641,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
break;
case ACTIVATE_READ_INIT_RESPONSE:
fp_dbg ("Activate: read init response\n");
fp_dbg ("Activate: read init response");
aesX660_read_response (ssm, _dev, TRUE, FALSE, INIT_LEN, activate_read_init_cb);
break;

View File

@@ -31,6 +31,9 @@ static const FpIdEntry id_table[] = {
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xDF, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xF9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xFC, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xC2, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -659,6 +662,155 @@ verify (FpDevice *device)
synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
}
static void
identify_complete_after_finger_removal (FpiDeviceSynaptics *self)
{
FpDevice *device = FP_DEVICE (self);
if (self->finger_on_sensor)
{
fp_dbg ("delaying identify report until after finger removal!");
self->cmd_complete_on_removal = TRUE;
}
else
{
fpi_device_identify_complete (device, NULL);
}
}
static void
identify_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error)
{
FpDevice *device = FP_DEVICE (self);
if (error)
{
fpi_device_identify_complete (device, error);
return;
}
if (resp == NULL && self->cmd_complete_on_removal)
{
fpi_device_identify_complete (device, NULL);
return;
}
g_assert (resp != NULL);
switch (resp->response_id)
{
case BMKT_RSP_ID_READY:
fp_info ("Place Finger on the Sensor!");
break;
case BMKT_RSP_ID_FAIL:
if (resp->result == BMKT_SENSOR_STIMULUS_ERROR)
{
fp_info ("Match error occurred");
fpi_device_identify_report (device, NULL, NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_NO_MATCH)
{
fp_info ("Print didn't match");
fpi_device_identify_report (device, NULL, NULL, NULL);
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
{
fp_info ("Print is not in database");
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
}
else
{
fp_warn ("identify has failed: %d", resp->result);
fpi_device_identify_complete (device,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected result from device %d",
resp->result));
}
break;
case BMKT_RSP_ID_OK:
{
FpPrint *print = NULL;
GPtrArray *prints = NULL;
g_autoptr(GVariant) data = NULL;
guint8 finger;
const guint8 *user_id;
gsize user_id_len = 0;
gint cnt = 0;
gboolean find = FALSE;
fpi_device_get_identify_data (device, &prints);
for (cnt = 0; cnt < prints->len; cnt++)
{
print = g_ptr_array_index (prints, cnt);
g_object_get (print, "fpi-data", &data, NULL);
g_debug ("data is %p", data);
parse_print_data (data, &finger, &user_id, &user_id_len);
if (user_id)
{
if (memcmp (resp->response.id_resp.user_id, user_id, user_id_len) == 0)
{
find = TRUE;
break;
}
}
}
if(find)
{
fpi_device_identify_report (device, print, print, NULL);
fpi_device_identify_complete (device, NULL);
}
else
{
fpi_device_identify_report (device, NULL, NULL, NULL);
identify_complete_after_finger_removal (self);
}
}
}
}
static void
identify (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
FpPrint *print = NULL;
GPtrArray *prints = NULL;
g_autoptr(GVariant) data = NULL;
guint8 finger;
const guint8 *user_id;
gsize user_id_len = 0;
gint cnt = 0;
fpi_device_get_identify_data (device, &prints);
for (cnt = 0; cnt < prints->len; cnt++)
{
print = g_ptr_array_index (prints, cnt);
g_object_get (print, "fpi-data", &data, NULL);
g_debug ("data is %p", data);
if (!parse_print_data (data, &finger, &user_id, &user_id_len))
{
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return;
}
}
G_DEBUG_HERE ();
synaptics_sensor_cmd (self, 0, BMKT_CMD_ID_USER, NULL, 0, identify_msg_cb);
}
static void
enroll_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
@@ -1152,6 +1304,7 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
dev_class->close = dev_exit;
dev_class->probe = dev_probe;
dev_class->verify = verify;
dev_class->identify = identify;
dev_class->enroll = enroll;
dev_class->delete = delete_print;
dev_class->cancel = cancel;

View File

@@ -171,7 +171,7 @@ finger_present (unsigned char *img, size_t len, int sum_threshold)
if (img[i] < 160)
sum++;
fp_dbg ("finger_present: sum is %d\n", sum);
fp_dbg ("finger_present: sum is %d", sum);
return sum < sum_threshold ? 0 : 1;
}
@@ -184,7 +184,7 @@ finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
if (error)
{
fp_dbg ("data transfer status %s\n", error->message);
fp_dbg ("data transfer status %s", error->message);
fpi_image_device_session_error (dev, error);
return;
}
@@ -212,7 +212,7 @@ finger_det_cmd_cb (FpiUsbTransfer *t, FpDevice *device,
if (error)
{
fp_dbg ("req transfer status %s\n", error->message);
fp_dbg ("req transfer status %s", error->message);
fpi_image_device_session_error (dev, error);
return;
}
@@ -411,7 +411,7 @@ dev_init (FpImageDevice *dev)
break;
default:
fp_err ("Device variant %lu is not known\n", driver_data);
fp_err ("Device variant %lu is not known", driver_data);
g_assert_not_reached ();
fpi_image_device_open_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
return;

View File

@@ -78,6 +78,7 @@ upektc_img_cmd_update_crc (unsigned char *cmd_buf, size_t size)
cmd_buf[size - 1] = (crc & 0xff00) >> 8;
}
FP_GNUC_ACCESS (read_only, 3, 4)
static void
upektc_img_submit_req (FpiSsm *ssm,
FpImageDevice *dev,
@@ -193,7 +194,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
if (self->deactivating)
{
fp_dbg ("Deactivate requested\n");
fp_dbg ("Deactivate requested");
fpi_ssm_mark_completed (transfer->ssm);
return;
}
@@ -208,7 +209,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
if (fpi_ssm_get_cur_state (transfer->ssm) == CAPTURE_READ_DATA_TERM)
{
fp_dbg ("Terminating SSM\n");
fp_dbg ("Terminating SSM");
fpi_ssm_mark_completed (transfer->ssm);
return;
}
@@ -219,7 +220,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
response_size += 9; /* 7 bytes for header, 2 for CRC */
if (response_size > transfer->actual_length)
{
fp_dbg ("response_size is %lu, actual_length is %d\n",
fp_dbg ("response_size is %lu, actual_length is %d",
response_size, (gint) transfer->actual_length);
fp_dbg ("Waiting for rest of transfer");
BUG_ON (self->response_rest);
@@ -237,7 +238,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
{
/* No finger */
case 0x28:
fp_dbg ("18th byte is %.2x\n", data[18]);
fp_dbg ("18th byte is %.2x", data[18]);
switch (data[18])
{
case 0x0c:
@@ -254,7 +255,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
case 0x1e:
/* short scan */
fp_err ("short scan, aborting\n");
fp_err ("short scan, aborting");
fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY_TOO_SHORT);
fpi_image_device_report_finger_status (dev,
@@ -265,7 +266,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
case 0x1d:
/* too much horisontal movement */
fp_err ("too much horisontal movement, aborting\n");
fp_err ("too much horisontal movement, aborting");
fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY_CENTER_FINGER);
fpi_image_device_report_finger_status (dev,
@@ -276,7 +277,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
default:
/* some error happened, cancel scan */
fp_err ("something bad happened, stop scan\n");
fp_err ("something bad happened, stop scan");
fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY);
fpi_image_device_report_finger_status (dev,
@@ -307,7 +308,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
upektc_img_process_image_frame (self->image_bits + self->image_size,
data);
BUG_ON (self->image_size != IMAGE_SIZE);
fp_dbg ("Image size is %lu\n",
fp_dbg ("Image size is %lu",
self->image_size);
img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
img->flags |= FPI_IMAGE_PARTIAL;
@@ -320,7 +321,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
break;
default:
fp_err ("Unknown response!\n");
fp_err ("Unknown response!");
fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
break;
}
@@ -331,7 +332,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
break;
default:
fp_err ("Not handled response!\n");
fp_err ("Not handled response!");
fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
}
}

View File

@@ -723,7 +723,7 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
num_lines);
if (flags & BLOCKF_CHANGE_KEY)
{
fp_dbg ("changing encryption keys.\n");
fp_dbg ("changing encryption keys.");
img->block_info[self->img_block].flags &= ~BLOCKF_CHANGE_KEY;
img->key_number++;
self->img_enc_seed = rand ();

View File

@@ -42,6 +42,7 @@ async_write_callback (FpiUsbTransfer *transfer, FpDevice *device,
}
/* Send data to EP1, the only out endpoint */
FP_GNUC_ACCESS (read_only, 3, 4)
static void
async_write (FpiSsm *ssm,
FpDevice *dev,

View File

@@ -93,6 +93,7 @@ usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **
*out = g_steal_pointer (&transfer);
}
FP_GNUC_ACCESS (read_only, 2, 3)
static void
usb_send (FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error)
{
@@ -508,30 +509,30 @@ vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
FpDevice *device,
gpointer user_data, GError *error)
{
FpDeviceVfs301 *dev = user_data;
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (device);
if (error)
{
g_warning ("Error receiving data: %s", error->message);
g_error_free (error);
dev->recv_progress = VFS301_FAILURE;
self->recv_progress = VFS301_FAILURE;
return;
}
else if (transfer->actual_length < transfer->length)
{
/* TODO: process the data anyway? */
dev->recv_progress = VFS301_ENDED;
self->recv_progress = VFS301_ENDED;
return;
}
else
{
FpiUsbTransfer *new;
if (!vfs301_proto_process_data (dev,
if (!vfs301_proto_process_data (self,
transfer->length == VFS301_FP_RECV_LEN_1,
transfer->buffer,
transfer->actual_length))
{
dev->recv_progress = VFS301_ENDED;
self->recv_progress = VFS301_ENDED;
return;
}

View File

@@ -42,6 +42,7 @@ struct _FpDeviceVirtualImage
GSocketListener *listener;
GSocketConnection *connection;
GCancellable *listen_cancellable;
GCancellable *cancellable;
gint socket_fd;
@@ -185,15 +186,25 @@ recv_image_hdr_recv_cb (GObject *source_object,
}
static void
recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
recv_image (FpDeviceVirtualImage *self, GInputStream *stream)
{
g_input_stream_read_all_async (stream,
dev->recv_img_hdr,
sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT,
dev->cancellable,
recv_image_hdr_recv_cb,
dev);
FpiImageDeviceState state;
g_object_get (self, "fpi-image-device-state", &state, NULL);
g_debug ("Starting image receive (if active), state is: %i", state);
/* Only register if the state is active. */
if (state != FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
g_input_stream_read_all_async (stream,
self->recv_img_hdr,
sizeof (self->recv_img_hdr),
G_PRIORITY_DEFAULT,
self->cancellable,
recv_image_hdr_recv_cb,
self);
}
}
static void
@@ -217,11 +228,23 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
start_listen (dev);
}
/* Always further connections (but we disconnect them immediately
/* Always accept further connections (but we disconnect them immediately
* if we already have a connection). */
start_listen (dev);
if (dev->connection)
{
/* We may not have noticed that the stream was closed,
* if the device is deactivated. Double check here. */
g_input_stream_is_closed (g_io_stream_get_input_stream (G_IO_STREAM (dev->connection)));
g_io_stream_close (G_IO_STREAM (dev->connection), NULL, NULL);
g_clear_object (&dev->connection);
}
if (dev->connection)
{
g_warning ("Rejecting new connection");
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
g_object_unref (connection);
return;
@@ -231,16 +254,15 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
dev->automatic_finger = TRUE;
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
recv_image (dev, stream);
fp_dbg ("Got a new connection!");
recv_image (dev, stream);
}
static void
start_listen (FpDeviceVirtualImage *dev)
{
g_socket_listener_accept_async (dev->listener,
dev->cancellable,
dev->listen_cancellable,
new_connection_cb,
dev);
}
@@ -285,10 +307,12 @@ dev_init (FpImageDevice *dev)
self->listener = g_steal_pointer (&listener);
self->cancellable = g_cancellable_new ();
self->listen_cancellable = g_cancellable_new ();
start_listen (self);
fpi_image_device_open_complete (dev, NULL);
/* Delay result to open up the possibility of testing race conditions. */
fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_open_complete, NULL, NULL);
}
static void
@@ -299,11 +323,38 @@ dev_deinit (FpImageDevice *dev)
G_DEBUG_HERE ();
g_cancellable_cancel (self->cancellable);
g_cancellable_cancel (self->listen_cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listen_cancellable);
g_clear_object (&self->listener);
g_clear_object (&self->connection);
fpi_image_device_close_complete (dev, NULL);
/* Delay result to open up the possibility of testing race conditions. */
fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_close_complete, NULL, NULL);
}
static void
dev_activate (FpImageDevice *dev)
{
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
if (self->connection)
recv_image (self, g_io_stream_get_input_stream (G_IO_STREAM (self->connection)));
fpi_image_device_activate_complete (dev, NULL);
}
static void
dev_deactivate (FpImageDevice *dev)
{
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
self->cancellable = g_cancellable_new ();
/* XXX: Need to wait for the operation to be cancelled. */
fpi_device_add_timeout (FP_DEVICE (dev), 10, (FpTimeoutFunc) fpi_image_device_deactivate_complete, NULL, NULL);
}
static void
@@ -329,4 +380,7 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
}

View File

@@ -29,11 +29,13 @@ typedef struct
gboolean active;
gboolean cancelling;
gboolean enroll_await_on_pending;
gboolean finger_present;
gint enroll_stage;
guint pending_activation_timeout_id;
gboolean pending_activation_timeout_waiting_finger_off;
gboolean minutiae_scan_active;
GError *action_error;
FpImage *capture_image;
gint bz3_threshold;
} FpImageDevicePrivate;

View File

@@ -56,44 +56,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
* - sanitize_image seems a bit odd, in particular the sizing stuff.
**/
/* Static helper functions */
static gboolean
pending_activation_timeout (gpointer user_data)
{
FpImageDevice *self = FP_IMAGE_DEVICE (user_data);
FpDevice *device = FP_DEVICE (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpiDeviceAction action = fpi_device_get_current_action (device);
GError *error;
priv->pending_activation_timeout_id = 0;
if (priv->pending_activation_timeout_waiting_finger_off)
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_REMOVE_FINGER,
"Remove finger before requesting another scan operation");
else
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL, error);
fpi_device_verify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_report (device, NULL, NULL, error);
fpi_device_identify_complete (device, NULL);
}
else
{
/* Can this happen for enroll? */
fpi_device_action_error (device, error);
}
return G_SOURCE_REMOVE;
}
/* Callbacks/vfuncs */
static void
fp_image_device_open (FpDevice *device)
@@ -112,19 +74,8 @@ fp_image_device_close (FpDevice *device)
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
/* In the close case we may need to wait/force deactivation first.
* Three possible cases:
* 1. We are inactive
* -> immediately close
* 2. We are waiting for finger off
* -> immediately deactivate
* 3. We are deactivating
* -> handled by deactivate_complete */
if (!priv->active)
cls->img_close (self);
else if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE)
fpi_image_device_deactivate (self);
g_assert (priv->active == FALSE);
cls->img_close (self);
}
static void
@@ -146,12 +97,6 @@ fp_image_device_cancel_action (FpDevice *device)
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
/* XXX: Some nicer way of doing this would be good. */
fpi_device_action_error (FP_DEVICE (self),
g_error_new (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Device operation was cancelled"));
}
}
@@ -188,27 +133,9 @@ fp_image_device_start_capture_action (FpDevice *device)
}
priv->enroll_stage = 0;
priv->enroll_await_on_pending = FALSE;
/* The device might still be deactivating from a previous call.
* In that situation, try to wait for a bit before reporting back an
* error (which will usually say that the user should remove the
* finger).
*/
if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE || priv->active)
{
g_debug ("Got a new request while the device was still active");
g_assert (priv->pending_activation_timeout_id == 0);
priv->pending_activation_timeout_id =
g_timeout_add (100, pending_activation_timeout, device);
if (priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
priv->pending_activation_timeout_waiting_finger_off = TRUE;
else
priv->pending_activation_timeout_waiting_finger_off = FALSE;
return;
}
/* The internal state machine guarantees both of these. */
g_assert (!priv->finger_present);
g_assert (!priv->minutiae_scan_active);
/* And activate the device; we rely on fpi_image_device_activate_complete()
* to be called when done (or immediately). */
@@ -225,7 +152,6 @@ fp_image_device_finalize (GObject *object)
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_assert (priv->active == FALSE);
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
G_OBJECT_CLASS (fp_image_device_parent_class)->finalize (object);
}

View File

@@ -37,3 +37,9 @@ typedef struct _FpDeviceClass FpDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpDeviceClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDate, g_date_free);
#endif
#if __GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 1)
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
#else
#define FP_GNUC_ACCESS(m, p, s)
#endif

View File

@@ -56,11 +56,7 @@ fpi_image_device_activate (FpImageDevice *self)
priv->state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
/* We might have been waiting for deactivation to finish before
* starting the next operation. */
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
fp_dbg ("Activating image device\n");
fp_dbg ("Activating image device");
cls->activate (self);
}
@@ -71,7 +67,7 @@ fpi_image_device_deactivate (FpImageDevice *self)
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (device);
if (!priv->active)
if (!priv->active || priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
/* XXX: We currently deactivate both from minutiae scan result
* and finger off report. */
@@ -84,7 +80,7 @@ fpi_image_device_deactivate (FpImageDevice *self)
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
fp_dbg ("Deactivating image device\n");
fp_dbg ("Deactivating image device");
cls->deactivate (self);
}
@@ -100,13 +96,9 @@ fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
/* Cannot change to inactive using this function. */
g_assert (state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
/* We might have been waiting for the finger to go OFF to start the
* next operation. */
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
fp_dbg ("Image device internal state change from %s to %s\n",
fp_dbg ("Image device internal state change from %s to %s",
prev_state_str, state_str);
priv->state = state;
@@ -119,15 +111,75 @@ fp_image_device_enroll_maybe_await_finger_on (FpImageDevice *self)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
if (priv->enroll_await_on_pending)
/* We wait for both the minutiae scan to complete and the finger to
* be removed before we switch to AWAIT_FINGER_ON. */
if (priv->minutiae_scan_active || priv->finger_present)
return;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
static void
fp_image_device_maybe_complete_action (FpImageDevice *self, GError *error)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpDevice *device = FP_DEVICE (self);
FpiDeviceAction action;
if (error)
{
priv->enroll_await_on_pending = FALSE;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
/* Keep the first error we encountered, but not if it is of type retry */
if (priv->action_error && !(priv->action_error->domain == FP_DEVICE_RETRY))
{
g_warning ("Will complete with first error, new error was: %s", error->message);
g_free (error);
}
else
{
g_clear_error (&priv->action_error);
priv->action_error = error;
}
}
/* Do not complete if the device is still active or a minutiae scan is pending. */
if (priv->active || priv->minutiae_scan_active)
return;
if (!priv->action_error)
g_cancellable_set_error_if_cancelled (fpi_device_get_cancellable (device), &priv->action_error);
if (priv->action_error)
{
fpi_device_action_error (device, g_steal_pointer (&priv->action_error));
g_clear_object (&priv->capture_image);
return;
}
/* We are done, report the result. */
action = fpi_device_get_current_action (FP_DEVICE (self));
if (action == FPI_DEVICE_ACTION_ENROLL)
{
FpPrint *enroll_print;
fpi_device_get_enroll_data (device, &enroll_print);
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
}
else if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_CAPTURE)
{
fpi_device_capture_complete (device, g_steal_pointer (&priv->capture_image), NULL);
}
else
{
fp_dbg ("Awaiting finger on");
priv->enroll_await_on_pending = TRUE;
g_assert_not_reached ();
}
}
@@ -143,13 +195,15 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
FpiDeviceAction action;
/* Note: We rely on the device to not disappear during an operation. */
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
priv->minutiae_scan_active = FALSE;
if (!fp_image_detect_minutiae_finish (image, res, &error))
{
/* Cancel operation . */
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
fpi_device_action_error (device, g_steal_pointer (&error));
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_image_device_deactivate (self);
return;
}
@@ -161,13 +215,12 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_GENERAL, "Minutiae detection failed, please retry");
}
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
action = fpi_device_get_current_action (device);
if (action == FPI_DEVICE_ACTION_CAPTURE)
{
fpi_device_capture_complete (device, g_steal_pointer (&image), error);
fpi_image_device_deactivate (self);
priv->capture_image = g_steal_pointer (&image);
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
return;
}
@@ -181,7 +234,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (error->domain != FP_DEVICE_RETRY)
{
fpi_device_action_error (device, error);
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
/* We might not yet be deactivating, if we are enrolling. */
fpi_image_device_deactivate (self);
return;
}
@@ -205,7 +259,7 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
/* Start another scan or deactivate. */
if (priv->enroll_stage == IMG_ENROLL_STAGES)
{
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_image_device_deactivate (self);
}
else
@@ -226,8 +280,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
fpi_device_verify_complete (device, error);
fpi_image_device_deactivate (self);
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
@@ -249,8 +303,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_identify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
fpi_device_identify_complete (device, error);
fpi_image_device_deactivate (self);
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
}
else
{
@@ -323,24 +377,18 @@ fpi_image_device_report_finger_status (FpImageDevice *self,
g_debug ("Image device reported finger status: %s", present ? "on" : "off");
priv->finger_present = present;
if (present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_CAPTURE);
}
else if (!present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
{
/* We need to deactivate or continue to await finger */
/* There are three possible situations:
* 1. We are deactivating the device and the action is still in progress
* (minutiae detection).
* 2. We are still deactivating the device after an action completed
* 3. We were waiting for finger removal to start the new action
* Either way, we always end up deactivating except for the enroll case.
/* If we are in the non-enroll case, we always deactivate.
*
* The enroll case is special as AWAIT_FINGER_ON should only happen after
* minutiae detection to prevent deactivation (without cancellation)
* from the AWAIT_FINGER_ON state.
* In the enroll case, the decision can only be made after minutiae
* detection has finished.
*/
if (action != FPI_DEVICE_ACTION_ENROLL)
fpi_image_device_deactivate (self);
@@ -378,16 +426,18 @@ fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
action == FPI_DEVICE_ACTION_IDENTIFY ||
action == FPI_DEVICE_ACTION_CAPTURE);
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
g_debug ("Image device captured an image");
priv->minutiae_scan_active = TRUE;
/* XXX: We also detect minutiae in capture mode, we solely do this
* to normalize the image which will happen as a by-product. */
fp_image_detect_minutiae (image,
fpi_device_get_cancellable (FP_DEVICE (self)),
fpi_image_device_minutiae_detected,
self);
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
}
/**
@@ -423,36 +473,33 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
g_debug ("Reporting retry during enroll");
fpi_device_enroll_progress (FP_DEVICE (self), priv->enroll_stage, NULL, error);
/* Wait for finger removal and re-touch.
* TODO: Do we need to check that the finger is already off? */
priv->enroll_await_on_pending = TRUE;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
}
else if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
fp_image_device_maybe_complete_action (self, NULL);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_verify_complete (FP_DEVICE (self), NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
fp_image_device_maybe_complete_action (self, NULL);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_identify_complete (FP_DEVICE (self), NULL);
}
else
{
/* We abort the operation and let the surrounding code retry in the
* non-enroll case (this is identical to a session error). */
g_debug ("Abort current operation due to retry (non-enroll case)");
/* The capture case where there is no early reporting. */
g_debug ("Abort current operation due to retry (no early-reporting)");
fp_image_device_maybe_complete_action (self, error);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_action_error (FP_DEVICE (self), error);
}
}
@@ -512,9 +559,9 @@ fpi_image_device_session_error (FpImageDevice *self, GError *error)
g_warning ("Driver should report retries using fpi_image_device_retry_scan!");
priv->cancelling = TRUE;
fp_image_device_maybe_complete_action (self, error);
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_action_error (FP_DEVICE (self), error);
}
/**
@@ -565,8 +612,6 @@ void
fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
FpiDeviceAction action;
g_return_if_fail (priv->active == TRUE);
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE);
@@ -575,26 +620,10 @@ fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
priv->active = FALSE;
/* Deactivation completed. As we deactivate in the background
* there may already be a new task pending. Check whether we
* need to do anything. */
action = fpi_device_get_current_action (FP_DEVICE (self));
/* Assume finger was removed. */
priv->finger_present = FALSE;
/* Special case, if we should be closing, but didn't due to a running
* deactivation, then do so now. */
if (action == FPI_DEVICE_ACTION_CLOSE)
{
cls->img_close (self);
return;
}
/* We might be waiting to be able to activate again. */
if (priv->pending_activation_timeout_id)
{
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
priv->pending_activation_timeout_id =
g_idle_add ((GSourceFunc) fpi_image_device_activate, self);
}
fp_image_device_maybe_complete_action (self, error);
}
/**

View File

@@ -354,6 +354,24 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
fpi_usb_transfer_unref (transfer);
}
static gboolean
transfer_cancel_cb (FpiUsbTransfer *transfer)
{
GError *error;
FpiUsbTransferCallback callback;
error = g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Transfer was cancelled before being started");
callback = transfer->callback;
transfer->callback = NULL;
transfer->actual_length = -1;
callback (transfer, transfer->device, transfer->user_data, error);
fpi_usb_transfer_unref (transfer);
return G_SOURCE_REMOVE;
}
/**
* fpi_usb_transfer_submit:
@@ -387,6 +405,18 @@ fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
log_transfer (transfer, TRUE, NULL);
/* Work around libgusb cancellation issue, see
* https://github.com/hughsie/libgusb/pull/42
* should be fixed with libgusb 0.3.7.
* Note that this is not race free, we rely on libfprint and API users
* not cancelling from a different thread here.
*/
if (cancellable && g_cancellable_is_cancelled (cancellable))
{
g_idle_add ((GSourceFunc) transfer_cancel_cb, transfer);
return;
}
switch (transfer->type)
{
case FP_TRANSFER_BULK:

View File

@@ -20,6 +20,7 @@
#pragma once
#include <gusb.h>
#include "fpi-compat.h"
#include "fpi-device.h"
G_BEGIN_DECLS
@@ -115,6 +116,7 @@ void fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer,
guint8 endpoint,
gsize length);
FP_GNUC_ACCESS (read_only, 3, 4)
void fpi_usb_transfer_fill_bulk_full (FpiUsbTransfer *transfer,
guint8 endpoint,
guint8 *buffer,
@@ -134,6 +136,7 @@ void fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer,
guint8 endpoint,
gsize length);
FP_GNUC_ACCESS (read_only, 3, 4)
void fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer,
guint8 endpoint,
guint8 *buffer,

View File

@@ -1,53 +0,0 @@
To create a new umockdev test, you should:
1. Decide on what to test, the easiest case is just using the existing
capture test case.
2. Find the USB device you are testing with lsusb, e.g.:
Bus 001 Device 005: ID 138a:0090 Validity Sensors, Inc. VFS7500 Touch Fingerprint Sensor
This means we need to record USB device /dev/bus/usb/001/005
3. Run "umockdev-record /dev/bus/usb/001/005 >device"
This records the information about device, it should be placed into test/DRIVER/device
4. Run the test, for a capture test this would be:
umockdev-record -i /dev/bus/usb/001/005=capture.ioctl -- ./capture.py capture.png
This will create a capture.ioctl and capture.png file.
Please set the FP_DEVICE_EMULATION=1 environment variable. You may need
to adjust the driver to adapt to the emulated environment (mainly if it
uses random numbers, see synaptics.c for an example).
5. Place all files into the driver subdirectory test/DRIVER,
i.e. device, capture.ioctl, capture.png
6. Add glue to meson.build
7. Test whether everything works as expected
Please note, there is no need to use a real finger print in this case. If
you would like to avoid submitting your own fingerprint then please just
use e.g. the side of your finger, arm, or anything else that will produce
an image with the device.
Note that umockdev-record groups URBs aggressively. In most cases, manual
intervention is unfortunately required. In most cases, drivers do a chain
of commands like e.g. A then B each with a different reply. Umockdev will
create a file like:
A
reply 1
reply 2
B
reply 1
reply 2
which then needs to be re-ordered to be:
A
reply 1
B
reply 1
A
reply 2
B
reply 2
Other changes may be needed to get everything working. For example the elan
driver relies on a timeout that is not reported correctly. In this case the
driver works around it by interpreting the protocol error differently in
the virtual environment.

File diff suppressed because one or more lines are too long

BIN
tests/aes3500/capture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

561
tests/aes3500/device Normal file
View File

@@ -0,0 +1,561 @@
P: /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0/usb3/3-1/3-1.1/3-1.1.3
N: bus/usb/003/004=12011001FFFFFF08FF0831570000000100010902200001010080320904000002FFFFFF000705810240000007050202080000
E: BUSNUM=003
E: DEVNAME=/dev/bus/usb/003/004
E: DEVNUM=004
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_MODEL=Fingerprint_Sensor
E: ID_MODEL_ENC=Fingerprint\x20Sensor
E: ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor
E: ID_MODEL_ID=5731
E: ID_REVISION=0000
E: ID_SERIAL=08ff_Fingerprint_Sensor
E: ID_USB_INTERFACES=:ffffff:
E: ID_VENDOR=08ff
E: ID_VENDOR_ENC=08ff
E: ID_VENDOR_FROM_DATABASE=AuthenTec, Inc.
E: ID_VENDOR_ID=08ff
E: LIBFPRINT_DRIVER=AuthenTec AES3500
E: MAJOR=189
E: MINOR=259
E: PRODUCT=8ff/5731/0
E: SUBSYSTEM=usb
E: TYPE=255/255/255
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=ff
A: bDeviceProtocol=ff
A: bDeviceSubClass=ff
A: bMaxPacketSize0=8
A: bMaxPower=100mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0000
A: bmAttributes=80
A: busnum=3
A: configuration=
H: descriptors=12011001FFFFFF08FF0831570000000100010902200001010080320904000002FFFFFF000705810240000007050202080000
A: dev=189:259
A: devnum=4
A: devpath=1.1.3
L: driver=../../../../../../../../../../bus/usb/drivers/usb
A: idProduct=5731
A: idVendor=08ff
A: ltm_capable=no
A: maxchild=0
L: port=../3-1.1:1.0/3-1.1-port3
A: power/active_duration=3601332
A: power/async=enabled
A: power/autosuspend=2
A: power/autosuspend_delay_ms=2000
A: power/connected_duration=3601332
A: power/control=auto
A: power/level=auto
A: power/persist=1
A: power/runtime_active_kids=0
A: power/runtime_active_time=3601128
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=0
A: product=Fingerprint Sensor
A: quirks=0x0
A: removable=removable
A: speed=12
A: urbnum=82
A: version= 1.10
P: /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0/usb3/3-1/3-1.1
N: bus/usb/003/003=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
E: BUSNUM=003
E: DEVNAME=/dev/bus/usb/003/003
E: DEVNUM=003
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_39_00_0-usb-0_1_1
E: ID_MODEL=USB2.0_Hub
E: ID_MODEL_ENC=USB2.0\x20Hub\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
E: ID_MODEL_ID=0006
E: ID_PATH=pci-0000:39:00.0-usb-0:1.1
E: ID_PATH_TAG=pci-0000_39_00_0-usb-0_1_1
E: ID_REVISION=9100
E: ID_SERIAL=VIA_Labs__Inc._USB2.0_Hub
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR=VIA_Labs__Inc.
E: ID_VENDOR_ENC=VIA\x20Labs\x2c\x20Inc.\x20\x20\x20\x20\x20\x20\x20\x20\x20
E: ID_VENDOR_ID=2230
E: MAJOR=189
E: MINOR=258
E: PRODUCT=2230/6/9100
E: SUBSYSTEM=usb
E: TAGS=:seat:
E: TYPE=9/0/1
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=09
A: bDeviceProtocol=01
A: bDeviceSubClass=00
A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=9100
A: bmAttributes=e0
A: busnum=3
A: configuration=
H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
A: dev=189:258
A: devnum=3
A: devpath=1.1
L: driver=../../../../../../../../../bus/usb/drivers/usb
A: idProduct=0006
A: idVendor=2230
A: ltm_capable=no
A: manufacturer=VIA Labs, Inc.
A: maxchild=4
L: port=../3-1:1.0/3-1-port1
A: power/active_duration=3601776
A: power/async=enabled
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=3601776
A: power/control=auto
A: power/level=auto
A: power/runtime_active_kids=2
A: power/runtime_active_time=3601572
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=USB2.0 Hub
A: quirks=0x0
A: removable=fixed
A: speed=480
A: urbnum=40
A: version= 2.10
P: /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0/usb3/3-1
N: bus/usb/003/002=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
E: BUSNUM=003
E: DEVNAME=/dev/bus/usb/003/002
E: DEVNUM=002
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_39_00_0-usb-0_1
E: ID_MODEL=USB2.0_Hub
E: ID_MODEL_ENC=USB2.0\x20Hub\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
E: ID_MODEL_ID=0006
E: ID_PATH=pci-0000:39:00.0-usb-0:1
E: ID_PATH_TAG=pci-0000_39_00_0-usb-0_1
E: ID_REVISION=9100
E: ID_SERIAL=VIA_Labs__Inc._USB2.0_Hub
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR=VIA_Labs__Inc.
E: ID_VENDOR_ENC=VIA\x20Labs\x2c\x20Inc.\x20\x20\x20\x20\x20\x20\x20\x20\x20
E: ID_VENDOR_ID=2230
E: MAJOR=189
E: MINOR=257
E: PRODUCT=2230/6/9100
E: SUBSYSTEM=usb
E: TAGS=:seat:
E: TYPE=9/0/1
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=09
A: bDeviceProtocol=01
A: bDeviceSubClass=00
A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=9100
A: bmAttributes=e0
A: busnum=3
A: configuration=
H: descriptors=12011002090001403022060000910102000109021900010100E0000904000001090000000705810301000C
A: dev=189:257
A: devnum=2
A: devpath=1
L: driver=../../../../../../../../bus/usb/drivers/usb
A: idProduct=0006
A: idVendor=2230
A: ltm_capable=no
A: manufacturer=VIA Labs, Inc.
A: maxchild=4
L: port=../3-0:1.0/usb3-port1
A: power/active_duration=3602292
A: power/async=enabled
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=3602292
A: power/control=auto
A: power/level=auto
A: power/runtime_active_kids=1
A: power/runtime_active_time=3602016
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=USB2.0 Hub
A: quirks=0x0
A: removable=removable
A: speed=480
A: urbnum=31
A: version= 2.10
P: /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0/usb3
N: bus/usb/003/001=12010002090001406B1D020015040302010109021900010100E0000904000001090000000705810304000C
E: BUSNUM=003
E: DEVNAME=/dev/bus/usb/003/001
E: DEVNUM=001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_39_00_0
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_MODEL_ID=0002
E: ID_PATH=pci-0000:39:00.0
E: ID_PATH_TAG=pci-0000_39_00_0
E: ID_REVISION=0415
E: ID_SERIAL=Linux_4.15.0-117-generic_xhci-hcd_xHCI_Host_Controller_0000:39:00.0
E: ID_SERIAL_SHORT=0000:39:00.0
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR=Linux_4.15.0-117-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x204.15.0-117-generic\x20xhci-hcd
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_VENDOR_ID=1d6b
E: MAJOR=189
E: MINOR=256
E: PRODUCT=1d6b/2/415
E: SUBSYSTEM=usb
E: TAGS=:seat:
E: TYPE=9/0/1
A: authorized=1
A: authorized_default=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=09
A: bDeviceProtocol=01
A: bDeviceSubClass=00
A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0415
A: bmAttributes=e0
A: busnum=3
A: configuration=
H: descriptors=12010002090001406B1D020015040302010109021900010100E0000904000001090000000705810304000C
A: dev=189:256
A: devnum=1
A: devpath=0
L: driver=../../../../../../../bus/usb/drivers/usb
A: idProduct=0002
A: idVendor=1d6b
A: interface_authorized_default=1
A: ltm_capable=no
A: manufacturer=Linux 4.15.0-117-generic xhci-hcd
A: maxchild=2
A: power/active_duration=3602700
A: power/async=enabled
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=3602700
A: power/control=auto
A: power/level=auto
A: power/runtime_active_kids=1
A: power/runtime_active_time=3602700
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=xHCI Host Controller
A: quirks=0x0
A: removable=unknown
A: serial=0000:39:00.0
A: speed=480
A: urbnum=24
A: version= 2.00
P: /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0
E: DRIVER=xhci_hcd
E: ID_MODEL_FROM_DATABASE=DSL6340 USB 3.1 Controller [Alpine Ridge]
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d000015B5sv00002222sd00001111bc0Csc03i30
E: PCI_CLASS=C0330
E: PCI_ID=8086:15B5
E: PCI_SLOT_NAME=0000:39:00.0
E: PCI_SUBSYS_ID=2222:1111
E: SUBSYSTEM=pci
A: broken_parity_status=0
A: class=0x0c0330
H: config=8680B515060410000030030C200000000000F0D9000000000000000000000000000000000000000000000000222211110000000080000000000000000B010000
A: consistent_dma_mask_bits=64
A: current_link_speed=2.5 GT/s
A: current_link_width=4
A: d3cold_allowed=1
A: dbc=disabled
A: device=0x15b5
A: dma_mask_bits=64
L: driver=../../../../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)
A: enable=1
L: iommu=../../../../../virtual/iommu/dmar1
L: iommu_group=../../../../../../kernel/iommu_groups/17
A: irq=141
A: local_cpulist=0-3
A: local_cpus=f
A: max_link_speed=2.5 GT/s
A: max_link_width=4
A: modalias=pci:v00008086d000015B5sv00002222sd00001111bc0Csc03i30
A: msi_bus=1
A: msi_irqs/141=msi
A: numa_node=-1
A: pools=poolinfo - 0.1\nbuffer-2048 3 6 2048 3\nbuffer-512 12 16 512 2\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 15 15 2112 15\nxHCI ring segments 44 46 4096 46\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 3 32 128 1\nbuffer-32 0 0 32 0
A: power/async=enabled
A: power/control=on
A: power/runtime_active_kids=2
A: power/runtime_active_time=3602712
A: power/runtime_enabled=forbidden
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=1
A: power/wakeup=enabled
A: power/wakeup_abort_count=0
A: power/wakeup_active=0
A: power/wakeup_active_count=0
A: power/wakeup_count=0
A: power/wakeup_expire_count=0
A: power/wakeup_last_time_ms=224549241
A: power/wakeup_max_time_ms=0
A: power/wakeup_total_time_ms=0
A: resource=0x00000000d9f00000 0x00000000d9f0ffff 0x0000000000040200\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000
A: revision=0x00
A: subsystem_device=0x1111
A: subsystem_vendor=0x2222
A: vendor=0x8086
P: /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0
E: DRIVER=pcieport
E: ID_MODEL_FROM_DATABASE=DSL6340 Thunderbolt 3 Bridge [Alpine Ridge 2C 2015]
E: ID_PCI_CLASS_FROM_DATABASE=Bridge
E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode
E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d00001576sv00002222sd00001111bc06sc04i00
E: PCI_CLASS=60400
E: PCI_ID=8086:1576
E: PCI_SLOT_NAME=0000:02:02.0
E: PCI_SUBSYS_ID=2222:1111
E: SUBSYSTEM=pci
A: broken_parity_status=0
A: class=0x060400
H: config=86807615060410000000040620000100000000000000000002393900F1010000F0D9F0D9F1FF010000000000000000000000000080000000000000000B011000
A: consistent_dma_mask_bits=32
A: current_link_speed=2.5 GT/s
A: current_link_width=4
A: d3cold_allowed=1
A: device=0x1576
A: dma_mask_bits=32
L: driver=../../../../../bus/pci/drivers/pcieport
A: driver_override=(null)
A: enable=1
L: iommu=../../../../virtual/iommu/dmar1
L: iommu_group=../../../../../kernel/iommu_groups/17
A: irq=140
A: local_cpulist=0-3
A: local_cpus=f
A: max_link_speed=2.5 GT/s
A: max_link_width=4
A: modalias=pci:v00008086d00001576sv00002222sd00001111bc06sc04i00
A: msi_bus=1
A: msi_irqs/140=msi
A: numa_node=-1
A: power/async=enabled
A: power/clk_ctl=0
A: power/control=on
A: power/link_state=0
A: power/runtime_active_kids=1
A: power/runtime_active_time=3602728
A: power/runtime_enabled=forbidden
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=2
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: resource=0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x00000000d9f00000 0x00000000d9ffffff 0x0000000000000200\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000
A: revision=0x00
A: secondary_bus_number=57
A: subordinate_bus_number=57
A: subsystem_device=0x1111
A: subsystem_vendor=0x2222
A: vendor=0x8086
P: /devices/pci0000:00/0000:00:1c.0/0000:01:00.0
E: DRIVER=pcieport
E: ID_MODEL_FROM_DATABASE=DSL6340 Thunderbolt 3 Bridge [Alpine Ridge 2C 2015]
E: ID_PCI_CLASS_FROM_DATABASE=Bridge
E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode
E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d00001576sv00002222sd00001111bc06sc04i00
E: PCI_CLASS=60400
E: PCI_ID=8086:1576
E: PCI_SLOT_NAME=0000:01:00.0
E: PCI_SUBSYS_ID=2222:1111
E: SUBSYSTEM=pci
A: broken_parity_status=0
A: class=0x060400
H: config=86807615060410000000040620000100000000000000000001023900F101000000C400DA01A0F1C100000000000000000000000080000000000000000B011000
A: consistent_dma_mask_bits=32
A: current_link_speed=8 GT/s
A: current_link_width=2
A: d3cold_allowed=1
A: device=0x1576
A: dma_mask_bits=32
L: driver=../../../../bus/pci/drivers/pcieport
A: driver_override=(null)
A: enable=1
L: iommu=../../../virtual/iommu/dmar1
L: iommu_group=../../../../kernel/iommu_groups/14
A: irq=137
A: local_cpulist=0-3
A: local_cpus=f
A: max_link_speed=8 GT/s
A: max_link_width=4
A: modalias=pci:v00008086d00001576sv00002222sd00001111bc06sc04i00
A: msi_bus=1
A: msi_irqs/137=msi
A: numa_node=-1
A: power/async=enabled
A: power/control=on
A: power/runtime_active_kids=2
A: power/runtime_active_time=3602740
A: power/runtime_enabled=forbidden
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=2
A: power/wakeup=enabled
A: power/wakeup_abort_count=0
A: power/wakeup_active=0
A: power/wakeup_active_count=0
A: power/wakeup_count=0
A: power/wakeup_expire_count=0
A: power/wakeup_last_time_ms=224549237
A: power/wakeup_max_time_ms=0
A: power/wakeup_total_time_ms=0
A: resource=0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x00000000c4000000 0x00000000da0fffff 0x0000000000000200\n0x00000000a0000000 0x00000000c1ffffff 0x0000000000102201\n0x0000000000000000 0x0000000000000000 0x0000000000000000
A: revision=0x00
A: secondary_bus_number=2
A: subordinate_bus_number=57
A: subsystem_device=0x1111
A: subsystem_vendor=0x2222
A: vendor=0x8086
P: /devices/pci0000:00/0000:00:1c.0
E: DRIVER=pcieport
E: ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port
E: ID_PCI_CLASS_FROM_DATABASE=Bridge
E: ID_PCI_INTERFACE_FROM_DATABASE=Normal decode
E: ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d00009D10sv00001028sd0000075Bbc06sc04i00
E: PCI_CLASS=60400
E: PCI_ID=8086:9D10
E: PCI_SLOT_NAME=0000:00:1c.0
E: PCI_SUBSYS_ID=1028:075B
E: SUBSYSTEM=pci
A: broken_parity_status=0
A: class=0x060400
H: config=8680109D07041000F1000406000081000000000000000000000139002020002000C400DA01A0F1C100000000000000000000000040000000000000000B011000
A: consistent_dma_mask_bits=32
A: current_link_speed=8 GT/s
A: current_link_width=2
A: d3cold_allowed=1
A: device=0x9d10
A: dma_mask_bits=32
L: driver=../../../bus/pci/drivers/pcieport
A: driver_override=(null)
A: enable=1
L: iommu=../../virtual/iommu/dmar1
L: iommu_group=../../../kernel/iommu_groups/6
A: irq=123
A: local_cpulist=0-3
A: local_cpus=f
A: max_link_speed=8 GT/s
A: max_link_width=2
A: modalias=pci:v00008086d00009D10sv00001028sd0000075Bbc06sc04i00
A: msi_bus=1
A: msi_irqs/123=msi
A: numa_node=-1
A: power/async=enabled
A: power/control=on
A: power/runtime_active_kids=1
A: power/runtime_active_time=228151860
A: power/runtime_enabled=forbidden
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=2
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: resource=0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000002000 0x0000000000002fff 0x0000000000000100\n0x00000000c4000000 0x00000000da0fffff 0x0000000000000200\n0x00000000a0000000 0x00000000c1ffffff 0x0000000000102201\n0x0000000000000000 0x0000000000000000 0x0000000000000000
A: revision=0xf1
A: secondary_bus_number=1
A: subordinate_bus_number=57
A: subsystem_device=0x075b
A: subsystem_vendor=0x1028
A: vendor=0x8086

View File

@@ -17,6 +17,7 @@ envs.set('FP_DRIVERS_WHITELIST', 'virtual_image')
envs.set('NO_AT_BRIDGE', '1')
drivers_tests = [
'aes3500',
'elan',
'synaptics',
'vfs0050',