diff options
author | Matthew Mirvish <matthew@mm12.xyz> | 2022-05-03 21:02:26 -0400 |
---|---|---|
committer | Matthew Mirvish <matthew@mm12.xyz> | 2022-05-03 21:02:26 -0400 |
commit | 46591d7bfa46c463a2c108b8bb8ef535f116b70e (patch) | |
tree | 6efcde9998ebb2d9652dbcbf0026d1b859bd7179 | |
parent | eda8d13927564bd1bd324fb9aedb9011df5193e3 (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.c | 60 | ||||
-rw-r--r-- | libfprint/drivers/elanspi.h | 175 |
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 |