Compare commits

..

8 Commits

Author SHA1 Message Date
Benjamin Berg
2a9ad74ec4 print: Reject enroll images that can't be matched
If the score of a print matching itself is too low to match, then
reject it. It can never match and it is therefore completely useless.

Also change this into a non-fatal error, the user is free to retry the
enroll step in the hope that more minutiae is found (e.g. longer swipe).
2022-05-17 19:16:32 +00:00
Benjamin Berg
56ae75d2b2 device: Fully re-evaluate suspend/resume logic when delayed
If we delayed the suspend(/resume) call, then the circumstances may have
changed. In particular, an active action may have completed already
which means that the driver handler should not be called anymore.
2022-05-17 20:29:00 +02:00
Benjamin Berg
54a98bb286 device: Run critical section flushing with a high priority
These delayed calls are pushed into the mainloop for consistency.
However, they should run immediately and not be delayed, as such, it
makes sense to run them at a higher priority.

This actually solves an issue inside the CI where an URB reply is played
back even though it should be cancelled by the client.
2022-05-17 20:29:00 +02:00
Benjamin Berg
bfbe24b172 synaptics: Correctly handle critical section during interrupt resubmit
We re-aquire the critical section at the start of the callback, however,
it needs to be dropped again (or not taken) if the interrupt transfer is
resubmitted.
2022-05-17 20:29:00 +02:00
Benjamin Berg
1f925fef7c tests: Test suspend/resume and sysfs attributes in synaptics 2022-05-17 20:29:00 +02:00
Benjamin Berg
7b0093b4c6 tests: Reset the USB device before testing
The kernel caches URBs to get descriptor values. Doing a reset before
starting the record ensures that we will see any descriptor reads in the
usbmon trace and can therefore correctly replay them (possibly not true
if they happen multiple times).
2022-05-17 20:29:00 +02:00
Benjamin Berg
0fd5a617ab device: Do not update sysfs attributes if value is correct
This avoids spurious warnings on e.g. SELinux enabled systems.
2022-05-17 20:29:00 +02:00
Matthew Mirvish
e7d041d258 elanspi: add 04f3:241f
Reported as working with this config in
https://github.com/mincrmatt12/elan-spi-fingerprint/issues/11.
2022-05-08 18:32:29 -04:00
13 changed files with 408 additions and 475 deletions

View File

@@ -63,7 +63,6 @@ struct _FpiDeviceElanSpi
guint16 gdac_step; guint16 gdac_step;
guint16 best_gdac; guint16 best_gdac;
guint16 best_meandiff; guint16 best_meandiff;
guint16 target_mean;
} hv_data; } hv_data;
}; };
@@ -409,10 +408,6 @@ elanspi_determine_sensor (FpiDeviceElanSpi *self, GError **err)
self->frame_width = self->sensor_width; self->frame_width = self->sensor_width;
self->frame_height = self->sensor_height > ELANSPI_MAX_FRAME_HEIGHT ? ELANSPI_MAX_FRAME_HEIGHT : self->sensor_height; self->frame_height = self->sensor_height > ELANSPI_MAX_FRAME_HEIGHT ? ELANSPI_MAX_FRAME_HEIGHT : self->sensor_height;
} }
/* check x571 flag */
if (self->sensor_id == 0xe)
self->hv_data.target_mean = (fpi_device_get_driver_data (FP_DEVICE (self)) & ELANSPI_QUIRK_X571 ? ELANSPI_HV_X571_CALIBRATION_TARGET_MEAN : ELANSPI_HV_CALIBRATION_TARGET_MEAN);
} }
static void static void
@@ -547,7 +542,7 @@ elanspi_write_regtable (FpiDeviceElanSpi *self, const struct elanspi_regtable *
for (int i = 0; table->entries[i].table; i += 1) for (int i = 0; table->entries[i].table; i += 1)
{ {
if (table->entries[i].sid == self->sensor_id && table->entries[i].quirk == (fpi_device_get_driver_data (FP_DEVICE (self)) & ELANSPI_QUIRK_MASK)) if (table->entries[i].sid == self->sensor_id)
{ {
starting_entry = table->entries[i].table; starting_entry = table->entries[i].table;
break; break;
@@ -697,8 +692,6 @@ static void
elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpointer unused_data, GError *error) elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpointer unused_data, GError *error)
{ {
FpiDeviceElanSpi *self = FPI_DEVICE_ELANSPI (dev); FpiDeviceElanSpi *self = FPI_DEVICE_ELANSPI (dev);
ptrdiff_t outptr = 0, inptr = 0;
guint16 value = 0;
if (error) if (error)
{ {
@@ -706,41 +699,26 @@ elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpoin
return; return;
} }
if (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571) int i, outptr;
guint16 value = 0;
for (i = 0, outptr = 0; i < transfer->length_rd && outptr < (self->sensor_height * self->sensor_width * 2); i += 1)
{ {
/* decode image in x571 mode (just copy and fix endian) */ if (transfer->buffer_rd[i] != 0xff)
for (int y = 0; y < self->sensor_height; y += 1)
{
inptr += 2; /* 2 dummy bytes per line at start */
for (int x = 0; x < self->sensor_width; x += 1)
{
self->last_image[outptr / 2] = transfer->buffer_rd[inptr] + transfer->buffer_rd[inptr + 1] * 0x100;
inptr += 2;
outptr += 2;
}
}
}
else
{
/* decode image (normal case; with weird 0xff checks) */
for (inptr = 0, outptr = 0; inptr < transfer->length_rd && outptr < (self->sensor_height * self->sensor_width * 2); inptr += 1)
{
if (transfer->buffer_rd[inptr] != 0xff)
{ {
if (outptr % 2) if (outptr % 2)
{ {
value <<= 8; value <<= 8;
value |= transfer->buffer_rd[inptr]; value |= transfer->buffer_rd[i];
self->last_image[outptr / 2] = value; self->last_image[outptr / 2] = value;
} }
else else
{ {
value = transfer->buffer_rd[inptr]; value = transfer->buffer_rd[i];
} }
outptr += 1; outptr += 1;
} }
} }
}
if (outptr != (self->sensor_height * self->sensor_width * 2)) if (outptr != (self->sensor_height * self->sensor_width * 2))
{ {
@@ -796,16 +774,11 @@ elanspi_capture_hv_handler (FpiSsm *ssm, FpDevice *dev)
return; return;
} }
/* otherwise, read the image /* otherwise, read the image
* the hv sensors seem to use variable-length padding(?) this is only tested on the 0xe sensors * the hv sensors seem to use 128 bytes of padding(?) this is only tested on the 0xe sensors */
*
* in the x571 mode, the padding appears to be disabled and it just has 2 bytes of junk */
xfer = fpi_spi_transfer_new (dev, self->spi_fd); xfer = fpi_spi_transfer_new (dev, self->spi_fd);
xfer->ssm = ssm; xfer->ssm = ssm;
fpi_spi_transfer_write (xfer, 2); fpi_spi_transfer_write (xfer, 2);
xfer->buffer_wr[0] = 0x10; /* receieve line/image */ xfer->buffer_wr[0] = 0x10; /* receieve line */
if (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571)
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 2) - 2);
else
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 48)); fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 48));
fpi_spi_transfer_submit (xfer, fpi_device_get_cancellable (dev), elanspi_capture_hv_image_handler, NULL); fpi_spi_transfer_submit (xfer, fpi_device_get_cancellable (dev), elanspi_capture_hv_image_handler, NULL);
return; return;
@@ -900,7 +873,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
case ELANSPI_CALIBHV_PROCESS: case ELANSPI_CALIBHV_PROCESS:
/* compute mean */ /* compute mean */
mean_diff = abs (elanspi_mean_image (self, self->last_image) - self->hv_data.target_mean); mean_diff = abs (elanspi_mean_image (self, self->last_image) - ELANSPI_HV_CALIBRATION_TARGET_MEAN);
if (mean_diff < 100) if (mean_diff < 100)
{ {
fp_dbg ("<calibhv> calibration ok (mdiff < 100 w/ gdac=%04x)", self->hv_data.gdac_value); fp_dbg ("<calibhv> calibration ok (mdiff < 100 w/ gdac=%04x)", self->hv_data.gdac_value);
@@ -923,7 +896,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
return; return;
} }
/* update gdac */ /* update gdac */
if (elanspi_mean_image (self, self->last_image) < self->hv_data.target_mean) if (elanspi_mean_image (self, self->last_image) < ELANSPI_HV_CALIBRATION_TARGET_MEAN)
self->hv_data.gdac_value -= self->hv_data.gdac_step; self->hv_data.gdac_value -= self->hv_data.gdac_step;
else else
self->hv_data.gdac_value += self->hv_data.gdac_step; self->hv_data.gdac_value += self->hv_data.gdac_step;

View File

@@ -71,7 +71,6 @@ struct elanspi_regtable
struct struct
{ {
unsigned char sid; unsigned char sid;
unsigned quirk;
const struct elanspi_reg_entry *table; const struct elanspi_reg_entry *table;
} entries[]; } entries[];
}; };
@@ -173,11 +172,11 @@ static const struct elanspi_reg_entry elanspi_calibration_table_id0[] = {
static const struct elanspi_regtable elanspi_calibration_table_old = { static const struct elanspi_regtable elanspi_calibration_table_old = {
.other = elanspi_calibration_table_default, .other = elanspi_calibration_table_default,
.entries = { .entries = {
{ .sid = 0x0, .quirk = 0, .table = elanspi_calibration_table_id0 }, { .sid = 0x0, .table = elanspi_calibration_table_id0 },
{ .sid = 0x5, .quirk = 0, .table = elanspi_calibration_table_id57 }, { .sid = 0x5, .table = elanspi_calibration_table_id57 },
{ .sid = 0x6, .quirk = 0, .table = elanspi_calibration_table_id6 }, { .sid = 0x6, .table = elanspi_calibration_table_id6 },
{ .sid = 0x7, .quirk = 0, .table = elanspi_calibration_table_id57 }, { .sid = 0x7, .table = elanspi_calibration_table_id57 },
{ .sid = 0x0, .quirk = 0, .table = NULL } { .sid = 0x0, .table = NULL }
} }
}; };
@@ -313,133 +312,20 @@ static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14[] = {
{0xff, 0xff} {0xff, 0xff}
}; };
static const struct elanspi_reg_entry elanspi_calibration_table_page0_id14_x571[] = { static const struct elanspi_regtable elanspi_calibration_table_new_page0 = {
{0x00, 0x5a}, .other = NULL,
{0x01, 0x00}, .entries = {
{0x02, 0x4f}, { .sid = 0xe, .table = elanspi_calibration_table_page0_id14 },
{0x03, 0x00}, { .sid = 0x0, .table = NULL }
{0x09, 0x04}, }
{0x04, 0x4f},
{0x05, 0xa0},
{0x06, 0x57},
{0x07, 0x02},
{0x08, 0x00},
{0x0a, 0x63},
{0x0b, 0x01},
{0x0c, 0x08},
{0x0d, 0x00},
{0x0e, 0x00},
{0x0f, 0x13},
{0x10, 0x38},
{0x11, 0x01},
{0x12, 0x04},
{0x13, 0x00},
{0x14, 0x00},
{0x15, 0x04},
{0x16, 0x02},
{0x17, 0x00},
{0x18, 0x01},
{0x19, 0xf4},
{0x1a, 0x00},
{0x1b, 0x00},
{0x1c, 0x00},
{0x1d, 0x00},
{0x1e, 0x00},
{0x1f, 0x00},
{0x20, 0x00},
{0x21, 0x00},
{0x22, 0x06},
{0x23, 0x00},
{0x24, 0x00},
{0x25, 0x00},
{0x26, 0x00},
{0x27, 0xff},
{0x28, 0x00},
{0x29, 0x04},
{0x2b, 0xe2},
{0x2e, 0xd0},
{0x2f, 0x40},
{0x30, 0x01},
{0x31, 0x38},
{0x32, 0x00},
{0x33, 0x00},
{0x34, 0x00},
{0x35, 0x1f},
{0x36, 0xff},
{0x37, 0x00},
{0x38, 0x00},
{0x39, 0x00},
{0x3a, 0x00},
{0x2a, 0x5f},
{0x2c, 0x10},
{0xff, 0xff}
}; };
static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14_x571[] = { static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
{0x00, 0xfb}, .other = NULL,
{0x01, 0xff}, .entries = {
{0x02, 0x7f}, { .sid = 0xe, .table = elanspi_calibration_table_page1_id14 },
{0x03, 0xd4}, { .sid = 0x0, .table = NULL }
{0x04, 0x7d}, }
{0x05, 0x19},
{0x06, 0x80},
{0x07, 0x40},
{0x08, 0x11},
{0x09, 0x00},
{0x0a, 0x00},
{0x0b, 0x00},
{0x0c, 0x00},
{0x0d, 0x00},
{0x0e, 0x32},
{0x0f, 0x00},
{0x10, 0x00},
{0x11, 0x32},
{0x12, 0x02},
{0x13, 0x08},
{0x14, 0x5c},
{0x15, 0x01},
{0x16, 0x15},
{0x17, 0x01},
{0x18, 0x14},
{0x19, 0x01},
{0x1a, 0x14},
{0x1b, 0x01},
{0x1c, 0x16},
{0x1d, 0x01},
{0x1e, 0x0b},
{0x1f, 0x01},
{0x20, 0x0b},
{0x21, 0x02},
{0x22, 0x08},
{0x23, 0x29},
{0x24, 0x00},
{0x25, 0x0c},
{0x26, 0x1b},
{0x27, 0x15},
{0x28, 0x1b},
{0x29, 0x15},
{0x2a, 0x00},
{0x2b, 0x00},
{0x2c, 0x01},
{0x2d, 0x16},
{0x2e, 0x01},
{0x2f, 0x16},
{0x30, 0x04},
{0x31, 0x44},
{0x32, 0x04},
{0x33, 0x44},
{0x34, 0x14},
{0x35, 0x00},
{0x36, 0x00},
{0x37, 0x00},
{0x38, 0x00},
{0x39, 0x03},
{0x3a, 0xfe},
{0x3b, 0x00},
{0x3c, 0x00},
{0x3d, 0x02},
{0x3e, 0x00},
{0x3f, 0x00}
}; };
#define ELANSPI_NO_ROTATE 0 #define ELANSPI_NO_ROTATE 0
@@ -449,33 +335,10 @@ static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14_x571[
#define ELANSPI_HV_FLIPPED 1 #define ELANSPI_HV_FLIPPED 1
#define ELANSPI_ROTATE_MASK 3
#define ELANSPI_QUIRK_X571 (1 << 2)
#define ELANSPI_QUIRK_MASK (ELANSPI_QUIRK_X571)
#define ELANSPI_UDEV_TYPES FPI_DEVICE_UDEV_SUBTYPE_SPIDEV | FPI_DEVICE_UDEV_SUBTYPE_HIDRAW #define ELANSPI_UDEV_TYPES FPI_DEVICE_UDEV_SUBTYPE_SPIDEV | FPI_DEVICE_UDEV_SUBTYPE_HIDRAW
#define ELANSPI_TP_VID 0x04f3 #define ELANSPI_TP_VID 0x04f3
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = { // using checkargs ACPI:HIDPID
.other = NULL,
.entries = {
{ .sid = 0xe, .quirk = 0, .table = elanspi_calibration_table_page0_id14 },
{ .sid = 0xe, .quirk = ELANSPI_QUIRK_X571, .table = elanspi_calibration_table_page0_id14_x571 },
{ .sid = 0x0, .table = NULL }
}
};
static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
.other = NULL,
.entries = {
{ .sid = 0xe, .quirk = 0, .table = elanspi_calibration_table_page1_id14 },
{ .sid = 0xe, .quirk = ELANSPI_QUIRK_X571, .table = elanspi_calibration_table_page1_id14_x571 },
{ .sid = 0x0, .table = NULL }
}
};
static const FpIdEntry elanspi_id_table[] = { static const FpIdEntry elanspi_id_table[] = {
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE}, {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE}, {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
@@ -485,7 +348,7 @@ static const FpIdEntry elanspi_id_table[] = {
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE}, {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE}, {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE}, {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3104}, .driver_data = ELANSPI_QUIRK_X571 | ELANSPI_90RIGHT_ROTATE}, {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x241f}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = 0} {.udev_types = 0}
}; };
@@ -495,7 +358,6 @@ static const FpIdEntry elanspi_id_table[] = {
#define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000 #define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000
#define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000 #define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000
#define ELANSPI_HV_X571_CALIBRATION_TARGET_MEAN 7000
#define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6 #define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6
#define ELANSPI_MAX_REAL_INVALID_PERCENT 3 #define ELANSPI_MAX_REAL_INVALID_PERCENT 3

View File

@@ -225,6 +225,7 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
} }
else else
{ {
fpi_device_critical_leave (device);
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer), fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
0, 0,
NULL, NULL,

View File

@@ -130,6 +130,9 @@ typedef struct
void match_data_free (FpMatchData *match_data); void match_data_free (FpMatchData *match_data);
void fpi_device_suspend (FpDevice *device);
void fpi_device_resume (FpDevice *device);
void fpi_device_configure_wakeup (FpDevice *device, void fpi_device_configure_wakeup (FpDevice *device,
gboolean enabled); gboolean enabled);
void fpi_device_update_temp (FpDevice *device, void fpi_device_update_temp (FpDevice *device,

View File

@@ -949,16 +949,6 @@ fp_device_close_finish (FpDevice *device,
return g_task_propagate_boolean (G_TASK (result), error); return g_task_propagate_boolean (G_TASK (result), error);
} }
static void
complete_suspend_resume_task (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_assert (priv->suspend_resume_task);
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
}
/** /**
* fp_device_suspend: * fp_device_suspend:
* @device: a #FpDevice * @device: a #FpDevice
@@ -1009,48 +999,7 @@ fp_device_suspend (FpDevice *device,
priv->suspend_resume_task = g_steal_pointer (&task); priv->suspend_resume_task = g_steal_pointer (&task);
/* If the device is currently idle, just complete immediately. fpi_device_suspend (device);
* For long running tasks, call the driver handler right away, for short
* tasks, wait for completion and then return the task.
*/
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_suspend_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->suspend)
{
if (priv->critical_section)
priv->suspend_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->suspend (device);
}
else
{
fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
g_signal_connect_object (priv->current_task,
"notify::completed",
G_CALLBACK (complete_suspend_resume_task),
device,
G_CONNECT_SWAPPED);
break;
}
} }
/** /**
@@ -1115,41 +1064,7 @@ fp_device_resume (FpDevice *device,
priv->suspend_resume_task = g_steal_pointer (&task); priv->suspend_resume_task = g_steal_pointer (&task);
switch (priv->current_action) fpi_device_resume (device);
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_resume_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->resume)
{
if (priv->critical_section)
priv->resume_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->resume (device);
}
else
{
fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
/* cannot happen as we make sure these tasks complete before suspend */
g_assert_not_reached ();
complete_suspend_resume_task (device);
break;
}
} }
/** /**

View File

@@ -866,16 +866,16 @@ fpi_device_critical_section_flush_idle_cb (FpDevice *device)
if (priv->suspend_queued) if (priv->suspend_queued)
{ {
cls->suspend (device);
priv->suspend_queued = FALSE; priv->suspend_queued = FALSE;
fpi_device_suspend (device);
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
} }
if (priv->resume_queued) if (priv->resume_queued)
{ {
cls->resume (device);
priv->resume_queued = FALSE; priv->resume_queued = FALSE;
fpi_device_resume (device);
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
} }
@@ -912,6 +912,7 @@ fpi_device_critical_leave (FpDevice *device)
return; return;
priv->critical_section_flush_source = g_idle_source_new (); priv->critical_section_flush_source = g_idle_source_new ();
g_source_set_priority (priv->critical_section_flush_source, G_PRIORITY_HIGH);
g_source_set_callback (priv->critical_section_flush_source, g_source_set_callback (priv->critical_section_flush_source,
(GSourceFunc) fpi_device_critical_section_flush_idle_cb, (GSourceFunc) fpi_device_critical_section_flush_idle_cb,
device, device,
@@ -1550,6 +1551,148 @@ fpi_device_list_complete (FpDevice *device,
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
} }
static int
update_attr (const char *attr, const char *value)
{
int fd, err;
gssize r;
char buf[50] = { 0 };
fd = open (attr, O_RDONLY);
err = -errno;
if (fd < 0)
return -err;
r = read (fd, buf, sizeof (buf) - 1);
err = errno;
close (fd);
if (r < 0)
return -err;
g_strchomp (buf);
if (g_strcmp0 (buf, value) == 0)
return 0;
/* O_TRUNC makes things work in the umockdev environment */
fd = open (attr, O_WRONLY | O_TRUNC);
err = errno;
if (fd < 0)
return -err;
r = write (fd, value, strlen (value));
err = -errno;
close (fd);
if (r < 0)
{
/* Write failures are weird, and are worth a warning */
g_warning ("Could not write %s to %s", value, attr);
return -err;
}
return 0;
}
static void
complete_suspend_resume_task (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_assert (priv->suspend_resume_task);
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
}
void
fpi_device_suspend (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
/* If the device is currently idle, just complete immediately.
* For long running tasks, call the driver handler right away, for short
* tasks, wait for completion and then return the task.
*/
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_suspend_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->suspend)
{
if (priv->critical_section)
priv->suspend_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->suspend (device);
}
else
{
fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
g_signal_connect_object (priv->current_task,
"notify::completed",
G_CALLBACK (complete_suspend_resume_task),
device,
G_CONNECT_SWAPPED);
break;
}
}
void
fpi_device_resume (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_resume_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->resume)
{
if (priv->critical_section)
priv->resume_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->resume (device);
}
else
{
fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
/* cannot happen as we make sure these tasks complete before suspend */
g_assert_not_reached ();
complete_suspend_resume_task (device);
break;
}
}
void void
fpi_device_configure_wakeup (FpDevice *device, gboolean enabled) fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
{ {
@@ -1565,8 +1708,7 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
guint8 bus, port; guint8 bus, port;
g_autofree gchar *sysfs_wakeup = NULL; g_autofree gchar *sysfs_wakeup = NULL;
g_autofree gchar *sysfs_persist = NULL; g_autofree gchar *sysfs_persist = NULL;
gssize r; int res;
int fd;
ports = g_string_new (NULL); ports = g_string_new (NULL);
bus = g_usb_device_get_bus (priv->usb_device); bus = g_usb_device_get_bus (priv->usb_device);
@@ -1582,20 +1724,9 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
g_string_set_size (ports, ports->len - 1); g_string_set_size (ports, ports->len - 1);
sysfs_wakeup = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/wakeup", bus, ports->str); sysfs_wakeup = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/wakeup", bus, ports->str);
fd = open (sysfs_wakeup, O_WRONLY); res = update_attr (sysfs_wakeup, wakeup_command);
if (res < 0)
if (fd < 0) g_debug ("Failed to set %s to %s", sysfs_wakeup, wakeup_command);
{
/* Wakeup not existing appears to be relatively normal. */
g_debug ("Failed to open %s", sysfs_wakeup);
}
else
{
r = write (fd, wakeup_command, strlen (wakeup_command));
if (r < 0)
g_warning ("Could not configure wakeup to %s by writing %s", wakeup_command, sysfs_wakeup);
close (fd);
}
/* Persist means that the kernel tries to keep the USB device open /* Persist means that the kernel tries to keep the USB device open
* in case it is "replugged" due to suspend. * in case it is "replugged" due to suspend.
@@ -1603,20 +1734,9 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
* state. Instead, seeing an unplug and a new device makes more sense. * state. Instead, seeing an unplug and a new device makes more sense.
*/ */
sysfs_persist = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/persist", bus, ports->str); sysfs_persist = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/persist", bus, ports->str);
fd = open (sysfs_persist, O_WRONLY); res = update_attr (sysfs_persist, "0");
if (res < 0)
if (fd < 0) g_warning ("Failed to disable USB persist by writing to %s", sysfs_persist);
{
g_warning ("Failed to open %s", sysfs_persist);
return;
}
else
{
r = write (fd, "0", 1);
if (r < 0)
g_message ("Could not disable USB persist by writing to %s", sysfs_persist);
close (fd);
}
break; break;
} }

