Compare commits
51 commits
Author | SHA1 | Date | |
---|---|---|---|
f579a77bfd | |||
03deb3011b | |||
c7650b6ec9 | |||
128d809227 | |||
9356e895a2 | |||
3c2883b992 | |||
eb568a62aa | |||
d763f8f41a | |||
df41ed56f6 | |||
aff063c23c | |||
e2511095d1 | |||
9515cc2e59 | |||
b3cfc40dea | |||
c162b895c0 | |||
40b3923ca6 | |||
d7e7d8e036 | |||
ec53abfc3a | |||
83541a2ddc | |||
e22497d51b | |||
0dcb4be4d3 | |||
8f93aef122 | |||
8dfa12e41d | |||
88cb452e05 | |||
909865ed8d | |||
39333a0642 | |||
4340be728c | |||
dba5ca5535 | |||
2a70cd7e02 | |||
3108ac3144 | |||
c928d7bd8f | |||
ec42b2ade1 | |||
4edfa48608 | |||
1a5df96751 | |||
62448492af | |||
874513e79a | |||
5c89bda7f3 | |||
8147372bdd | |||
43336a204f | |||
968331c383 | |||
d547c000fc | |||
ff6caca2e3 | |||
77756e111d | |||
23a4f5b77a | |||
5b7c5e7c09 | |||
da28731adc | |||
6440a7d12f | |||
71e0c29f28 | |||
a2d950044d | |||
96e5888110 | |||
dd476c0ccf | |||
4cdca4da24 |
|
@ -1,6 +1,6 @@
|
|||
include:
|
||||
- local: '.gitlab-ci/libfprint-templates.yaml'
|
||||
- project: 'wayland/ci-templates'
|
||||
- project: 'freedesktop/ci-templates'
|
||||
ref: master
|
||||
file: '/templates/fedora.yml'
|
||||
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/master/flatpak/flatpak_ci_initiative.yml'
|
||||
|
@ -9,6 +9,7 @@ variables:
|
|||
extends: .libfprint_common_variables
|
||||
FDO_DISTRIBUTION_TAG: latest
|
||||
FDO_DISTRIBUTION_VERSION: rawhide
|
||||
FDO_UPSTREAM_REPO: "libfprint/$CI_PROJECT_NAME"
|
||||
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
||||
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
||||
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||
|
@ -19,7 +20,7 @@ stages:
|
|||
- test
|
||||
- flatpak
|
||||
|
||||
image: "$FEDORA_IMAGE"
|
||||
image: $FEDORA_IMAGE
|
||||
|
||||
.build_one_driver_template: &build_one_driver
|
||||
script:
|
||||
|
@ -69,6 +70,7 @@ test:
|
|||
- cat _build/meson-logs/coverage.txt
|
||||
artifacts:
|
||||
expose_as: 'Coverage Report'
|
||||
when: always
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
- _build/meson-logs/coveragereport/index.html
|
||||
|
@ -86,6 +88,7 @@ test_valgrind:
|
|||
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
|
||||
artifacts:
|
||||
expose_as: 'Valgrind test logs'
|
||||
when: always
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
- _build/meson-logs/testlog-valgrind.txt
|
||||
|
@ -157,6 +160,7 @@ container_fedora_build:
|
|||
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||
variables:
|
||||
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||
FDO_FORCE_REBUILD: 1
|
||||
# a list of packages to install
|
||||
FDO_DISTRIBUTION_PACKAGES:
|
||||
$LIBFPRINT_DEPENDENCIES
|
||||
|
|
|
@ -26,3 +26,4 @@
|
|||
uncrustify
|
||||
valgrind
|
||||
clang-analyzer
|
||||
diffutils
|
||||
|
|
12
NEWS
12
NEWS
|
@ -1,6 +1,18 @@
|
|||
This file lists notable changes in each release. For the full history of all
|
||||
changes, see ChangeLog.
|
||||
|
||||
2021-06-30: v1.94.0 release
|
||||
|
||||
Highlights:
|
||||
* Implement suspend/resume handling including USB wakeup configuration.
|
||||
This requires writing the "persist" and "wakeup" sysfs attributes.
|
||||
* Add simple temperature module to prevent devices from becoming too hot
|
||||
* Add feature for continuous scanning
|
||||
* New internal "critical section" API to simplify driver development
|
||||
* elan: new PID 0x0c58
|
||||
* elanmoc: Fixes for multi-user handling and FW changes
|
||||
* virtual-device: Do not time out for SCAN command
|
||||
|
||||
2021-06-30: v1.92.1 release
|
||||
|
||||
Highlights:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
# Supported by libfprint driver aes1610
|
||||
usb:v08FFp1600*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver aes1660
|
||||
usb:v08FFp1660*
|
||||
|
@ -24,16 +25,19 @@ usb:v08FFp168D*
|
|||
usb:v08FFp168E*
|
||||
usb:v08FFp168F*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver aes2501
|
||||
usb:v08FFp2500*
|
||||
usb:v08FFp2580*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver aes2550
|
||||
usb:v08FFp2550*
|
||||
usb:v08FFp2810*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver aes2660
|
||||
usb:v08FFp2660*
|
||||
|
@ -55,19 +59,23 @@ usb:v08FFp268E*
|
|||
usb:v08FFp268F*
|
||||
usb:v08FFp2691*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver aes3500
|
||||
usb:v08FFp5731*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver aes4000
|
||||
usb:v5501p08FF*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver egis0570
|
||||
usb:v1C7Ap0570*
|
||||
usb:v1C7Ap0571*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver elan
|
||||
usb:v04F3p0903*
|
||||
|
@ -129,15 +137,19 @@ usb:v04F3p0C4D*
|
|||
usb:v04F3p0C4F*
|
||||
usb:v04F3p0C63*
|
||||
usb:v04F3p0C6E*
|
||||
usb:v04F3p0C58*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver elanmoc
|
||||
usb:v04F3p0C7E*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver etes603
|
||||
usb:v1C7Ap0603*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver goodixmoc
|
||||
usb:v27C6p5840*
|
||||
|
@ -145,6 +157,7 @@ usb:v27C6p609C*
|
|||
usb:v27C6p60A2*
|
||||
usb:v27C6p639C*
|
||||
usb:v27C6p63AC*
|
||||
usb:v27C6p63BC*
|
||||
usb:v27C6p6496*
|
||||
usb:v27C6p6584*
|
||||
usb:v27C6p658C*
|
||||
|
@ -153,10 +166,12 @@ usb:v27C6p6594*
|
|||
usb:v27C6p659C*
|
||||
usb:v27C6p6A94*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver nb1010
|
||||
usb:v298Dp1010*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver synaptics
|
||||
usb:v06CBp00BD*
|
||||
|
@ -168,22 +183,29 @@ usb:v06CBp00C9*
|
|||
usb:v06CBp0100*
|
||||
usb:v06CBp00F0*
|
||||
usb:v06CBp0103*
|
||||
usb:v06CBp0123*
|
||||
usb:v06CBp0126*
|
||||
usb:v06CBp0129*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver upeksonly
|
||||
usb:v147Ep2016*
|
||||
usb:v147Ep1000*
|
||||
usb:v147Ep1001*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver upektc
|
||||
usb:v0483p2015*
|
||||
usb:v147Ep3001*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver upektc_img
|
||||
usb:v147Ep2020*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver uru4000
|
||||
usb:v045Ep00BC*
|
||||
|
@ -193,23 +215,28 @@ usb:v05BAp0007*
|
|||
usb:v05BAp0008*
|
||||
usb:v05BAp000A*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver vcom5s
|
||||
usb:v061Ap0110*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver vfs0050
|
||||
usb:v138Ap0050*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver vfs101
|
||||
usb:v138Ap0001*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver vfs301
|
||||
usb:v138Ap0005*
|
||||
usb:v138Ap0008*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver vfs5011
|
||||
usb:v138Ap0010*
|
||||
|
@ -218,10 +245,12 @@ usb:v138Ap0015*
|
|||
usb:v138Ap0017*
|
||||
usb:v138Ap0018*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver vfs7552
|
||||
usb:v138Ap0091*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Known unsupported devices
|
||||
usb:v04F3p036B*
|
||||
|
@ -244,6 +273,7 @@ usb:v06CBp00C4*
|
|||
usb:v06CBp00CB*
|
||||
usb:v06CBp00D8*
|
||||
usb:v06CBp00DA*
|
||||
usb:v06CBp00E7*
|
||||
usb:v06CBp00E9*
|
||||
usb:v0A5Cp5801*
|
||||
usb:v0A5Cp5805*
|
||||
|
@ -252,6 +282,7 @@ usb:v0A5Cp5840*
|
|||
usb:v0A5Cp5841*
|
||||
usb:v0A5Cp5842*
|
||||
usb:v0A5Cp5843*
|
||||
usb:v0A5Cp5844*
|
||||
usb:v0A5Cp5845*
|
||||
usb:v10A5p0007*
|
||||
usb:v1188p9545*
|
||||
|
@ -294,3 +325,4 @@ usb:v2808p9338*
|
|||
usb:v298Dp2033*
|
||||
usb:v3538p0930*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
|
|
@ -50,6 +50,8 @@ fp_device_capture
|
|||
fp_device_delete_print
|
||||
fp_device_list_prints
|
||||
fp_device_clear_storage
|
||||
fp_device_suspend
|
||||
fp_device_resume
|
||||
fp_device_open_finish
|
||||
fp_device_close_finish
|
||||
fp_device_enroll_finish
|
||||
|
@ -59,6 +61,8 @@ fp_device_capture_finish
|
|||
fp_device_delete_print_finish
|
||||
fp_device_list_prints_finish
|
||||
fp_device_clear_storage_finish
|
||||
fp_device_suspend_finish
|
||||
fp_device_resume_finish
|
||||
fp_device_open_sync
|
||||
fp_device_close_sync
|
||||
fp_device_enroll_sync
|
||||
|
@ -68,6 +72,8 @@ fp_device_capture_sync
|
|||
fp_device_delete_print_sync
|
||||
fp_device_list_prints_sync
|
||||
fp_device_clear_storage_sync
|
||||
fp_device_suspend_sync
|
||||
fp_device_resume_sync
|
||||
FpDevice
|
||||
</SECTION>
|
||||
|
||||
|
@ -160,6 +166,8 @@ fpi_device_add_timeout
|
|||
fpi_device_set_nr_enroll_stages
|
||||
fpi_device_set_scan_type
|
||||
fpi_device_update_features
|
||||
fpi_device_critical_enter
|
||||
fpi_device_critical_leave
|
||||
fpi_device_remove
|
||||
fpi_device_report_finger_status
|
||||
fpi_device_report_finger_status_changes
|
||||
|
@ -172,10 +180,12 @@ fpi_device_verify_complete
|
|||
fpi_device_identify_complete
|
||||
fpi_device_capture_complete
|
||||
fpi_device_delete_complete
|
||||
fpi_device_list_complete
|
||||
fpi_device_suspend_complete
|
||||
fpi_device_resume_complete
|
||||
fpi_device_enroll_progress
|
||||
fpi_device_verify_report
|
||||
fpi_device_identify_report
|
||||
fpi_device_list_complete
|
||||
fpi_device_class_auto_initialize_features
|
||||
</SECTION>
|
||||
|
||||
|
|
|
@ -219,6 +219,7 @@ static const FpIdEntry elan_id_table[] = {
|
|||
{.vid = ELAN_VEND_ID, .pid = 0x0c4f, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c63, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c6e, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = ELAN_VEND_ID, .pid = 0x0c58, .driver_data = ELAN_ALL_DEV},
|
||||
{.vid = 0, .pid = 0, .driver_data = 0},
|
||||
};
|
||||
|
||||
|
|
|
@ -331,7 +331,8 @@ elanmoc_reenroll_cb (FpiDeviceElanmoc *self,
|
|||
if ((self->curr_enrolled == (ELAN_MAX_ENROLL_NUM + 1)) && (buffer_in[1] == 0x00))
|
||||
{
|
||||
fp_warn ("elanmoc_reenroll_cb over enroll max");
|
||||
fpi_ssm_mark_completed (self->task_ssm);
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL));
|
||||
return;
|
||||
}
|
||||
if (buffer_in[1] == 0x00)
|
||||
|
@ -431,7 +432,7 @@ elan_enroll_run_state (FpiSsm *ssm, FpDevice *dev)
|
|||
case MOC_ENROLL_REENROLL_CHECK:
|
||||
data = fpi_ssm_get_data (ssm);
|
||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_check_reenroll_cmd);
|
||||
cmd_buf[4] = data[16];
|
||||
memcpy (cmd_buf + 3, data, ELAN_USERDATE_SIZE);
|
||||
elanmoc_get_cmd (dev, cmd_buf, elanmoc_check_reenroll_cmd.cmd_len, elanmoc_check_reenroll_cmd.resp_len, 0, elanmoc_reenroll_cb);
|
||||
break;
|
||||
|
||||
|
@ -688,7 +689,10 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
|||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_enroll_complete (device, NULL, error);
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_complete (device, error);
|
||||
else
|
||||
fpi_device_identify_complete (device, error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -802,7 +806,7 @@ elanmoc_enroll (FpDevice *device)
|
|||
FpPrint *print = NULL;
|
||||
GVariant *data = NULL;
|
||||
GVariant *uid = NULL;
|
||||
g_autofree gchar *user_id;
|
||||
g_autofree gchar *user_id = NULL;
|
||||
gsize user_id_len;
|
||||
guint8 *userdata = g_malloc0 (ELAN_USERDATE_SIZE);
|
||||
|
||||
|
@ -1121,6 +1125,7 @@ fpi_device_elanmoc_class_init (FpiDeviceElanmocClass *klass)
|
|||
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||
dev_class->id_table = id_table;
|
||||
dev_class->nr_enroll_stages = ELAN_MOC_ENROLL_TIMES;
|
||||
dev_class->temp_hot_seconds = -1;
|
||||
|
||||
dev_class->open = elanmoc_open;
|
||||
dev_class->close = elanmoc_close;
|
||||
|
|
|
@ -34,7 +34,7 @@ G_DECLARE_FINAL_TYPE (FpiDeviceElanmoc, fpi_device_elanmoc, FPI, DEVICE_ELANMOC,
|
|||
#define ELAN_EP_MOC_CMD_IN (0x4 | LIBUSB_ENDPOINT_IN)
|
||||
#define ELAN_EP_IMG_IN (0x2 | LIBUSB_ENDPOINT_IN)
|
||||
|
||||
#define ELAN_MOC_CMD_TIMEOUT 2000
|
||||
#define ELAN_MOC_CMD_TIMEOUT 5000
|
||||
#define ELAN_MOC_CAL_RETRY 500
|
||||
#define ELAN_MOC_ENROLL_TIMES 9
|
||||
#define ELAN_MAX_USER_ID_LEN 92
|
||||
|
@ -135,7 +135,7 @@ static const struct elanmoc_cmd elanmoc_set_mod_cmd = {
|
|||
|
||||
static const struct elanmoc_cmd elanmoc_check_reenroll_cmd = {
|
||||
.cmd_header = {0x40, 0xff, 0x22},
|
||||
.cmd_len = 5,
|
||||
.cmd_len = 3 + ELAN_USERDATE_SIZE,
|
||||
.resp_len = 2,
|
||||
};
|
||||
|
||||
|
|
|
@ -1320,6 +1320,7 @@ gx_fp_probe (FpDevice *device)
|
|||
case 0x609C:
|
||||
case 0x639C:
|
||||
case 0x63AC:
|
||||
case 0x63BC:
|
||||
case 0x6A94:
|
||||
self->max_enroll_stage = 12;
|
||||
break;
|
||||
|
@ -1543,6 +1544,7 @@ static const FpIdEntry id_table[] = {
|
|||
{ .vid = 0x27c6, .pid = 0x60A2, },
|
||||
{ .vid = 0x27c6, .pid = 0x639C, },
|
||||
{ .vid = 0x27c6, .pid = 0x63AC, },
|
||||
{ .vid = 0x27c6, .pid = 0x63BC, },
|
||||
{ .vid = 0x27c6, .pid = 0x6496, },
|
||||
{ .vid = 0x27c6, .pid = 0x6584, },
|
||||
{ .vid = 0x27c6, .pid = 0x658C, },
|
||||
|
@ -1565,6 +1567,7 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass)
|
|||
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||
dev_class->id_table = id_table;
|
||||
dev_class->nr_enroll_stages = DEFAULT_ENROLL_SAMPLES;
|
||||
dev_class->temp_hot_seconds = -1;
|
||||
|
||||
dev_class->open = gx_fp_init;
|
||||
dev_class->close = gx_fp_exit;
|
||||
|
|
|
@ -40,6 +40,9 @@ static const FpIdEntry id_table[] = {
|
|||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||
};
|
||||
|
||||
|
@ -198,12 +201,17 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
|
|||
GError *error)
|
||||
{
|
||||
g_debug ("interrupt transfer done");
|
||||
fpi_device_critical_enter (device);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
g_error_free (error);
|
||||
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
|
||||
if (FPI_DEVICE_SYNAPTICS (device)->cmd_suspended)
|
||||
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_SUSPENDED);
|
||||
else
|
||||
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -264,6 +272,9 @@ synaptics_cmd_run_state (FpiSsm *ssm,
|
|||
break;
|
||||
|
||||
case SYNAPTICS_CMD_WAIT_INTERRUPT:
|
||||
/* Interruptions are permitted only during an interrupt transfer */
|
||||
fpi_device_critical_leave (dev);
|
||||
|
||||
transfer = fpi_usb_transfer_new (dev);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_fill_interrupt (transfer, USB_EP_INTERRUPT, USB_INTERRUPT_DATA_SIZE);
|
||||
|
@ -291,6 +302,17 @@ synaptics_cmd_run_state (FpiSsm *ssm,
|
|||
case SYNAPTICS_CMD_RESTART:
|
||||
fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_SEND_PENDING);
|
||||
break;
|
||||
|
||||
case SYNAPTICS_CMD_SUSPENDED:
|
||||
/* The resume handler continues to the next state! */
|
||||
fpi_device_critical_leave (dev);
|
||||
fpi_device_suspend_complete (dev, NULL);
|
||||
break;
|
||||
|
||||
case SYNAPTICS_CMD_RESUME:
|
||||
fpi_device_critical_enter (dev);
|
||||
fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_WAIT_INTERRUPT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,6 +328,7 @@ cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||
if (error || self->cmd_complete_on_removal)
|
||||
callback (self, NULL, error);
|
||||
|
||||
fpi_device_critical_leave (dev);
|
||||
self->cmd_complete_on_removal = FALSE;
|
||||
}
|
||||
|
||||
|
@ -415,6 +438,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
|
|||
SYNAPTICS_CMD_NUM_STATES);
|
||||
fpi_ssm_set_data (self->cmd_ssm, callback, NULL);
|
||||
|
||||
fpi_device_critical_enter (FP_DEVICE (self));
|
||||
fpi_ssm_start (self->cmd_ssm, cmd_ssm_done);
|
||||
}
|
||||
}
|
||||
|
@ -510,6 +534,12 @@ verify_msg_cb (FpiDeviceSynaptics *self,
|
|||
FpDevice *device = FP_DEVICE (self);
|
||||
bmkt_verify_resp_t *verify_resp;
|
||||
|
||||
if (self->action_starting)
|
||||
{
|
||||
fpi_device_critical_leave (device);
|
||||
self->action_starting = FALSE;
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_verify_complete (device, error);
|
||||
|
@ -602,6 +632,8 @@ verify (FpDevice *device)
|
|||
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
self->action_starting = TRUE;
|
||||
fpi_device_critical_enter (device);
|
||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
|
||||
}
|
||||
|
||||
|
@ -629,6 +661,12 @@ identify_msg_cb (FpiDeviceSynaptics *self,
|
|||
{
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
|
||||
if (self->action_starting)
|
||||
{
|
||||
fpi_device_critical_leave (device);
|
||||
self->action_starting = FALSE;
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_identify_complete (device, error);
|
||||
|
@ -718,6 +756,7 @@ static void
|
|||
identify (FpDevice *device)
|
||||
{
|
||||
GPtrArray *prints = NULL;
|
||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
|
||||
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
|
||||
|
@ -732,6 +771,9 @@ identify (FpDevice *device)
|
|||
return;
|
||||
}
|
||||
|
||||
self->action_starting = TRUE;
|
||||
fpi_device_critical_enter (device);
|
||||
|
||||
init_identify_msg (device);
|
||||
compose_and_send_identify_msg (device);
|
||||
}
|
||||
|
@ -834,6 +876,12 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
|
|||
FpDevice *device = FP_DEVICE (self);
|
||||
bmkt_enroll_resp_t *enroll_resp;
|
||||
|
||||
if (self->action_starting)
|
||||
{
|
||||
fpi_device_critical_leave (device);
|
||||
self->action_starting = FALSE;
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_enroll_complete (device, NULL, error);
|
||||
|
@ -980,6 +1028,9 @@ enroll (FpDevice *device)
|
|||
payload[1] = finger;
|
||||
memcpy (payload + 2, user_id, user_id_len);
|
||||
|
||||
self->action_starting = TRUE;
|
||||
fpi_device_critical_enter (device);
|
||||
|
||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_ENROLL_USER, payload, user_id_len + 2, enroll_msg_cb);
|
||||
}
|
||||
|
||||
|
@ -993,6 +1044,7 @@ delete_msg_cb (FpiDeviceSynaptics *self,
|
|||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_critical_leave (device);
|
||||
fpi_device_delete_complete (device, error);
|
||||
return;
|
||||
}
|
||||
|
@ -1007,6 +1059,7 @@ delete_msg_cb (FpiDeviceSynaptics *self,
|
|||
break;
|
||||
|
||||
case BMKT_RSP_DEL_USER_FP_FAIL:
|
||||
fpi_device_critical_leave (device);
|
||||
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS ||
|
||||
resp->result == BMKT_FP_DATABASE_EMPTY)
|
||||
{
|
||||
|
@ -1023,6 +1076,7 @@ delete_msg_cb (FpiDeviceSynaptics *self,
|
|||
|
||||
case BMKT_RSP_DEL_USER_FP_OK:
|
||||
fp_info ("Successfully deleted enrolled user");
|
||||
fpi_device_critical_leave (device);
|
||||
fpi_device_delete_complete (device, NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -1057,6 +1111,7 @@ delete_print (FpDevice *device)
|
|||
payload[0] = finger;
|
||||
memcpy (payload + 1, user_id, user_id_len);
|
||||
|
||||
fpi_device_critical_enter (device);
|
||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb);
|
||||
}
|
||||
|
||||
|
@ -1296,8 +1351,12 @@ fps_deinit_cb (FpiDeviceSynaptics *self,
|
|||
bmkt_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
g_autoptr(GError) err = NULL;
|
||||
|
||||
/* Release usb interface */
|
||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &error);
|
||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &err);
|
||||
if (!error)
|
||||
error = g_steal_pointer (&err);
|
||||
|
||||
g_clear_object (&self->interrupt_cancellable);
|
||||
|
||||
|
@ -1368,6 +1427,59 @@ cancel (FpDevice *dev)
|
|||
self->interrupt_cancellable = g_cancellable_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
suspend (FpDevice *dev)
|
||||
{
|
||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
|
||||
FpiDeviceAction action = fpi_device_get_current_action (dev);
|
||||
|
||||
g_debug ("got suspend request");
|
||||
|
||||
if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_suspend_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are guaranteed to have a cmd_ssm running at this time. */
|
||||
g_assert (self->cmd_ssm);
|
||||
g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == SYNAPTICS_CMD_WAIT_INTERRUPT);
|
||||
self->cmd_suspended = TRUE;
|
||||
|
||||
/* Cancel the current transfer.
|
||||
* The CMD SSM will go into the suspend state and signal readyness. */
|
||||
g_cancellable_cancel (self->interrupt_cancellable);
|
||||
g_clear_object (&self->interrupt_cancellable);
|
||||
self->interrupt_cancellable = g_cancellable_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
resume (FpDevice *dev)
|
||||
{
|
||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
|
||||
FpiDeviceAction action = fpi_device_get_current_action (dev);
|
||||
|
||||
g_debug ("got resume request");
|
||||
|
||||
if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
fpi_device_resume_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We must have a suspended cmd_ssm at this point */
|
||||
g_assert (self->cmd_ssm);
|
||||
g_assert (self->cmd_suspended);
|
||||
g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == SYNAPTICS_CMD_SUSPENDED);
|
||||
self->cmd_suspended = FALSE;
|
||||
|
||||
/* Restart interrupt transfer. */
|
||||
fpi_ssm_jump_to_state (self->cmd_ssm, SYNAPTICS_CMD_RESUME);
|
||||
|
||||
fpi_device_resume_complete (dev, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_device_synaptics_init (FpiDeviceSynaptics *self)
|
||||
{
|
||||
|
@ -1385,6 +1497,7 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
|
|||
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||
dev_class->id_table = id_table;
|
||||
dev_class->nr_enroll_stages = ENROLL_SAMPLES;
|
||||
dev_class->temp_hot_seconds = -1;
|
||||
|
||||
dev_class->open = dev_init;
|
||||
dev_class->close = dev_exit;
|
||||
|
@ -1395,6 +1508,8 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
|
|||
dev_class->delete = delete_print;
|
||||
dev_class->clear_storage = clear_storage;
|
||||
dev_class->cancel = cancel;
|
||||
dev_class->suspend = suspend;
|
||||
dev_class->resume = resume;
|
||||
|
||||
fpi_device_class_auto_initialize_features (dev_class);
|
||||
}
|
||||
|
|
|
@ -93,6 +93,8 @@ typedef enum {
|
|||
SYNAPTICS_CMD_WAIT_INTERRUPT,
|
||||
SYNAPTICS_CMD_SEND_ASYNC,
|
||||
SYNAPTICS_CMD_RESTART,
|
||||
SYNAPTICS_CMD_SUSPENDED,
|
||||
SYNAPTICS_CMD_RESUME,
|
||||
SYNAPTICS_CMD_NUM_STATES,
|
||||
} SynapticsCmdState;
|
||||
|
||||
|
@ -110,10 +112,12 @@ struct _FpiDeviceSynaptics
|
|||
FpiSsm *cmd_ssm;
|
||||
FpiUsbTransfer *cmd_pending_transfer;
|
||||
gboolean cmd_complete_on_removal;
|
||||
gboolean cmd_suspended;
|
||||
guint8 id_idx;
|
||||
|
||||
bmkt_sensor_version_t mis_version;
|
||||
|
||||
gboolean action_starting;
|
||||
GCancellable *interrupt_cancellable;
|
||||
|
||||
gint enroll_stage;
|
||||
|
|
|
@ -360,9 +360,9 @@ start_irq_handler (FpImageDevice *dev)
|
|||
transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
|
||||
transfer->ssm = NULL;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_fill_bulk (transfer,
|
||||
EP_INTR,
|
||||
IRQ_LENGTH);
|
||||
fpi_usb_transfer_fill_interrupt (transfer,
|
||||
EP_INTR,
|
||||
IRQ_LENGTH);
|
||||
fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,12 +67,17 @@ dev_identify (FpDevice *dev)
|
|||
new_scan,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
NULL))
|
||||
error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND);
|
||||
{
|
||||
match = FALSE;
|
||||
g_clear_object (&new_scan);
|
||||
}
|
||||
else if (g_ptr_array_find_with_equal_func (prints,
|
||||
new_scan,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&idx))
|
||||
match = g_ptr_array_index (prints, idx);
|
||||
{
|
||||
match = g_ptr_array_index (prints, idx);
|
||||
}
|
||||
|
||||
if (!self->match_reported)
|
||||
{
|
||||
|
|
|
@ -150,6 +150,8 @@ process_cmds (FpDeviceVirtualDevice * self,
|
|||
char **scan_id,
|
||||
GError **error)
|
||||
{
|
||||
gboolean removed;
|
||||
|
||||
if (g_cancellable_is_cancelled (self->cancellable) ||
|
||||
(fpi_device_get_current_action (FP_DEVICE (self)) != FPI_DEVICE_ACTION_NONE &&
|
||||
g_cancellable_is_cancelled (fpi_device_get_cancellable (FP_DEVICE (self)))))
|
||||
|
@ -250,8 +252,11 @@ process_cmds (FpDeviceVirtualDevice * self,
|
|||
if (self->ignore_wait)
|
||||
return TRUE;
|
||||
|
||||
g_object_get (self, "removed", &removed, NULL);
|
||||
|
||||
g_assert (self->wait_command_id == 0);
|
||||
self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
|
||||
if (!scan || removed)
|
||||
self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -304,6 +309,7 @@ recv_instruction_cb (GObject *source_object,
|
|||
else if (g_str_has_prefix (cmd, UNPLUG_CMD))
|
||||
{
|
||||
fpi_device_remove (FP_DEVICE (self));
|
||||
maybe_continue_current_action (self);
|
||||
}
|
||||
else if (g_str_has_prefix (cmd, SET_ENROLL_STAGES_PREFIX))
|
||||
{
|
||||
|
@ -537,7 +543,7 @@ dev_verify (FpDevice *dev)
|
|||
|
||||
if (self->prints_storage && !g_hash_table_contains (self->prints_storage, scan_id))
|
||||
{
|
||||
error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND);
|
||||
g_clear_object (&new_scan);
|
||||
success = FALSE;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -574,7 +574,7 @@ fp_context_enumerate (FpContext *context)
|
|||
*
|
||||
* Get all devices. fp_context_enumerate() will be called as needed.
|
||||
*
|
||||
* Returns: (transfer none) (element-type FpDevice): a new #GPtrArray of #GUsbDevice's.
|
||||
* Returns: (transfer none) (element-type FpDevice): a new #GPtrArray of #FpDevice's.
|
||||
*/
|
||||
GPtrArray *
|
||||
fp_context_get_devices (FpContext *context)
|
||||
|
|
|
@ -22,6 +22,23 @@
|
|||
|
||||
#include "fpi-device.h"
|
||||
|
||||
/* Chosen so that if we turn on after WARM -> COLD, it takes exactly one time
|
||||
* constant to go from COLD -> HOT.
|
||||
* TEMP_COLD_THRESH = 1 / (e + 1)
|
||||
*/
|
||||
#define TEMP_COLD_THRESH (0.26894142136999512075)
|
||||
#define TEMP_WARM_HOT_THRESH (1.0 - TEMP_COLD_THRESH)
|
||||
#define TEMP_HOT_WARM_THRESH (0.5)
|
||||
|
||||
/* Delay updates by 100ms to avoid hitting the border exactly */
|
||||
#define TEMP_DELAY_SECONDS 0.1
|
||||
|
||||
/* Hopefully 3min is long enough to not get in the way, while also not
|
||||
* properly overheating any devices.
|
||||
*/
|
||||
#define DEFAULT_TEMP_HOT_SECONDS (3 * 60)
|
||||
#define DEFAULT_TEMP_COLD_SECONDS (9 * 60)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpDeviceType type;
|
||||
|
@ -36,6 +53,7 @@ typedef struct
|
|||
|
||||
gboolean is_removed;
|
||||
gboolean is_open;
|
||||
gboolean is_suspended;
|
||||
|
||||
gchar *device_id;
|
||||
gchar *device_name;
|
||||
|
@ -50,14 +68,37 @@ typedef struct
|
|||
/* We always make sure that only one task is run at a time. */
|
||||
FpiDeviceAction current_action;
|
||||
GTask *current_task;
|
||||
GError *current_cancellation_reason;
|
||||
GAsyncReadyCallback current_user_cb;
|
||||
GCancellable *current_cancellable;
|
||||
gulong current_cancellable_id;
|
||||
gulong current_task_cancellable_id;
|
||||
GSource *current_idle_cancel_source;
|
||||
GSource *current_task_idle_return_source;
|
||||
|
||||
/* State for tasks */
|
||||
gboolean wait_for_finger;
|
||||
FpFingerStatusFlags finger_status;
|
||||
|
||||
/* Driver critical sections */
|
||||
guint critical_section;
|
||||
GSource *critical_section_flush_source;
|
||||
gboolean cancel_queued;
|
||||
gboolean suspend_queued;
|
||||
gboolean resume_queued;
|
||||
|
||||
/* Suspend/resume tasks */
|
||||
GTask *suspend_resume_task;
|
||||
GError *suspend_error;
|
||||
|
||||
/* Device temperature model information and state */
|
||||
GSource *temp_timeout;
|
||||
FpTemperature temp_current;
|
||||
gint32 temp_hot_seconds;
|
||||
gint32 temp_cold_seconds;
|
||||
gint64 temp_last_update;
|
||||
gboolean temp_last_active;
|
||||
gdouble temp_current_ratio;
|
||||
} FpDevicePrivate;
|
||||
|
||||
|
||||
|
@ -88,3 +129,8 @@ typedef struct
|
|||
} FpMatchData;
|
||||
|
||||
void match_data_free (FpMatchData *match_data);
|
||||
|
||||
void fpi_device_configure_wakeup (FpDevice *device,
|
||||
gboolean enabled);
|
||||
void fpi_device_update_temp (FpDevice *device,
|
||||
gboolean is_active);
|
||||
|
|
|
@ -48,6 +48,7 @@ enum {
|
|||
PROP_NR_ENROLL_STAGES,
|
||||
PROP_SCAN_TYPE,
|
||||
PROP_FINGER_STATUS,
|
||||
PROP_TEMPERATURE,
|
||||
PROP_FPI_ENVIRON,
|
||||
PROP_FPI_USB_DEVICE,
|
||||
PROP_FPI_UDEV_DATA_SPIDEV,
|
||||
|
@ -93,7 +94,10 @@ fp_device_cancel_in_idle_cb (gpointer user_data)
|
|||
|
||||
priv->current_idle_cancel_source = NULL;
|
||||
|
||||
cls->cancel (self);
|
||||
if (priv->critical_section)
|
||||
priv->cancel_queued = TRUE;
|
||||
else
|
||||
cls->cancel (self);
|
||||
|
||||
fpi_device_report_finger_status (self, FP_FINGER_STATUS_NONE);
|
||||
|
||||
|
@ -118,20 +122,40 @@ fp_device_cancelled_cb (GCancellable *cancellable, FpDevice *self)
|
|||
g_source_unref (priv->current_idle_cancel_source);
|
||||
}
|
||||
|
||||
/* Forward the external task cancellable to the internal one. */
|
||||
static void
|
||||
maybe_cancel_on_cancelled (FpDevice *device,
|
||||
GCancellable *cancellable)
|
||||
fp_device_task_cancelled_cb (GCancellable *cancellable, FpDevice *self)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (self);
|
||||
|
||||
g_cancellable_cancel (priv->current_cancellable);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_task_cancellable (FpDevice *device)
|
||||
{
|
||||
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (!cancellable || !cls->cancel)
|
||||
return;
|
||||
/* Create an internal cancellable and hook it up. */
|
||||
priv->current_cancellable = g_cancellable_new ();
|
||||
if (cls->cancel)
|
||||
{
|
||||
priv->current_cancellable_id = g_cancellable_connect (priv->current_cancellable,
|
||||
G_CALLBACK (fp_device_cancelled_cb),
|
||||
device,
|
||||
NULL);
|
||||
}
|
||||
|
||||
priv->current_cancellable_id = g_cancellable_connect (cancellable,
|
||||
G_CALLBACK (fp_device_cancelled_cb),
|
||||
device,
|
||||
NULL);
|
||||
/* Task cancellable is the externally visible one, make our internal one
|
||||
* a slave of the external one. */
|
||||
if (g_task_get_cancellable (priv->current_task))
|
||||
{
|
||||
priv->current_task_cancellable_id = g_cancellable_connect (g_task_get_cancellable (priv->current_task),
|
||||
G_CALLBACK (fp_device_task_cancelled_cb),
|
||||
device,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -151,6 +175,36 @@ fp_device_constructed (GObject *object)
|
|||
priv->device_name = g_strdup (cls->full_name);
|
||||
priv->device_id = g_strdup ("0");
|
||||
|
||||
if (cls->temp_hot_seconds > 0)
|
||||
{
|
||||
priv->temp_hot_seconds = cls->temp_hot_seconds;
|
||||
priv->temp_cold_seconds = cls->temp_cold_seconds;
|
||||
g_assert (priv->temp_cold_seconds > 0);
|
||||
}
|
||||
else if (cls->temp_hot_seconds == 0)
|
||||
{
|
||||
priv->temp_hot_seconds = DEFAULT_TEMP_HOT_SECONDS;
|
||||
priv->temp_cold_seconds = DEFAULT_TEMP_COLD_SECONDS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Temperature management disabled */
|
||||
priv->temp_hot_seconds = -1;
|
||||
priv->temp_cold_seconds = -1;
|
||||
}
|
||||
|
||||
/* Start out at not completely cold (i.e. assume we are only at the upper
|
||||
* bound of COLD).
|
||||
* To be fair, the warm-up from 0 to WARM should be really short either way.
|
||||
*
|
||||
* Note that a call to fpi_device_update_temp() is not needed here as no
|
||||
* timeout must be registered.
|
||||
*/
|
||||
priv->temp_current = FP_TEMPERATURE_COLD;
|
||||
priv->temp_current_ratio = TEMP_COLD_THRESH;
|
||||
priv->temp_last_update = g_get_monotonic_time ();
|
||||
priv->temp_last_active = FALSE;
|
||||
|
||||
G_OBJECT_CLASS (fp_device_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
|
@ -165,6 +219,8 @@ fp_device_finalize (GObject *object)
|
|||
if (priv->is_open)
|
||||
g_warning ("User destroyed open device! Not cleaning up properly!");
|
||||
|
||||
g_clear_pointer (&priv->temp_timeout, g_source_destroy);
|
||||
|
||||
g_slist_free_full (priv->sources, (GDestroyNotify) g_source_destroy);
|
||||
|
||||
g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
|
||||
|
@ -189,6 +245,7 @@ fp_device_get_property (GObject *object,
|
|||
{
|
||||
FpDevice *self = FP_DEVICE (object);
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (self);
|
||||
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
|
@ -204,6 +261,10 @@ fp_device_get_property (GObject *object,
|
|||
g_value_set_flags (value, priv->finger_status);
|
||||
break;
|
||||
|
||||
case PROP_TEMPERATURE:
|
||||
g_value_set_enum (value, priv->temp_current);
|
||||
break;
|
||||
|
||||
case PROP_DRIVER:
|
||||
g_value_set_static_string (value, FP_DEVICE_GET_CLASS (self)->id);
|
||||
break;
|
||||
|
@ -224,6 +285,24 @@ fp_device_get_property (GObject *object,
|
|||
g_value_set_boolean (value, priv->is_removed);
|
||||
break;
|
||||
|
||||
case PROP_FPI_USB_DEVICE:
|
||||
g_value_set_object (value, priv->usb_device);
|
||||
break;
|
||||
|
||||
case PROP_FPI_UDEV_DATA_SPIDEV:
|
||||
if (cls->type == FP_DEVICE_TYPE_UDEV)
|
||||
g_value_set_string (value, g_strdup (priv->udev_data.spidev_path));
|
||||
else
|
||||
g_value_set_string (value, NULL);
|
||||
break;
|
||||
|
||||
case PROP_FPI_UDEV_DATA_HIDRAW:
|
||||
if (cls->type == FP_DEVICE_TYPE_UDEV)
|
||||
g_value_set_string (value, g_strdup (priv->udev_data.hidraw_path));
|
||||
else
|
||||
g_value_set_string (value, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
|
@ -279,6 +358,24 @@ fp_device_set_property (GObject *object,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_idle_probe_cb (FpDevice *self, gpointer user_data)
|
||||
{
|
||||
/* This should not be an idle handler, see comment where it is registered.
|
||||
*
|
||||
* This effectively disables USB "persist" for us, and possibly turns off
|
||||
* USB wakeup if it was enabled for some reason.
|
||||
*/
|
||||
fpi_device_configure_wakeup (self, FALSE);
|
||||
|
||||
if (!FP_DEVICE_GET_CLASS (self)->probe)
|
||||
fpi_device_probe_complete (self, NULL, NULL, NULL);
|
||||
else
|
||||
FP_DEVICE_GET_CLASS (self)->probe (self);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
fp_device_async_initable_init_async (GAsyncInitable *initable,
|
||||
int io_priority,
|
||||
|
@ -298,17 +395,16 @@ fp_device_async_initable_init_async (GAsyncInitable *initable,
|
|||
if (g_task_return_error_if_cancelled (task))
|
||||
return;
|
||||
|
||||
if (!FP_DEVICE_GET_CLASS (self)->probe)
|
||||
{
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->current_action = FPI_DEVICE_ACTION_PROBE;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (self, cancellable);
|
||||
setup_task_cancellable (self);
|
||||
|
||||
FP_DEVICE_GET_CLASS (self)->probe (self);
|
||||
/* We push this into an idle handler for compatibility with libgusb
|
||||
* 0.3.7 and before.
|
||||
* See https://github.com/hughsie/libgusb/pull/50
|
||||
*/
|
||||
g_source_set_name (fpi_device_add_timeout (self, 0, device_idle_probe_cb, NULL, NULL),
|
||||
"libusb probe in idle");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -358,6 +454,13 @@ fp_device_class_init (FpDeviceClass *klass)
|
|||
FP_TYPE_FINGER_STATUS_FLAGS, FP_FINGER_STATUS_NONE,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
|
||||
properties[PROP_TEMPERATURE] =
|
||||
g_param_spec_enum ("temperature",
|
||||
"Temperature",
|
||||
"The temperature estimation for device to prevent overheating.",
|
||||
FP_TYPE_TEMPERATURE, FP_TEMPERATURE_COLD,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
|
||||
properties[PROP_DRIVER] =
|
||||
g_param_spec_string ("driver",
|
||||
"Driver",
|
||||
|
@ -446,7 +549,7 @@ fp_device_class_init (FpDeviceClass *klass)
|
|||
"USB Device",
|
||||
"Private: The USB device for the device",
|
||||
G_USB_TYPE_DEVICE,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* FpDevice::fpi-udev-data-spidev: (skip)
|
||||
*
|
||||
|
@ -459,7 +562,7 @@ fp_device_class_init (FpDeviceClass *klass)
|
|||
"Udev data: spidev path",
|
||||
"Private: The path to /dev/spidevN.M",
|
||||
NULL,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
/**
|
||||
* FpDevice::fpi-udev-data-hidraw: (skip)
|
||||
*
|
||||
|
@ -472,7 +575,7 @@ fp_device_class_init (FpDeviceClass *klass)
|
|||
"Udev data: hidraw path",
|
||||
"Private: The path to /dev/hidrawN",
|
||||
NULL,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
/**
|
||||
* FpDevice::fpi-driver-data: (skip)
|
||||
|
@ -616,6 +719,25 @@ fp_device_get_nr_enroll_stages (FpDevice *device)
|
|||
return priv->nr_enroll_stages;
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_get_temperature:
|
||||
* @device: A #FpDevice
|
||||
*
|
||||
* Retrieves simple temperature information for device. It is not possible
|
||||
* to use a device when this is #FP_TEMPERATURE_HOT.
|
||||
*
|
||||
* Returns: The current temperature estimation.
|
||||
*/
|
||||
FpTemperature
|
||||
fp_device_get_temperature (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_return_val_if_fail (FP_IS_DEVICE (device), -1);
|
||||
|
||||
return priv->temp_current;
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_supports_identify:
|
||||
* @device: A #FpDevice
|
||||
|
@ -708,7 +830,7 @@ fp_device_open (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -737,7 +859,7 @@ fp_device_open (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_OPEN;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
|
||||
FP_DEVICE_GET_CLASS (device)->open (device);
|
||||
|
@ -793,7 +915,7 @@ fp_device_close (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -802,7 +924,7 @@ fp_device_close (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_CLOSE;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
FP_DEVICE_GET_CLASS (device)->close (device);
|
||||
}
|
||||
|
@ -826,6 +948,230 @@ fp_device_close_finish (FpDevice *device,
|
|||
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:
|
||||
* @device: a #FpDevice
|
||||
* @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
|
||||
* @callback: the function to call on completion
|
||||
* @user_data: the data to pass to @callback
|
||||
*
|
||||
* Prepare the device for system suspend. Retrieve the result with
|
||||
* fp_device_suspend_finish().
|
||||
*
|
||||
* The suspend method can be called at any time (even if the device is not
|
||||
* opened) and must be paired with a corresponding resume call. It is undefined
|
||||
* when or how any ongoing operation is finished. This call might wait for an
|
||||
* ongoing operation to finish, might cancel the ongoing operation or may
|
||||
* prepare the device so that the host is resumed when the operation can be
|
||||
* finished.
|
||||
*
|
||||
* If an ongoing operation must be cancelled then it will complete with an error
|
||||
* code of #FP_DEVICE_ERROR_BUSY before the suspend async routine finishes.
|
||||
*
|
||||
* Any operation started while the device is suspended will fail with
|
||||
* #FP_DEVICE_ERROR_BUSY, this includes calls to open or close the device.
|
||||
*/
|
||||
void
|
||||
fp_device_suspend (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
task = g_task_new (device, cancellable, callback, user_data);
|
||||
|
||||
if (priv->suspend_resume_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->is_removed)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_REMOVED));
|
||||
return;
|
||||
}
|
||||
|
||||
priv->suspend_resume_task = g_steal_pointer (&task);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_suspend_finish:
|
||||
* @device: A #FpDevice
|
||||
* @result: A #GAsyncResult
|
||||
* @error: Return location for errors, or %NULL to ignore
|
||||
*
|
||||
* Finish an asynchronous operation to prepare the device for suspend.
|
||||
* See fp_device_suspend().
|
||||
*
|
||||
* The API user should accept an error of #FP_DEVICE_ERROR_NOT_SUPPORTED.
|
||||
*
|
||||
* Returns: (type void): %FALSE on error, %TRUE otherwise
|
||||
*/
|
||||
gboolean
|
||||
fp_device_suspend_finish (FpDevice *device,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_resume:
|
||||
* @device: a #FpDevice
|
||||
* @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
|
||||
* @callback: the function to call on completion
|
||||
* @user_data: the data to pass to @callback
|
||||
*
|
||||
* Resume device after system suspend. Retrieve the result with
|
||||
* fp_device_suspend_finish().
|
||||
*
|
||||
* Note that it is not defined when any ongoing operation may return (success or
|
||||
* error). You must be ready to handle this before, during or after the
|
||||
* resume operation.
|
||||
*/
|
||||
void
|
||||
fp_device_resume (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
task = g_task_new (device, cancellable, callback, user_data);
|
||||
|
||||
if (priv->suspend_resume_task || !priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->is_removed)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_REMOVED));
|
||||
return;
|
||||
}
|
||||
|
||||
priv->suspend_resume_task = g_steal_pointer (&task);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_resume_finish:
|
||||
* @device: A #FpDevice
|
||||
* @result: A #GAsyncResult
|
||||
* @error: Return location for errors, or %NULL to ignore
|
||||
*
|
||||
* Finish an asynchronous operation to resume the device after suspend.
|
||||
* See fp_device_resume().
|
||||
*
|
||||
* The API user should accept an error of #FP_DEVICE_ERROR_NOT_SUPPORTED.
|
||||
*
|
||||
* Returns: (type void): %FALSE on error, %TRUE otherwise
|
||||
*/
|
||||
gboolean
|
||||
fp_device_resume_finish (FpDevice *device,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fp_device_enroll:
|
||||
|
@ -874,7 +1220,7 @@ fp_device_enroll (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -900,7 +1246,15 @@ fp_device_enroll (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
|
||||
fpi_device_update_temp (device, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
data = g_new0 (FpEnrollData, 1);
|
||||
data->print = g_object_ref_sink (template_print);
|
||||
|
@ -976,7 +1330,7 @@ fp_device_verify (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -993,7 +1347,15 @@ fp_device_verify (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
|
||||
fpi_device_update_temp (device, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
data = g_new0 (FpMatchData, 1);
|
||||
data->enrolled_print = g_object_ref (enrolled_print);
|
||||
|
@ -1095,7 +1457,7 @@ fp_device_identify (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -1112,7 +1474,15 @@ fp_device_identify (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
|
||||
fpi_device_update_temp (device, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
data = g_new0 (FpMatchData, 1);
|
||||
/* We cannot store the gallery directly, because the ptr array may not own
|
||||
|
@ -1212,7 +1582,7 @@ fp_device_capture (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -1229,7 +1599,15 @@ fp_device_capture (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
|
||||
fpi_device_update_temp (device, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->wait_for_finger = wait_for_finger;
|
||||
|
||||
|
@ -1295,7 +1673,7 @@ fp_device_delete_print (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -1311,7 +1689,7 @@ fp_device_delete_print (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_DELETE;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
g_task_set_task_data (priv->current_task,
|
||||
g_object_ref (enrolled_print),
|
||||
|
@ -1373,7 +1751,7 @@ fp_device_list_prints (FpDevice *device,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->current_task)
|
||||
if (priv->current_task || priv->is_suspended)
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
|
||||
|
@ -1390,7 +1768,7 @@ fp_device_list_prints (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_LIST;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
cls->list (device);
|
||||
}
|
||||
|
@ -1475,7 +1853,7 @@ fp_device_clear_storage (FpDevice *device,
|
|||
|
||||
priv->current_action = FPI_DEVICE_ACTION_CLEAR_STORAGE;
|
||||
priv->current_task = g_steal_pointer (&task);
|
||||
maybe_cancel_on_cancelled (device, cancellable);
|
||||
setup_task_cancellable (device);
|
||||
|
||||
cls->clear_storage (device);
|
||||
|
||||
|
@ -1769,6 +2147,7 @@ fp_device_list_prints_sync (FpDevice *device,
|
|||
return fp_device_list_prints_finish (device, task, error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fp_device_clear_storage_sync:
|
||||
* @device: a #FpDevice
|
||||
|
@ -1797,6 +2176,58 @@ fp_device_clear_storage_sync (FpDevice *device,
|
|||
return fp_device_clear_storage_finish (device, task, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_suspend_sync:
|
||||
* @device: a #FpDevice
|
||||
* @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
|
||||
* @error: Return location for errors, or %NULL to ignore
|
||||
*
|
||||
* Prepare device for suspend.
|
||||
*
|
||||
* Returns: (type void): %FALSE on error, %TRUE otherwise
|
||||
*/
|
||||
gboolean
|
||||
fp_device_suspend_sync (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GAsyncResult) task = NULL;
|
||||
|
||||
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
|
||||
|
||||
fp_device_suspend (device, cancellable, async_result_ready, &task);
|
||||
while (!task)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
return fp_device_suspend_finish (device, task, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_resume_sync:
|
||||
* @device: a #FpDevice
|
||||
* @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
|
||||
* @error: Return location for errors, or %NULL to ignore
|
||||
*
|
||||
* Resume device after suspend.
|
||||
*
|
||||
* Returns: (type void): %FALSE on error, %TRUE otherwise
|
||||
*/
|
||||
gboolean
|
||||
fp_device_resume_sync (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GAsyncResult) task = NULL;
|
||||
|
||||
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
|
||||
|
||||
fp_device_resume (device, cancellable, async_result_ready, &task);
|
||||
while (!task)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
return fp_device_resume_finish (device, task, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_get_features:
|
||||
* @device: a #FpDevice
|
||||
|
|
|
@ -58,6 +58,7 @@ typedef enum {
|
|||
* @FP_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates
|
||||
* @FP_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage
|
||||
* @FP_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection
|
||||
* @FP_DEVICE_FEATURE_ALWAYS_ON: Whether the device can run continuously
|
||||
*/
|
||||
typedef enum /*< flags >*/ {
|
||||
FP_DEVICE_FEATURE_NONE = 0,
|
||||
|
@ -69,6 +70,7 @@ typedef enum /*< flags >*/ {
|
|||
FP_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5,
|
||||
FP_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6,
|
||||
FP_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7,
|
||||
FP_DEVICE_FEATURE_ALWAYS_ON = 1 << 8,
|
||||
} FpDeviceFeature;
|
||||
|
||||
/**
|
||||
|
@ -81,6 +83,23 @@ typedef enum {
|
|||
FP_SCAN_TYPE_PRESS,
|
||||
} FpScanType;
|
||||
|
||||
/**
|
||||
* FpTemperature:
|
||||
* @FP_TEMPERATURE_COLD: Sensor is considered cold.
|
||||
* @FP_TEMPERATURE_WARM: Sensor is warm, usage time may be limited.
|
||||
* @FP_TEMPERATURE_HOT: Sensor is hot and cannot be used.
|
||||
*
|
||||
* When a device is created, it is assumed to be cold. Applications such as
|
||||
* fprintd may want to ensure all devices on the system are cold before
|
||||
* shutting down in order to ensure that the cool-off period is not violated
|
||||
* because the internal libfprint state about the device is lost.
|
||||
*/
|
||||
typedef enum {
|
||||
FP_TEMPERATURE_COLD,
|
||||
FP_TEMPERATURE_WARM,
|
||||
FP_TEMPERATURE_HOT,
|
||||
} FpTemperature;
|
||||
|
||||
/**
|
||||
* FpDeviceRetry:
|
||||
* @FP_DEVICE_RETRY_GENERAL: The scan did not succeed due to poor scan quality
|
||||
|
@ -118,6 +137,7 @@ typedef enum {
|
|||
* @FP_DEVICE_ERROR_DATA_FULL: No space on device available for operation
|
||||
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
|
||||
* @FP_DEVICE_ERROR_REMOVED: The device has been removed.
|
||||
* @FP_DEVICE_ERROR_TOO_HOT: The device might be getting too hot
|
||||
*
|
||||
* Error codes for device operations. More specific errors from other domains
|
||||
* such as #G_IO_ERROR or #G_USB_DEVICE_ERROR may also be reported.
|
||||
|
@ -135,6 +155,7 @@ typedef enum {
|
|||
FP_DEVICE_ERROR_DATA_DUPLICATE,
|
||||
/* Leave some room to add more DATA related errors */
|
||||
FP_DEVICE_ERROR_REMOVED = 0x100,
|
||||
FP_DEVICE_ERROR_TOO_HOT,
|
||||
} FpDeviceError;
|
||||
|
||||
GQuark fp_device_retry_quark (void);
|
||||
|
@ -201,6 +222,7 @@ gboolean fp_device_is_open (FpDevice *device);
|
|||
FpScanType fp_device_get_scan_type (FpDevice *device);
|
||||
FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device);
|
||||
gint fp_device_get_nr_enroll_stages (FpDevice *device);
|
||||
FpTemperature fp_device_get_temperature (FpDevice *device);
|
||||
|
||||
FpDeviceFeature fp_device_get_features (FpDevice *device);
|
||||
gboolean fp_device_has_feature (FpDevice *device,
|
||||
|
@ -217,6 +239,16 @@ void fp_device_close (FpDevice *device,
|
|||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void fp_device_suspend (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void fp_device_resume (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void fp_device_enroll (FpDevice *device,
|
||||
FpPrint *template_print,
|
||||
GCancellable *cancellable,
|
||||
|
@ -272,6 +304,12 @@ gboolean fp_device_open_finish (FpDevice *device,
|
|||
gboolean fp_device_close_finish (FpDevice *device,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
gboolean fp_device_suspend_finish (FpDevice *device,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
gboolean fp_device_resume_finish (FpDevice *device,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
FpPrint *fp_device_enroll_finish (FpDevice *device,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
@ -340,6 +378,13 @@ GPtrArray * fp_device_list_prints_sync (FpDevice *device,
|
|||
gboolean fp_device_clear_storage_sync (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean fp_device_suspend_sync (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean fp_device_resume_sync (FpDevice *device,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
/* Deprecated functions */
|
||||
G_DEPRECATED_FOR (fp_device_get_features)
|
||||
gboolean fp_device_supports_identify (FpDevice *device);
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
*/
|
||||
|
||||
#define FP_COMPONENT "device"
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "fpi-log.h"
|
||||
|
||||
#include "fp-device-private.h"
|
||||
|
@ -78,6 +81,9 @@ fpi_device_class_auto_initialize_features (FpDeviceClass *device_class)
|
|||
|
||||
if (device_class->delete && (device_class->list || device_class->clear_storage))
|
||||
device_class->features |= FP_DEVICE_FEATURE_STORAGE;
|
||||
|
||||
if (device_class->temp_hot_seconds < 0)
|
||||
device_class->features |= FP_DEVICE_FEATURE_ALWAYS_ON;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,6 +183,10 @@ fpi_device_error_new (FpDeviceError error)
|
|||
msg = "This device has been removed from the system.";
|
||||
break;
|
||||
|
||||
case FP_DEVICE_ERROR_TOO_HOT:
|
||||
msg = "Device disabled to prevent overheating.";
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Unsupported error, returning general error instead!");
|
||||
error = FP_DEVICE_ERROR_GENERAL;
|
||||
|
@ -488,14 +498,11 @@ gboolean
|
|||
fpi_device_action_is_cancelled (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
GCancellable *cancellable;
|
||||
|
||||
g_return_val_if_fail (FP_IS_DEVICE (device), TRUE);
|
||||
g_return_val_if_fail (priv->current_action != FPI_DEVICE_ACTION_NONE, TRUE);
|
||||
|
||||
cancellable = g_task_get_cancellable (priv->current_task);
|
||||
|
||||
return g_cancellable_is_cancelled (cancellable);
|
||||
return g_cancellable_is_cancelled (priv->current_cancellable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -673,7 +680,7 @@ fpi_device_get_cancellable (FpDevice *device)
|
|||
g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (priv->current_action != FPI_DEVICE_ACTION_NONE, NULL);
|
||||
|
||||
return g_task_get_cancellable (priv->current_task);
|
||||
return priv->current_cancellable;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -802,6 +809,120 @@ fpi_device_action_error (FpDevice *device,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_critical_enter:
|
||||
* @device: The #FpDevice
|
||||
*
|
||||
* Enter a critical section in the driver code where no outside calls from
|
||||
* libfprint should happen. Drivers can already assume that everything
|
||||
* happens from the same thread, however, that still allows e.g. the cancel
|
||||
* vfunc to be called at any point in time.
|
||||
*
|
||||
* Using this kind of critical section, the driver can assume that libfprint
|
||||
* will not forward any external requests to the driver for the time being.
|
||||
* This is for example useful to prevent cancellation while the device is being
|
||||
* set up. Or, said differently, using this feature means that the cancel
|
||||
* handler is able to make more assumptions about the current state.
|
||||
*
|
||||
* Please note that the driver is not shielded from all external changes. For
|
||||
* example the cancellable as returned by fpi_device_get_cancellable() will
|
||||
* still change immediately.
|
||||
*
|
||||
* The driver may call this function multiple times, but must also ensure that
|
||||
* fpi_device_critical_leave() is called an equal amount of times and that all
|
||||
* critical sections are left before command completion.
|
||||
*/
|
||||
void
|
||||
fpi_device_critical_enter (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_return_if_fail (priv->current_action != FPI_DEVICE_ACTION_NONE);
|
||||
|
||||
priv->critical_section += 1;
|
||||
|
||||
/* Stop flushing events if that was previously queued. */
|
||||
if (priv->critical_section_flush_source)
|
||||
g_source_destroy (priv->critical_section_flush_source);
|
||||
priv->critical_section_flush_source = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fpi_device_critical_section_flush_idle_cb (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (priv->cancel_queued)
|
||||
{
|
||||
/* Cancellation must only happen if the driver is busy. */
|
||||
if (priv->current_action != FPI_DEVICE_ACTION_NONE &&
|
||||
priv->current_task_idle_return_source == NULL)
|
||||
cls->cancel (device);
|
||||
priv->cancel_queued = FALSE;
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
if (priv->suspend_queued)
|
||||
{
|
||||
cls->suspend (device);
|
||||
priv->suspend_queued = FALSE;
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
if (priv->resume_queued)
|
||||
{
|
||||
cls->resume (device);
|
||||
priv->resume_queued = FALSE;
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
priv->critical_section_flush_source = NULL;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_critical_leave:
|
||||
* @device: The #FpDevice
|
||||
*
|
||||
* Leave a critical section started by fpi_device_critical_enter().
|
||||
*
|
||||
* Once all critical sections have been left, libfprint will start flushing
|
||||
* out the queued up requests. This is done from the mainloop and the driver
|
||||
* is protected from reentrency issues.
|
||||
*/
|
||||
void
|
||||
fpi_device_critical_leave (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_return_if_fail (priv->current_action != FPI_DEVICE_ACTION_NONE);
|
||||
g_return_if_fail (priv->critical_section);
|
||||
|
||||
priv->critical_section -= 1;
|
||||
if (priv->critical_section)
|
||||
return;
|
||||
|
||||
/* We left the critical section, make sure a flush is queued. */
|
||||
if (priv->critical_section_flush_source)
|
||||
return;
|
||||
|
||||
priv->critical_section_flush_source = g_idle_source_new ();
|
||||
g_source_set_callback (priv->critical_section_flush_source,
|
||||
(GSourceFunc) fpi_device_critical_section_flush_idle_cb,
|
||||
device,
|
||||
NULL);
|
||||
g_source_set_name (priv->critical_section_flush_source,
|
||||
"Flush libfprint driver critical section");
|
||||
g_source_attach (priv->critical_section_flush_source,
|
||||
g_task_get_context (priv->current_task));
|
||||
g_source_unref (priv->critical_section_flush_source);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_device_cancel_action (FpDevice *device)
|
||||
{
|
||||
|
@ -811,10 +932,17 @@ clear_device_cancel_action (FpDevice *device)
|
|||
|
||||
if (priv->current_cancellable_id)
|
||||
{
|
||||
g_cancellable_disconnect (g_task_get_cancellable (priv->current_task),
|
||||
g_cancellable_disconnect (priv->current_cancellable,
|
||||
priv->current_cancellable_id);
|
||||
priv->current_cancellable_id = 0;
|
||||
}
|
||||
|
||||
if (priv->current_task_cancellable_id)
|
||||
{
|
||||
g_cancellable_disconnect (g_task_get_cancellable (priv->current_task),
|
||||
priv->current_task_cancellable_id);
|
||||
priv->current_task_cancellable_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum _FpDeviceTaskReturnType {
|
||||
|
@ -841,6 +969,7 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
|
|||
FpiDeviceAction action;
|
||||
|
||||
g_autoptr(GTask) task = NULL;
|
||||
g_autoptr(GError) cancellation_reason = NULL;
|
||||
|
||||
|
||||
action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
||||
|
@ -850,6 +979,10 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
|
|||
action = priv->current_action;
|
||||
priv->current_action = FPI_DEVICE_ACTION_NONE;
|
||||
priv->current_task_idle_return_source = NULL;
|
||||
g_clear_object (&priv->current_cancellable);
|
||||
cancellation_reason = g_steal_pointer (&priv->current_cancellation_reason);
|
||||
|
||||
fpi_device_update_temp (data->device, FALSE);
|
||||
|
||||
if (action == FPI_DEVICE_ACTION_OPEN &&
|
||||
data->type != FP_DEVICE_TASK_RETURN_ERROR)
|
||||
|
@ -866,6 +999,8 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
|
|||
g_object_notify (G_OBJECT (data->device), "open");
|
||||
}
|
||||
|
||||
/* TODO: Port/use the cancellation mechanism for device removal! */
|
||||
|
||||
/* Return FP_DEVICE_ERROR_REMOVED if the device is removed,
|
||||
* with the exception of a successful open, which is an odd corner case. */
|
||||
if (priv->is_removed &&
|
||||
|
@ -901,7 +1036,18 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
|
|||
break;
|
||||
|
||||
case FP_DEVICE_TASK_RETURN_ERROR:
|
||||
g_task_return_error (task, g_steal_pointer (&data->result));
|
||||
/* Return internal cancellation reason instead if we have one.
|
||||
* Note that an external cancellation always returns G_IO_ERROR_CANCELLED
|
||||
*/
|
||||
if (cancellation_reason)
|
||||
{
|
||||
g_task_set_task_data (task, NULL, NULL);
|
||||
g_task_return_error (task, g_steal_pointer (&cancellation_reason));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_error (task, g_steal_pointer (&data->result));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1404,6 +1550,183 @@ fpi_device_list_complete (FpDevice *device,
|
|||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
}
|
||||
|
||||
void
|
||||
fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
switch (priv->type)
|
||||
{
|
||||
case FP_DEVICE_TYPE_USB:
|
||||
{
|
||||
g_autoptr(GString) ports = NULL;
|
||||
GUsbDevice *dev, *parent;
|
||||
const char *wakeup_command = enabled ? "enabled" : "disabled";
|
||||
guint8 bus, port;
|
||||
g_autofree gchar *sysfs_wakeup = NULL;
|
||||
g_autofree gchar *sysfs_persist = NULL;
|
||||
gssize r;
|
||||
int fd;
|
||||
|
||||
ports = g_string_new (NULL);
|
||||
bus = g_usb_device_get_bus (priv->usb_device);
|
||||
|
||||
/* Walk up, skipping the root hub. */
|
||||
dev = priv->usb_device;
|
||||
while ((parent = g_usb_device_get_parent (dev)))
|
||||
{
|
||||
port = g_usb_device_get_port_number (dev);
|
||||
g_string_prepend (ports, g_strdup_printf ("%d.", port));
|
||||
dev = parent;
|
||||
}
|
||||
g_string_set_size (ports, ports->len - 1);
|
||||
|
||||
sysfs_wakeup = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/wakeup", bus, ports->str);
|
||||
fd = open (sysfs_wakeup, O_WRONLY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
/* 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
|
||||
* in case it is "replugged" due to suspend.
|
||||
* This is not helpful, as it will receive a reset and will be in a bad
|
||||
* 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);
|
||||
fd = open (sysfs_persist, O_WRONLY);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
case FP_DEVICE_TYPE_VIRTUAL:
|
||||
case FP_DEVICE_TYPE_UDEV:
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_device_suspend_completed (FpDevice *device)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
/* We have an ongoing operation, allow the device to wake up the machine. */
|
||||
if (priv->current_action != FPI_DEVICE_ACTION_NONE)
|
||||
fpi_device_configure_wakeup (device, TRUE);
|
||||
|
||||
if (priv->critical_section)
|
||||
g_warning ("Driver was in a critical section at suspend time. It likely deadlocked!");
|
||||
|
||||
if (priv->suspend_error)
|
||||
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task),
|
||||
g_steal_pointer (&priv->suspend_error));
|
||||
else
|
||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_suspend_complete:
|
||||
* @device: The #FpDevice
|
||||
* @error: The #GError or %NULL on success
|
||||
*
|
||||
* Finish a suspend request. Only return a %NULL error if suspend has been
|
||||
* correctly configured and the current action as returned by
|
||||
* fpi_device_get_current_action() will continue to run after resume.
|
||||
*
|
||||
* In all other cases an error must be returned. Should this happen, the
|
||||
* current action will be cancelled before the error is forwarded to the
|
||||
* application.
|
||||
*
|
||||
* It is recommended to set @error to #FP_ERROR_NOT_IMPLEMENTED.
|
||||
*/
|
||||
void
|
||||
fpi_device_suspend_complete (FpDevice *device,
|
||||
GError *error)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->suspend_resume_task);
|
||||
g_return_if_fail (priv->suspend_error == NULL);
|
||||
|
||||
priv->suspend_error = error;
|
||||
priv->is_suspended = TRUE;
|
||||
|
||||
/* If there is no error, we have no running task, return immediately. */
|
||||
if (error == NULL || !priv->current_task || g_task_get_completed (priv->current_task))
|
||||
{
|
||||
fpi_device_suspend_completed (device);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for completion of the current task. */
|
||||
g_signal_connect_object (priv->current_task,
|
||||
"notify::completed",
|
||||
G_CALLBACK (fpi_device_suspend_completed),
|
||||
device,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
/* And cancel any action that might be long-running. */
|
||||
if (!priv->current_cancellation_reason)
|
||||
priv->current_cancellation_reason = fpi_device_error_new_msg (FP_DEVICE_ERROR_BUSY,
|
||||
"Cannot run while suspended.");
|
||||
|
||||
g_cancellable_cancel (priv->current_cancellable);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_resume_complete:
|
||||
* @device: The #FpDevice
|
||||
* @error: The #GError or %NULL on success
|
||||
*
|
||||
* Finish a resume request.
|
||||
*/
|
||||
void
|
||||
fpi_device_resume_complete (FpDevice *device,
|
||||
GError *error)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->suspend_resume_task);
|
||||
|
||||
priv->is_suspended = FALSE;
|
||||
fpi_device_configure_wakeup (device, FALSE);
|
||||
|
||||
if (error)
|
||||
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task), error);
|
||||
else
|
||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_clear_storage_complete:
|
||||
* @device: The #FpDevice
|
||||
|
@ -1685,3 +2008,128 @@ fpi_device_report_finger_status_changes (FpDevice *device,
|
|||
|
||||
return fpi_device_report_finger_status (device, finger_status);
|
||||
}
|
||||
|
||||
static void
|
||||
update_temp_timeout (FpDevice *device, gpointer user_data)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
fpi_device_update_temp (device, priv->temp_last_active);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_update_temp:
|
||||
* @device: The #FpDevice
|
||||
* @is_active: Whether the device is now active
|
||||
*
|
||||
* Purely internal function to update the temperature. Also ensure that the
|
||||
* state is updated once a threshold is reached.
|
||||
*/
|
||||
void
|
||||
fpi_device_update_temp (FpDevice *device, gboolean is_active)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
gint64 now = g_get_monotonic_time ();
|
||||
gdouble passed_seconds;
|
||||
gdouble alpha;
|
||||
gdouble next_threshold;
|
||||
gdouble old_ratio;
|
||||
FpTemperature old_temp;
|
||||
g_autofree char *old_temp_str = NULL;
|
||||
g_autofree char *new_temp_str = NULL;
|
||||
|
||||
if (priv->temp_hot_seconds < 0)
|
||||
{
|
||||
g_debug ("Not updating temperature model, device can run continuously!");
|
||||
return;
|
||||
}
|
||||
|
||||
passed_seconds = (now - priv->temp_last_update) / 1e6;
|
||||
old_ratio = priv->temp_current_ratio;
|
||||
|
||||
if (priv->temp_last_active)
|
||||
{
|
||||
alpha = exp (-passed_seconds / priv->temp_hot_seconds);
|
||||
priv->temp_current_ratio = alpha * priv->temp_current_ratio + 1 - alpha;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = exp (-passed_seconds / priv->temp_cold_seconds);
|
||||
priv->temp_current_ratio = alpha * priv->temp_current_ratio;
|
||||
}
|
||||
|
||||
priv->temp_last_active = is_active;
|
||||
priv->temp_last_update = now;
|
||||
|
||||
old_temp = priv->temp_current;
|
||||
if (priv->temp_current_ratio < TEMP_COLD_THRESH)
|
||||
{
|
||||
priv->temp_current = FP_TEMPERATURE_COLD;
|
||||
next_threshold = is_active ? TEMP_COLD_THRESH : -1.0;
|
||||
}
|
||||
else if (priv->temp_current_ratio < TEMP_HOT_WARM_THRESH)
|
||||
{
|
||||
priv->temp_current = FP_TEMPERATURE_WARM;
|
||||
next_threshold = is_active ? TEMP_WARM_HOT_THRESH : TEMP_COLD_THRESH;
|
||||
}
|
||||
else if (priv->temp_current_ratio < TEMP_WARM_HOT_THRESH)
|
||||
{
|
||||
/* Keep HOT until we reach TEMP_HOT_WARM_THRESH */
|
||||
if (priv->temp_current != FP_TEMPERATURE_HOT)
|
||||
priv->temp_current = FP_TEMPERATURE_WARM;
|
||||
|
||||
next_threshold = is_active ? TEMP_WARM_HOT_THRESH : TEMP_HOT_WARM_THRESH;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->temp_current = FP_TEMPERATURE_HOT;
|
||||
next_threshold = is_active ? -1.0 : TEMP_HOT_WARM_THRESH;
|
||||
}
|
||||
|
||||
old_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, old_temp);
|
||||
new_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, priv->temp_current);
|
||||
g_debug ("Updated temperature model after %0.2f seconds, ratio %0.2f -> %0.2f, active %d -> %d, %s -> %s",
|
||||
passed_seconds,
|
||||
old_ratio,
|
||||
priv->temp_current_ratio,
|
||||
priv->temp_last_active,
|
||||
is_active,
|
||||
old_temp_str,
|
||||
new_temp_str);
|
||||
|
||||
if (priv->temp_current != old_temp)
|
||||
g_object_notify (G_OBJECT (device), "temperature");
|
||||
|
||||
/* If the device is HOT, then do an internal cancellation of long running tasks. */
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
if (priv->current_action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
priv->current_action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
priv->current_action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
priv->current_action == FPI_DEVICE_ACTION_CAPTURE)
|
||||
{
|
||||
if (!priv->current_cancellation_reason)
|
||||
priv->current_cancellation_reason = fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT);
|
||||
|
||||
g_cancellable_cancel (priv->current_cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_pointer (&priv->temp_timeout, g_source_destroy);
|
||||
|
||||
if (next_threshold < 0)
|
||||
return;
|
||||
|
||||
/* Set passed_seconds to the time until the next update is needed */
|
||||
if (is_active)
|
||||
passed_seconds = -priv->temp_hot_seconds * log ((next_threshold - 1.0) / (priv->temp_current_ratio - 1.0));
|
||||
else
|
||||
passed_seconds = -priv->temp_cold_seconds * log (next_threshold / priv->temp_current_ratio);
|
||||
|
||||
passed_seconds += TEMP_DELAY_SECONDS;
|
||||
|
||||
priv->temp_timeout = fpi_device_add_timeout (device,
|
||||
passed_seconds * 1000,
|
||||
update_temp_timeout,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#include "fp-image.h"
|
||||
#include "fpi-print.h"
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/**
|
||||
* FpiDeviceUdevSubtype:
|
||||
* @FPI_DEVICE_UDEV_SUBTYPE_SPIDEV: The device requires an spidev node
|
||||
|
@ -82,6 +80,10 @@ struct _FpIdEntry
|
|||
* fpi_device_set_nr_enroll_stages() from @probe if this is dynamic.
|
||||
* @scan_type: The scan type of supported devices; use
|
||||
* fpi_device_set_scan_type() from @probe if this is dynamic.
|
||||
* @temp_hot_seconds: Assumed time in seconds for the device to become too hot
|
||||
* after being mostly cold. Set to -1 if the device can be always-on.
|
||||
* @temp_cold_seconds: Assumed time in seconds for the device to be mostly cold
|
||||
* after having been too hot to operate.
|
||||
* @usb_discover: Class method to check whether a USB device is supported by
|
||||
* the driver. Should return 0 if the device is unsupported and a positive
|
||||
* score otherwise. The default score is 50 and the driver with the highest
|
||||
|
@ -104,6 +106,10 @@ struct _FpIdEntry
|
|||
* @clear_storage: Delete all prints from the device
|
||||
* @cancel: Called on cancellation, this is a convenience to not need to handle
|
||||
* the #GCancellable directly by using fpi_device_get_cancellable().
|
||||
* @suspend: Called when an interactive action is running (ENROLL, VERIFY,
|
||||
* IDENTIFY or CAPTURE) and the system is about to go into suspend.
|
||||
* @resume: Called to resume an ongoing interactive action after the system has
|
||||
* resumed from suspend.
|
||||
*
|
||||
* NOTE: If your driver is image based, then you should subclass #FpImageDevice
|
||||
* instead. #FpImageDevice based drivers use a different way of interacting
|
||||
|
@ -122,6 +128,9 @@ struct _FpIdEntry
|
|||
* operation (i.e. any operation that requires capturing). It is entirely fine
|
||||
* to ignore cancellation requests for short operations (e.g. open/close).
|
||||
*
|
||||
* Note that @cancel, @suspend and @resume will not be called while the device
|
||||
* is within a fpi_device_critical_enter()/fpi_device_critical_leave() block.
|
||||
*
|
||||
* This API is solely intended for drivers. It is purely internal and neither
|
||||
* API nor ABI stable.
|
||||
*/
|
||||
|
@ -142,6 +151,10 @@ struct _FpDeviceClass
|
|||
gint nr_enroll_stages;
|
||||
FpScanType scan_type;
|
||||
|
||||
/* Simple device temperature model constants */
|
||||
gint32 temp_hot_seconds;
|
||||
gint32 temp_cold_seconds;
|
||||
|
||||
/* Callbacks */
|
||||
gint (*usb_discover) (GUsbDevice *usb_device);
|
||||
void (*probe) (FpDevice *device);
|
||||
|
@ -156,6 +169,8 @@ struct _FpDeviceClass
|
|||
void (*clear_storage) (FpDevice * device);
|
||||
|
||||
void (*cancel) (FpDevice *device);
|
||||
void (*suspend) (FpDevice *device);
|
||||
void (*resume) (FpDevice *device);
|
||||
};
|
||||
|
||||
void fpi_device_class_auto_initialize_features (FpDeviceClass *device_class);
|
||||
|
@ -256,6 +271,9 @@ void fpi_device_update_features (FpDevice *device,
|
|||
void fpi_device_action_error (FpDevice *device,
|
||||
GError *error);
|
||||
|
||||
void fpi_device_critical_enter (FpDevice *device);
|
||||
void fpi_device_critical_leave (FpDevice *device);
|
||||
|
||||
void fpi_device_probe_complete (FpDevice *device,
|
||||
const gchar *device_id,
|
||||
const gchar *device_name,
|
||||
|
@ -281,6 +299,10 @@ void fpi_device_list_complete (FpDevice *device,
|
|||
GError *error);
|
||||
void fpi_device_clear_storage_complete (FpDevice *device,
|
||||
GError *error);
|
||||
void fpi_device_suspend_complete (FpDevice *device,
|
||||
GError *error);
|
||||
void fpi_device_resume_complete (FpDevice *device,
|
||||
GError *error);
|
||||
|
||||
void fpi_device_enroll_progress (FpDevice *device,
|
||||
gint completed_stages,
|
||||
|
|
|
@ -49,6 +49,7 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||
{ .vid = 0x06cb, .pid = 0x00cb },
|
||||
{ .vid = 0x06cb, .pid = 0x00d8 },
|
||||
{ .vid = 0x06cb, .pid = 0x00da },
|
||||
{ .vid = 0x06cb, .pid = 0x00e7 },
|
||||
{ .vid = 0x06cb, .pid = 0x00e9 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5801 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5805 },
|
||||
|
@ -57,6 +58,7 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||
{ .vid = 0x0a5c, .pid = 0x5841 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5842 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5843 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5844 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5845 },
|
||||
{ .vid = 0x10a5, .pid = 0x0007 },
|
||||
{ .vid = 0x1188, .pid = 0x9545 },
|
||||
|
@ -165,7 +167,10 @@ print_driver (const FpDeviceClass *cls)
|
|||
}
|
||||
|
||||
if (num_printed > 0)
|
||||
g_print (" ID_AUTOSUSPEND=1\n");
|
||||
{
|
||||
g_print (" ID_AUTOSUSPEND=1\n");
|
||||
g_print (" ID_PERSIST=0\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
project('libfprint', [ 'c', 'cpp' ],
|
||||
version: '1.92.1',
|
||||
version: '1.94.0',
|
||||
license: 'LGPLv2.1+',
|
||||
default_options: [
|
||||
'buildtype=debugoptimized',
|
||||
|
|
|
@ -15,57 +15,23 @@ script, capture it and store the capture to `custom.pcapng`.
|
|||
-----------------------
|
||||
A new 'capture' test is created by means of `capture.py` script:
|
||||
|
||||
1. Create (if needed) a directory for the driver under `tests`
|
||||
directory:
|
||||
1. Make sure that libfprint is built with support for the device driver
|
||||
that you want to capture a test case for.
|
||||
|
||||
`mkdir DRIVER`
|
||||
2. From the build directory, run tests/create-driver-test.py as root. Note
|
||||
that if you're capturing data for a driver which already has a test case
|
||||
but the hardware is slightly different, you might want to pass a variant
|
||||
name as a command-line options, for example:
|
||||
```sh
|
||||
$ sudo tests/create-driver-test.py driver [variant]
|
||||
```
|
||||
|
||||
Note that the name must be the exact name of the libfprint driver,
|
||||
or the exact name of the driver followed by a `-` and a unique identifier
|
||||
of your choosing.
|
||||
3. If the capture is not successful, run the tool again to start another capture.
|
||||
|
||||
2. Prepare your execution environment.
|
||||
4. Add driver test name to `drivers_tests` in the `meson.build`, as instructed,
|
||||
and change the ownership of the just-created test directory in the source.
|
||||
|
||||
In the next step a working and up to date libfprint is needed. This can be
|
||||
achieved by installing it into your system. Alternatively, you can set
|
||||
the following environment variables to run a local build:
|
||||
- `export LD_PRELOAD=<meson-build-dir>/libfprint/libfprint-2.so`
|
||||
- `export GI_TYPELIB_PATH=<meson-build-dir>/libfprint`
|
||||
|
||||
Also, sometimes the driver must be adapted to the emulated environment
|
||||
(mainly if it uses random numbers, see `synaptics.c` for an example).
|
||||
Set the following environment variable to enable this adaptation:
|
||||
- `export FP_DEVICE_EMULATION=1`
|
||||
|
||||
Run the next steps in the same terminal.
|
||||
|
||||
3. Find the real USB fingerprint device with `lsusb`, e.g.:
|
||||
|
||||
`Bus 001 Device 005: ID 138a:0090 Validity Sensors, Inc. VFS7500 Touch Fingerprint Sensor`
|
||||
|
||||
The following USB device is used in the example above:
|
||||
`/dev/bus/usb/001/005`.
|
||||
|
||||
For the following commands, it is assumed that the user that's
|
||||
running the commands has full access to the device node, whether
|
||||
by running the commands as `root`, or changing the permissions for
|
||||
that device node.
|
||||
|
||||
4. Record information about this device:
|
||||
|
||||
`umockdev-record /dev/bus/usb/001/005 > DRIVER/device`
|
||||
|
||||
5. Record interaction of `capture.py` (or other test) with the device. To do
|
||||
so, start wireshark and record `usbmonX` (where X is the bus number). Then
|
||||
run the test script:
|
||||
|
||||
`python3 ./capture.py DRIVER/capture.png`
|
||||
|
||||
Save the wireshark recording as `capture.pcapng`. The command will create
|
||||
`capture.png`.
|
||||
|
||||
6. Add driver's name to `drivers_tests` in the `meson.build`.
|
||||
7. Check whether everything works as expected.
|
||||
5. Check whether `meson test` passes with this new test.
|
||||
|
||||
**Note.** To avoid submitting a real fingerprint, the side of finger,
|
||||
arm, or anything else producing an image with the device can be used.
|
||||
|
|
BIN
tests/aes2501/capture.pcapng
Normal file
BIN
tests/aes2501/capture.pcapng
Normal file
Binary file not shown.
BIN
tests/aes2501/capture.png
Normal file
BIN
tests/aes2501/capture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
223
tests/aes2501/device
Normal file
223
tests/aes2501/device
Normal file
|
@ -0,0 +1,223 @@
|
|||
P: /devices/pci0000:00/0000:00:14.0/usb1/1-10
|
||||
N: bus/usb/001/044=12011001FFFFFF08FF08802523060001000109022000010100A0320904000002FFFFFF000705810220000007050202080000
|
||||
E: DEVNAME=/dev/bus/usb/001/044
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=8ff/2580/623
|
||||
E: TYPE=255/255/255
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=044
|
||||
E: MAJOR=189
|
||||
E: MINOR=43
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=08ff
|
||||
E: ID_VENDOR_ENC=08ff
|
||||
E: ID_VENDOR_ID=08ff
|
||||
E: ID_MODEL=Fingerprint_Sensor
|
||||
E: ID_MODEL_ENC=Fingerprint\x20Sensor
|
||||
E: ID_MODEL_ID=2580
|
||||
E: ID_REVISION=0623
|
||||
E: ID_SERIAL=08ff_Fingerprint_Sensor
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:ffffff:
|
||||
E: ID_VENDOR_FROM_DATABASE=AuthenTec, Inc.
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=AES2501 Fingerprint Sensor
|
||||
E: ID_PATH=pci-0000:00:14.0-usb-0:10
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_10
|
||||
E: LIBFPRINT_DRIVER=AuthenTec AES2501
|
||||
A: authorized=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=ff\n
|
||||
A: bDeviceProtocol=ff\n
|
||||
A: bDeviceSubClass=ff\n
|
||||
A: bMaxPacketSize0=8\n
|
||||
A: bMaxPower=100mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0623\n
|
||||
A: bmAttributes=a0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12011001FFFFFF08FF08802523060001000109022000010100A0320904000002FFFFFF000705810220000007050202080000
|
||||
A: dev=189:43\n
|
||||
A: devnum=44\n
|
||||
A: devpath=10\n
|
||||
L: driver=../../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d/device:57
|
||||
A: idProduct=2580\n
|
||||
A: idVendor=08ff\n
|
||||
A: ltm_capable=no\n
|
||||
A: maxchild=0\n
|
||||
L: port=../1-0:1.0/usb1-port10
|
||||
A: power/active_duration=10573\n
|
||||
A: power/autosuspend=2\n
|
||||
A: power/autosuspend_delay_ms=2000\n
|
||||
A: power/connected_duration=23441\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/persist=0\n
|
||||
A: power/runtime_active_time=10430\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=12771\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=Fingerprint Sensor\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=removable\n
|
||||
A: rx_lanes=1\n
|
||||
A: speed=12\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=13241\n
|
||||
A: version= 1.10\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||
N: bus/usb/001/001=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
E: DEVNAME=/dev/bus/usb/001/001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=1d6b/2/513
|
||||
E: TYPE=9/0/1
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=001
|
||||
E: MAJOR=189
|
||||
E: MINOR=0
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Linux_5.13.12-200.fc34.x86_64_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.13.12-200.fc34.x86_64\x20xhci-hcd
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_REVISION=0513
|
||||
E: ID_SERIAL=Linux_5.13.12-200.fc34.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: authorized_default=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=09\n
|
||||
A: bDeviceProtocol=01\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=0mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0513\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0\n
|
||||
A: devnum=1\n
|
||||
A: devpath=0\n
|
||||
L: driver=../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 5.13.12-200.fc34.x86_64 xhci-hcd\n
|
||||
A: maxchild=16\n
|
||||
A: power/active_duration=767293591\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=767293591\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=767293588\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=xHCI Host Controller\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=unknown\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial=0000:00:14.0\n
|
||||
A: speed=480\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=1086\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:A36D
|
||||
E: PCI_SUBSYS_ID=17AA:312A
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: MODALIAS=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30
|
||||
E: SUBSYSTEM=pci
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=86806DA3060490021030030C00008000040032B1000000000000000000000000000000000000000000000000AA172A31000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F00000000560BBD0700000000316000000000000000000000000000000180C2C1080000000000000000000000059087009802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F400200000100006000000008020000010000000400000090000000001800000005000000000000000300000C0000004000000080000000030000000000000000000000000000000000000000000000B50F110112000000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: dbc=disabled\n
|
||||
A: device=0xa36d\n
|
||||
A: dma_mask_bits=64\n
|
||||
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||
A: driver_override=(null)\n
|
||||
A: enable=1\n
|
||||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c
|
||||
A: index=3\n
|
||||
A: irq=125\n
|
||||
A: label=Onboard - Other\n
|
||||
A: local_cpulist=0-5\n
|
||||
A: local_cpus=3f\n
|
||||
A: modalias=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/125=msi\n
|
||||
A: numa_node=-1\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 15 20 2112 20\nxHCI ring segments 46 76 4096 76\nbuffer-2048 0 32 2048 16\nbuffer-512 0 32 512 4\nbuffer-128 3 32 128 1\nbuffer-32 0 128 32 1\n
|
||||
A: power/control=on\n
|
||||
A: power/runtime_active_time=767293736\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=enabled\n
|
||||
A: power/wakeup_abort_count=0\n
|
||||
A: power/wakeup_active=0\n
|
||||
A: power/wakeup_active_count=59\n
|
||||
A: power/wakeup_count=0\n
|
||||
A: power/wakeup_expire_count=59\n
|
||||
A: power/wakeup_last_time_ms=763021754\n
|
||||
A: power/wakeup_max_time_ms=108\n
|
||||
A: power/wakeup_total_time_ms=6149\n
|
||||
A: power_state=D0\n
|
||||
A: resource=0x00000000b1320000 0x00000000b132ffff 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: revision=0x10\n
|
||||
A: subsystem_device=0x312a\n
|
||||
A: subsystem_vendor=0x17aa\n
|
||||
A: vendor=0x8086\n
|
||||
|
162
tests/create-driver-test.py.in
Executable file
162
tests/create-driver-test.py.in
Executable file
|
@ -0,0 +1,162 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
BUILDDIR='@BUILDDIR@'
|
||||
SRCDIR='@SRCDIR@'
|
||||
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
library_path = BUILDDIR + '/libfprint/'
|
||||
|
||||
# Relaunch ourselves with a changed environment so
|
||||
# that we're loading the development version of libfprint
|
||||
if 'LD_LIBRARY_PATH' not in os.environ or not library_path in os.environ['LD_LIBRARY_PATH']:
|
||||
os.environ['LD_LIBRARY_PATH'] = library_path
|
||||
os.environ['GI_TYPELIB_PATH'] = f'{BUILDDIR}/libfprint/'
|
||||
os.environ['FP_DEVICE_EMULATION'] = '1'
|
||||
try:
|
||||
os.execv(sys.argv[0], sys.argv)
|
||||
except Exception as e:
|
||||
print('Could not run script with new library path')
|
||||
sys.exit(1)
|
||||
|
||||
import gi
|
||||
gi.require_version('FPrint', '2.0')
|
||||
from gi.repository import FPrint
|
||||
|
||||
gi.require_version('GUsb', '1.0')
|
||||
from gi.repository import GUsb
|
||||
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
def print_usage():
|
||||
print(f'Usage: {sys.argv[0]} driver [test-variant-name]')
|
||||
print('A test variant name is optional, and must be all lower case letters, or dashes, with no spaces')
|
||||
print(f'The captured data will be stored in {SRCDIR}/tests/[driver name]-[test variant name]')
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
driver_name = sys.argv[1]
|
||||
os.environ['FP_DRIVERS_WHITELIST'] = driver_name
|
||||
|
||||
test_variant = None
|
||||
if len(sys.argv) == 3:
|
||||
valid_re = re.compile('[a-z-]*')
|
||||
test_variant = sys.argv[2]
|
||||
if (not valid_re.match(test_variant) or
|
||||
test_variant.startswith('-') or
|
||||
test_variant.endswith('-')):
|
||||
print(f'Invalid variant name {test_variant}\n')
|
||||
print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
# Check that running as root
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print(f'{sys.argv[0]} is expected to be run as root')
|
||||
sys.exit(1)
|
||||
|
||||
# Check that tshark is available
|
||||
|
||||
tshark = shutil.which('tshark')
|
||||
if not tshark:
|
||||
print("The 'tshark' WireShark command-line tool must be installed to capture USB traffic")
|
||||
sys.exit(1)
|
||||
|
||||
# Find the fingerprint reader
|
||||
ctx = FPrint.Context()
|
||||
ctx.enumerate()
|
||||
devices = ctx.get_devices()
|
||||
if len(devices) == 0:
|
||||
print('Could not find a supported fingerprint reader')
|
||||
sys.exit(1)
|
||||
elif len(devices) > 1:
|
||||
print('Capture requires a single supported fingerprint reader to be plugged in')
|
||||
sys.exit(1)
|
||||
|
||||
test_name = driver_name
|
||||
if test_variant:
|
||||
test_name = driver_name + '-' + test_variant
|
||||
usb_device = devices[0].get_property('fpi-usb-device')
|
||||
bus_num = usb_device.get_bus()
|
||||
device_num = usb_device.get_address()
|
||||
|
||||
print(f'### Detected USB device /dev/bus/usb/{bus_num:03d}/{device_num:03d}')
|
||||
|
||||
# Make directory
|
||||
|
||||
test_dir = SRCDIR + '/tests/' + test_name
|
||||
os.makedirs(test_dir, mode=0o775, exist_ok=True)
|
||||
|
||||
# Capture device info
|
||||
|
||||
args = ['umockdev-record', f'/dev/bus/usb/{bus_num:03d}/{device_num:03d}']
|
||||
device_out = open(test_dir + '/device', 'w')
|
||||
process = subprocess.Popen(args, stdout=device_out)
|
||||
process.wait()
|
||||
|
||||
# Run capture
|
||||
# https://osqa-ask.wireshark.org/questions/53919/how-can-i-precisely-specify-a-usb-device-to-capture-with-tshark/
|
||||
|
||||
print(f'### Starting USB capture on usbmon{bus_num}')
|
||||
capture_pid = os.fork()
|
||||
assert(capture_pid >= 0)
|
||||
|
||||
unfiltered_cap_path = os.path.join(tempfile.gettempdir(), 'capture-unfiltered.pcapng')
|
||||
if capture_pid == 0:
|
||||
os.setpgrp()
|
||||
args = ['tshark', '-q', '-i', f'usbmon{bus_num}', '-w', unfiltered_cap_path]
|
||||
os.execv(tshark, args)
|
||||
|
||||
# Wait 1 sec to settle (we can assume setpgrp happened)
|
||||
time.sleep(1)
|
||||
|
||||
print('### Capturing fingerprint, please swipe or press your finger on the reader')
|
||||
with subprocess.Popen(['python3', SRCDIR + '/tests/capture.py', test_dir + '/capture.png']) as capture_process:
|
||||
capture_process.wait()
|
||||
if capture_process.returncode != 0:
|
||||
print('Failed to capture fingerprint')
|
||||
os.killpg(capture_pid, signal.SIGKILL)
|
||||
sys.exit(1)
|
||||
|
||||
def t_waitpid(pid, timeout):
|
||||
timeout = time.time() + timeout
|
||||
r = os.waitpid(pid, os.WNOHANG)
|
||||
while timeout > time.time() and r[0] == 0:
|
||||
time.sleep(0.1)
|
||||
r = os.waitpid(pid, os.WNOHANG)
|
||||
|
||||
return r
|
||||
|
||||
os.kill(capture_pid, signal.SIGTERM)
|
||||
try:
|
||||
r = t_waitpid(capture_pid, 2)
|
||||
# Kill if nothing died
|
||||
if r[0] == 0:
|
||||
os.kill(capture_pid, signal.SIGKILL)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
|
||||
try:
|
||||
while True:
|
||||
r = t_waitpid(-capture_pid, timeout=2)
|
||||
# Kill the process group, if nothing died (and there are children)
|
||||
if r[0] == 0:
|
||||
os.killpg(capture_pid, signal.SIGKILL)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
|
||||
# Filter the capture
|
||||
print(f'\n### Saving USB capture as test case {test_name}')
|
||||
args = ['tshark', '-r', unfiltered_cap_path, '-Y', f'usb.bus_id == {bus_num} and usb.device_address == {device_num}',
|
||||
'-w', test_dir + '/capture.pcapng']
|
||||
with subprocess.Popen(args, stderr=subprocess.DEVNULL) as filter_process:
|
||||
filter_process.wait()
|
||||
|
||||
print(f"\nDone! Don't forget to add {test_name} to tests/meson.build")
|
BIN
tests/elan-cobo/capture.pcapng
Normal file
BIN
tests/elan-cobo/capture.pcapng
Normal file
Binary file not shown.
BIN
tests/elan-cobo/capture.png
Normal file
BIN
tests/elan-cobo/capture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
217
tests/elan-cobo/device
Normal file
217
tests/elan-cobo/device
Normal file
|
@ -0,0 +1,217 @@
|
|||
P: /devices/pci0000:00/0000:00:14.0/usb1/1-10
|
||||
N: bus/usb/001/045=1201000200000008F304260C40010102000109023E0001010080320904000005FF0000000921100100012215000705810240000107050102400001070582024000010705830240000107050302400001
|
||||
E: DEVNAME=/dev/bus/usb/001/045
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=4f3/c26/140
|
||||
E: TYPE=0/0/0
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=045
|
||||
E: MAJOR=189
|
||||
E: MINOR=44
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=ELAN
|
||||
E: ID_VENDOR_ENC=ELAN
|
||||
E: ID_VENDOR_ID=04f3
|
||||
E: ID_MODEL=ELAN:Fingerprint
|
||||
E: ID_MODEL_ENC=ELAN:Fingerprint
|
||||
E: ID_MODEL_ID=0c26
|
||||
E: ID_REVISION=0140
|
||||
E: ID_SERIAL=ELAN_ELAN:Fingerprint
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:ff0000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp.
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_PATH=pci-0000:00:14.0-usb-0:10
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_10
|
||||
E: LIBFPRINT_DRIVER=ElanTech Fingerprint Sensor
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_10
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=00\n
|
||||
A: bDeviceProtocol=00\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=8\n
|
||||
A: bMaxPower=100mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0140\n
|
||||
A: bmAttributes=80\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=1201000200000008F304260C40010102000109023E0001010080320904000005FF0000000921100100012215000705810240000107050102400001070582024000010705830240000107050302400001
|
||||
A: dev=189:44\n
|
||||
A: devnum=45\n
|
||||
A: devpath=10\n
|
||||
L: driver=../../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d/device:57
|
||||
A: idProduct=0c26\n
|
||||
A: idVendor=04f3\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=ELAN\n
|
||||
A: maxchild=0\n
|
||||
L: port=../1-0:1.0/usb1-port10
|
||||
A: power/active_duration=21526\n
|
||||
A: power/autosuspend=2\n
|
||||
A: power/autosuspend_delay_ms=2000\n
|
||||
A: power/connected_duration=96442\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/persist=0\n
|
||||
A: power/runtime_active_time=21572\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=74628\n
|
||||
A: product=ELAN:Fingerprint\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=removable\n
|
||||
A: rx_lanes=1\n
|
||||
A: speed=12\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=103\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||
N: bus/usb/001/001=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
E: DEVNAME=/dev/bus/usb/001/001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=1d6b/2/513
|
||||
E: TYPE=9/0/1
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=001
|
||||
E: MAJOR=189
|
||||
E: MINOR=0
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Linux_5.13.12-200.fc34.x86_64_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.13.12-200.fc34.x86_64\x20xhci-hcd
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_REVISION=0513
|
||||
E: ID_SERIAL=Linux_5.13.12-200.fc34.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: authorized_default=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=09\n
|
||||
A: bDeviceProtocol=01\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=0mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0513\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0\n
|
||||
A: devnum=1\n
|
||||
A: devpath=0\n
|
||||
L: driver=../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 5.13.12-200.fc34.x86_64 xhci-hcd\n
|
||||
A: maxchild=16\n
|
||||
A: power/active_duration=767973436\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=767973436\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=767973433\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=xHCI Host Controller\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=unknown\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial=0000:00:14.0\n
|
||||
A: speed=480\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=1174\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:A36D
|
||||
E: PCI_SUBSYS_ID=17AA:312A
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: MODALIAS=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30
|
||||
E: SUBSYSTEM=pci
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=86806DA3060490021030030C00008000040032B1000000000000000000000000000000000000000000000000AA172A31000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F00000000420DD90700000000316000000000000000000000000000000180C2C1080000000000000000000000059087009802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F400200000100006000000008020000010000000400000090000000001800000005000000000000000300000C0000004000000080000000030000000000000000000000000000000000000000000000B50F110112000000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: dbc=disabled\n
|
||||
A: device=0xa36d\n
|
||||
A: dma_mask_bits=64\n
|
||||
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||
A: driver_override=(null)\n
|
||||
A: enable=1\n
|
||||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c
|
||||
A: index=3\n
|
||||
A: irq=125\n
|
||||
A: label=Onboard - Other\n
|
||||
A: local_cpulist=0-5\n
|
||||
A: local_cpus=3f\n
|
||||
A: modalias=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/125=msi\n
|
||||
A: numa_node=-1\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 15 20 2112 20\nxHCI ring segments 52 76 4096 76\nbuffer-2048 0 32 2048 16\nbuffer-512 0 32 512 4\nbuffer-128 3 32 128 1\nbuffer-32 0 128 32 1\n
|
||||
A: power/control=on\n
|
||||
A: power/runtime_active_time=767973582\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=enabled\n
|
||||
A: power/wakeup_abort_count=0\n
|
||||
A: power/wakeup_active=0\n
|
||||
A: power/wakeup_active_count=59\n
|
||||
A: power/wakeup_count=0\n
|
||||
A: power/wakeup_expire_count=59\n
|
||||
A: power/wakeup_last_time_ms=763021754\n
|
||||
A: power/wakeup_max_time_ms=108\n
|
||||
A: power/wakeup_total_time_ms=6149\n
|
||||
A: power_state=D0\n
|
||||
A: resource=0x00000000b1320000 0x00000000b132ffff 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: revision=0x10\n
|
||||
A: subsystem_device=0x312a\n
|
||||
A: subsystem_vendor=0x17aa\n
|
||||
A: vendor=0x8086\n
|
||||
|
Binary file not shown.
|
@ -1,14 +1,14 @@
|
|||
P: /devices/pci0000:00/0000:00:14.0/usb1/1-3
|
||||
N: bus/usb/001/017=1201000200000040F3047E0C06030102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
|
||||
E: DEVNAME=/dev/bus/usb/001/017
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb1/1-1
|
||||
N: bus/usb/001/010=1201000200000040F3047E0C05030102000109025300010103A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
|
||||
E: DEVNAME=/dev/bus/usb/001/010
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=4f3/c7e/306
|
||||
E: PRODUCT=4f3/c7e/305
|
||||
E: TYPE=0/0/0
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=017
|
||||
E: DEVNUM=010
|
||||
E: MAJOR=189
|
||||
E: MINOR=16
|
||||
E: MINOR=9
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=ELAN
|
||||
E: ID_VENDOR_ENC=ELAN
|
||||
|
@ -16,208 +16,210 @@ E: ID_VENDOR_ID=04f3
|
|||
E: ID_MODEL=ELAN:ARM-M4
|
||||
E: ID_MODEL_ENC=ELAN:ARM-M4
|
||||
E: ID_MODEL_ID=0c7e
|
||||
E: ID_REVISION=0306
|
||||
E: ID_REVISION=0305
|
||||
E: ID_SERIAL=ELAN_ELAN:ARM-M4
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:ff0000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp.
|
||||
E: ID_PATH=pci-0000:00:14.0-usb-0:3
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_3
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_3
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=00\n
|
||||
A: bDeviceProtocol=00\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=100mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0306\n
|
||||
A: bmAttributes=a0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=1201000200000040F3047E0C06030102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
|
||||
A: dev=189:16\n
|
||||
A: devnum=17\n
|
||||
A: devpath=3\n
|
||||
E: ID_PATH=pci-0000:00:14.0-usb-0:1
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_1
|
||||
A: authorized=1
|
||||
A: avoid_reset_quirk=0
|
||||
A: bConfigurationValue=1
|
||||
A: bDeviceClass=00
|
||||
A: bDeviceProtocol=00
|
||||
A: bDeviceSubClass=00
|
||||
A: bMaxPacketSize0=64
|
||||
A: bMaxPower=100mA
|
||||
A: bNumConfigurations=1
|
||||
A: bNumInterfaces= 1
|
||||
A: bcdDevice=0305
|
||||
A: bmAttributes=a0
|
||||
A: busnum=1
|
||||
A: configuration=add909c9-e67e-4126-a6f7-1e31179e27d9
|
||||
H: descriptors=1201000200000040F3047E0C05030102000109025300010103A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
|
||||
A: dev=189:9
|
||||
A: devnum=10
|
||||
A: devpath=1
|
||||
L: driver=../../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d/device:20
|
||||
A: idProduct=0c7e\n
|
||||
A: idVendor=04f3\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=ELAN\n
|
||||
A: maxchild=0\n
|
||||
L: port=../1-0:1.0/usb1-port3
|
||||
A: power/active_duration=2748\n
|
||||
A: power/autosuspend=2\n
|
||||
A: power/autosuspend_delay_ms=2000\n
|
||||
A: power/connected_duration=18266\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/persist=1\n
|
||||
A: power/runtime_active_time=2603\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=15422\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=ELAN:ARM-M4\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=removable\n
|
||||
A: rx_lanes=1\n
|
||||
A: speed=12\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=12\n
|
||||
A: version= 2.00\n
|
||||
A: idProduct=0c7e
|
||||
A: idVendor=04f3
|
||||
A: ltm_capable=no
|
||||
A: manufacturer=ELAN
|
||||
A: maxchild=0
|
||||
L: port=../1-0:1.0/usb1-port1
|
||||
A: power/active_duration=94712
|
||||
A: power/async=enabled
|
||||
A: power/autosuspend=2
|
||||
A: power/autosuspend_delay_ms=2000
|
||||
A: power/connected_duration=94712
|
||||
A: power/control=on
|
||||
A: power/level=on
|
||||
A: power/persist=1
|
||||
A: power/runtime_active_kids=0
|
||||
A: power/runtime_active_time=94436
|
||||
A: power/runtime_enabled=forbidden
|
||||
A: power/runtime_status=active
|
||||
A: power/runtime_suspended_time=0
|
||||
A: power/runtime_usage=1
|
||||
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=ELAN:ARM-M4
|
||||
A: quirks=0x0
|
||||
A: removable=removable
|
||||
A: rx_lanes=1
|
||||
A: speed=12
|
||||
A: tx_lanes=1
|
||||
A: urbnum=12
|
||||
A: version= 2.00
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||
N: bus/usb/001/001=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
|
||||
N: bus/usb/001/001=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C
|
||||
E: DEVNAME=/dev/bus/usb/001/001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=1d6b/2/512
|
||||
E: PRODUCT=1d6b/2/504
|
||||
E: TYPE=9/0/1
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=001
|
||||
E: MAJOR=189
|
||||
E: MINOR=0
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Linux_5.12.12-300.fc34.x86_64_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.12.12-300.fc34.x86_64\x20xhci-hcd
|
||||
E: ID_VENDOR=Linux_5.4.0-42-generic_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.4.0-42-generic\x20xhci-hcd
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_REVISION=0512
|
||||
E: ID_SERIAL=Linux_5.12.12-300.fc34.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_REVISION=0504
|
||||
E: ID_SERIAL=Linux_5.4.0-42-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: authorized_default=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=09\n
|
||||
A: bDeviceProtocol=01\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=0mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0512\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=1\n
|
||||
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=0504
|
||||
A: bmAttributes=e0
|
||||
A: busnum=1
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0\n
|
||||
A: devnum=1\n
|
||||
A: devpath=0\n
|
||||
H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0
|
||||
A: devnum=1
|
||||
A: devpath=0
|
||||
L: driver=../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 5.12.12-300.fc34.x86_64 xhci-hcd\n
|
||||
A: maxchild=12\n
|
||||
A: power/active_duration=187216979\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=187239996\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=187220224\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=xHCI Host Controller\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=unknown\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial=0000:00:14.0\n
|
||||
A: speed=480\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=3372\n
|
||||
A: version= 2.00\n
|
||||
A: idProduct=0002
|
||||
A: idVendor=1d6b
|
||||
A: interface_authorized_default=1
|
||||
A: ltm_capable=no
|
||||
A: manufacturer=Linux 5.4.0-42-generic xhci-hcd
|
||||
A: maxchild=12
|
||||
A: power/active_duration=74604360
|
||||
A: power/async=enabled
|
||||
A: power/autosuspend=0
|
||||
A: power/autosuspend_delay_ms=0
|
||||
A: power/connected_duration=74606456
|
||||
A: power/control=auto
|
||||
A: power/level=auto
|
||||
A: power/runtime_active_kids=4
|
||||
A: power/runtime_active_time=74605838
|
||||
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: rx_lanes=1
|
||||
A: serial=0000:00:14.0
|
||||
A: speed=480
|
||||
A: tx_lanes=1
|
||||
A: urbnum=490
|
||||
A: version= 2.00
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:9DED
|
||||
E: PCI_SUBSYS_ID=17AA:2292
|
||||
E: PCI_SUBSYS_ID=103C:85EF
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: MODALIAS=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30
|
||||
E: MODALIAS=pci:v00008086d00009DEDsv0000103Csd000085EFbc0Csc03i30
|
||||
E: SUBSYSTEM=pci
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=8680ED9D060490021130030C00008000040022EA000000000000000000000000000000000000000000000000AA179222000000007000000000000000FF010000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: dbc=disabled\n
|
||||
A: device=0x9ded\n
|
||||
A: dma_mask_bits=64\n
|
||||
A: ari_enabled=0
|
||||
A: broken_parity_status=0
|
||||
A: class=0x0c0330
|
||||
H: config=8680ED9D060490023030030C00008000040030A10000000000000000000000000000000000000000000000003C10EF85000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F00000000181C030400000000316000000000000000000000000000000180C2C1080000000000000000000000059087007802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F40020000010000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000B50F300112000000
|
||||
A: consistent_dma_mask_bits=64
|
||||
A: d3cold_allowed=1
|
||||
A: dbc=disabled
|
||||
A: device=0x9ded
|
||||
A: dma_mask_bits=64
|
||||
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||
A: driver_override=(null)\n
|
||||
A: enable=1\n
|
||||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c
|
||||
A: irq=128\n
|
||||
A: local_cpulist=0-7\n
|
||||
A: local_cpus=ff\n
|
||||
A: modalias=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/128=msi\n
|
||||
A: numa_node=-1\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 11 12 2112 12\nxHCI ring segments 58 62 4096 62\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: power/control=on\n
|
||||
A: power/runtime_active_time=187221117\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=enabled\n
|
||||
A: power/wakeup_abort_count=0\n
|
||||
A: power/wakeup_active=0\n
|
||||
A: power/wakeup_active_count=0\n
|
||||
A: power/wakeup_count=0\n
|
||||
A: power/wakeup_expire_count=0\n
|
||||
A: power/wakeup_last_time_ms=0\n
|
||||
A: power/wakeup_max_time_ms=0\n
|
||||
A: power/wakeup_total_time_ms=0\n
|
||||
A: power_state=D0\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\n
|
||||
A: revision=0x11\n
|
||||
A: subsystem_device=0x2292\n
|
||||
A: subsystem_vendor=0x17aa\n
|
||||
A: vendor=0x8086\n
|
||||
A: driver_override=(null)
|
||||
A: enable=1
|
||||
A: irq=124
|
||||
A: local_cpulist=0-3
|
||||
A: local_cpus=f
|
||||
A: modalias=pci:v00008086d00009DEDsv0000103Csd000085EFbc0Csc03i30
|
||||
A: msi_bus=1
|
||||
A: msi_irqs/124=msi
|
||||
A: numa_node=-1
|
||||
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 32 128 1\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 11 12 2112 12\nxHCI ring segments 54 54 4096 54\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 9 32 128 1\nbuffer-32 0 0 32 0
|
||||
A: power/async=enabled
|
||||
A: power/control=auto
|
||||
A: power/runtime_active_kids=1
|
||||
A: power/runtime_active_time=74606194
|
||||
A: power/runtime_enabled=enabled
|
||||
A: power/runtime_status=active
|
||||
A: power/runtime_suspended_time=0
|
||||
A: power/runtime_usage=0
|
||||
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=0
|
||||
A: power/wakeup_max_time_ms=0
|
||||
A: power/wakeup_total_time_ms=0
|
||||
A: resource=0x00000000a1300000 0x00000000a130ffff 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=0x30
|
||||
A: subsystem_device=0x85ef
|
||||
A: subsystem_vendor=0x103c
|
||||
A: vendor=0x8086
|
||||
|
||||
|
|
|
@ -22,12 +22,16 @@ envs.set('FP_DRIVERS_WHITELIST', ':'.join([
|
|||
envs.set('NO_AT_BRIDGE', '1')
|
||||
|
||||
drivers_tests = [
|
||||
'aes2501',
|
||||
'aes3500',
|
||||
'elan',
|
||||
'elan-cobo',
|
||||
'elanmoc',
|
||||
'elanspi',
|
||||
'synaptics',
|
||||
'upektc_img',
|
||||
'uru4000-msv2',
|
||||
'uru4000-4500',
|
||||
'vfs0050',
|
||||
'vfs301',
|
||||
'vfs5011',
|
||||
|
@ -37,6 +41,15 @@ drivers_tests = [
|
|||
'egis0570',
|
||||
]
|
||||
|
||||
if get_option('introspection')
|
||||
conf = configuration_data()
|
||||
conf.set('SRCDIR', meson.source_root())
|
||||
conf.set('BUILDDIR', meson.build_root())
|
||||
configure_file(configuration: conf,
|
||||
input: 'create-driver-test.py.in',
|
||||
output: 'create-driver-test.py')
|
||||
endif
|
||||
|
||||
if get_option('introspection')
|
||||
envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint'))
|
||||
virtual_devices_tests = [
|
||||
|
@ -86,11 +99,7 @@ if get_option('introspection')
|
|||
endforeach
|
||||
|
||||
foreach driver_test: drivers_tests
|
||||
if driver_test.contains('-')
|
||||
driver_name = driver_test.split('-')[0]
|
||||
else
|
||||
driver_name = driver_test
|
||||
endif
|
||||
driver_name = driver_test.split('-')[0]
|
||||
driver_envs = envs
|
||||
driver_envs.set('FP_DRIVERS_WHITELIST', driver_name)
|
||||
|
||||
|
|
|
@ -271,6 +271,26 @@ fpi_device_fake_cancel (FpDevice *device)
|
|||
g_assert_cmpuint (fpi_device_get_current_action (device), !=, FPI_DEVICE_ACTION_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_device_fake_suspend (FpDevice *device)
|
||||
{
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
fake_dev->last_called_function = fpi_device_fake_suspend;
|
||||
|
||||
fpi_device_suspend_complete (device, g_steal_pointer (&fake_dev->ret_suspend));
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_device_fake_resume (FpDevice *device)
|
||||
{
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
fake_dev->last_called_function = fpi_device_fake_resume;
|
||||
|
||||
fpi_device_resume_complete (device, g_steal_pointer (&fake_dev->ret_resume));
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_device_fake_init (FpiDeviceFake *self)
|
||||
{
|
||||
|
@ -299,6 +319,8 @@ fpi_device_fake_class_init (FpiDeviceFakeClass *klass)
|
|||
dev_class->delete = fpi_device_fake_delete;
|
||||
dev_class->cancel = fpi_device_fake_cancel;
|
||||
dev_class->clear_storage = fpi_device_fake_clear_storage;
|
||||
dev_class->suspend = fpi_device_fake_suspend;
|
||||
dev_class->resume = fpi_device_fake_resume;
|
||||
|
||||
fpi_device_class_auto_initialize_features (dev_class);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ struct _FpiDeviceFake
|
|||
gpointer last_called_function;
|
||||
gboolean return_action_error;
|
||||
|
||||
GCancellable *ext_cancellable;
|
||||
|
||||
GError *ret_error;
|
||||
FpPrint *ret_print;
|
||||
FpPrint *ret_match;
|
||||
|
@ -39,6 +41,9 @@ struct _FpiDeviceFake
|
|||
FpImage *ret_image;
|
||||
GPtrArray *ret_list;
|
||||
|
||||
GError *ret_suspend;
|
||||
GError *ret_resume;
|
||||
|
||||
gpointer action_data;
|
||||
gpointer user_data;
|
||||
|
||||
|
|
|
@ -35,9 +35,11 @@ typedef FpDevice FpAutoCloseDevice;
|
|||
static FpAutoCloseDevice *
|
||||
auto_close_fake_device_new (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpAutoCloseDevice *device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
if (!fp_device_open_sync (device, NULL, &error))
|
||||
g_error ("Could not open device: %s", error->message);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
@ -45,6 +47,7 @@ auto_close_fake_device_new (void)
|
|||
static void
|
||||
auto_close_fake_device_free (FpAutoCloseDevice *device)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
if (fake_dev->return_action_error)
|
||||
|
@ -54,7 +57,8 @@ auto_close_fake_device_free (FpAutoCloseDevice *device)
|
|||
}
|
||||
|
||||
if (fp_device_is_open (device))
|
||||
g_assert_true (fp_device_close_sync (device, NULL, NULL));
|
||||
if (!fp_device_close_sync (device, NULL, &error))
|
||||
g_error ("Could not close device: %s", error->message);
|
||||
|
||||
g_object_unref (device);
|
||||
}
|
||||
|
@ -1224,6 +1228,11 @@ test_driver_match_cb (FpDevice *device,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fake_device_stub_verify (FpDevice *device)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify (void)
|
||||
{
|
||||
|
@ -1588,6 +1597,28 @@ fake_device_stub_identify (FpDevice *device)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_cb (FpDevice *device,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
MatchCbData *data = user_data;
|
||||
gboolean r;
|
||||
|
||||
g_assert (data->called == FALSE);
|
||||
data->called = TRUE;
|
||||
|
||||
r = fp_device_identify_finish (device, res, &data->match, &data->print, &data->error);
|
||||
|
||||
if (r)
|
||||
g_assert_no_error (data->error);
|
||||
else
|
||||
g_assert_nonnull (data->error);
|
||||
|
||||
if (data->match)
|
||||
g_assert_no_error (data->error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_supports_identify (void)
|
||||
{
|
||||
|
@ -1941,6 +1972,314 @@ test_driver_identify_report_no_callback (void)
|
|||
g_assert_false (match);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_suspend_continues (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(MatchCbData) identify_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(GPtrArray) prints = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
void (*orig_identify) (FpDevice *device);
|
||||
FpiDeviceFake *fake_dev;
|
||||
FpPrint *expected_matched;
|
||||
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
orig_identify = dev_class->identify;
|
||||
dev_class->identify = fake_device_stub_identify;
|
||||
|
||||
prints = make_fake_prints_gallery (device, 500);
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
fp_device_identify (device, prints, NULL,
|
||||
test_driver_match_cb, match_data, NULL,
|
||||
(GAsyncReadyCallback) test_driver_identify_cb, identify_data);
|
||||
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
|
||||
fake_dev->ret_suspend = NULL;
|
||||
fp_device_suspend_sync (device, NULL, &error);
|
||||
g_assert (fake_dev->last_called_function == dev_class->suspend);
|
||||
g_assert_no_error (error);
|
||||
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
|
||||
g_assert_false (match_data->called);
|
||||
g_assert_false (identify_data->called);
|
||||
|
||||
fake_dev->ret_resume = NULL;
|
||||
fp_device_resume_sync (device, NULL, &error);
|
||||
g_assert (fake_dev->last_called_function == dev_class->resume);
|
||||
g_assert_no_error (error);
|
||||
|
||||
orig_identify (device);
|
||||
|
||||
/* This currently happens immediately (not ABI though) */
|
||||
g_assert_true (match_data->called);
|
||||
g_assert (match_data->match == expected_matched);
|
||||
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
|
||||
g_assert_true (identify_data->called);
|
||||
g_assert (identify_data->match == expected_matched);
|
||||
|
||||
g_assert (fake_dev->last_called_function == orig_identify);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_suspend_succeeds (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(MatchCbData) identify_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(GPtrArray) prints = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
void (*orig_identify) (FpDevice *device);
|
||||
FpiDeviceFake *fake_dev;
|
||||
FpPrint *expected_matched;
|
||||
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
orig_identify = dev_class->identify;
|
||||
dev_class->identify = fake_device_stub_identify;
|
||||
|
||||
prints = make_fake_prints_gallery (device, 500);
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
fp_device_identify (device, prints, NULL,
|
||||
test_driver_match_cb, match_data, NULL,
|
||||
(GAsyncReadyCallback) test_driver_identify_cb, identify_data);
|
||||
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
|
||||
/* suspend_sync hangs until cancellation, so we need to trigger orig_identify
|
||||
* from the mainloop after calling suspend_sync.
|
||||
*/
|
||||
fpi_device_add_timeout (device, 0, (FpTimeoutFunc) orig_identify, NULL, NULL);
|
||||
|
||||
fake_dev->ret_suspend = fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED);
|
||||
fp_device_suspend_sync (device, NULL, &error);
|
||||
|
||||
/* At this point we are done with everything */
|
||||
g_assert (fake_dev->last_called_function == orig_identify);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED);
|
||||
g_clear_error (&error);
|
||||
|
||||
/* We suspended, but device reported success and that will be reported. */
|
||||
g_assert_true (match_data->called);
|
||||
g_assert (match_data->match == expected_matched);
|
||||
g_assert_true (identify_data->called);
|
||||
g_assert (identify_data->match == expected_matched);
|
||||
|
||||
/* Resuming the device does not call resume handler, as the action was
|
||||
* cancelled already.
|
||||
*/
|
||||
fake_dev->last_called_function = NULL;
|
||||
fp_device_resume_sync (device, NULL, &error);
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_suspend_busy_error (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(MatchCbData) identify_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(GPtrArray) prints = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
void (*orig_identify) (FpDevice *device);
|
||||
FpiDeviceFake *fake_dev;
|
||||
FpPrint *expected_matched;
|
||||
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
orig_identify = dev_class->identify;
|
||||
dev_class->identify = fake_device_stub_identify;
|
||||
|
||||
prints = make_fake_prints_gallery (device, 500);
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
fp_device_identify (device, prints, NULL,
|
||||
test_driver_match_cb, match_data, NULL,
|
||||
(GAsyncReadyCallback) test_driver_identify_cb, identify_data);
|
||||
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
|
||||
/* suspend_sync hangs until cancellation, so we need to trigger orig_identify
|
||||
* from the mainloop after calling suspend_sync.
|
||||
*/
|
||||
fpi_device_add_timeout (device, 0, (FpTimeoutFunc) orig_identify, NULL, NULL);
|
||||
|
||||
fake_dev->ret_suspend = fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED);
|
||||
fp_device_suspend_sync (device, NULL, &error);
|
||||
fake_dev->ret_error = NULL;
|
||||
|
||||
/* At this point we are done with everything */
|
||||
g_assert (fake_dev->last_called_function == orig_identify);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED);
|
||||
g_clear_error (&error);
|
||||
|
||||
/* The device reported an error, an this error will be overwritten.
|
||||
*/
|
||||
g_assert_false (match_data->called);
|
||||
g_assert_true (identify_data->called);
|
||||
g_assert_null (identify_data->match);
|
||||
g_assert_error (identify_data->error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_BUSY);
|
||||
|
||||
fake_dev->last_called_function = NULL;
|
||||
fp_device_resume_sync (device, NULL, &error);
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_suspend_while_idle (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpiDeviceFake *fake_dev;
|
||||
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
/* Suspending and resuming a closed device works */
|
||||
fp_device_suspend (device, NULL, (GAsyncReadyCallback) fp_device_suspend_finish, &error);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
fp_device_resume (device, NULL, (GAsyncReadyCallback) fp_device_resume_finish, NULL);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
fake_dev->last_called_function = NULL;
|
||||
fp_device_suspend (device, NULL, (GAsyncReadyCallback) fp_device_suspend_finish, &error);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
g_assert_no_error (error);
|
||||
|
||||
fp_device_resume (device, NULL, (GAsyncReadyCallback) fp_device_resume_finish, NULL);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_warmup_cooldown (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(MatchCbData) identify_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(GPtrArray) prints = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
void (*orig_identify) (FpDevice *device);
|
||||
FpiDeviceFake *fake_dev;
|
||||
gint64 start_time;
|
||||
|
||||
dev_class->temp_hot_seconds = 2;
|
||||
dev_class->temp_cold_seconds = 5;
|
||||
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
orig_identify = dev_class->identify;
|
||||
dev_class->identify = fake_device_stub_identify;
|
||||
|
||||
prints = make_fake_prints_gallery (device, 500);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
fake_dev->last_called_function = NULL;
|
||||
|
||||
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
|
||||
|
||||
/* Undefined: Whether match_cb is called. */
|
||||
fp_device_identify (device, prints, NULL,
|
||||
NULL, NULL, NULL,
|
||||
(GAsyncReadyCallback) test_driver_identify_cb, identify_data);
|
||||
|
||||
/* Identify is running, the temperature will change after only a short time.
|
||||
* Changes are delayed by 100ms and we give 150ms of slack for the test.
|
||||
*/
|
||||
start_time = g_get_monotonic_time ();
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_COLD);
|
||||
while (fp_device_get_temperature (device) == FP_TEMPERATURE_COLD)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_WARM);
|
||||
g_assert_false (g_cancellable_is_cancelled (fpi_device_get_cancellable (device)));
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 0 + 250000);
|
||||
|
||||
/* we reach hot 2 seconds later */
|
||||
while (fp_device_get_temperature (device) == FP_TEMPERATURE_WARM)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_HOT);
|
||||
g_assert_true (g_cancellable_is_cancelled (fpi_device_get_cancellable (device)));
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 2000000 + 250000);
|
||||
|
||||
/* cancel vfunc will be called now */
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == dev_class->cancel);
|
||||
|
||||
orig_identify (device);
|
||||
fake_dev->ret_error = NULL;
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert_true (identify_data->called);
|
||||
g_assert_error (identify_data->error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_TOO_HOT);
|
||||
|
||||
/* Now, wait for it to cool down again;
|
||||
* WARM should be reached after about 2s
|
||||
* COLD after 5s but give it some more slack. */
|
||||
start_time = g_get_monotonic_time ();
|
||||
while (fp_device_get_temperature (device) == FP_TEMPERATURE_HOT)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_WARM);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 2000000 + 250000);
|
||||
|
||||
while (fp_device_get_temperature (device) == FP_TEMPERATURE_WARM)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_COLD);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 5000000 + 500000);
|
||||
}
|
||||
|
||||
static void
|
||||
fake_device_stub_capture (FpDevice *device)
|
||||
{
|
||||
|
@ -2284,6 +2623,89 @@ test_driver_cancel_fail (void)
|
|||
g_assert_no_error (error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_critical (void)
|
||||
{
|
||||
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
|
||||
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
|
||||
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
void (*orig_verify) (FpDevice *device) = dev_class->verify;
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
fake_dev->last_called_function = NULL;
|
||||
|
||||
dev_class->verify = fake_device_stub_verify;
|
||||
fp_device_verify (device, enrolled_print, cancellable,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
/* We started a verify operation, now emulate a "critical" section */
|
||||
fpi_device_critical_enter (device);
|
||||
|
||||
/* Throw a suspend and external cancellation against it. */
|
||||
fp_device_suspend (device, NULL, NULL, NULL);
|
||||
g_cancellable_cancel (cancellable);
|
||||
|
||||
/* The only thing that happens is that the cancellable is cancelled */
|
||||
g_assert_true (fpi_device_action_is_cancelled (device));
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
|
||||
/* Leaving and entering the critical section in the same mainloop iteration
|
||||
* does not do anything. */
|
||||
fpi_device_critical_leave (device);
|
||||
fpi_device_critical_enter (device);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
|
||||
/* Leaving it and running the mainloop will first run the cancel handler */
|
||||
fpi_device_critical_leave (device);
|
||||
while (g_main_context_iteration (NULL, FALSE) && !fake_dev->last_called_function)
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == dev_class->cancel);
|
||||
g_assert_true (fpi_device_action_is_cancelled (device));
|
||||
fake_dev->last_called_function = NULL;
|
||||
|
||||
/* Then the suspend handler */
|
||||
while (g_main_context_iteration (NULL, FALSE) && !fake_dev->last_called_function)
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == dev_class->suspend);
|
||||
fake_dev->last_called_function = NULL;
|
||||
|
||||
/* Nothing happens afterwards */
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
|
||||
|
||||
/* Throw a resume at the system */
|
||||
fpi_device_critical_enter (device);
|
||||
fp_device_resume (device, NULL, NULL, NULL);
|
||||
|
||||
/* Nothing will happen, as the resume is delayed */
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
|
||||
/* Finally the resume is called from the mainloop after leaving the critical section */
|
||||
fpi_device_critical_leave (device);
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
while (g_main_context_iteration (NULL, FALSE) && !fake_dev->last_called_function)
|
||||
continue;
|
||||
g_assert (fake_dev->last_called_function == dev_class->resume);
|
||||
fake_dev->last_called_function = NULL;
|
||||
|
||||
|
||||
/* The "verify" operation is still ongoing, finish it. */
|
||||
orig_verify (device);
|
||||
while (g_main_context_iteration (NULL, FALSE))
|
||||
continue;
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_current_action (void)
|
||||
{
|
||||
|
@ -2350,32 +2772,32 @@ test_driver_action_get_cancellable_open (void)
|
|||
}
|
||||
|
||||
static void
|
||||
test_driver_action_get_cancellable_open_fail_vfunc (FpDevice *device)
|
||||
test_driver_action_get_cancellable_open_internal_vfunc (FpDevice *device)
|
||||
{
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FPI_DEVICE_ACTION_OPEN);
|
||||
fake_dev->last_called_function = test_driver_action_get_cancellable_open_fail_vfunc;
|
||||
fake_dev->last_called_function = test_driver_action_get_cancellable_open_internal_vfunc;
|
||||
|
||||
g_assert_false (G_IS_CANCELLABLE (fpi_device_get_cancellable (device)));
|
||||
g_assert_true (G_IS_CANCELLABLE (fpi_device_get_cancellable (device)));
|
||||
|
||||
fpi_device_open_complete (device, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_action_get_cancellable_open_fail (void)
|
||||
test_driver_action_get_cancellable_open_internal (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
FpiDeviceFake *fake_dev;
|
||||
|
||||
dev_class->open = test_driver_action_get_cancellable_open_fail_vfunc;
|
||||
dev_class->open = test_driver_action_get_cancellable_open_internal_vfunc;
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
g_assert (fake_dev->last_called_function == test_driver_action_get_cancellable_open_fail_vfunc);
|
||||
g_assert (fake_dev->last_called_function == test_driver_action_get_cancellable_open_internal_vfunc);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2400,7 +2822,11 @@ test_driver_action_is_cancelled_open_vfunc (FpDevice *device)
|
|||
g_assert_true (G_IS_CANCELLABLE (fpi_device_get_cancellable (device)));
|
||||
g_assert_false (fpi_device_action_is_cancelled (device));
|
||||
|
||||
g_cancellable_cancel (fpi_device_get_cancellable (device));
|
||||
if (fake_dev->ext_cancellable)
|
||||
g_cancellable_cancel (fake_dev->ext_cancellable);
|
||||
else
|
||||
g_cancellable_cancel (fpi_device_get_cancellable (device));
|
||||
|
||||
g_assert_true (fpi_device_action_is_cancelled (device));
|
||||
|
||||
fpi_device_open_complete (device, NULL);
|
||||
|
@ -2419,13 +2845,34 @@ test_driver_action_is_cancelled_open (void)
|
|||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
cancellable = fake_dev->ext_cancellable = g_cancellable_new ();
|
||||
g_assert_false (fp_device_open_sync (device, cancellable, &error));
|
||||
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
|
||||
|
||||
g_assert (fake_dev->last_called_function == test_driver_action_is_cancelled_open_vfunc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_action_internally_cancelled_open (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(GCancellable) cancellable = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpiDeviceFake *fake_dev;
|
||||
|
||||
dev_class->open = test_driver_action_is_cancelled_open_vfunc;
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
/* No error, just some internal cancellation but we let nothing happen externally. */
|
||||
cancellable = g_cancellable_new ();
|
||||
g_assert_true (fp_device_open_sync (device, cancellable, &error));
|
||||
g_assert_null (error);
|
||||
|
||||
g_assert (fake_dev->last_called_function == test_driver_action_is_cancelled_open_vfunc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_action_is_cancelled_error (void)
|
||||
{
|
||||
|
@ -2874,6 +3321,14 @@ main (int argc, char *argv[])
|
|||
g_test_add_func ("/driver/identify/not_reported", test_driver_identify_not_reported);
|
||||
g_test_add_func ("/driver/identify/complete_retry", test_driver_identify_complete_retry);
|
||||
g_test_add_func ("/driver/identify/report_no_cb", test_driver_identify_report_no_callback);
|
||||
|
||||
g_test_add_func ("/driver/identify/suspend_continues", test_driver_identify_suspend_continues);
|
||||
g_test_add_func ("/driver/identify/suspend_succeeds", test_driver_identify_suspend_succeeds);
|
||||
g_test_add_func ("/driver/identify/suspend_busy_error", test_driver_identify_suspend_busy_error);
|
||||
g_test_add_func ("/driver/identify/suspend_while_idle", test_driver_identify_suspend_while_idle);
|
||||
|
||||
g_test_add_func ("/driver/identify/warmup_cooldown", test_driver_identify_warmup_cooldown);
|
||||
|
||||
g_test_add_func ("/driver/capture", test_driver_capture);
|
||||
g_test_add_func ("/driver/capture/not_supported", test_driver_capture_not_supported);
|
||||
g_test_add_func ("/driver/capture/error", test_driver_capture_error);
|
||||
|
@ -2887,12 +3342,15 @@ main (int argc, char *argv[])
|
|||
g_test_add_func ("/driver/cancel", test_driver_cancel);
|
||||
g_test_add_func ("/driver/cancel/fail", test_driver_cancel_fail);
|
||||
|
||||
g_test_add_func ("/driver/critical", test_driver_critical);
|
||||
|
||||
g_test_add_func ("/driver/get_current_action", test_driver_current_action);
|
||||
g_test_add_func ("/driver/get_current_action/open", test_driver_current_action_open);
|
||||
g_test_add_func ("/driver/get_cancellable/error", test_driver_action_get_cancellable_error);
|
||||
g_test_add_func ("/driver/get_cancellable/open", test_driver_action_get_cancellable_open);
|
||||
g_test_add_func ("/driver/get_cancellable/open/fail", test_driver_action_get_cancellable_open_fail);
|
||||
g_test_add_func ("/driver/get_cancellable/open/internal", test_driver_action_get_cancellable_open_internal);
|
||||
g_test_add_func ("/driver/action_is_cancelled/open", test_driver_action_is_cancelled_open);
|
||||
g_test_add_func ("/driver/action_is_cancelled/open/internal", test_driver_action_internally_cancelled_open);
|
||||
g_test_add_func ("/driver/action_is_cancelled/error", test_driver_action_is_cancelled_error);
|
||||
g_test_add_func ("/driver/complete_action/all/error", test_driver_complete_actions_errors);
|
||||
g_test_add_func ("/driver/action_error/error", test_driver_action_error_error);
|
||||
|
|
|
@ -18,7 +18,7 @@ try:
|
|||
if version < (0, 13, 2):
|
||||
print('umockdev is too old for test to be reliable, expect random failures!')
|
||||
print('Please update umockdev to at least 0.13.2.')
|
||||
pcap_supported = version >= (0, 16, 2) or os.getenv('CI_PROJECT_NAME') == "libfprint"
|
||||
pcap_supported = version >= (0, 16, 3) or os.getenv('CI_PROJECT_NAME') == "libfprint"
|
||||
spi_supported = version >= (0, 16) or os.getenv('CI_PROJECT_NAME') == "libfprint"
|
||||
|
||||
except FileNotFoundError:
|
||||
|
|
BIN
tests/uru4000-4500/capture.pcapng
Normal file
BIN
tests/uru4000-4500/capture.pcapng
Normal file
Binary file not shown.
BIN
tests/uru4000-4500/capture.png
Normal file
BIN
tests/uru4000-4500/capture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
220
tests/uru4000-4500/device
Normal file
220
tests/uru4000-4500/device
Normal file
|
@ -0,0 +1,220 @@
|
|||
P: /devices/pci0000:00/0000:00:14.0/usb1/1-10
|
||||
N: bus/usb/001/050=1201000200000040BA050A000301010203010902200001010080640904000002FFFFFF000705810340000807058202400000
|
||||
E: DEVNAME=/dev/bus/usb/001/050
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=5ba/a/103
|
||||
E: TYPE=0/0/0
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=050
|
||||
E: MAJOR=189
|
||||
E: MINOR=49
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=DigitalPersona__Inc.
|
||||
E: ID_VENDOR_ENC=DigitalPersona\x2c\x20Inc.
|
||||
E: ID_VENDOR_ID=05ba
|
||||
E: ID_MODEL=U.are.U®_4500_Fingerprint_Reader
|
||||
E: ID_MODEL_ENC=U.are.U®\x204500\x20Fingerprint\x20Reader
|
||||
E: ID_MODEL_ID=000a
|
||||
E: ID_REVISION=0103
|
||||
E: ID_SERIAL=DigitalPersona__Inc._U.are.U®_4500_Fingerprint_Reader__FB0B9071-2E08-7742-BC16-2FAA247CEF66_
|
||||
E: ID_SERIAL_SHORT=_FB0B9071-2E08-7742-BC16-2FAA247CEF66_
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:ffffff:
|
||||
E: ID_VENDOR_FROM_DATABASE=DigitalPersona, Inc.
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=Fingerprint Reader
|
||||
E: ID_PATH=pci-0000:00:14.0-usb-0:10
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_10
|
||||
E: LIBFPRINT_DRIVER=Digital Persona U.are.U 4000/4000B/4500
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_10
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=00\n
|
||||
A: bDeviceProtocol=00\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=200mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0103\n
|
||||
A: bmAttributes=80\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=1201000200000040BA050A000301010203010902200001010080640904000002FFFFFF000705810340000807058202400000
|
||||
A: dev=189:49\n
|
||||
A: devnum=50\n
|
||||
A: devpath=10\n
|
||||
L: driver=../../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d/device:57
|
||||
A: idProduct=000a\n
|
||||
A: idVendor=05ba\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=DigitalPersona, Inc.\n
|
||||
A: maxchild=0\n
|
||||
L: port=../1-0:1.0/usb1-port10
|
||||
A: power/active_duration=2761\n
|
||||
A: power/autosuspend=2\n
|
||||
A: power/autosuspend_delay_ms=2000\n
|
||||
A: power/connected_duration=118841\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/persist=0\n
|
||||
A: power/runtime_active_time=2616\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=115982\n
|
||||
A: product=U.are.U\302\256 4500 Fingerprint Reader\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=removable\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial={FB0B9071-2E08-7742-BC16-2FAA247CEF66}\n
|
||||
A: speed=12\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=13\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||
N: bus/usb/001/001=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
E: DEVNAME=/dev/bus/usb/001/001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=1d6b/2/513
|
||||
E: TYPE=9/0/1
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=001
|
||||
E: MAJOR=189
|
||||
E: MINOR=0
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Linux_5.13.12-200.fc34.x86_64_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.13.12-200.fc34.x86_64\x20xhci-hcd
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_REVISION=0513
|
||||
E: ID_SERIAL=Linux_5.13.12-200.fc34.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: authorized_default=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=09\n
|
||||
A: bDeviceProtocol=01\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=0mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0513\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0\n
|
||||
A: devnum=1\n
|
||||
A: devpath=0\n
|
||||
L: driver=../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 5.13.12-200.fc34.x86_64 xhci-hcd\n
|
||||
A: maxchild=16\n
|
||||
A: power/active_duration=837797629\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=837797629\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=837797626\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=xHCI Host Controller\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=unknown\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial=0000:00:14.0\n
|
||||
A: speed=480\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=1498\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:A36D
|
||||
E: PCI_SUBSYS_ID=17AA:312A
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: MODALIAS=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30
|
||||
E: SUBSYSTEM=pci
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=86806DA3060490021030030C00008000040032B1000000000000000000000000000000000000000000000000AA172A31000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F000000009A1CF40100000000316000000000000000000000000000000180C2C1080000000000000000000000059087009802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F400200000100006000000008020000010000000400000090000000001800000005000000000000000300000C0000004000000080000000030000000000000000000000000000000000000000000000B50F110112000000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: dbc=disabled\n
|
||||
A: device=0xa36d\n
|
||||
A: dma_mask_bits=64\n
|
||||
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||
A: driver_override=(null)\n
|
||||
A: enable=1\n
|
||||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c
|
||||
A: index=3\n
|
||||
A: irq=125\n
|
||||
A: label=Onboard - Other\n
|
||||
A: local_cpulist=0-5\n
|
||||
A: local_cpus=3f\n
|
||||
A: modalias=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/125=msi\n
|
||||
A: numa_node=-1\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 15 20 2112 20\nxHCI ring segments 46 76 4096 76\nbuffer-2048 0 32 2048 16\nbuffer-512 0 32 512 4\nbuffer-128 3 32 128 1\nbuffer-32 0 128 32 1\n
|
||||
A: power/control=on\n
|
||||
A: power/runtime_active_time=837797789\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=enabled\n
|
||||
A: power/wakeup_abort_count=0\n
|
||||
A: power/wakeup_active=0\n
|
||||
A: power/wakeup_active_count=67\n
|
||||
A: power/wakeup_count=0\n
|
||||
A: power/wakeup_expire_count=67\n
|
||||
A: power/wakeup_last_time_ms=835747082\n
|
||||
A: power/wakeup_max_time_ms=108\n
|
||||
A: power/wakeup_total_time_ms=6974\n
|
||||
A: power_state=D0\n
|
||||
A: resource=0x00000000b1320000 0x00000000b132ffff 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: revision=0x10\n
|
||||
A: subsystem_device=0x312a\n
|
||||
A: subsystem_vendor=0x17aa\n
|
||||
A: vendor=0x8086\n
|
||||
|
BIN
tests/uru4000-msv2/capture.pcapng
Normal file
BIN
tests/uru4000-msv2/capture.pcapng
Normal file
Binary file not shown.
BIN
tests/uru4000-msv2/capture.png
Normal file
BIN
tests/uru4000-msv2/capture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
220
tests/uru4000-msv2/device
Normal file
220
tests/uru4000-msv2/device
Normal file
|
@ -0,0 +1,220 @@
|
|||
P: /devices/pci0000:00/0000:00:14.0/usb1/1-10
|
||||
N: bus/usb/001/047=12010002000000405E04CA000001010203010902200001010080820904000002FFFFFF000705810340000807058202400000
|
||||
E: DEVNAME=/dev/bus/usb/001/047
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=45e/ca/100
|
||||
E: TYPE=0/0/0
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=047
|
||||
E: MAJOR=189
|
||||
E: MINOR=46
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Microsoft
|
||||
E: ID_VENDOR_ENC=Microsoft
|
||||
E: ID_VENDOR_ID=045e
|
||||
E: ID_MODEL=Microsoft®_Fingerprint_Reader
|
||||
E: ID_MODEL_ENC=Microsoft®\x20Fingerprint\x20Reader
|
||||
E: ID_MODEL_ID=00ca
|
||||
E: ID_REVISION=0100
|
||||
E: ID_SERIAL=Microsoft_Microsoft®_Fingerprint_Reader__BE815DAD-15E4-0745-AA30-41DEBCAC5913_
|
||||
E: ID_SERIAL_SHORT=_BE815DAD-15E4-0745-AA30-41DEBCAC5913_
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:ffffff:
|
||||
E: ID_VENDOR_FROM_DATABASE=Microsoft Corp.
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=Fingerprint Reader
|
||||
E: ID_PATH=pci-0000:00:14.0-usb-0:10
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_10
|
||||
E: LIBFPRINT_DRIVER=Digital Persona U.are.U 4000/4000B/4500
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_10
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=00\n
|
||||
A: bDeviceProtocol=00\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=260mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0100\n
|
||||
A: bmAttributes=80\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002000000405E04CA000001010203010902200001010080820904000002FFFFFF000705810340000807058202400000
|
||||
A: dev=189:46\n
|
||||
A: devnum=47\n
|
||||
A: devpath=10\n
|
||||
L: driver=../../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d/device:57
|
||||
A: idProduct=00ca\n
|
||||
A: idVendor=045e\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Microsoft\n
|
||||
A: maxchild=0\n
|
||||
L: port=../1-0:1.0/usb1-port10
|
||||
A: power/active_duration=31642\n
|
||||
A: power/autosuspend=2\n
|
||||
A: power/autosuspend_delay_ms=2000\n
|
||||
A: power/connected_duration=1177852\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/persist=0\n
|
||||
A: power/runtime_active_time=31877\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=1145731\n
|
||||
A: product=Microsoft\302\256 Fingerprint Reader\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=removable\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial={BE815DAD-15E4-0745-AA30-41DEBCAC5913}\n
|
||||
A: speed=12\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=183\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||
N: bus/usb/001/001=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
E: DEVNAME=/dev/bus/usb/001/001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=1d6b/2/513
|
||||
E: TYPE=9/0/1
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=001
|
||||
E: MAJOR=189
|
||||
E: MINOR=0
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Linux_5.13.12-200.fc34.x86_64_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.13.12-200.fc34.x86_64\x20xhci-hcd
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_REVISION=0513
|
||||
E: ID_SERIAL=Linux_5.13.12-200.fc34.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: authorized_default=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=09\n
|
||||
A: bDeviceProtocol=01\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=0mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0513\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020013050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0\n
|
||||
A: devnum=1\n
|
||||
A: devpath=0\n
|
||||
L: driver=../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 5.13.12-200.fc34.x86_64 xhci-hcd\n
|
||||
A: maxchild=16\n
|
||||
A: power/active_duration=775798957\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=775798957\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=775798954\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=xHCI Host Controller\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=unknown\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial=0000:00:14.0\n
|
||||
A: speed=480\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=1381\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:A36D
|
||||
E: PCI_SUBSYS_ID=17AA:312A
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: MODALIAS=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30
|
||||
E: SUBSYSTEM=pci
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=86806DA3060490021030030C00008000040032B1000000000000000000000000000000000000000000000000AA172A31000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F00000000970B083900000000316000000000000000000000000000000180C2C1080000000000000000000000059087009802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F400200000100006000000008020000010000000400000090000000001800000005000000000000000300000C0000004000000080000000030000000000000000000000000000000000000000000000B50F110112000000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: dbc=disabled\n
|
||||
A: device=0xa36d\n
|
||||
A: dma_mask_bits=64\n
|
||||
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||
A: driver_override=(null)\n
|
||||
A: enable=1\n
|
||||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c
|
||||
A: index=3\n
|
||||
A: irq=125\n
|
||||
A: label=Onboard - Other\n
|
||||
A: local_cpulist=0-5\n
|
||||
A: local_cpus=3f\n
|
||||
A: modalias=pci:v00008086d0000A36Dsv000017AAsd0000312Abc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/125=msi\n
|
||||
A: numa_node=-1\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 15 20 2112 20\nxHCI ring segments 46 76 4096 76\nbuffer-2048 0 32 2048 16\nbuffer-512 0 32 512 4\nbuffer-128 3 32 128 1\nbuffer-32 0 128 32 1\n
|
||||
A: power/control=on\n
|
||||
A: power/runtime_active_time=775799103\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=enabled\n
|
||||
A: power/wakeup_abort_count=0\n
|
||||
A: power/wakeup_active=0\n
|
||||
A: power/wakeup_active_count=61\n
|
||||
A: power/wakeup_count=0\n
|
||||
A: power/wakeup_expire_count=61\n
|
||||
A: power/wakeup_last_time_ms=773160682\n
|
||||
A: power/wakeup_max_time_ms=108\n
|
||||
A: power/wakeup_total_time_ms=6358\n
|
||||
A: power_state=D0\n
|
||||
A: resource=0x00000000b1320000 0x00000000b132ffff 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: revision=0x10\n
|
||||
A: subsystem_device=0x312a\n
|
||||
A: subsystem_vendor=0x17aa\n
|
||||
A: vendor=0x8086\n
|
||||
|
|
@ -81,3 +81,145 @@ A: speed=12
|
|||
A: tx_lanes=1
|
||||
A: urbnum=8
|
||||
A: version= 1.10
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||
N: bus/usb/001/001=12010002090001406B1D020011050302010109021900010100E0000904000001090000000705810304000C
|
||||
E: DEVNAME=/dev/bus/usb/001/001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=1d6b/2/511
|
||||
E: TYPE=9/0/1
|
||||
E: BUSNUM=001
|
||||
E: DEVNUM=001
|
||||
E: MAJOR=189
|
||||
E: MINOR=0
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Linux_5.11.2-arch1-1_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.11.2-arch1-1\x20xhci-hcd
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_REVISION=0511
|
||||
E: ID_SERIAL=Linux_5.11.2-arch1-1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: authorized_default=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=09\n
|
||||
A: bDeviceProtocol=01\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=0mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0511\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020011050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0\n
|
||||
A: devnum=1\n
|
||||
A: devpath=0\n
|
||||
L: driver=../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 5.11.2-arch1-1 xhci-hcd\n
|
||||
A: maxchild=16\n
|
||||
A: power/active_duration=3289930\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=34389654\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=3289845\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=31099805\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=xHCI Host Controller\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=unknown\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial=0000:00:14.0\n
|
||||
A: speed=480\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=2355\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:A12F
|
||||
E: PCI_SUBSYS_ID=1028:07BE
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: MODALIAS=pci:v00008086d0000A12Fsv00001028sd000007BEbc0Csc03i30
|
||||
E: SUBSYSTEM=pci
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=86802FA1060490023130030C000080000400D1ED0000000000000000000000000000000000000000000000002810BE07000000007000000000000000FF010000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: device=0xa12f\n
|
||||
A: dma_mask_bits=64\n
|
||||
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||
A: driver_override=(null)\n
|
||||
A: enable=1\n
|
||||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c
|
||||
L: iommu=../../virtual/iommu/dmar1
|
||||
L: iommu_group=../../../kernel/iommu_groups/4
|
||||
A: irq=143\n
|
||||
A: local_cpulist=0-7\n
|
||||
A: local_cpus=ff\n
|
||||
A: modalias=pci:v00008086d0000A12Fsv00001028sd000007BEbc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/143=msi\n
|
||||
A: numa_node=-1\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 7 10 2112 10\nxHCI ring segments 30 38 4096 38\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\n
|
||||
A: power/control=on\n
|
||||
A: power/runtime_active_time=34390988\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=enabled\n
|
||||
A: power/wakeup_abort_count=0\n
|
||||
A: power/wakeup_active=0\n
|
||||
A: power/wakeup_active_count=0\n
|
||||
A: power/wakeup_count=0\n
|
||||
A: power/wakeup_expire_count=0\n
|
||||
A: power/wakeup_last_time_ms=0\n
|
||||
A: power/wakeup_max_time_ms=0\n
|
||||
A: power/wakeup_total_time_ms=0\n
|
||||
A: power_state=D0\n
|
||||
A: resource=0x00000000edd10000 0x00000000edd1ffff 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: revision=0x31\n
|
||||
A: subsystem_device=0x07be\n
|
||||
A: subsystem_vendor=0x1028\n
|
||||
A: vendor=0x8086\n
|
||||
|
||||
|
|
|
@ -78,3 +78,145 @@ A: speed=12
|
|||
A: tx_lanes=1
|
||||
A: urbnum=7
|
||||
A: version= 1.10
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb2
|
||||
N: bus/usb/002/001=12010002090001406B1D020011050302010109021900010100E0000904000001090000000705810304000C
|
||||
E: DEVNAME=/dev/bus/usb/002/001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: PRODUCT=1d6b/2/511
|
||||
E: TYPE=9/0/1
|
||||
E: BUSNUM=002
|
||||
E: DEVNUM=001
|
||||
E: MAJOR=189
|
||||
E: MINOR=0
|
||||
E: SUBSYSTEM=usb
|
||||
E: ID_VENDOR=Linux_5.11.2-arch1-1_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x205.11.2-arch1-1\x20xhci-hcd
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_REVISION=0511
|
||||
E: ID_SERIAL=Linux_5.11.2-arch1-1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_BUS=usb
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: TAGS=:seat:
|
||||
E: CURRENT_TAGS=:seat:
|
||||
A: authorized=1\n
|
||||
A: authorized_default=1\n
|
||||
A: avoid_reset_quirk=0\n
|
||||
A: bConfigurationValue=1\n
|
||||
A: bDeviceClass=09\n
|
||||
A: bDeviceProtocol=01\n
|
||||
A: bDeviceSubClass=00\n
|
||||
A: bMaxPacketSize0=64\n
|
||||
A: bMaxPower=0mA\n
|
||||
A: bNumConfigurations=1\n
|
||||
A: bNumInterfaces= 1\n
|
||||
A: bcdDevice=0511\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=1\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020011050302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:0\n
|
||||
A: devnum=1\n
|
||||
A: devpath=0\n
|
||||
L: driver=../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c/device:4d
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 5.11.2-arch1-1 xhci-hcd\n
|
||||
A: maxchild=16\n
|
||||
A: power/active_duration=3289930\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=34389654\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=3289845\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=31099805\n
|
||||
A: power/wakeup=disabled\n
|
||||
A: power/wakeup_abort_count=\n
|
||||
A: power/wakeup_active=\n
|
||||
A: power/wakeup_active_count=\n
|
||||
A: power/wakeup_count=\n
|
||||
A: power/wakeup_expire_count=\n
|
||||
A: power/wakeup_last_time_ms=\n
|
||||
A: power/wakeup_max_time_ms=\n
|
||||
A: power/wakeup_total_time_ms=\n
|
||||
A: product=xHCI Host Controller\n
|
||||
A: quirks=0x0\n
|
||||
A: removable=unknown\n
|
||||
A: rx_lanes=1\n
|
||||
A: serial=0000:00:14.0\n
|
||||
A: speed=480\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=2355\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:A12F
|
||||
E: PCI_SUBSYS_ID=1028:07BE
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: MODALIAS=pci:v00008086d0000A12Fsv00001028sd000007BEbc0Csc03i30
|
||||
E: SUBSYSTEM=pci
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=86802FA1060490023130030C000080000400D1ED0000000000000000000000000000000000000000000000002810BE07000000007000000000000000FF010000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: device=0xa12f\n
|
||||
A: dma_mask_bits=64\n
|
||||
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||
A: driver_override=(null)\n
|
||||
A: enable=1\n
|
||||
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4c
|
||||
L: iommu=../../virtual/iommu/dmar1
|
||||
L: iommu_group=../../../kernel/iommu_groups/4
|
||||
A: irq=143\n
|
||||
A: local_cpulist=0-7\n
|
||||
A: local_cpus=ff\n
|
||||
A: modalias=pci:v00008086d0000A12Fsv00001028sd000007BEbc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/143=msi\n
|
||||
A: numa_node=-1\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 7 10 2112 10\nxHCI ring segments 30 38 4096 38\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\n
|
||||
A: power/control=on\n
|
||||
A: power/runtime_active_time=34390988\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=0\n
|
||||
A: power/wakeup=enabled\n
|
||||
A: power/wakeup_abort_count=0\n
|
||||
A: power/wakeup_active=0\n
|
||||
A: power/wakeup_active_count=0\n
|
||||
A: power/wakeup_count=0\n
|
||||
A: power/wakeup_expire_count=0\n
|
||||
A: power/wakeup_last_time_ms=0\n
|
||||
A: power/wakeup_max_time_ms=0\n
|
||||
A: power/wakeup_total_time_ms=0\n
|
||||
A: power_state=D0\n
|
||||
A: resource=0x00000000edd10000 0x00000000edd1ffff 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: revision=0x31\n
|
||||
A: subsystem_device=0x07be\n
|
||||
A: subsystem_vendor=0x1028\n
|
||||
A: vendor=0x8086\n
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ class VirtualDeviceBase(unittest.TestCase):
|
|||
else:
|
||||
self.assertFalse(match)
|
||||
|
||||
if isinstance(scan_nick, str):
|
||||
if isinstance(scan_nick, str) and not self.dev.has_storage():
|
||||
self.assertEqual(self._verify_fp.props.fpi_data.get_string(), scan_nick)
|
||||
|
||||
|
||||
|
@ -470,15 +470,8 @@ class VirtualDevice(VirtualDeviceBase):
|
|||
def test_enroll_verify_no_match(self):
|
||||
matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING)
|
||||
|
||||
if self.dev.has_storage():
|
||||
with self.assertRaises(GLib.Error) as error:
|
||||
self.check_verify(matching, 'not-testprint', match=False,
|
||||
identify=self.dev.supports_identify())
|
||||
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.DATA_NOT_FOUND))
|
||||
else:
|
||||
self.check_verify(matching, 'not-testprint', match=False,
|
||||
identify=self.dev.supports_identify())
|
||||
self.check_verify(matching, 'not-testprint', match=False,
|
||||
identify=self.dev.supports_identify())
|
||||
|
||||
def test_enroll_verify_error(self):
|
||||
matching = self.enroll_print('testprint', FPrint.Finger.LEFT_RING)
|
||||
|
@ -597,14 +590,11 @@ class VirtualDevice(VirtualDeviceBase):
|
|||
FPrint.DeviceRetry.TOO_SHORT))
|
||||
|
||||
self.send_command('SCAN', 'another-id')
|
||||
verify_match, verify_fp = self.dev.verify_sync(enrolled)
|
||||
self.assertFalse(verify_match)
|
||||
if self.dev.has_storage():
|
||||
with self.assertRaises(GLib.GError) as error:
|
||||
self.dev.verify_sync(enrolled)
|
||||
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.DATA_NOT_FOUND))
|
||||
self.assertIsNone(verify_fp)
|
||||
else:
|
||||
verify_match, verify_fp = self.dev.verify_sync(enrolled)
|
||||
self.assertFalse(verify_match)
|
||||
self.assertFalse(verify_fp.equal(enrolled))
|
||||
|
||||
self.send_auto(enrolled)
|
||||
|
@ -821,13 +811,7 @@ class VirtualDevice(VirtualDeviceBase):
|
|||
self.wait_timeout(10)
|
||||
self.assertFalse(self._verify_completed)
|
||||
|
||||
if self.dev.has_storage():
|
||||
with self.assertRaises(GLib.Error) as error:
|
||||
self.complete_verify()
|
||||
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.DATA_NOT_FOUND))
|
||||
else:
|
||||
self.complete_verify()
|
||||
self.complete_verify()
|
||||
self.assertTrue(self._verify_reported)
|
||||
|
||||
def test_close_error(self):
|
||||
|
@ -1159,18 +1143,12 @@ class VirtualDeviceStorage(VirtualDevice):
|
|||
FPrint.DeviceError.DATA_NOT_FOUND))
|
||||
|
||||
def test_verify_missing_print(self):
|
||||
with self.assertRaises(GLib.Error) as error:
|
||||
self.check_verify(FPrint.Print.new(self.dev),
|
||||
'not-existing-print', False, identify=False)
|
||||
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.DATA_NOT_FOUND))
|
||||
self.check_verify(FPrint.Print.new(self.dev),
|
||||
'not-existing-print', False, identify=False)
|
||||
|
||||
def test_identify_missing_print(self):
|
||||
with self.assertRaises(GLib.Error) as error:
|
||||
self.check_verify(FPrint.Print.new(self.dev),
|
||||
'not-existing-print', False, identify=True)
|
||||
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.DATA_NOT_FOUND))
|
||||
self.check_verify(FPrint.Print.new(self.dev),
|
||||
'not-existing-print', False, identify=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in a new issue