mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
elanspi: preliminary support for 04f3:3104
Also adds "quirk" flags to driver_data so other special case things can be handled with less effort going forwards.
This commit is contained in:
@@ -63,6 +63,7 @@ struct _FpiDeviceElanSpi
|
||||
guint16 gdac_step;
|
||||
guint16 best_gdac;
|
||||
guint16 best_meandiff;
|
||||
guint16 target_mean;
|
||||
} hv_data;
|
||||
};
|
||||
|
||||
@@ -408,6 +409,10 @@ elanspi_determine_sensor (FpiDeviceElanSpi *self, GError **err)
|
||||
self->frame_width = self->sensor_width;
|
||||
self->frame_height = self->sensor_height > ELANSPI_MAX_FRAME_HEIGHT ? ELANSPI_MAX_FRAME_HEIGHT : self->sensor_height;
|
||||
}
|
||||
|
||||
/* check x571 flag */
|
||||
if (self->sensor_id == 0xe)
|
||||
self->hv_data.target_mean = (fpi_device_get_driver_data (FP_DEVICE (self)) & ELANSPI_QUIRK_X571 ? ELANSPI_HV_X571_CALIBRATION_TARGET_MEAN : ELANSPI_HV_CALIBRATION_TARGET_MEAN);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -542,7 +547,7 @@ elanspi_write_regtable (FpiDeviceElanSpi *self, const struct elanspi_regtable *
|
||||
|
||||
for (int i = 0; table->entries[i].table; i += 1)
|
||||
{
|
||||
if (table->entries[i].sid == self->sensor_id)
|
||||
if (table->entries[i].sid == self->sensor_id && table->entries[i].quirk == (fpi_device_get_driver_data (FP_DEVICE (self)) & ELANSPI_QUIRK_MASK))
|
||||
{
|
||||
starting_entry = table->entries[i].table;
|
||||
break;
|
||||
@@ -692,6 +697,8 @@ static void
|
||||
elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpointer unused_data, GError *error)
|
||||
{
|
||||
FpiDeviceElanSpi *self = FPI_DEVICE_ELANSPI (dev);
|
||||
ptrdiff_t outptr = 0, inptr = 0;
|
||||
guint16 value = 0;
|
||||
|
||||
if (error)
|
||||
{
|
||||
@@ -699,24 +706,39 @@ elanspi_capture_hv_image_handler (FpiSpiTransfer *transfer, FpDevice *dev, gpoin
|
||||
return;
|
||||
}
|
||||
|
||||
int i, outptr;
|
||||
guint16 value = 0;
|
||||
|
||||
for (i = 0, outptr = 0; i < transfer->length_rd && outptr < (self->sensor_height * self->sensor_width * 2); i += 1)
|
||||
if (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571)
|
||||
{
|
||||
if (transfer->buffer_rd[i] != 0xff)
|
||||
/* decode image in x571 mode (just copy and fix endian) */
|
||||
for (int y = 0; y < self->sensor_height; y += 1)
|
||||
{
|
||||
if (outptr % 2)
|
||||
inptr += 2; /* 2 dummy bytes per line at start */
|
||||
for (int x = 0; x < self->sensor_width; x += 1)
|
||||
{
|
||||
value <<= 8;
|
||||
value |= transfer->buffer_rd[i];
|
||||
self->last_image[outptr / 2] = value;
|
||||
self->last_image[outptr / 2] = transfer->buffer_rd[inptr] + transfer->buffer_rd[inptr + 1] * 0x100;
|
||||
inptr += 2;
|
||||
outptr += 2;
|
||||
}
|
||||
else
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* decode image (normal case; with weird 0xff checks) */
|
||||
for (inptr = 0, outptr = 0; inptr < transfer->length_rd && outptr < (self->sensor_height * self->sensor_width * 2); inptr += 1)
|
||||
{
|
||||
if (transfer->buffer_rd[inptr] != 0xff)
|
||||
{
|
||||
value = transfer->buffer_rd[i];
|
||||
if (outptr % 2)
|
||||
{
|
||||
value <<= 8;
|
||||
value |= transfer->buffer_rd[inptr];
|
||||
self->last_image[outptr / 2] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = transfer->buffer_rd[inptr];
|
||||
}
|
||||
outptr += 1;
|
||||
}
|
||||
outptr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -774,12 +796,14 @@ elanspi_capture_hv_handler (FpiSsm *ssm, FpDevice *dev)
|
||||
return;
|
||||
}
|
||||
/* otherwise, read the image
|
||||
* the hv sensors seem to use 128 bytes of padding(?) this is only tested on the 0xe sensors */
|
||||
* the hv sensors seem to use variable-length padding(?) this is only tested on the 0xe sensors
|
||||
*
|
||||
* in the x571 mode, the padding appears to be disabled and it just has 2 bytes of junk */
|
||||
xfer = fpi_spi_transfer_new (dev, self->spi_fd);
|
||||
xfer->ssm = ssm;
|
||||
fpi_spi_transfer_write (xfer, 2);
|
||||
xfer->buffer_wr[0] = 0x10; /* receieve line */
|
||||
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + 48));
|
||||
xfer->buffer_wr[0] = 0x10; /* receieve line/image */
|
||||
fpi_spi_transfer_read (xfer, self->sensor_height * (self->sensor_width * 2 + (fpi_device_get_driver_data (dev) & ELANSPI_QUIRK_X571 ? 2 : 48)));
|
||||
fpi_spi_transfer_submit (xfer, fpi_device_get_cancellable (dev), elanspi_capture_hv_image_handler, NULL);
|
||||
return;
|
||||
}
|
||||
@@ -873,7 +897,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
|
||||
|
||||
case ELANSPI_CALIBHV_PROCESS:
|
||||
/* compute mean */
|
||||
mean_diff = abs (elanspi_mean_image (self, self->last_image) - ELANSPI_HV_CALIBRATION_TARGET_MEAN);
|
||||
mean_diff = abs (elanspi_mean_image (self, self->last_image) - self->hv_data.target_mean);
|
||||
if (mean_diff < 100)
|
||||
{
|
||||
fp_dbg ("<calibhv> calibration ok (mdiff < 100 w/ gdac=%04x)", self->hv_data.gdac_value);
|
||||
@@ -896,7 +920,7 @@ elanspi_calibrate_hv_handler (FpiSsm *ssm, FpDevice *dev)
|
||||
return;
|
||||
}
|
||||
/* update gdac */
|
||||
if (elanspi_mean_image (self, self->last_image) < ELANSPI_HV_CALIBRATION_TARGET_MEAN)
|
||||
if (elanspi_mean_image (self, self->last_image) < self->hv_data.target_mean)
|
||||
self->hv_data.gdac_value -= self->hv_data.gdac_step;
|
||||
else
|
||||
self->hv_data.gdac_value += self->hv_data.gdac_step;
|
||||
|
||||
@@ -71,6 +71,7 @@ struct elanspi_regtable
|
||||
struct
|
||||
{
|
||||
unsigned char sid;
|
||||
unsigned quirk;
|
||||
const struct elanspi_reg_entry *table;
|
||||
} entries[];
|
||||
};
|
||||
@@ -172,11 +173,11 @@ static const struct elanspi_reg_entry elanspi_calibration_table_id0[] = {
|
||||
static const struct elanspi_regtable elanspi_calibration_table_old = {
|
||||
.other = elanspi_calibration_table_default,
|
||||
.entries = {
|
||||
{ .sid = 0x0, .table = elanspi_calibration_table_id0 },
|
||||
{ .sid = 0x5, .table = elanspi_calibration_table_id57 },
|
||||
{ .sid = 0x6, .table = elanspi_calibration_table_id6 },
|
||||
{ .sid = 0x7, .table = elanspi_calibration_table_id57 },
|
||||
{ .sid = 0x0, .table = NULL }
|
||||
{ .sid = 0x0, .quirk = 0, .table = elanspi_calibration_table_id0 },
|
||||
{ .sid = 0x5, .quirk = 0, .table = elanspi_calibration_table_id57 },
|
||||
{ .sid = 0x6, .quirk = 0, .table = elanspi_calibration_table_id6 },
|
||||
{ .sid = 0x7, .quirk = 0, .table = elanspi_calibration_table_id57 },
|
||||
{ .sid = 0x0, .quirk = 0, .table = NULL }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -312,20 +313,133 @@ static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14[] = {
|
||||
{0xff, 0xff}
|
||||
};
|
||||
|
||||
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = {
|
||||
.other = NULL,
|
||||
.entries = {
|
||||
{ .sid = 0xe, .table = elanspi_calibration_table_page0_id14 },
|
||||
{ .sid = 0x0, .table = NULL }
|
||||
}
|
||||
static const struct elanspi_reg_entry elanspi_calibration_table_page0_id14_x571[] = {
|
||||
{0x00, 0x5a},
|
||||
{0x01, 0x00},
|
||||
{0x02, 0x4f},
|
||||
{0x03, 0x00},
|
||||
{0x09, 0x04},
|
||||
{0x04, 0x4f},
|
||||
{0x05, 0xa0},
|
||||
{0x06, 0x57},
|
||||
{0x07, 0x02},
|
||||
{0x08, 0x00},
|
||||
{0x0a, 0x63},
|
||||
{0x0b, 0x01},
|
||||
{0x0c, 0x08},
|
||||
{0x0d, 0x00},
|
||||
{0x0e, 0x00},
|
||||
{0x0f, 0x13},
|
||||
{0x10, 0x38},
|
||||
{0x11, 0x01},
|
||||
{0x12, 0x04},
|
||||
{0x13, 0x00},
|
||||
{0x14, 0x00},
|
||||
{0x15, 0x04},
|
||||
{0x16, 0x02},
|
||||
{0x17, 0x00},
|
||||
{0x18, 0x01},
|
||||
{0x19, 0xf4},
|
||||
{0x1a, 0x00},
|
||||
{0x1b, 0x00},
|
||||
{0x1c, 0x00},
|
||||
{0x1d, 0x00},
|
||||
{0x1e, 0x00},
|
||||
{0x1f, 0x00},
|
||||
{0x20, 0x00},
|
||||
{0x21, 0x00},
|
||||
{0x22, 0x06},
|
||||
{0x23, 0x00},
|
||||
{0x24, 0x00},
|
||||
{0x25, 0x00},
|
||||
{0x26, 0x00},
|
||||
{0x27, 0xff},
|
||||
{0x28, 0x00},
|
||||
{0x29, 0x04},
|
||||
{0x2b, 0xe2},
|
||||
{0x2e, 0xd0},
|
||||
{0x2f, 0x40},
|
||||
{0x30, 0x01},
|
||||
{0x31, 0x38},
|
||||
{0x32, 0x00},
|
||||
{0x33, 0x00},
|
||||
{0x34, 0x00},
|
||||
{0x35, 0x1f},
|
||||
{0x36, 0xff},
|
||||
{0x37, 0x00},
|
||||
{0x38, 0x00},
|
||||
{0x39, 0x00},
|
||||
{0x3a, 0x00},
|
||||
{0x2a, 0x5f},
|
||||
{0x2c, 0x10},
|
||||
{0xff, 0xff}
|
||||
};
|
||||
|
||||
static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
|
||||
.other = NULL,
|
||||
.entries = {
|
||||
{ .sid = 0xe, .table = elanspi_calibration_table_page1_id14 },
|
||||
{ .sid = 0x0, .table = NULL }
|
||||
}
|
||||
static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14_x571[] = {
|
||||
{0x00, 0xfb},
|
||||
{0x01, 0xff},
|
||||
{0x02, 0x7f},
|
||||
{0x03, 0xd4},
|
||||
{0x04, 0x7d},
|
||||
{0x05, 0x19},
|
||||
{0x06, 0x80},
|
||||
{0x07, 0x40},
|
||||
{0x08, 0x11},
|
||||
{0x09, 0x00},
|
||||
{0x0a, 0x00},
|
||||
{0x0b, 0x00},
|
||||
{0x0c, 0x00},
|
||||
{0x0d, 0x00},
|
||||
{0x0e, 0x32},
|
||||
{0x0f, 0x00},
|
||||
{0x10, 0x00},
|
||||
{0x11, 0x32},
|
||||
{0x12, 0x02},
|
||||
{0x13, 0x08},
|
||||
{0x14, 0x5c},
|
||||
{0x15, 0x01},
|
||||
{0x16, 0x15},
|
||||
{0x17, 0x01},
|
||||
{0x18, 0x14},
|
||||
{0x19, 0x01},
|
||||
{0x1a, 0x14},
|
||||
{0x1b, 0x01},
|
||||
{0x1c, 0x16},
|
||||
{0x1d, 0x01},
|
||||
{0x1e, 0x0b},
|
||||
{0x1f, 0x01},
|
||||
{0x20, 0x0b},
|
||||
{0x21, 0x02},
|
||||
{0x22, 0x08},
|
||||
{0x23, 0x29},
|
||||
{0x24, 0x00},
|
||||
{0x25, 0x0c},
|
||||
{0x26, 0x1b},
|
||||
{0x27, 0x15},
|
||||
{0x28, 0x1b},
|
||||
{0x29, 0x15},
|
||||
{0x2a, 0x00},
|
||||
{0x2b, 0x00},
|
||||
{0x2c, 0x01},
|
||||
{0x2d, 0x16},
|
||||
{0x2e, 0x01},
|
||||
{0x2f, 0x16},
|
||||
{0x30, 0x04},
|
||||
{0x31, 0x44},
|
||||
{0x32, 0x04},
|
||||
{0x33, 0x44},
|
||||
{0x34, 0x14},
|
||||
{0x35, 0x00},
|
||||
{0x36, 0x00},
|
||||
{0x37, 0x00},
|
||||
{0x38, 0x00},
|
||||
{0x39, 0x03},
|
||||
{0x3a, 0xfe},
|
||||
{0x3b, 0x00},
|
||||
{0x3c, 0x00},
|
||||
{0x3d, 0x02},
|
||||
{0x3e, 0x00},
|
||||
{0x3f, 0x00}
|
||||
};
|
||||
|
||||
#define ELANSPI_NO_ROTATE 0
|
||||
@@ -335,10 +449,33 @@ static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
|
||||
|
||||
#define ELANSPI_HV_FLIPPED 1
|
||||
|
||||
#define ELANSPI_ROTATE_MASK 3
|
||||
|
||||
#define ELANSPI_QUIRK_X571 (1 << 2)
|
||||
|
||||
#define ELANSPI_QUIRK_MASK (ELANSPI_QUIRK_X571)
|
||||
|
||||
#define ELANSPI_UDEV_TYPES FPI_DEVICE_UDEV_SUBTYPE_SPIDEV | FPI_DEVICE_UDEV_SUBTYPE_HIDRAW
|
||||
#define ELANSPI_TP_VID 0x04f3
|
||||
|
||||
// using checkargs ACPI:HIDPID
|
||||
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = {
|
||||
.other = NULL,
|
||||
.entries = {
|
||||
{ .sid = 0xe, .quirk = 0, .table = elanspi_calibration_table_page0_id14 },
|
||||
{ .sid = 0xe, .quirk = ELANSPI_QUIRK_X571, .table = elanspi_calibration_table_page0_id14_x571 },
|
||||
{ .sid = 0x0, .table = NULL }
|
||||
}
|
||||
};
|
||||
|
||||
static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
|
||||
.other = NULL,
|
||||
.entries = {
|
||||
{ .sid = 0xe, .quirk = 0, .table = elanspi_calibration_table_page1_id14 },
|
||||
{ .sid = 0xe, .quirk = ELANSPI_QUIRK_X571, .table = elanspi_calibration_table_page1_id14_x571 },
|
||||
{ .sid = 0x0, .table = NULL }
|
||||
}
|
||||
};
|
||||
|
||||
static const FpIdEntry elanspi_id_table[] = {
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
|
||||
@@ -348,6 +485,7 @@ static const FpIdEntry elanspi_id_table[] = {
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
|
||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3104}, .driver_data = ELANSPI_QUIRK_X571 | ELANSPI_90RIGHT_ROTATE},
|
||||
{.udev_types = 0}
|
||||
};
|
||||
|
||||
@@ -357,6 +495,7 @@ static const FpIdEntry elanspi_id_table[] = {
|
||||
#define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000
|
||||
|
||||
#define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000
|
||||
#define ELANSPI_HV_X571_CALIBRATION_TARGET_MEAN 7000
|
||||
|
||||
#define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6
|
||||
#define ELANSPI_MAX_REAL_INVALID_PERCENT 3
|
||||
|
||||
Reference in New Issue
Block a user