View File

@@ -277,7 +277,7 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
{ {
print = fp_print_new (device); print = fp_print_new (device);
fpi_print_set_type (print, FPI_PRINT_NBIS); fpi_print_set_type (print, FPI_PRINT_NBIS);
if (!fpi_print_add_from_image (print, image, &error)) if (!fpi_print_add_from_image (print, image, priv->bz3_threshold, &error))
{ {
g_clear_object (&print); g_clear_object (&print);

View File

@@ -154,11 +154,14 @@ minutiae_to_xyt (struct fp_minutiae *minutiae,
gboolean gboolean
fpi_print_add_from_image (FpPrint *print, fpi_print_add_from_image (FpPrint *print,
FpImage *image, FpImage *image,
gint bz3_threshold,
GError **error) GError **error)
{ {
g_autofree struct xyt_struct *xyt = NULL;
GPtrArray *minutiae; GPtrArray *minutiae;
struct fp_minutiae _minutiae; struct fp_minutiae _minutiae;
struct xyt_struct *xyt; gint probe_len;
gint score;
if (print->type != FPI_PRINT_NBIS || !image) if (print->type != FPI_PRINT_NBIS || !image)
{ {
@@ -173,8 +176,8 @@ fpi_print_add_from_image (FpPrint *print,
if (!minutiae || minutiae->len == 0) if (!minutiae || minutiae->len == 0)
{ {
g_set_error (error, g_set_error (error,
G_IO_ERROR, FP_DEVICE_RETRY,
G_IO_ERROR_INVALID_DATA, FP_DEVICE_RETRY_GENERAL,
"No minutiae found in image or not yet detected!"); "No minutiae found in image or not yet detected!");
return FALSE; return FALSE;
} }
@@ -185,7 +188,20 @@ fpi_print_add_from_image (FpPrint *print,
xyt = g_new0 (struct xyt_struct, 1); xyt = g_new0 (struct xyt_struct, 1);
minutiae_to_xyt (&_minutiae, image->width, image->height, xyt); minutiae_to_xyt (&_minutiae, image->width, image->height, xyt);
g_ptr_array_add (print->prints, xyt);
probe_len = bozorth_probe_init (xyt);
score = bozorth_to_gallery (probe_len, xyt, xyt);
fp_dbg ("self-match score %d/%d", score, bz3_threshold);
if (score <= bz3_threshold)
{
g_set_error (error,
FP_DEVICE_RETRY,
FP_DEVICE_RETRY_GENERAL,
"Not enough minutiae to generate a match!");
return FPI_MATCH_SUCCESS;
}
g_ptr_array_add (print->prints, g_steal_pointer (&xyt));
g_clear_object (&print->image); g_clear_object (&print->image);
print->image = g_object_ref (image); print->image = g_object_ref (image);

View File

@@ -40,6 +40,7 @@ void fpi_print_set_device_stored (FpPrint *print,
gboolean fpi_print_add_from_image (FpPrint *print, gboolean fpi_print_add_from_image (FpPrint *print,
FpImage *image, FpImage *image,
gint bz3_threshold,
GError **error); GError **error);
FpiMatchResult fpi_print_bz3_match (FpPrint * template, FpiMatchResult fpi_print_bz3_match (FpPrint * template,

View File

@@ -105,6 +105,11 @@ process.wait()
# Run capture # Run capture
# https://osqa-ask.wireshark.org/questions/53919/how-can-i-precisely-specify-a-usb-device-to-capture-with-tshark/ # https://osqa-ask.wireshark.org/questions/53919/how-can-i-precisely-specify-a-usb-device-to-capture-with-tshark/
print(f'### Reseting USB port (as descriptors could be missing in the dump otherwise)')
usb_device.open()
usb_device.reset()
usb_device.close()
print(f'### Starting USB capture on usbmon{bus_num}') print(f'### Starting USB capture on usbmon{bus_num}')
capture_pid = os.fork() capture_pid = os.fork()
assert(capture_pid >= 0) assert(capture_pid >= 0)

Binary file not shown.

View File

@@ -1,10 +1,14 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os
import gi import gi
gi.require_version('FPrint', '2.0') gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib from gi.repository import FPrint, GLib
ctx = GLib.main_context_default() import sys
import traceback
sys.excepthook = lambda *args : (traceback.print_exception(*args), sys.exit(1))
c = FPrint.Context() c = FPrint.Context()
c.enumerate() c.enumerate()
@@ -13,6 +17,24 @@ devices = c.get_devices()
d = devices[0] d = devices[0]
del devices del devices
usb_device = d.get_property('fpi-usb-device')
bus_num = usb_device.get_bus()
port = []
while True:
parent = usb_device.get_parent()
if parent is None:
break
port.append(str(usb_device.get_port_number()))
usb_device = parent
port = '.'.join(port)
persist = f'/sys/bus/usb/devices/{bus_num}-{port}/power/persist'
wakeup = f'/sys/bus/usb/devices/{bus_num}-{port}/power/wakeup'
# may not have written anything
assert open(persist).read().strip() == "0"
assert open(wakeup).read().strip() == "disabled"
assert d.get_driver() == "synaptics" assert d.get_driver() == "synaptics"
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE) assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY) assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
@@ -29,7 +51,7 @@ d.clear_storage_sync()
template = FPrint.Print.new(d) template = FPrint.Print.new(d)
def enroll_progress(*args): def enroll_progress(*args):
assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED #assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED
print('enroll progress: ' + str(args)) print('enroll progress: ' + str(args))
# List, enroll, list, verify, delete, list # List, enroll, list, verify, delete, list
@@ -41,6 +63,21 @@ print("enroll done")
print("verifying") print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
# Inject a suspend/resume cycle into the verify
def suspend_resume():
d.suspend_sync()
assert open(persist).read().strip() == "0"
assert open(wakeup).read().strip() == "enabled"
assert open(persist, 'w').write('0\n')
d.resume_sync()
# This tests that libfprint doesn't write if the value is correct
# (i.e. the trailing \ would be lost inside umockdev if written)
assert open(persist).read() == "0\n"
assert open(wakeup).read().strip() == "disabled"
GLib.idle_add(suspend_resume, priority=GLib.PRIORITY_HIGH)
verify_res, verify_print = d.verify_sync(p) verify_res, verify_print = d.verify_sync(p)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done") print("verify done")

View File

@@ -1,14 +1,14 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-9 P: /devices/pci0000:00/0000:00:14.0/usb1/1-9
N: bus/usb/001/005 N: bus/usb/001/004=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004
E: DEVNAME=/dev/bus/usb/001/005 E: DEVNAME=/dev/bus/usb/001/004
E: DEVTYPE=usb_device E: DEVTYPE=usb_device
E: DRIVER=usb E: DRIVER=usb
E: PRODUCT=6cb/bd/0 E: PRODUCT=6cb/bd/0
E: TYPE=255/16/255 E: TYPE=255/16/255
E: BUSNUM=001 E: BUSNUM=001
E: DEVNUM=005 E: DEVNUM=004
E: MAJOR=189 E: MAJOR=189
E: MINOR=4 E: MINOR=3
E: SUBSYSTEM=usb E: SUBSYSTEM=usb
E: ID_VENDOR=06cb E: ID_VENDOR=06cb
E: ID_VENDOR_ENC=06cb E: ID_VENDOR_ENC=06cb
@@ -24,82 +24,82 @@ E: ID_USB_INTERFACES=:ff0000:
E: ID_VENDOR_FROM_DATABASE=Synaptics, Inc. E: ID_VENDOR_FROM_DATABASE=Synaptics, Inc.
E: ID_AUTOSUSPEND=1 E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Prometheus MIS Touch Fingerprint Reader E: ID_MODEL_FROM_DATABASE=Prometheus MIS Touch Fingerprint Reader
E: ID_PERSIST=0
E: ID_PATH=pci-0000:00:14.0-usb-0:9 E: ID_PATH=pci-0000:00:14.0-usb-0:9
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9 E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9
E: LIBFPRINT_DRIVER=Synaptics Sensors A: authorized=1
A: authorized=1\n A: avoid_reset_quirk=0
A: avoid_reset_quirk=0\n A: bConfigurationValue=1
A: bConfigurationValue=1\n A: bDeviceClass=ff
A: bDeviceClass=ff\n A: bDeviceProtocol=ff
A: bDeviceProtocol=ff\n A: bDeviceSubClass=10
A: bDeviceSubClass=10\n A: bMaxPacketSize0=8
A: bMaxPacketSize0=8\n A: bMaxPower=100mA
A: bMaxPower=100mA\n A: bNumConfigurations=1
A: bNumConfigurations=1\n A: bNumInterfaces= 1
A: bNumInterfaces= 1\n A: bcdDevice=0000
A: bcdDevice=0000\n A: bmAttributes=a0
A: bmAttributes=a0\n A: busnum=1
A: busnum=1\n
A: configuration= A: configuration=
H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004 H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004
A: dev=189:4\n A: dev=189:3
A: devnum=5\n A: devnum=4
A: devpath=9\n A: devpath=9
L: driver=../../../../../bus/usb/drivers/usb L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d/device:28 L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d/device:28
A: idProduct=00bd\n A: idProduct=00bd
A: idVendor=06cb\n A: idVendor=06cb
A: ltm_capable=no\n A: ltm_capable=no
A: maxchild=0\n A: maxchild=0
L: port=../1-0:1.0/usb1-port9 L: port=../1-0:1.0/usb1-port9
A: power/active_duration=82065\n A: power/active_duration=9424964
A: power/autosuspend=2\n A: power/autosuspend=2
A: power/autosuspend_delay_ms=2000\n A: power/autosuspend_delay_ms=2000
A: power/connected_duration=4271349\n A: power/connected_duration=866169213
A: power/control=auto\n A: power/control=auto
A: power/level=auto\n A: power/level=auto
A: power/persist=1\n A: power/persist=0
A: power/runtime_active_time=82975\n A: power/runtime_active_time=9431408
A: power/runtime_status=suspended\n A: power/runtime_status=active
A: power/runtime_suspended_time=4186597\n A: power/runtime_suspended_time=856661633
A: power/wakeup=disabled\n A: power/wakeup=disabled
A: power/wakeup_abort_count=\n A: power/wakeup_abort_count=
A: power/wakeup_active=\n A: power/wakeup_active=
A: power/wakeup_active_count=\n A: power/wakeup_active_count=
A: power/wakeup_count=\n A: power/wakeup_count=
A: power/wakeup_expire_count=\n A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=\n A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=\n A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=\n A: power/wakeup_total_time_ms=
A: quirks=0x0\n A: quirks=0x0
A: removable=fixed\n A: removable=fixed
A: rx_lanes=1\n A: rx_lanes=1
A: serial=c087f7d72126\n A: serial=c087f7d72126
A: speed=12\n A: speed=12
A: tx_lanes=1\n A: tx_lanes=1
A: urbnum=618\n A: urbnum=8945
A: version= 2.00\n A: version= 2.00
P: /devices/pci0000:00/0000:00:14.0/usb1 P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C N: bus/usb/001/001=12010002090001406B1D020016050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001 E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device E: DEVTYPE=usb_device
E: DRIVER=usb E: DRIVER=usb
E: PRODUCT=1d6b/2/512 E: PRODUCT=1d6b/2/516
E: TYPE=9/0/1 E: TYPE=9/0/1
E: BUSNUM=001 E: BUSNUM=001
E: DEVNUM=001 E: DEVNUM=001
E: MAJOR=189 E: MAJOR=189
E: MINOR=0 E: MINOR=0
E: SUBSYSTEM=usb E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.12.9-300.fc34.x86_64_xhci-hcd E: ID_VENDOR=Linux_5.16.8-200.fc35.x86_64_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.12.9-300.fc34.x86_64\x20xhci-hcd E: ID_VENDOR_ENC=Linux\x205.16.8-200.fc35.x86_64\x20xhci-hcd
E: ID_VENDOR_ID=1d6b E: ID_VENDOR_ID=1d6b
E: ID_MODEL=xHCI_Host_Controller E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_ID=0002 E: ID_MODEL_ID=0002
E: ID_REVISION=0512 E: ID_REVISION=0516
E: ID_SERIAL=Linux_5.12.9-300.fc34.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0 E: ID_SERIAL=Linux_5.16.8-200.fc35.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0 E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_BUS=usb E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000: E: ID_USB_INTERFACES=:090000:
@@ -111,60 +111,60 @@ E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_FOR_SEAT=usb-pci-0000_00_14_0 E: ID_FOR_SEAT=usb-pci-0000_00_14_0
E: TAGS=:seat: E: TAGS=:seat:
E: CURRENT_TAGS=:seat: E: CURRENT_TAGS=:seat:
A: authorized=1\n A: authorized=1
A: authorized_default=1\n A: authorized_default=1
A: avoid_reset_quirk=0\n A: avoid_reset_quirk=0
A: bConfigurationValue=1\n A: bConfigurationValue=1
A: bDeviceClass=09\n A: bDeviceClass=09
A: bDeviceProtocol=01\n A: bDeviceProtocol=01
A: bDeviceSubClass=00\n A: bDeviceSubClass=00
A: bMaxPacketSize0=64\n A: bMaxPacketSize0=64
A: bMaxPower=0mA\n A: bMaxPower=0mA
A: bNumConfigurations=1\n A: bNumConfigurations=1
A: bNumInterfaces= 1\n A: bNumInterfaces= 1
A: bcdDevice=0512\n A: bcdDevice=0516
A: bmAttributes=e0\n A: bmAttributes=e0
A: busnum=1\n A: busnum=1
A: configuration= A: configuration=
H: descriptors=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C H: descriptors=12010002090001406B1D020016050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0\n A: dev=189:0
A: devnum=1\n A: devnum=1
A: devpath=0\n A: devpath=0
L: driver=../../../../bus/usb/drivers/usb L: driver=../../../../bus/usb/drivers/usb
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d
A: idProduct=0002\n A: idProduct=0002
A: idVendor=1d6b\n A: idVendor=1d6b
A: interface_authorized_default=1\n A: interface_authorized_default=1
A: ltm_capable=no\n A: ltm_capable=no
A: manufacturer=Linux 5.12.9-300.fc34.x86_64 xhci-hcd\n A: manufacturer=Linux 5.16.8-200.fc35.x86_64 xhci-hcd
A: maxchild=12\n A: maxchild=12
A: power/active_duration=4270585\n A: power/active_duration=865968060
A: power/autosuspend=0\n A: power/autosuspend=0
A: power/autosuspend_delay_ms=0\n A: power/autosuspend_delay_ms=0
A: power/connected_duration=4272308\n A: power/connected_duration=866169920
A: power/control=auto\n A: power/control=auto
A: power/level=auto\n A: power/level=auto
A: power/runtime_active_time=4270770\n A: power/runtime_active_time=866093998
A: power/runtime_status=active\n A: power/runtime_status=active
A: power/runtime_suspended_time=0\n A: power/runtime_suspended_time=0
A: power/wakeup=disabled\n A: power/wakeup=disabled
A: power/wakeup_abort_count=\n A: power/wakeup_abort_count=
A: power/wakeup_active=\n A: power/wakeup_active=
A: power/wakeup_active_count=\n A: power/wakeup_active_count=
A: power/wakeup_count=\n A: power/wakeup_count=
A: power/wakeup_expire_count=\n A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=\n A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=\n A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=\n A: power/wakeup_total_time_ms=
A: product=xHCI Host Controller\n A: product=xHCI Host Controller
A: quirks=0x0\n A: quirks=0x0
A: removable=unknown\n A: removable=unknown
A: rx_lanes=1\n A: rx_lanes=1
A: serial=0000:00:14.0\n A: serial=0000:00:14.0
A: speed=480\n A: speed=480
A: tx_lanes=1\n A: tx_lanes=1
A: urbnum=463\n A: urbnum=9372
A: version= 2.00\n A: version= 2.00
P: /devices/pci0000:00/0000:00:14.0 P: /devices/pci0000:00/0000:00:14.0
E: DRIVER=xhci_hcd E: DRIVER=xhci_hcd
@@ -180,44 +180,44 @@ E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_VENDOR_FROM_DATABASE=Intel Corporation E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: ID_AUTOSUSPEND=1 E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller E: ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller
A: ari_enabled=0\n A: ari_enabled=0
A: broken_parity_status=0\n A: broken_parity_status=0
A: class=0x0c0330\n A: class=0x0c0330
H: config=8680ED9D060490021130030C00008000040022EA000000000000000000000000000000000000000000000000AA179222000000007000000000000000FF010000 H: config=8680ED9D060490021130030C00008000040022EA000000000000000000000000000000000000000000000000AA179222000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F0000000060069A2400000000316000000000000000000000000000000180C2C108000000000000000000000005908700D802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F40020000010000000000000000000008000000040000000000000000000000000000000000000000000000000000000800000004000000000000000000000000000000000000000000000000000000B50F320112000000
A: consistent_dma_mask_bits=64\n A: consistent_dma_mask_bits=64
A: d3cold_allowed=1\n A: d3cold_allowed=1
A: dbc=disabled\n A: dbc=disabled
A: device=0x9ded\n A: device=0x9ded
A: dma_mask_bits=64\n A: dma_mask_bits=64
L: driver=../../../bus/pci/drivers/xhci_hcd L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)\n A: driver_override=(null)
A: enable=1\n A: enable=1
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c
A: irq=128\n A: irq=126
A: local_cpulist=0-7\n A: local_cpulist=0-7
A: local_cpus=ff\n A: local_cpus=ff
A: modalias=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30\n A: modalias=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30
A: msi_bus=1\n A: msi_bus=1
A: msi_irqs/128=msi\n A: msi_irqs/126=msi
A: numa_node=-1\n A: numa_node=-1
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\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 9 12 2112 12\nxHCI ring segments 40 50 4096 50\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 6 32 128 1\nbuffer-32 0 0 32 0\n A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\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 21 24 2112 24\nxHCI ring segments 68 80 4096 80\nbuffer-2048 0 38 2048 19\nbuffer-512 0 0 512 0\nbuffer-128 18 32 128 1\nbuffer-32 0 128 32 1
A: power/control=auto\n A: power/control=auto
A: power/runtime_active_time=4271635\n A: power/runtime_active_time=866094158
A: power/runtime_status=active\n A: power/runtime_status=active
A: power/runtime_suspended_time=0\n A: power/runtime_suspended_time=0
A: power/wakeup=enabled\n A: power/wakeup=enabled
A: power/wakeup_abort_count=0\n A: power/wakeup_abort_count=0
A: power/wakeup_active=0\n A: power/wakeup_active=0
A: power/wakeup_active_count=0\n A: power/wakeup_active_count=2
A: power/wakeup_count=0\n A: power/wakeup_count=0
A: power/wakeup_expire_count=0\n A: power/wakeup_expire_count=2
A: power/wakeup_last_time_ms=0\n A: power/wakeup_last_time_ms=476219021
A: power/wakeup_max_time_ms=0\n A: power/wakeup_max_time_ms=103
A: power/wakeup_total_time_ms=0\n A: power/wakeup_total_time_ms=207
A: power_state=D0\n A: power_state=D0
A: resource=0x00000000ea220000 0x00000000ea22ffff 0x0000000000140204\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\n A: resource=0x00000000ea220000 0x00000000ea22ffff 0x0000000000140204\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=0x11\n A: revision=0x11
A: subsystem_device=0x2292\n A: subsystem_device=0x2292
A: subsystem_vendor=0x17aa\n A: subsystem_vendor=0x17aa
A: vendor=0x8086\n A: vendor=0x8086