Merge branch 'elan-0c8e-support' into 'master'

drivers: Add elanmoc2 driver for 0c8e sensor

Closes #751

See merge request libfprint/libfprint!560
This commit is contained in:
REYSEIL FULLBRYGER 2026-01-21 01:31:10 +00:00
commit f71c32bd14
9 changed files with 1752 additions and 0 deletions

View file

@ -171,6 +171,11 @@ usb:v04F3p0CB0*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver elanmoc2
usb:v04F3p0C8E*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver etes603
usb:v1C7Ap0603*
ID_AUTOSUSPEND=1

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,209 @@
/*
* 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 PATCHED"
#define ELANMOC2_VEND_ID 0x04f3
#define ELANMOC2_ENROLL_TIMES 8
#define ELANMOC2_CMD_MAX_LEN 16
#define ELANMOC2_MAX_PRINTS 10
// 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 60000
// 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_0C4C (1 << 0)
#define ELANMOC2_DEV_0C5E (1 << 1)
#define ELANMOC2_DEV_0C8E (1 << 2)
// 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)
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 cancellable;
};
// Cancellable commands
static const struct elanmoc2_cmd cmd_identify = {
.cmd = {0xff, 0x03, 0x00},
.out_len = 4,
.in_len = 2, // Windows returns 2 bytes (e.g. 4000, 40fd, 4043)
.ep_in = ELANMOC2_EP_MOC_CMD_IN, // EP 4 (0x84) based on Windows capture
.cancellable = true,
};
static const struct elanmoc2_cmd cmd_enroll = {
.cmd = {0xff, 0x01},
.out_len = 7,
.in_len = 64,
.ep_in = ELANMOC2_EP_MOC_CMD_IN,
.cancellable = true,
};
// Not cancellable / quick commands
static const struct elanmoc2_cmd 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 struct elanmoc2_cmd cmd_finger_info = {
.cmd = {0xff, 0x12},
.out_len = 4,
.in_len = 64,
.ep_in = ELANMOC2_EP_CMD_IN,
};
static const struct elanmoc2_cmd cmd_get_enrolled_count = {
.cmd = {0xff, 0x04},
.out_len = 3,
.in_len = 64, // Increased from 2 to handle variable responses
.ep_in = ELANMOC2_EP_CMD_IN,
};
static const struct elanmoc2_cmd cmd_abort = {
.cmd = {0xff, 0x02},
.out_len = 3,
.in_len = 2,
.ep_in = ELANMOC2_EP_CMD_IN,
};
static const struct elanmoc2_cmd cmd_commit = {
.cmd = {0xff, 0x11},
.out_len = 72,
.in_len = 64, // Increased from 2
.ep_in = ELANMOC2_EP_CMD_IN,
};
static const struct elanmoc2_cmd cmd_check_enroll_collision = {
.cmd = {0xff, 0x10},
.out_len = 3,
.in_len = 64, // Increased from 3
.ep_in = ELANMOC2_EP_CMD_IN,
};
static const struct elanmoc2_cmd cmd_delete = {
.cmd = {0xff, 0x13},
.out_len = 72,
.in_len = 2,
.ep_in = ELANMOC2_EP_CMD_IN,
};
static const struct elanmoc2_cmd cmd_wipe_sensor = {
.cmd = {0xff, 0x99},
.out_len = 3,
.in_len = 0,
.ep_in = ELANMOC2_EP_CMD_IN,
};
enum identify_states {
IDENTIFY_GET_NUM_ENROLLED,
IDENTIFY_CHECK_NUM_ENROLLED,
IDENTIFY_IDENTIFY,
IDENTIFY_GET_FINGER_INFO,
IDENTIFY_CHECK_FINGER_INFO,
IDENTIFY_NUM_STATES
};
enum list_states {
LIST_GET_NUM_ENROLLED,
LIST_CHECK_NUM_ENROLLED,
LIST_GET_FINGER_INFO,
LIST_CHECK_FINGER_INFO,
LIST_NUM_STATES
};
enum enroll_states {
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 delete_states {
DELETE_GET_NUM_ENROLLED,
DELETE_DELETE,
DELETE_CHECK_DELETED,
DELETE_NUM_STATES
};
enum clear_storage_states {
CLEAR_STORAGE_WIPE_SENSOR,
CLEAR_STORAGE_GET_NUM_ENROLLED,
CLEAR_STORAGE_CHECK_NUM_ENROLLED,
CLEAR_STORAGE_NUM_STATES
};

View file

@ -153,6 +153,8 @@ driver_sources = {
[ 'drivers/realtek/realtek.c' ],
'focaltech_moc' :
[ 'drivers/focaltech_moc/focaltech_moc.c' ],
'elanmoc2' :
[ 'drivers/elanmoc2/elanmoc2.c' ],
}
helper_sources = {

View file

@ -144,6 +144,7 @@ default_drivers = [
'fpcmoc',
'realtek',
'focaltech_moc',
'elanmoc2',
]
spi_drivers = [
@ -168,6 +169,7 @@ endian_independent_drivers = virtual_drivers + [
'elanmoc',
'etes603',
'focaltech_moc',
'elanmoc2',
'nb1010',
'realtek',
'synaptics',

Binary file not shown.

54
tests/elanmoc2/custom.py Executable file
View file

@ -0,0 +1,54 @@
#!/usr/bin/python3
import traceback
import sys
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
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.STORAGE)
d.open_sync()
template = FPrint.Print.new(d)
def enroll_progress(*args):
if len(args) > 1:
print("enroll progress stage: ", args[1])
def identify_done(dev, res):
global identified
identified = True
match, print_found = dev.identify_finish(res)
print("MATCH FOUND!" if match else "NO MATCH FOUND")
# Enroll
print("--- ENROLLING ---")
p = d.enroll_sync(template, None, enroll_progress, None)
print("--- ENROLL DONE ---")
# List
print("--- LISTING ---")
stored = d.list_prints_sync()
print(f"--- LIST DONE: Found {len(stored)} prints ---")
# Verify
print("--- VERIFYING ---")
verify_res, verify_print = d.verify_sync(p)
print(f"--- VERIFY DONE: Result {verify_res} ---")
# Identify
print("--- ASYNC IDENTIFYING ---")
identified = False
deserialized_prints = [FPrint.Print.deserialize(sp.serialize()) for sp in stored]
d.identify(deserialized_prints, callback=identify_done)
while not identified:
ctx.iteration(True)
print("--- IDENTIFY DONE ---")
# Delete
print("--- DELETING ---")
p_to_delete = next((sp for sp in stored if sp.equal(p)), None)
if p_to_delete:
d.delete_print_sync(p_to_delete)
print("--- DELETE DONE ---")
d.close_sync()

260
tests/elanmoc2/device Normal file
View file

@ -0,0 +1,260 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-7
N: bus/usb/001/003=1201000200000008F3048E0C02070102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
E: BUSNUM=001
E: CURRENT_TAGS=:uaccess:seat:
E: DEVNAME=/dev/bus/usb/001/003
E: DEVNUM=003
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_7
E: ID_MODEL=ELAN:ARM-M4
E: ID_MODEL_ENC=ELAN:ARM-M4
E: ID_MODEL_ID=0c8e
E: ID_PATH=pci-0000:00:14.0-usb-0:7
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_7
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:7
E: ID_REVISION=0702
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=0c8e
E: ID_USB_REVISION=0702
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=2
E: PRODUCT=4f3/c8e/702
E: SUBSYSTEM=usb
E: TAGS=:uaccess: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=0702\n
A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=
H: descriptors=1201000200000008F3048E0C02070102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
A: dev=189:2\n
A: devnum=3\n
A: devpath=7\n
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:50/device:51/device:59
A: idProduct=0c8e\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=../1-0:1.0/usb1-port7
A: power/active_duration=27442\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=710484\n
A: power/control=auto\n
A: power/level=auto\n
A: power/persist=0\n
A: power/runtime_active_time=27667\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=682578\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=75\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020018060302010109021900010100E0000904000001090000000705810304000C
E: BUSNUM=001
E: CURRENT_TAGS=:seat:
E: DEVNAME=/dev/bus/usb/001/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=0618
E: ID_SERIAL=Linux_6.18.1-arch1-2_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=0618
E: ID_USB_SERIAL=Linux_6.18.1-arch1-2_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_USB_SERIAL_SHORT=0000:00:14.0
E: ID_USB_VENDOR=Linux_6.18.1-arch1-2_xhci-hcd
E: ID_USB_VENDOR_ENC=Linux\x206.18.1-arch1-2\x20xhci-hcd
E: ID_USB_VENDOR_ID=1d6b
E: ID_VENDOR=Linux_6.18.1-arch1-2_xhci-hcd
E: ID_VENDOR_ENC=Linux\x206.18.1-arch1-2\x20xhci-hcd
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_VENDOR_ID=1d6b
E: MAJOR=189
E: MINOR=0
E: PRODUCT=1d6b/2/618
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=0618\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002090001406B1D020018060302010109021900010100E0000904000001090000000705810304000C
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:50/device:51
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 6.18.1-arch1-2 xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=33329\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=710870\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_time=33324\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=677543\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=270\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=Alder Lake PCH USB 3.2 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:v00008086d000051EDsv0000103Csd00008B34bc0Csc03i30
E: PCI_CLASS=C0330
E: PCI_ID=8086:51ED
E: PCI_SLOT_NAME=0000:00:14.0
E: PCI_SUBSYS_ID=103C:8B34
E: SUBSYSTEM=pci
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED51060490020130030C00008000040012016000000000000000000000000000000000000000000000003C10348B000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C10800000000000000000000000590B7001803E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F110112000000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: dbc=disabled\n
A: dbc_bInterfaceProtocol=01\n
A: dbc_bcdDevice=0010\n
A: dbc_idProduct=0010\n
A: dbc_idVendor=1d6b\n
A: dbc_poll_interval_ms=64\n
A: device=0x51ed\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:50
A: irq=122\n
A: local_cpulist=0-11\n
A: local_cpus=fff\n
A: modalias=pci:v00008086d000051EDsv0000103Csd00008B34bc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/122=msi\n
A: msi_irqs/123=msi\n
A: msi_irqs/124=msi\n
A: msi_irqs/125=msi\n
A: msi_irqs/126=msi\n
A: msi_irqs/127=msi\n
A: msi_irqs/128=msi\n
A: msi_irqs/129=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 256 port bw ctx arrays 0 0 256 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 6 7 2112 7\nxHCI ring segments 37 37 4096 37\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=auto\n
A: power/runtime_active_time=34188\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=677377\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=0x0000006001120000 0x000000600112ffff 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=0x01\n
A: subsystem_device=0x8b34\n
A: subsystem_vendor=0x103c\n
A: vendor=0x8086\n

View file

@ -59,6 +59,7 @@ drivers_tests = [
'realtek',
'realtek-5816',
'focaltech_moc',
'elanmoc2',
]
if get_option('introspection')