summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Mirvish <matthew@mm12.xyz>2022-05-03 21:02:26 -0400
committerMatthew Mirvish <matthew@mm12.xyz>2022-05-03 21:02:26 -0400
commit46591d7bfa46c463a2c108b8bb8ef535f116b70e (patch)
tree6efcde9998ebb2d9652dbcbf0026d1b859bd7179
parenteda8d13927564bd1bd324fb9aedb9011df5193e3 (diff)
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.
-rw-r--r--libfprint/drivers/elanspi.c60
-rw-r--r--libfprint/drivers/elanspi.h175
2 files changed, 199 insertions, 36 deletions
diff --git a/libfprint/drivers/elanspi.c b/libfprint/drivers/elanspi.c
index 9338013..0280eb0 100644
--- a/libfprint/drivers/elanspi.c
+++ b/libfprint/drivers/elanspi.c
@@ -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;
diff --git a/libfprint/drivers/elanspi.h b/libfprint/drivers/elanspi.h
index ffe3416..f4f90cc 100644
--- a/libfprint/drivers/elanspi.h
+++ b/libfprint/drivers/elanspi.h
@@ -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