Merge branch 'codex/upek-147e-1002-experiment' into 'master'

Draft: upeksonly: experiment with 147e:1002 support

See merge request libfprint/libfprint!585
This commit is contained in:
Nikolay Metchev 2026-05-06 09:19:37 +00:00
commit 7a155316eb
6 changed files with 879 additions and 30 deletions

View file

@ -110,7 +110,7 @@ test_valgrind:
extends:
- .standard_job
script:
- meson setup _build -Ddrivers=all
- meson setup _build -Ddrivers=all -Dintrospection=false
- meson compile -C _build
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
artifacts:

View file

@ -293,6 +293,7 @@ usb:v06CBp01A0*
# Supported by libfprint driver upeksonly
usb:v147Ep2016*
usb:v147Ep1000*
usb:v147Ep1002*
usb:v147Ep1001*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@ -443,7 +444,6 @@ usb:v138Ap0097*
usb:v138Ap009D*
usb:v138Ap00AB*
usb:v138Ap00A6*
usb:v147Ep1002*
usb:v1491p0088*
usb:v16D1p1027*
usb:v1C7Ap0300*

View file

@ -272,15 +272,14 @@ static void
fpc_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
CommandData *data = fpi_ssm_get_data (ssm);
self->cmd_ssm = NULL;
/* Notify about the SSM failure from here instead. */
if (error)
{
fp_err ("%s error: %s ", G_STRFUNC, error->message);
if (data->callback)
data->callback (self, NULL, error);
if (((CommandData *) fpi_ssm_get_data (ssm))->callback)
((CommandData *) fpi_ssm_get_data (ssm))->callback (self, NULL, error);
}
}

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,12 @@
#define IMG_WIDTH_2016 288
#define IMG_WIDTH_1000 288
#define IMG_WIDTH_1002 162
#define IMG_CROP_X_1002 18
#define IMG_CROP_WIDTH_1002 108
#define IMG_CROP_ROWS_1002 992
#define IMG_CROP_OFFSET_1002 0
#define IMG_HEIGHT_SCALE_1002 4
#define IMG_WIDTH_1001 216
struct sonly_regwrite
@ -33,6 +39,15 @@ struct sonly_regwrite
guint8 value;
};
struct sonly_regwrite_data
{
guint8 reg;
guint8 len;
guint8 value[8];
};
#define UPEKSONLY_READ(reg, len) { reg, 0, { len } }
/***** AWAIT FINGER *****/
static const struct sonly_regwrite awfsm_2016_writev_1[] = {
@ -55,6 +70,15 @@ static const struct sonly_regwrite awfsm_1000_writev_1[] = {
{ 0x10, 0x00 }, { 0x11, 0xbf },
};
static const struct sonly_regwrite awfsm_1002_writev_1[] = {
/* Windows sets up the 1002 wait path with this 3e/1a prelude before
* enabling the finger detector. */
{ 0x49, 0x08 },
{ 0x3e, 0x45 }, { 0x3e, 0x92 }, { 0x3e, 0xd9 }, { 0x3e, 0x3a },
{ 0x3e, 0x99 }, { 0x3e, 0x8c }, { 0x3e, 0xc6 }, { 0x3e, 0xb9 },
{ 0x1a, 0x01 },
};
static const struct sonly_regwrite awfsm_2016_writev_2[] = {
{ 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
{ 0x0f, 0x0d }, { 0x0b, 0x00 },
@ -65,6 +89,13 @@ static const struct sonly_regwrite awfsm_1000_writev_2[] = {
{ 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 },
};
static const struct sonly_regwrite awfsm_1002_writev_2[] = {
/* Windows arms 147e:1002 wait mode with the 1a/0b/49 prelude followed by
* the actual detector-enable writes on 0x30/0x15. */
{ 0x1a, 0x03 }, { 0x0b, 0x00 }, { 0x49, 0x0c },
{ 0x30, 0xe1 }, { 0x15, 0x05 }, { 0x15, 0x85 },
};
static const struct sonly_regwrite awfsm_2016_writev_3[] = {
{ 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 },
{ 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 },
@ -92,6 +123,52 @@ static const struct sonly_regwrite capsm_1000_writev[] = {
{ 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */
};
static const struct sonly_regwrite capsm_1002_writev[] = {
/* BSAPI submits bulk URBs before these capture-start writes. */
{ 0x09, 0x22 }, { 0x13, 0x75 }, { 0x0b, 0x80 },
};
static const struct sonly_regwrite_data capsm_1002_writev_data[] = {
/* Finger-detect mode changes security state; replay the final BSAPI
* key/tail immediately before the low-security streaming setup. */
{ 0x49, 1, { 0x08 } },
{ 0x3e, 1, { 0x15 } }, { 0x3e, 1, { 0x5c } },
{ 0x3e, 1, { 0x27 } }, { 0x3e, 1, { 0xf5 } },
{ 0x3e, 1, { 0xfb } }, { 0x3e, 1, { 0x82 } },
{ 0x3e, 1, { 0x25 } }, { 0x3e, 1, { 0x61 } },
{ 0x09, 1, { 0x2a } }, { 0x1a, 1, { 0x01 } },
UPEKSONLY_READ (0x0b, 8), { 0x0b, 1, { 0x00 } },
UPEKSONLY_READ (0x13, 8), { 0x13, 1, { 0x45 } },
{ 0x04, 1, { 0x00 } }, { 0x05, 1, { 0x00 } },
/* Replay the BSAPI low-security streaming setup after finger-detect mode. */
{ 0x7e, 1, { 0x0f } },
{ 0x6e, 1, { 0x20 } }, { 0x6e, 1, { 0x00 } },
{ 0x6f, 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 0x77, 7, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 0x74, 8, { 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff } },
{ 0x7c, 1, { 0x07 } }, { 0x6e, 1, { 0x10 } },
{ 0x7e, 1, { 0x05 } }, { 0x6e, 1, { 0x1f } },
{ 0x7e, 1, { 0x0f } }, { 0x6e, 1, { 0x10 } },
{ 0x7e, 1, { 0x05 } }, { 0x1a, 1, { 0x03 } },
UPEKSONLY_READ (0x17, 8), UPEKSONLY_READ (0x0a, 8),
UPEKSONLY_READ (0x03, 8), UPEKSONLY_READ (0x00, 8),
UPEKSONLY_READ (0x01, 8), UPEKSONLY_READ (0x30, 8),
UPEKSONLY_READ (0x15, 8), UPEKSONLY_READ (0x12, 8),
UPEKSONLY_READ (0x25, 8), UPEKSONLY_READ (0x31, 8),
UPEKSONLY_READ (0x08, 8), UPEKSONLY_READ (0x07, 8),
UPEKSONLY_READ (0x24, 8), UPEKSONLY_READ (0x26, 8),
UPEKSONLY_READ (0x1d, 8),
{ 0x00, 2, { 0x53, 0xee } },
{ 0x03, 1, { 0x27 } },
{ 0x07, 8, { 0x00, 0x00, 0x2a, 0x20, 0x00, 0x0f, 0x09, 0x0a } },
{ 0x0f, 3, { 0x09, 0x00, 0x8f } },
{ 0x1d, 1, { 0x02 } },
{ 0x25, 4, { 0x10, 0x00, 0x8f, 0x23 } },
{ 0x31, 1, { 0x44 } },
{ 0x07, 1, { 0x10 } },
};
static const struct sonly_regwrite capsm_1001_writev_1[] = {
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
@ -191,6 +268,84 @@ static const struct sonly_regwrite initsm_1000_writev_1[] = {
{ 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */
};
#define UPEKSONLY_1002_CAL_PASS \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x0a } }, \
{ 0x47, 1, { 0x00 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x0a } }, \
{ 0x47, 1, { 0x00 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x0a } }, \
{ 0x47, 1, { 0x00 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x02 } }, \
{ 0x47, 1, { 0x02 } }, { 0x47, 1, { 0x0a } }, \
{ 0x47, 1, { 0x00 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }, { 0x47, 1, { 0x04 } }, \
{ 0x47, 1, { 0x04 } }
static const struct sonly_regwrite_data initsm_1002_writev_1[] = {
/* Captured from Linux BSAPI 4.0 in low sensor-security mode. */
UPEKSONLY_READ (0x4b, 8),
{ 0x4b, 1, { 0x01 } }, { 0x4f, 1, { 0x06 } },
{ 0x4f, 1, { 0x05 } }, { 0x4f, 1, { 0x04 } },
{ 0x4b, 1, { 0x00 } },
UPEKSONLY_READ (0x49, 8),
{ 0x3e, 1, { 0x45 } }, { 0x3e, 1, { 0x92 } },
{ 0x3e, 1, { 0xd9 } }, { 0x3e, 1, { 0x3a } },
{ 0x3e, 1, { 0x99 } }, { 0x3e, 1, { 0x8c } },
{ 0x3e, 1, { 0xc6 } }, { 0x3e, 1, { 0xb9 } },
UPEKSONLY_READ (0x1a, 8), UPEKSONLY_READ (0x09, 8),
{ 0x09, 1, { 0x2a } }, { 0x1a, 1, { 0x01 } },
{ 0x09, 1, { 0x22 } }, { 0x1a, 1, { 0x03 } },
{ 0x49, 1, { 0x09 } },
UPEKSONLY_1002_CAL_PASS,
{ 0x49, 1, { 0x08 } },
{ 0x3e, 1, { 0x2e } }, { 0x3e, 1, { 0xfe } },
{ 0x3e, 1, { 0x14 } }, { 0x3e, 1, { 0xd5 } },
{ 0x3e, 1, { 0x33 } }, { 0x3e, 1, { 0x34 } },
{ 0x3e, 1, { 0xc5 } }, { 0x3e, 1, { 0xbf } },
{ 0x09, 1, { 0x2a } }, { 0x1a, 1, { 0x01 } },
{ 0x09, 1, { 0x22 } }, { 0x1a, 1, { 0x03 } },
{ 0x49, 1, { 0x09 } },
UPEKSONLY_1002_CAL_PASS,
{ 0x49, 1, { 0x08 } },
{ 0x3e, 1, { 0x15 } }, { 0x3e, 1, { 0x5c } },
{ 0x3e, 1, { 0x27 } }, { 0x3e, 1, { 0xf5 } },
{ 0x3e, 1, { 0xfb } }, { 0x3e, 1, { 0x82 } },
{ 0x3e, 1, { 0x25 } }, { 0x3e, 1, { 0x61 } },
{ 0x09, 1, { 0x2a } }, { 0x1a, 1, { 0x01 } },
UPEKSONLY_READ (0x0b, 8), { 0x0b, 1, { 0x00 } },
UPEKSONLY_READ (0x13, 8), { 0x13, 1, { 0x45 } },
/* Do not preload the capture stream here. The capture-specific low-security
* programming is replayed in CAPSM once a real finger interrupt arrives. */
{ 0x04, 1, { 0x00 } }, { 0x05, 1, { 0x00 } },
};
#undef UPEKSONLY_1002_CAL_PASS
static const struct sonly_regwrite initsm_1001_writev_1[] = {
{ 0x4a, 0x9d },
{ 0x4f, 0x06 },

View file

@ -117,7 +117,6 @@ static const FpIdEntry allowlist_id_table[] = {
{ .vid = 0x138a, .pid = 0x009d },
{ .vid = 0x138a, .pid = 0x00ab },
{ .vid = 0x138a, .pid = 0x00a6 },
{ .vid = 0x147e, .pid = 0x1002 },
{ .vid = 0x1491, .pid = 0x0088 },
{ .vid = 0x16d1, .pid = 0x1027 },
{ .vid = 0x1c7a, .pid = 0x0300 },