mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-02-09 00:30:25 +01:00
Merge branch 'elanmoc2' into 'master'
Add driver for ELAN MoC 0c4c Closes #406 See merge request libfprint/libfprint!330
This commit is contained in:
commit
581bc90ff5
13 changed files with 1877 additions and 9 deletions
|
|
@ -171,6 +171,15 @@ usb:v04F3p0CB0*
|
|||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver elanmoc2
|
||||
usb:v04F3p0C00*
|
||||
usb:v04F3p0C4C*
|
||||
usb:v04F3p0C5E*
|
||||
usb:v04F3p0C7C*
|
||||
usb:v04F3p0C90*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
# Supported by libfprint driver etes603
|
||||
usb:v1C7Ap0603*
|
||||
ID_AUTOSUSPEND=1
|
||||
|
|
@ -354,10 +363,7 @@ usb:v047Dp8054*
|
|||
usb:v047Dp8055*
|
||||
usb:v04E8p730B*
|
||||
usb:v04F3p036B*
|
||||
usb:v04F3p0C00*
|
||||
usb:v04F3p0C4C*
|
||||
usb:v04F3p0C57*
|
||||
usb:v04F3p0C5E*
|
||||
usb:v04F3p0C5A*
|
||||
usb:v04F3p0C60*
|
||||
usb:v04F3p0C6C*
|
||||
|
|
|
|||
1194
libfprint/drivers/elanmoc2/elanmoc2.c
Normal file
1194
libfprint/drivers/elanmoc2/elanmoc2.c
Normal file
File diff suppressed because it is too large
Load diff
195
libfprint/drivers/elanmoc2/elanmoc2.h
Normal file
195
libfprint/drivers/elanmoc2/elanmoc2.h
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Driver for ELAN Match-On-Chip sensors
|
||||
* Copyright (C) 2021-2023 Davide Depau <davide@depau.eu>
|
||||
*
|
||||
* Based on original reverse-engineering work by Davide Depau. The protocol has
|
||||
* been reverse-engineered from captures of the official Windows driver, and by
|
||||
* testing commands on the sensor with a multiplatform Python prototype driver:
|
||||
* https://github.com/depau/Elan-Fingerprint-0c4c-PoC/
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Stdlib includes
|
||||
#include <stdbool.h>
|
||||
|
||||
// Library includes
|
||||
#include <libusb.h>
|
||||
|
||||
// Local includes
|
||||
#include "fpi-device.h"
|
||||
#include "fpi-ssm.h"
|
||||
|
||||
#define ELANMOC2_DRIVER_FULLNAME "ELAN Match-on-Chip 2"
|
||||
#define ELANMOC2_VEND_ID 0x04f3
|
||||
|
||||
#define ELANMOC2_ENROLL_TIMES 8
|
||||
#define ELANMOC2_CMD_MAX_LEN 2
|
||||
#define ELANMOC2_MAX_PRINTS 10
|
||||
#define ELANMOC2_MAX_RETRIES 3
|
||||
|
||||
// USB parameters
|
||||
#define ELANMOC2_EP_CMD_OUT (0x1 | FPI_USB_ENDPOINT_OUT)
|
||||
#define ELANMOC2_EP_CMD_IN (0x3 | FPI_USB_ENDPOINT_IN)
|
||||
#define ELANMOC2_EP_MOC_CMD_IN (0x4 | FPI_USB_ENDPOINT_IN)
|
||||
#define ELANMOC2_USB_SEND_TIMEOUT 10000
|
||||
#define ELANMOC2_USB_RECV_TIMEOUT 10000
|
||||
|
||||
// Response codes
|
||||
#define ELANMOC2_RESP_MOVE_DOWN 0x41
|
||||
#define ELANMOC2_RESP_MOVE_RIGHT 0x42
|
||||
#define ELANMOC2_RESP_MOVE_UP 0x43
|
||||
#define ELANMOC2_RESP_MOVE_LEFT 0x44
|
||||
#define ELANMOC2_RESP_MAX_ENROLLED_REACHED 0xdd
|
||||
#define ELANMOC2_RESP_SENSOR_DIRTY 0xfb
|
||||
#define ELANMOC2_RESP_NOT_ENROLLED 0xfd
|
||||
#define ELANMOC2_RESP_NOT_ENOUGH_SURFACE 0xfe
|
||||
|
||||
// Currently only one device is supported, but I'd like to future-proof this driver for any new contributions.
|
||||
#define ELANMOC2_ALL_DEV 0
|
||||
#define ELANMOC2_DEV_0C5E (1 << 0)
|
||||
|
||||
// Subtract the 2-byte header
|
||||
#define ELANMOC2_USER_ID_MAX_LEN (cmd_finger_info.in_len - 2)
|
||||
#define ELANMOC2_USER_ID_MAX_LEN_0C5E (cmd_finger_info.in_len - 3)
|
||||
|
||||
G_DECLARE_FINAL_TYPE (FpiDeviceElanMoC2, fpi_device_elanmoc2, FPI, DEVICE_ELANMOC2, FpDevice)
|
||||
|
||||
typedef struct elanmoc2_cmd
|
||||
{
|
||||
unsigned char cmd[ELANMOC2_CMD_MAX_LEN];
|
||||
gboolean is_single_byte_command;
|
||||
int out_len;
|
||||
int in_len;
|
||||
int ep_in;
|
||||
unsigned short devices;
|
||||
gboolean is_cancellable;
|
||||
gboolean ssm_not_required;
|
||||
} Elanmoc2Cmd;
|
||||
|
||||
|
||||
// Cancellable commands
|
||||
|
||||
static const Elanmoc2Cmd cmd_identify = {
|
||||
.cmd = {0xff, 0x03},
|
||||
.out_len = 3,
|
||||
.in_len = 2,
|
||||
.ep_in = ELANMOC2_EP_MOC_CMD_IN,
|
||||
.is_cancellable = TRUE,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_enroll = {
|
||||
.cmd = {0xff, 0x01},
|
||||
.out_len = 7,
|
||||
.in_len = 2,
|
||||
.ep_in = ELANMOC2_EP_MOC_CMD_IN,
|
||||
.is_cancellable = TRUE,
|
||||
};
|
||||
|
||||
|
||||
// Not cancellable / quick commands
|
||||
|
||||
static const Elanmoc2Cmd cmd_get_fw_ver = {
|
||||
.cmd = {0x19},
|
||||
.is_single_byte_command = TRUE,
|
||||
.out_len = 2,
|
||||
.in_len = 2,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_finger_info = {
|
||||
.cmd = {0xff, 0x12},
|
||||
.out_len = 4,
|
||||
.in_len = 64,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_get_enrolled_count = {
|
||||
.cmd = {0xff, 0x04},
|
||||
.out_len = 3,
|
||||
.in_len = 2,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_abort = {
|
||||
.cmd = {0xff, 0x02},
|
||||
.out_len = 3,
|
||||
.in_len = 2,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
.ssm_not_required = TRUE,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_commit = {
|
||||
.cmd = {0xff, 0x11},
|
||||
.out_len = 72,
|
||||
.in_len = 2,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_check_enroll_collision = {
|
||||
.cmd = {0xff, 0x10},
|
||||
.out_len = 3,
|
||||
.in_len = 3,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_delete = {
|
||||
.cmd = {0xff, 0x13},
|
||||
.out_len = 72,
|
||||
.in_len = 2,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
};
|
||||
|
||||
static const Elanmoc2Cmd cmd_wipe_sensor = {
|
||||
.cmd = {0xff, 0x99},
|
||||
.out_len = 3,
|
||||
.in_len = 0,
|
||||
.ep_in = ELANMOC2_EP_CMD_IN,
|
||||
};
|
||||
|
||||
|
||||
enum IdentifyStates {
|
||||
IDENTIFY_GET_NUM_ENROLLED,
|
||||
IDENTIFY_CHECK_NUM_ENROLLED,
|
||||
IDENTIFY_IDENTIFY,
|
||||
IDENTIFY_GET_FINGER_INFO,
|
||||
IDENTIFY_CHECK_FINGER_INFO,
|
||||
IDENTIFY_NUM_STATES
|
||||
};
|
||||
|
||||
enum EnrollStates {
|
||||
ENROLL_GET_NUM_ENROLLED,
|
||||
ENROLL_CHECK_NUM_ENROLLED,
|
||||
ENROLL_EARLY_REENROLL_CHECK,
|
||||
ENROLL_GET_ENROLLED_FINGER_INFO,
|
||||
ENROLL_ATTEMPT_DELETE,
|
||||
ENROLL_CHECK_DELETED,
|
||||
ENROLL_WIPE_SENSOR,
|
||||
ENROLL_ENROLL,
|
||||
ENROLL_CHECK_ENROLLED,
|
||||
ENROLL_LATE_REENROLL_CHECK,
|
||||
ENROLL_COMMIT,
|
||||
ENROLL_CHECK_COMMITTED,
|
||||
ENROLL_NUM_STATES
|
||||
};
|
||||
|
||||
enum ClearStorageStates {
|
||||
CLEAR_STORAGE_WIPE_SENSOR,
|
||||
CLEAR_STORAGE_GET_NUM_ENROLLED,
|
||||
CLEAR_STORAGE_CHECK_NUM_ENROLLED,
|
||||
CLEAR_STORAGE_NUM_STATES
|
||||
};
|
||||
|
|
@ -1647,8 +1647,9 @@ fp_device_delete_print (FpDevice *device,
|
|||
|
||||
/* Succeed immediately if delete is not implemented. */
|
||||
if (!cls->delete || !(priv->features & FP_DEVICE_FEATURE_STORAGE_DELETE))
|
||||
{
|
||||
g_task_return_boolean (task, TRUE);
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ fpi_device_class_auto_initialize_features (FpDeviceClass *device_class)
|
|||
if (device_class->clear_storage)
|
||||
device_class->features |= FP_DEVICE_FEATURE_STORAGE_CLEAR;
|
||||
|
||||
if (device_class->delete && (device_class->list || device_class->clear_storage))
|
||||
if (device_class->clear_storage || (device_class->delete && device_class->list))
|
||||
device_class->features |= FP_DEVICE_FEATURE_STORAGE;
|
||||
|
||||
if (device_class->temp_hot_seconds < 0)
|
||||
|
|
|
|||
|
|
@ -35,10 +35,7 @@ static const FpIdEntry allowlist_id_table[] = {
|
|||
{ .vid = 0x047d, .pid = 0x8055 },
|
||||
{ .vid = 0x04e8, .pid = 0x730b },
|
||||
{ .vid = 0x04f3, .pid = 0x036b },
|
||||
{ .vid = 0x04f3, .pid = 0x0c00 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c4c },
|
||||
{ .vid = 0x04f3, .pid = 0x0c57 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c5e },
|
||||
{ .vid = 0x04f3, .pid = 0x0c5a },
|
||||
{ .vid = 0x04f3, .pid = 0x0c60 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c6c },
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ driver_sources = {
|
|||
[ 'drivers/elan.c' ],
|
||||
'elanmoc' :
|
||||
[ 'drivers/elanmoc/elanmoc.c' ],
|
||||
'elanmoc2' :
|
||||
[ 'drivers/elanmoc2/elanmoc2.c' ],
|
||||
'elanspi' :
|
||||
[ 'drivers/elanspi.c' ],
|
||||
'nb1010' :
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ default_drivers = [
|
|||
'synaptics',
|
||||
'elan',
|
||||
'elanmoc',
|
||||
'elanmoc2',
|
||||
'uru4000',
|
||||
'upektc',
|
||||
'upeksonly',
|
||||
|
|
|
|||
48
tests/elanmoc-0c00/custom.py
Normal file
48
tests/elanmoc-0c00/custom.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version('FPrint', '2.0')
|
||||
from gi.repository import FPrint, GLib
|
||||
|
||||
# Exit with error on any exception, included those happening in async callbacks
|
||||
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||
|
||||
ctx = GLib.main_context_default()
|
||||
|
||||
c = FPrint.Context()
|
||||
c.enumerate()
|
||||
devices = c.get_devices()
|
||||
|
||||
d = devices[0]
|
||||
del devices
|
||||
|
||||
assert d.get_driver() == "elanmoc2"
|
||||
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
||||
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
||||
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||
|
||||
d.open_sync()
|
||||
|
||||
# The test aims to stress the "get enrolled count" command. Some devices occasionally respond with
|
||||
# an empty payload to this command and the driver should handle this gracefully by retrying the command.
|
||||
|
||||
print("clearing device storage")
|
||||
d.clear_storage_sync()
|
||||
|
||||
print("ensuring device storage is empty")
|
||||
stored = d.list_prints_sync()
|
||||
assert len(stored) == 0
|
||||
|
||||
d.close_sync()
|
||||
del d
|
||||
del c
|
||||
del ctx
|
||||
BIN
tests/elanmoc2/custom.pcapng
Normal file
BIN
tests/elanmoc2/custom.pcapng
Normal file
Binary file not shown.
164
tests/elanmoc2/custom.py
Normal file
164
tests/elanmoc2/custom.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
import gi
|
||||
|
||||
gi.require_version('FPrint', '2.0')
|
||||
from gi.repository import FPrint, GLib
|
||||
|
||||
# Exit with error on any exception, included those happening in async callbacks
|
||||
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||
|
||||
ctx = GLib.main_context_default()
|
||||
|
||||
c = FPrint.Context()
|
||||
c.enumerate()
|
||||
devices = c.get_devices()
|
||||
|
||||
d = devices[0]
|
||||
del devices
|
||||
|
||||
assert d.get_driver() == "elanmoc2"
|
||||
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
||||
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
||||
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||
|
||||
d.open_sync()
|
||||
|
||||
template = FPrint.Print.new(d)
|
||||
template.set_finger(FPrint.Finger.LEFT_INDEX)
|
||||
|
||||
|
||||
def dump_print(p: FPrint.Print):
|
||||
print("Type: ", p.get_property("fpi-type"))
|
||||
print("Finger: ", p.get_finger())
|
||||
print("Driver: ", p.get_driver())
|
||||
print("Device ID: ", p.get_device_id())
|
||||
print("FPI data: ", p.get_property("fpi-data"))
|
||||
print("User ID: ", bytes(p.get_property("fpi-data")[1]).decode("utf-8"))
|
||||
print("Description: ", p.get_description())
|
||||
print("Enroll date: ", p.get_enroll_date())
|
||||
print()
|
||||
|
||||
|
||||
def enroll_progress(*args):
|
||||
print("finger status: ", d.get_finger_status())
|
||||
print('enroll progress: ' + str(args))
|
||||
|
||||
|
||||
def identify_done(dev, res):
|
||||
global identified
|
||||
identified = True
|
||||
identify_match, identify_print = dev.identify_finish(res)
|
||||
print('identification done: ', identify_match, identify_print)
|
||||
assert identify_match.equal(identify_print)
|
||||
|
||||
|
||||
print("clearing device storage")
|
||||
d.clear_storage_sync()
|
||||
|
||||
print("ensuring device storage is empty")
|
||||
stored = d.list_prints_sync()
|
||||
assert len(stored) == 0
|
||||
|
||||
print("enrolling one finger")
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
enrolled = d.enroll_sync(template, None, enroll_progress, None)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print("enroll done")
|
||||
del template
|
||||
|
||||
# Verify before listing since the device may not be in a good mood
|
||||
print("verifying the enrolled finger")
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
verify_res, verify_print = d.verify_sync(enrolled)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print(f"verify done, {verify_res}, {verify_print}")
|
||||
assert verify_res
|
||||
|
||||
print("ensuring device storage has the enrolled finger")
|
||||
stored = d.list_prints_sync()
|
||||
assert len(stored) == 1
|
||||
assert stored[0].equal(enrolled)
|
||||
del enrolled
|
||||
del verify_print
|
||||
|
||||
print("attempting to enroll the same finger again")
|
||||
template = FPrint.Print.new(d)
|
||||
template.set_finger(FPrint.Finger.LEFT_INDEX)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
new_enrolled = d.enroll_sync(template, None, enroll_progress, None)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print("enroll done")
|
||||
|
||||
print("ensuring device storage has the enrolled finger")
|
||||
stored = d.list_prints_sync()
|
||||
assert len(stored) == 1
|
||||
assert stored[0].equal(new_enrolled)
|
||||
|
||||
print("enrolling another finger")
|
||||
template: FPrint.Print = FPrint.Print.new(d)
|
||||
template.set_finger(FPrint.Finger.RIGHT_LITTLE)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
enrolled2 = d.enroll_sync(template, None, enroll_progress, None)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print("enroll done")
|
||||
del template
|
||||
|
||||
print("verifying the enrolled finger")
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
verify_res, verify_print = d.verify_sync(enrolled2)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print("verify done")
|
||||
assert verify_res
|
||||
del verify_print
|
||||
|
||||
print("ensuring device storage has both enrolled fingers")
|
||||
stored = d.list_prints_sync()
|
||||
assert len(stored) == 2
|
||||
for p in stored:
|
||||
assert p.equal(new_enrolled) or p.equal(enrolled2)
|
||||
|
||||
print("identifying the enrolled fingers")
|
||||
identified = False
|
||||
deserialized_prints = []
|
||||
for p in stored:
|
||||
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
||||
assert deserialized_prints[-1].equal(p)
|
||||
del stored
|
||||
del p
|
||||
|
||||
d.identify(deserialized_prints, callback=identify_done)
|
||||
del deserialized_prints
|
||||
|
||||
while not identified:
|
||||
ctx.iteration(True)
|
||||
|
||||
print("delete the first enrolled finger")
|
||||
d.delete_print_sync(new_enrolled)
|
||||
|
||||
print("ensuring device storage has only the second enrolled finger")
|
||||
stored = d.list_prints_sync()
|
||||
assert len(stored) == 1
|
||||
assert stored[0].equal(enrolled2)
|
||||
|
||||
print("delete the second enrolled finger")
|
||||
d.delete_print_sync(enrolled2)
|
||||
|
||||
print("ensuring device storage is empty")
|
||||
stored = d.list_prints_sync()
|
||||
assert len(stored) == 0
|
||||
|
||||
del stored
|
||||
del enrolled2
|
||||
del new_enrolled
|
||||
d.close_sync()
|
||||
del d
|
||||
del c
|
||||
del ctx
|
||||
259
tests/elanmoc2/device
Normal file
259
tests/elanmoc2/device
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
P: /devices/pci0000:00/0000:00:14.0/usb3/3-9
|
||||
N: bus/usb/003/004=1201000200000008F3044C0C04030102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
|
||||
E: BUSNUM=003
|
||||
E: CURRENT_TAGS=:seat:
|
||||
E: DEVNAME=/dev/bus/usb/003/004
|
||||
E: DEVNUM=004
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_BUS=usb
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_9
|
||||
E: ID_MODEL=ELAN:ARM-M4
|
||||
E: ID_MODEL_ENC=ELAN:ARM-M4
|
||||
E: ID_MODEL_ID=0c4c
|
||||
E: ID_PATH=pci-0000:00:14.0-usb-0:9
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9
|
||||
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:9
|
||||
E: ID_PERSIST=0
|
||||
E: ID_REVISION=0304
|
||||
E: ID_SERIAL=ELAN_ELAN:ARM-M4
|
||||
E: ID_USB_INTERFACES=:ff0000:
|
||||
E: ID_USB_MODEL=ELAN:ARM-M4
|
||||
E: ID_USB_MODEL_ENC=ELAN:ARM-M4
|
||||
E: ID_USB_MODEL_ID=0c4c
|
||||
E: ID_USB_REVISION=0304
|
||||
E: ID_USB_SERIAL=ELAN_ELAN:ARM-M4
|
||||
E: ID_USB_VENDOR=ELAN
|
||||
E: ID_USB_VENDOR_ENC=ELAN
|
||||
E: ID_USB_VENDOR_ID=04f3
|
||||
E: ID_VENDOR=ELAN
|
||||
E: ID_VENDOR_ENC=ELAN
|
||||
E: ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp.
|
||||
E: ID_VENDOR_ID=04f3
|
||||
E: MAJOR=189
|
||||
E: MINOR=259
|
||||
E: NVME_HOST_IFACE=none
|
||||
E: PRODUCT=4f3/c4c/304
|
||||
E: SUBSYSTEM=usb
|
||||
E: TAGS=:seat:
|
||||
E: TYPE=0/0/0
|
||||
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=0304\n
|
||||
A: bmAttributes=a0\n
|
||||
A: busnum=3\n
|
||||
A: configuration=
|
||||
H: descriptors=1201000200000008F3044C0C04030102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
|
||||
A: dev=189:259\n
|
||||
A: devnum=4\n
|
||||
A: devpath=9\n
|
||||
L: driver=../../../../../bus/usb/drivers/usb
|
||||
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f/device:60
|
||||
A: idProduct=0c4c\n
|
||||
A: idVendor=04f3\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=ELAN\n
|
||||
A: maxchild=0\n
|
||||
A: physical_location/dock=no\n
|
||||
A: physical_location/horizontal_position=left\n
|
||||
A: physical_location/lid=no\n
|
||||
A: physical_location/panel=top\n
|
||||
A: physical_location/vertical_position=upper\n
|
||||
L: port=../3-0:1.0/usb3-port9
|
||||
A: power/active_duration=74066\n
|
||||
A: power/autosuspend=2\n
|
||||
A: power/autosuspend_delay_ms=2000\n
|
||||
A: power/connected_duration=15594864\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/persist=0\n
|
||||
A: power/runtime_active_time=74210\n
|
||||
A: power/runtime_status=active\n
|
||||
A: power/runtime_suspended_time=15458081\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=fixed\n
|
||||
A: rx_lanes=1\n
|
||||
A: speed=12\n
|
||||
A: tx_lanes=1\n
|
||||
A: urbnum=181\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0/usb3
|
||||
N: bus/usb/003/001=12010002090001406B1D020008060302010109021900010100E0000904000001090000000705810304000C
|
||||
E: BUSNUM=003
|
||||
E: CURRENT_TAGS=:seat:
|
||||
E: DEVNAME=/dev/bus/usb/003/001
|
||||
E: DEVNUM=001
|
||||
E: DEVTYPE=usb_device
|
||||
E: DRIVER=usb
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_BUS=usb
|
||||
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||
E: ID_MODEL=xHCI_Host_Controller
|
||||
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||
E: ID_MODEL_ID=0002
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_REVISION=0608
|
||||
E: ID_SERIAL=Linux_6.8.2-zen2-1-zen_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_USB_INTERFACES=:090000:
|
||||
E: ID_USB_MODEL=xHCI_Host_Controller
|
||||
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||
E: ID_USB_MODEL_ID=0002
|
||||
E: ID_USB_REVISION=0608
|
||||
E: ID_USB_SERIAL=Linux_6.8.2-zen2-1-zen_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||
E: ID_USB_SERIAL_SHORT=0000:00:14.0
|
||||
E: ID_USB_VENDOR=Linux_6.8.2-zen2-1-zen_xhci-hcd
|
||||
E: ID_USB_VENDOR_ENC=Linux\x206.8.2-zen2-1-zen\x20xhci-hcd
|
||||
E: ID_USB_VENDOR_ID=1d6b
|
||||
E: ID_VENDOR=Linux_6.8.2-zen2-1-zen_xhci-hcd
|
||||
E: ID_VENDOR_ENC=Linux\x206.8.2-zen2-1-zen\x20xhci-hcd
|
||||
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||
E: ID_VENDOR_ID=1d6b
|
||||
E: MAJOR=189
|
||||
E: MINOR=256
|
||||
E: PRODUCT=1d6b/2/608
|
||||
E: SUBSYSTEM=usb
|
||||
E: TAGS=:seat:
|
||||
E: TYPE=9/0/1
|
||||
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=0608\n
|
||||
A: bmAttributes=e0\n
|
||||
A: busnum=3\n
|
||||
A: configuration=
|
||||
H: descriptors=12010002090001406B1D020008060302010109021900010100E0000904000001090000000705810304000C
|
||||
A: dev=189:256\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:4e/device:4f
|
||||
A: idProduct=0002\n
|
||||
A: idVendor=1d6b\n
|
||||
A: interface_authorized_default=1\n
|
||||
A: ltm_capable=no\n
|
||||
A: manufacturer=Linux 6.8.2-zen2-1-zen xhci-hcd\n
|
||||
A: maxchild=12\n
|
||||
A: power/active_duration=15532764\n
|
||||
A: power/autosuspend=0\n
|
||||
A: power/autosuspend_delay_ms=0\n
|
||||
A: power/connected_duration=15595619\n
|
||||
A: power/control=auto\n
|
||||
A: power/level=auto\n
|
||||
A: power/runtime_active_time=15533289\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=490\n
|
||||
A: version= 2.00\n
|
||||
|
||||
P: /devices/pci0000:00/0000:00:14.0
|
||||
E: DRIVER=xhci_hcd
|
||||
E: ID_AUTOSUSPEND=1
|
||||
E: ID_MODEL_FROM_DATABASE=Tiger Lake-LP USB 3.2 Gen 2x1 xHCI Host Controller
|
||||
E: ID_PATH=pci-0000:00:14.0
|
||||
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||
E: MODALIAS=pci:v00008086d0000A0EDsv0000103Csd000087F7bc0Csc03i30
|
||||
E: PCI_CLASS=C0330
|
||||
E: PCI_ID=8086:A0ED
|
||||
E: PCI_SLOT_NAME=0000:00:14.0
|
||||
E: PCI_SUBSYS_ID=103C:87F7
|
||||
E: SUBSYSTEM=pci
|
||||
A: ari_enabled=0\n
|
||||
A: broken_parity_status=0\n
|
||||
A: class=0x0c0330\n
|
||||
H: config=8680EDA0060490022030030C000080000400263F6000000000000000000000000000000000000000000000003C10F787000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DDC0F000000000000000000000000316000000000000000000000000000000180C2C10800000000000000000000000590B7001806E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F210112000000
|
||||
A: consistent_dma_mask_bits=64\n
|
||||
A: d3cold_allowed=1\n
|
||||
A: device=0xa0ed\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:4e
|
||||
L: iommu=../../virtual/iommu/dmar3
|
||||
L: iommu_group=../../../kernel/iommu_groups/9
|
||||
A: irq=155\n
|
||||
A: local_cpulist=0-7\n
|
||||
A: local_cpus=ff\n
|
||||
A: modalias=pci:v00008086d0000A0EDsv0000103Csd000087F7bc0Csc03i30\n
|
||||
A: msi_bus=1\n
|
||||
A: msi_irqs/155=msi\n
|
||||
A: msi_irqs/156=msi\n
|
||||
A: msi_irqs/157=msi\n
|
||||
A: msi_irqs/158=msi\n
|
||||
A: msi_irqs/159=msi\n
|
||||
A: msi_irqs/160=msi\n
|
||||
A: msi_irqs/161=msi\n
|
||||
A: msi_irqs/162=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 28 29 2112 29\nxHCI ring segments 93 93 4096 93\nbuffer-2048 0 0 2048 0\nbuffer-512 3 8 512 1\nbuffer-128 4 32 128 1\nbuffer-32 0 0 32 0\n
|
||||
A: power/control=auto\n
|
||||
A: power/runtime_active_time=15533652\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=0x000000603f260000 0x000000603f26ffff 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=0x20\n
|
||||
A: subsystem_device=0x87f7\n
|
||||
A: subsystem_vendor=0x103c\n
|
||||
A: vendor=0x8086\n
|
||||
|
||||
|
|
@ -38,6 +38,7 @@ drivers_tests = [
|
|||
'elan',
|
||||
'elan-cobo',
|
||||
'elanmoc',
|
||||
'elanmoc2',
|
||||
'elanspi',
|
||||
'synaptics',
|
||||
'upektc_img',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue