diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index e9dad43e..2c4e3be4 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -41,14 +41,6 @@ #include "drivers_api.h" #include "elan.h" -#define dbg_buf(buf, len) \ - if (len == 1) \ - fp_dbg("%02x", buf[0]); \ - else if (len == 2) \ - fp_dbg("%04x", buf[0] << 8 | buf[1]); \ - else if (len > 2) \ - fp_dbg("%04x... (%d bytes)", buf[0] << 8 | buf[1], len) - unsigned char elan_get_pixel(struct fpi_frame_asmbl_ctx *ctx, struct fpi_frame *frame, unsigned int x, unsigned int y) @@ -63,7 +55,9 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = { .get_pixel = elan_get_pixel, }; -struct elan_dev { +struct _FpiDeviceElan { + FpImageDevice parent; + /* device config */ unsigned short dev_type; unsigned short fw_ver; @@ -73,12 +67,12 @@ struct elan_dev { /* commands */ const struct elan_cmd *cmd; int cmd_timeout; - fpi_usb_transfer *cur_transfer; /* end commands */ /* state */ - enum fp_imgdev_state dev_state; - enum fp_imgdev_state dev_state_next; + gboolean deactivating; + FpImageDeviceState dev_state; + FpImageDeviceState dev_state_next; unsigned char *last_read; unsigned char calib_atts_left; unsigned char calib_status; @@ -90,18 +84,19 @@ struct elan_dev { GSList *frames; /* end state */ }; +G_DECLARE_FINAL_TYPE(FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN, + FpImageDevice); +G_DEFINE_TYPE(FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE); int cmp_short(const void *a, const void *b) { return (int)(*(short *)a - *(short *)b); } -static void elan_dev_reset(struct elan_dev *elandev) +static void elan_dev_reset_state(FpiDeviceElan *elandev) { G_DEBUG_HERE(); - BUG_ON(elandev->cur_transfer); - elandev->cmd = NULL; elandev->cmd_timeout = ELAN_CMD_TIMEOUT; @@ -115,7 +110,7 @@ static void elan_dev_reset(struct elan_dev *elandev) elandev->num_frames = 0; } -static void elan_save_frame(struct elan_dev *elandev, unsigned short *frame) +static void elan_save_frame(FpiDeviceElan *self, unsigned short *frame) { G_DEBUG_HERE(); @@ -133,25 +128,25 @@ static void elan_save_frame(struct elan_dev *elandev, unsigned short *frame) * we also discard stripes of 'frame_margin' from bottom and top because * assembling works bad for tall frames */ - unsigned char frame_width = elandev->frame_width; - unsigned char frame_height = elandev->frame_height; - unsigned char raw_height = elandev->raw_frame_height; - unsigned char frame_margin = (raw_height - elandev->frame_height) / 2; + unsigned char frame_width = self->frame_width; + unsigned char frame_height = self->frame_height; + unsigned char raw_height = self->raw_frame_height; + unsigned char frame_margin = (raw_height - self->frame_height) / 2; int frame_idx, raw_idx; for (int y = 0; y < frame_height; y++) for (int x = 0; x < frame_width; x++) { - if (elandev->dev_type & ELAN_NOT_ROTATED) + if (self->dev_type & ELAN_NOT_ROTATED) raw_idx = x + (y + frame_margin) * frame_width; else raw_idx = frame_margin + y + x * raw_height; frame_idx = x + y * frame_width; frame[frame_idx] = - ((unsigned short *)elandev->last_read)[raw_idx]; + ((unsigned short *) self->last_read)[raw_idx]; } } -static void elan_save_background(struct elan_dev *elandev) +static void elan_save_background(FpiDeviceElan *elandev) { G_DEBUG_HERE(); @@ -197,7 +192,7 @@ static void elan_save_background(struct elan_dev *elandev) * \ * ======== 0 \___> ======== 0 */ -static int elan_save_img_frame(struct elan_dev *elandev) +static int elan_save_img_frame(FpiDeviceElan *elandev) { G_DEBUG_HERE(); @@ -290,157 +285,145 @@ static void elan_process_frame_thirds(unsigned short *raw_frame, *frames = g_slist_prepend(*frames, frame); } -static void elan_submit_image(struct fp_img_dev *dev) +static void elan_submit_image(FpImageDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); int num_frames; GSList *raw_frames; GSList *frames = NULL; - struct fp_img *img; + FpImage *img; G_DEBUG_HERE(); - num_frames = elandev->num_frames - ELAN_SKIP_LAST_FRAMES; - raw_frames = g_slist_nth(elandev->frames, ELAN_SKIP_LAST_FRAMES); + num_frames = self->num_frames - ELAN_SKIP_LAST_FRAMES; + raw_frames = g_slist_nth(self->frames, ELAN_SKIP_LAST_FRAMES); - assembling_ctx.frame_width = elandev->frame_width; - assembling_ctx.frame_height = elandev->frame_height; - assembling_ctx.image_width = elandev->frame_width * 3 / 2; - g_slist_foreach(raw_frames, (GFunc) elandev->process_frame, &frames); + assembling_ctx.frame_width = self->frame_width; + assembling_ctx.frame_height = self->frame_height; + assembling_ctx.image_width = self->frame_width * 3 / 2; + g_slist_foreach(raw_frames, (GFunc) self->process_frame, &frames); fpi_do_movement_estimation(&assembling_ctx, frames, num_frames); img = fpi_assemble_frames(&assembling_ctx, frames, num_frames); - img->flags |= FP_IMG_PARTIAL; - fpi_imgdev_image_captured(dev, img); + fpi_image_device_image_captured(dev, img); } -static void elan_cmd_done(fpi_ssm *ssm) +static void elan_cmd_done(FpiSsm *ssm) { G_DEBUG_HERE(); fpi_ssm_next_state(ssm); } -static void elan_cmd_cb(struct libusb_transfer *transfer, - struct fp_dev *_dev, - fpi_ssm *ssm, - void *user_data) +static void elan_cmd_cb(FpiUsbTransfer *transfer, FpDevice *dev, + gpointer user_data, GError *error) { - struct fp_img_dev *dev; - struct elan_dev *elandev; + FpiSsm *ssm = transfer->ssm; + FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); G_DEBUG_HERE(); - if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - fp_dbg("transfer cancelled"); + if (error) { + /* XXX: In the cancellation case we used to not + * mark the SSM as failed?! */ + fpi_ssm_mark_failed (transfer->ssm, error); return; } - dev = FP_IMG_DEV(_dev); - elandev = FP_INSTANCE_DATA(_dev); - elandev->cur_transfer = NULL; - - switch (transfer->status) { - case LIBUSB_TRANSFER_COMPLETED: - if (transfer->length != transfer->actual_length) { - fp_dbg("transfer length error: expected %d, got %d", - transfer->length, transfer->actual_length); - elan_dev_reset(elandev); - fpi_ssm_mark_failed(ssm, -EPROTO); - } else if (transfer->endpoint & LIBUSB_ENDPOINT_IN) { - /* just finished receiving */ - elandev->last_read = g_memdup(transfer->buffer, transfer->actual_length); - dbg_buf(transfer->buffer, transfer->actual_length); - elan_cmd_done(ssm); - } else { - /* just finished sending */ - G_DEBUG_HERE(); - elan_cmd_read(ssm, dev); - } - break; - case LIBUSB_TRANSFER_TIMED_OUT: - fp_dbg("transfer timed out"); - fpi_ssm_mark_failed(ssm, -ETIMEDOUT); - break; - default: - fp_dbg("transfer failed: %d", transfer->status); - elan_dev_reset(elandev); - fpi_ssm_mark_failed(ssm, -EIO); + /* XXX: We used to reset the device in error cases! */ + if (transfer->endpoint & FPI_USB_ENDPOINT_IN) { + /* just finished receiving */ + self->last_read = g_memdup(transfer->buffer, transfer->actual_length); + elan_cmd_done(ssm); + } else { + /* just finished sending */ + G_DEBUG_HERE(); + elan_cmd_read(ssm, dev); } } -static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev) +static void elan_cmd_read(FpiSsm *ssm, FpDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - int response_len = elandev->cmd->response_len; - unsigned char *buffer; + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); + FpiUsbTransfer *transfer; + GCancellable *cancellable = NULL; + int response_len = self->cmd->response_len; G_DEBUG_HERE(); - if (elandev->cmd->response_len == ELAN_CMD_SKIP_READ) { + if (self->cmd->response_len == ELAN_CMD_SKIP_READ) { fp_dbg("skipping read, not expecting anything"); elan_cmd_done(ssm); return; } - if (elandev->dev_type == ELAN_0C42) { + if (self->dev_type == ELAN_0C42) { /* ELAN_0C42 sends an extra byte in one byte responses */ - if (elandev->cmd->response_len == 1) + if (self->cmd->response_len == 1) response_len = 2; } - if (elandev->cmd->cmd == get_image_cmd.cmd) + if (self->cmd->cmd == get_image_cmd.cmd) /* raw data has 2-byte "pixels" and the frame is vertical */ response_len = - elandev->raw_frame_height * elandev->frame_width * 2; + self->raw_frame_height * self->frame_width * 2; - g_clear_pointer(&elandev->last_read, g_free); - buffer = g_malloc(response_len); + g_clear_pointer(&self->last_read, g_free); - elandev->cur_transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - ssm, - elandev->cmd->response_in, - buffer, - response_len, - elan_cmd_cb, - NULL, - elandev->cmd_timeout); - int r = fpi_usb_submit_transfer(elandev->cur_transfer); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + + fpi_usb_transfer_fill_bulk (transfer, + self->cmd->response_in, + response_len); + + if (!self->cmd->never_cancel) + cancellable = fpi_device_get_cancellable (dev); + + fpi_usb_transfer_submit (transfer, self->cmd_timeout, cancellable, elan_cmd_cb, NULL); + fpi_usb_transfer_unref (transfer); } static void -elan_run_cmd(fpi_ssm *ssm, - struct fp_img_dev *dev, +elan_run_cmd(FpiSsm *ssm, + FpDevice *dev, const struct elan_cmd *cmd, int cmd_timeout) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); + FpiUsbTransfer *transfer; + GCancellable *cancellable = NULL; - dbg_buf(cmd->cmd, 2); - - elandev->cmd = cmd; + self->cmd = cmd; if (cmd_timeout != -1) - elandev->cmd_timeout = cmd_timeout; + self->cmd_timeout = cmd_timeout; - if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & elandev->dev_type)) { + if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & self->dev_type)) { fp_dbg("skipping command 0x%x 0x%x for this device (for devices 0x%x but device is 0x%x)", - cmd->cmd[0], cmd->cmd[1], cmd->devices, elandev->dev_type); + cmd->cmd[0], cmd->cmd[1], cmd->devices, self->dev_type); elan_cmd_done(ssm); return; } - elandev->cur_transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), - ssm, - ELAN_EP_CMD_OUT, - g_memdup((char *) cmd->cmd, ELAN_CMD_LEN), - ELAN_CMD_LEN, - elan_cmd_cb, - NULL, - elandev->cmd_timeout); - int r = fpi_usb_submit_transfer(elandev->cur_transfer); - if (r < 0) - fpi_ssm_mark_failed(ssm, r); + transfer = fpi_usb_transfer_new (dev); + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + + fpi_usb_transfer_fill_bulk_full (transfer, + ELAN_EP_CMD_OUT, + (guint8*) cmd->cmd, + ELAN_CMD_LEN, + NULL); + + if (!self->cmd->never_cancel) + cancellable = fpi_device_get_cancellable (dev); + + fpi_usb_transfer_submit (transfer, + self->cmd_timeout, + cancellable, + elan_cmd_cb, + NULL); + fpi_usb_transfer_unref (transfer); } enum stop_capture_states { @@ -448,53 +431,57 @@ enum stop_capture_states { STOP_CAPTURE_NUM_STATES, }; -static void stop_capture_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) +static void stop_capture_run_state(FpiSsm *ssm, FpDevice *dev, + void *user_data) { G_DEBUG_HERE(); switch (fpi_ssm_get_cur_state(ssm)) { case STOP_CAPTURE: - elan_run_cmd(ssm, FP_IMG_DEV(dev), &stop_cmd, ELAN_CMD_TIMEOUT); + elan_run_cmd(ssm, dev, &stop_cmd, + ELAN_CMD_TIMEOUT); break; } } -static void stop_capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void stop_capture_complete(FpiSsm *ssm, FpDevice *_dev, + void *user_data, GError *error) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); - int error = fpi_ssm_get_error(ssm); + FpImageDevice *dev = user_data; + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); fpi_ssm_free(ssm); + /* The device is inactive at this point. */ + self->dev_state = FP_IMAGE_DEVICE_STATE_INACTIVE; + + if (self->deactivating) { + /* Simply complete the pending deactivation. */ + self->deactivating = FALSE; + fpi_image_device_deactivate_complete (dev, error); + return; + } + if (!error) { - fpi_imgdev_report_finger_status(dev, FALSE); - - /* If verify or identify fails because of short swipe, we need to restart - * capture manually. It feels like libfprint or the application should know - * better if they want to retry, but they don't. Unless we've been asked to - * deactivate, try to re-enter the capture loop. Since state change is - * async, there's still a chance to be deactivated by another pending - * event. */ - if (elandev->dev_state_next != IMGDEV_STATE_INACTIVE) - dev_change_state(dev, IMGDEV_STATE_AWAIT_FINGER_ON); - - } else if (error != -ECANCELED) - fpi_imgdev_abort_scan(dev, error); + fpi_image_device_report_finger_status(dev, FALSE); + } else { + /* NOTE: We cannot get a cancellation error here. */ + fpi_image_device_session_error (dev, error); + } } -static void elan_stop_capture(struct fp_img_dev *dev) +static void elan_stop_capture(FpDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); - elan_dev_reset(elandev); + elan_dev_reset_state(self); - fpi_ssm *ssm = - fpi_ssm_new(FP_DEV(dev), stop_capture_run_state, + FpiSsm *ssm = + fpi_ssm_new(dev, stop_capture_run_state, STOP_CAPTURE_NUM_STATES, dev); fpi_ssm_start(ssm, stop_capture_complete); } @@ -507,10 +494,10 @@ enum capture_states { CAPTURE_NUM_STATES, }; -static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void capture_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); + FpImageDevice *idev = FP_IMAGE_DEVICE(dev); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); int r; switch (fpi_ssm_get_cur_state(ssm)) { @@ -521,22 +508,24 @@ static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data elan_run_cmd(ssm, dev, &pre_scan_cmd, -1); break; case CAPTURE_READ_DATA: + self->dev_state = FP_IMAGE_DEVICE_STATE_CAPTURE; + /* 0x55 - finger present * 0xff - device not calibrated (probably) */ - if (elandev->last_read && elandev->last_read[0] == 0x55) { - if (elandev->dev_state == IMGDEV_STATE_AWAIT_FINGER_ON) - fpi_imgdev_report_finger_status(dev, TRUE); + if (self->last_read && self->last_read[0] == 0x55) { + fpi_image_device_report_finger_status(idev, TRUE); elan_run_cmd(ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT); - } else - fpi_ssm_mark_failed(ssm, -EBADMSG); + } else { + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); + } break; case CAPTURE_CHECK_ENOUGH_FRAMES: - r = elan_save_img_frame(elandev); + r = elan_save_img_frame(self); if (r < 0) - fpi_ssm_mark_failed(ssm, r); - else if (elandev->num_frames < ELAN_MAX_FRAMES) { + fpi_ssm_mark_failed(ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); + else if (self->num_frames < ELAN_MAX_FRAMES) { /* quickly stop if finger is removed */ - elandev->cmd_timeout = ELAN_FINGER_TIMEOUT; + self->cmd_timeout = ELAN_FINGER_TIMEOUT; fpi_ssm_jump_to_state(ssm, CAPTURE_WAIT_FINGER); } else { fpi_ssm_next_state(ssm); @@ -545,54 +534,51 @@ static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data } } -static void capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void capture_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data, + GError *error) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); + FpImageDevice *dev = user_data; + FpiDeviceElan *self = FPI_DEVICE_ELAN(_dev); G_DEBUG_HERE(); - if (fpi_ssm_get_error(ssm) == -ECANCELED) { - fpi_ssm_free(ssm); - return; - } + /* XXX: cancellation was specially handled by doing nothing! */ /* either max frames captured or timed out waiting for the next frame */ - if (!fpi_ssm_get_error(ssm) - || (fpi_ssm_get_error(ssm) == -ETIMEDOUT - && fpi_ssm_get_cur_state(ssm) == CAPTURE_WAIT_FINGER)) - if (elandev->num_frames >= ELAN_MIN_FRAMES) + if (!error || + (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) && + fpi_ssm_get_cur_state(ssm) == CAPTURE_WAIT_FINGER)) { + if (self->num_frames >= ELAN_MIN_FRAMES) elan_submit_image(dev); else { fp_dbg("swipe too short: want >= %d frames, got %d", - ELAN_MIN_FRAMES, elandev->num_frames); - fpi_imgdev_abort_scan(dev, FP_VERIFY_RETRY_TOO_SHORT); + ELAN_MIN_FRAMES, self->num_frames); + fpi_image_device_retry_scan(dev, FP_DEVICE_RETRY_TOO_SHORT); } - - /* other error - * It says "...abort_scan" but reporting 1 during verification makes it - * successful! */ - else - fpi_imgdev_abort_scan(dev, fpi_ssm_get_error(ssm)); + g_clear_error (&error); + } else { + fpi_image_device_session_error (dev, error); + } fpi_ssm_free(ssm); } -static void elan_capture(struct fp_img_dev *dev) +static void elan_capture(FpDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); - elan_dev_reset(elandev); - fpi_ssm *ssm = - fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); + elan_dev_reset_state(self); + FpiSsm *ssm = + fpi_ssm_new(dev, capture_run_state, CAPTURE_NUM_STATES, + dev); fpi_ssm_start(ssm, capture_complete); } /* this function needs to have elandev->background and elandev->last_read to be * the calibration mean */ -static int elan_need_calibration(struct elan_dev *elandev) +static int elan_need_calibration(FpiDeviceElan *elandev) { G_DEBUG_HERE(); @@ -635,7 +621,7 @@ enum calibrate_states { CALIBRATE_NUM_STATES, }; -static gboolean elan_supports_calibration(struct elan_dev *elandev) +static gboolean elan_supports_calibration(FpiDeviceElan *elandev) { if (elandev->dev_type == ELAN_0C42) return TRUE; @@ -643,10 +629,9 @@ static gboolean elan_supports_calibration(struct elan_dev *elandev) return elandev->fw_ver >= ELAN_MIN_CALIBRATION_FW; } -static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void calibrate_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); @@ -655,8 +640,8 @@ static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da elan_run_cmd(ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT); break; case CALIBRATE_SAVE_BACKGROUND: - elan_save_background(elandev); - if (!elan_supports_calibration(elandev)) { + elan_save_background(self); + if (!elan_supports_calibration(self)) { fp_dbg("FW does not support calibration"); fpi_ssm_mark_completed(ssm); } else @@ -666,20 +651,22 @@ static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da elan_run_cmd(ssm, dev, &get_calib_mean_cmd, ELAN_CMD_TIMEOUT); break; case CALIBRATE_CHECK_NEEDED: - if (elan_need_calibration(elandev)) { - elandev->calib_status = 0; + if (elan_need_calibration(self)) { + self->calib_status = 0; fpi_ssm_next_state(ssm); } else fpi_ssm_mark_completed(ssm); break; case CALIBRATE_GET_STATUS: - elandev->calib_atts_left -= 1; - if (elandev->calib_atts_left) + self->calib_atts_left -= 1; + if (self->calib_atts_left) elan_run_cmd(ssm, dev, &get_calib_status_cmd, ELAN_CMD_TIMEOUT); else { fp_dbg("calibration failed"); - fpi_ssm_mark_failed(ssm, -1); + fpi_ssm_mark_failed(ssm, + fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, + "Callibration failed!")); } break; case CALIBRATE_CHECK_STATUS: @@ -689,19 +676,21 @@ static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da * changes to 0x01. It stays that way for some time and then changes back * to 0x03. Because of this we don't just expect 0x03, we want to see 0x01 * first. This is to make sure that a full calibration loop has completed */ - fp_dbg("calibration status: 0x%02x", elandev->last_read[0]); - if (elandev->calib_status == 0x01 - && elandev->last_read[0] == 0x03) { - elandev->calib_status = 0x03; + fp_dbg("calibration status: 0x%02x", self->last_read[0]); + if (self->calib_status == 0x01 + && self->last_read[0] == 0x03) { + self->calib_status = 0x03; fpi_ssm_jump_to_state(ssm, CALIBRATE_GET_BACKGROUND); } else { - fpi_timeout *timeout; + GSource *timeout; - if (elandev->calib_status == 0x00 - && elandev->last_read[0] == 0x01) - elandev->calib_status = 0x01; - timeout = fpi_timeout_add(50, fpi_ssm_next_state_timeout_cb, _dev, ssm); - fpi_timeout_set_name(timeout, "calibrate_run_state"); + if (self->calib_status == 0x00 + && self->last_read[0] == 0x01) + self->calib_status = 0x01; + timeout = fpi_device_add_timeout(dev, 50, + fpi_ssm_next_state_timeout_cb, + ssm); + g_source_set_name(timeout, "calibrate_run_state"); } break; case CALIBRATE_REPEAT_STATUS: @@ -710,29 +699,34 @@ static void calibrate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da } } -static void calibrate_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void calibrate_complete(FpiSsm *ssm, FpDevice *dev, void *user_data, + GError *error) { - struct fp_img_dev *dev = user_data; + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); - - if (fpi_ssm_get_error(ssm) != -ECANCELED) + if (error) { + self->dev_state = FP_IMAGE_DEVICE_STATE_INACTIVE; + fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error); + } else { + self->dev_state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON; elan_capture(dev); + } fpi_ssm_free(ssm); } -static void elan_calibrate(struct fp_img_dev *dev) +static void elan_calibrate(FpDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); - elan_dev_reset(elandev); - elandev->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS; + elan_dev_reset_state(self); + self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS; - fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), calibrate_run_state, + FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), calibrate_run_state, CALIBRATE_NUM_STATES, dev); fpi_ssm_start(ssm, calibrate_complete); } @@ -746,10 +740,9 @@ enum activate_states { ACTIVATE_NUM_STATES, }; -static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void activate_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data) { - struct fp_img_dev *dev = user_data; - struct elan_dev *elandev = FP_INSTANCE_DATA(_dev); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); @@ -758,9 +751,9 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat elan_run_cmd(ssm, dev, &get_fw_ver_cmd, ELAN_CMD_TIMEOUT); break; case ACTIVATE_SET_FW_VER: - elandev->fw_ver = - (elandev->last_read[0] << 8 | elandev->last_read[1]); - fp_dbg("FW ver 0x%04hx", elandev->fw_ver); + self->fw_ver = + (self->last_read[0] << 8 | self->last_read[1]); + fp_dbg("FW ver 0x%04hx", self->fw_ver); fpi_ssm_next_state(ssm); break; case ACTIVATE_GET_SENSOR_DIM: @@ -768,27 +761,27 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat break; case ACTIVATE_SET_SENSOR_DIM: /* see elan_save_frame for details */ - if (elandev->dev_type & ELAN_NOT_ROTATED) { - elandev->frame_width = elandev->last_read[0]; - elandev->frame_height = elandev->raw_frame_height = - elandev->last_read[2]; + if (self->dev_type & ELAN_NOT_ROTATED) { + self->frame_width = self->last_read[0]; + self->frame_height = self->raw_frame_height = + self->last_read[2]; } else { - elandev->frame_width = elandev->last_read[2]; - elandev->frame_height = elandev->raw_frame_height = - elandev->last_read[0]; + self->frame_width = self->last_read[2]; + self->frame_height = self->raw_frame_height = + self->last_read[0]; } /* Work-around sensors returning the sizes as zero-based index * rather than the number of pixels. */ - if ((elandev->frame_width % 2 == 1) && - (elandev->frame_height % 2 == 1)) { - elandev->frame_width++; - elandev->frame_height++; - elandev->raw_frame_height = elandev->frame_height; + if ((self->frame_width % 2 == 1) && + (self->frame_height % 2 == 1)) { + self->frame_width++; + self->frame_height++; + self->raw_frame_height = self->frame_height; } - if (elandev->frame_height > ELAN_MAX_FRAME_HEIGHT) - elandev->frame_height = ELAN_MAX_FRAME_HEIGHT; - fp_dbg("sensor dimensions, WxH: %dx%d", elandev->frame_width, - elandev->raw_frame_height); + if (self->frame_height > ELAN_MAX_FRAME_HEIGHT) + self->frame_height = ELAN_MAX_FRAME_HEIGHT; + fp_dbg("sensor dimensions, WxH: %dx%d", self->frame_width, + self->raw_frame_height); fpi_ssm_next_state(ssm); break; case ACTIVATE_CMD_1: @@ -798,191 +791,195 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat } } -static void activate_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) +static void activate_complete(FpiSsm *ssm, FpDevice *dev, void *user_data, + GError *error) { - struct fp_img_dev *dev = user_data; + FpImageDevice *idev = FP_IMAGE_DEVICE (dev); G_DEBUG_HERE(); - if (fpi_ssm_get_error(ssm) != -ECANCELED) { - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); - } + fpi_image_device_activate_complete (idev, error); fpi_ssm_free(ssm); } -static void elan_activate(struct fp_img_dev *dev) +static void elan_activate(FpImageDevice *dev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); - elan_dev_reset(elandev); + elan_dev_reset_state(self); - fpi_ssm *ssm = - fpi_ssm_new(FP_DEV(dev), activate_run_state, ACTIVATE_NUM_STATES, dev); + FpiSsm *ssm = + fpi_ssm_new(FP_DEVICE(dev), activate_run_state, + ACTIVATE_NUM_STATES, dev); fpi_ssm_start(ssm, activate_complete); } -static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) +static void dev_init(FpImageDevice *dev) { - struct elan_dev *elandev; - int r; + GError *error = NULL; + FpiDeviceElan *self; G_DEBUG_HERE(); - r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - if (r < 0) { - fp_err("could not claim interface 0: %s", libusb_error_name(r)); - return r; + if (!g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error)) { + fpi_image_device_open_complete(dev, error); + return; } - elandev = g_malloc0(sizeof(struct elan_dev)); - fp_dev_set_instance_data(FP_DEV(dev), elandev); + self = FPI_DEVICE_ELAN(dev); /* common params */ - elandev->dev_type = driver_data; - elandev->background = NULL; - elandev->process_frame = elan_process_frame_thirds; + self->dev_type = fpi_device_get_driver_data (FP_DEVICE (dev)); + self->background = NULL; + self->process_frame = elan_process_frame_thirds; - switch (driver_data) { + switch (self->dev_type) { case ELAN_0907: - elandev->process_frame = elan_process_frame_linear; + self->process_frame = elan_process_frame_linear; break; } - fpi_imgdev_open_complete(dev, 0); - return 0; + fpi_image_device_open_complete(dev, NULL); } -static void elan_deactivate(struct fp_img_dev *dev) +static void dev_deinit(FpImageDevice *dev) { - G_DEBUG_HERE(); - - fpi_imgdev_deactivate_complete(dev); -} - -static void dev_deinit(struct fp_img_dev *dev) -{ - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); + GError *error = NULL; + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); - elan_dev_reset(elandev); - g_free(elandev->background); - g_free(elandev); - libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); - fpi_imgdev_close_complete(dev); + elan_dev_reset_state(self); + g_free(self->background); + g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), + 0, 0, &error); + fpi_image_device_close_complete(dev, error); } -static int dev_activate(struct fp_img_dev *dev) +static void dev_activate(FpImageDevice *dev) { G_DEBUG_HERE(); elan_activate(dev); - return 0; } -static void elan_change_state(struct fp_img_dev *dev) +static void elan_change_state(FpImageDevice *idev) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - enum fp_imgdev_state next_state = elandev->dev_state_next; + FpDevice *dev = FP_DEVICE(idev); + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); + FpImageDeviceState next_state = self->dev_state_next; - if (elandev->dev_state == next_state) { + if (self->dev_state == next_state) { fp_dbg("already in %d", next_state); return; - } else + } else { fp_dbg("changing to %d", next_state); + } switch (next_state) { - case IMGDEV_STATE_INACTIVE: - if (elandev->cur_transfer) - /* deactivation will complete in transfer callback */ - fpi_usb_cancel_transfer(elandev->cur_transfer); - else - elan_deactivate(dev); break; - case IMGDEV_STATE_AWAIT_FINGER_ON: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: /* activation completed or another enroll stage started */ elan_calibrate(dev); break; - case IMGDEV_STATE_CAPTURE: + case FP_IMAGE_DEVICE_STATE_CAPTURE: /* not used */ break; - case IMGDEV_STATE_AWAIT_FINGER_OFF: - elan_stop_capture(dev); + case FP_IMAGE_DEVICE_STATE_INACTIVE: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: + if (self->dev_state != FP_IMAGE_DEVICE_STATE_INACTIVE || + self->dev_state != FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF) + elan_stop_capture(dev); } - - elandev->dev_state = next_state; } static void -elan_change_state_async(struct fp_dev *dev, +elan_change_state_async(FpDevice *dev, void *data) { g_message ("state change dev: %p", dev); - elan_change_state(FP_IMG_DEV (dev)); + elan_change_state(FP_IMAGE_DEVICE(dev)); } -static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state) +static void dev_change_state(FpImageDevice *dev, FpImageDeviceState state) { - struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev)); - fpi_timeout *timeout; + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); + GSource *timeout; G_DEBUG_HERE(); + /* Inactive and await finger off are equivalent for the elan driver. */ + if (state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF) + state = FP_IMAGE_DEVICE_STATE_INACTIVE; + + if (self->dev_state_next == state) { + fp_dbg ("change to state %d already queued", state); + } + switch (state) { - case IMGDEV_STATE_INACTIVE: - case IMGDEV_STATE_AWAIT_FINGER_ON: - case IMGDEV_STATE_AWAIT_FINGER_OFF: { + case FP_IMAGE_DEVICE_STATE_INACTIVE: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: + case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: { char *name; /* schedule state change instead of calling it directly to allow all actions * related to the previous state to complete */ - elandev->dev_state_next = state; - timeout = fpi_timeout_add(10, elan_change_state_async, FP_DEV(dev), NULL); + self->dev_state_next = state; + timeout = fpi_device_add_timeout(FP_DEVICE(dev), 10, + elan_change_state_async, + NULL); name = g_strdup_printf ("dev_change_state to %d", state); - fpi_timeout_set_name(timeout, name); + g_source_set_name(timeout, name); g_free (name); break; } - case IMGDEV_STATE_CAPTURE: + case FP_IMAGE_DEVICE_STATE_CAPTURE: /* TODO MAYBE: split capture ssm into smaller ssms and use this state */ - elandev->dev_state = state; - elandev->dev_state_next = state; + self->dev_state = state; + self->dev_state_next = state; break; default: - fp_err("unrecognized state %d", state); - fpi_imgdev_session_error(dev, -EINVAL); - return -EINVAL; + g_assert_not_reached(); } - - /* as of time of writing libfprint never checks the return value */ - return 0; } -static void dev_deactivate(struct fp_img_dev *dev) +static void dev_deactivate(FpImageDevice *dev) { + FpiDeviceElan *self = FPI_DEVICE_ELAN(dev); G_DEBUG_HERE(); - dev_change_state(dev, IMGDEV_STATE_INACTIVE); + if (self->dev_state == FP_IMAGE_DEVICE_STATE_INACTIVE) { + /* The device is inactive already, complete the operation immediately. */ + fpi_image_device_deactivate_complete (dev, NULL); + } else { + /* The device is not yet inactive, flag that we are deactivating (and + * need to signal back deactivation) and then ensure we will change + * to the inactive state eventually. */ + self->deactivating = TRUE; + dev_change_state (dev, FP_IMAGE_DEVICE_STATE_INACTIVE); + } } -struct fp_img_driver elan_driver = { - .driver = { - .id = ELAN_ID, - .name = FP_COMPONENT, - .full_name = "ElanTech Fingerprint Sensor", - .id_table = elan_id_table, - .scan_type = FP_SCAN_TYPE_SWIPE, - }, - .flags = 0, +static void fpi_device_elan_init(FpiDeviceElan *self) { +} +static void fpi_device_elan_class_init(FpiDeviceElanClass *klass) { + FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); + FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass); - .bz3_threshold = 24, + dev_class->id = "elan"; + dev_class->full_name = "ElanTech Fingerprint Sensor"; + dev_class->type = FP_DEVICE_TYPE_USB; + dev_class->id_table = elan_id_table; + dev_class->scan_type = FP_SCAN_TYPE_SWIPE; - .open = dev_init, - .close = dev_deinit, - .activate = dev_activate, - .deactivate = dev_deactivate, - .change_state = dev_change_state, -}; + img_class->img_open = dev_init; + img_class->img_close = dev_deinit; + img_class->activate = dev_activate; + img_class->deactivate = dev_deactivate; + img_class->change_state = dev_change_state; + + img_class->bz3_threshold = 24; +} diff --git a/libfprint/drivers/elan.h b/libfprint/drivers/elan.h index c5f0f191..059f00ac 100644 --- a/libfprint/drivers/elan.h +++ b/libfprint/drivers/elan.h @@ -21,7 +21,7 @@ #ifndef __ELAN_H #define __ELAN_H -#include +#include #define ELAN_VEND_ID 0x04f3 @@ -59,9 +59,9 @@ #define ELAN_SKIP_LAST_FRAMES 2 #define ELAN_CMD_LEN 0x2 -#define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT) -#define ELAN_EP_CMD_IN (0x3 | LIBUSB_ENDPOINT_IN) -#define ELAN_EP_IMG_IN (0x2 | LIBUSB_ENDPOINT_IN) +#define ELAN_EP_CMD_OUT (0x1 | FPI_USB_ENDPOINT_OUT) +#define ELAN_EP_CMD_IN (0x3 | FPI_USB_ENDPOINT_IN) +#define ELAN_EP_IMG_IN (0x2 | FPI_USB_ENDPOINT_IN) /* used as response length to tell the driver to skip reading response */ #define ELAN_CMD_SKIP_READ 0 @@ -76,6 +76,7 @@ struct elan_cmd { int response_len; int response_in; unsigned short devices; + gboolean never_cancel; }; static const struct elan_cmd get_sensor_dim_cmd = { @@ -152,73 +153,73 @@ static const struct elan_cmd stop_cmd = { .response_len = ELAN_CMD_SKIP_READ, .response_in = ELAN_EP_CMD_IN, .devices = ELAN_ALL_DEV, + .never_cancel = TRUE, }; -static const struct usb_id elan_id_table[] = { - {.vendor = ELAN_VEND_ID,.product = 0x0903,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0907,.driver_data = ELAN_0907}, - {.vendor = ELAN_VEND_ID,.product = 0x0c01,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c02,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c03,.driver_data = ELAN_0C03}, - {.vendor = ELAN_VEND_ID,.product = 0x0c04,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c05,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c06,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c07,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c08,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c09,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0a,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0b,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0c,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0d,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0e,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c0f,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c10,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c11,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c12,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c13,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c14,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c15,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c16,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c17,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c18,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c19,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1a,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1b,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1c,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1d,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1e,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c1f,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c20,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c21,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c22,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c23,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c24,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c25,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c26,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c27,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c28,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c29,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2a,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2b,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2c,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2d,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2e,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c2f,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c30,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c31,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c32,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c33,.driver_data = ELAN_ALL_DEV}, - {.vendor = ELAN_VEND_ID,.product = 0x0c42,.driver_data = ELAN_0C42}, - {0, 0, 0,}, +static const FpIdEntry elan_id_table [ ] = { + {.vid = ELAN_VEND_ID, .pid = 0x0903, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0907, .driver_data = ELAN_0907}, + {.vid = ELAN_VEND_ID, .pid = 0x0c01, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c02, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c03, .driver_data = ELAN_0C03}, + {.vid = ELAN_VEND_ID, .pid = 0x0c04, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c05, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c06, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c07, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c08, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c09, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0a, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0b, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0c, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0d, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0e, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c0f, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c10, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c11, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c12, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c13, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c14, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c15, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c16, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c17, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c18, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c19, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1a, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1b, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1c, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1d, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1e, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c1f, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c20, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c21, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c22, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c23, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c24, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c25, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c26, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c27, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c28, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c29, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2a, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2b, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2c, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2d, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2e, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c2f, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c30, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c31, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV}, + {.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42}, + {.vid = 0, .pid = 0, .driver_data = 0}, }; -static void elan_cmd_done(fpi_ssm *ssm); -static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev); +static void elan_cmd_done(FpiSsm *ssm); +static void elan_cmd_read(FpiSsm *ssm, FpDevice *dev); -static void elan_calibrate(struct fp_img_dev *dev); -static void elan_capture(struct fp_img_dev *dev); -static void elan_deactivate(struct fp_img_dev *dev); +static void elan_calibrate(FpDevice *dev); +static void elan_capture(FpDevice *dev); -static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state); +static void dev_change_state(FpImageDevice *dev, FpImageDeviceState state); #endif diff --git a/meson.build b/meson.build index 5552e200..899d8068 100644 --- a/meson.build +++ b/meson.build @@ -51,7 +51,7 @@ mathlib_dep = cc.find_library('m', required: false) drivers = get_option('drivers').split(',') virtual_drivers = [ 'virtual_image' ] #default_drivers = [ 'upekts', 'upektc', 'upeksonly', 'vcom5s', 'uru4000', 'aes1610', 'aes1660', 'aes2501', 'aes2550', 'aes2660', 'aes3500', 'aes4000', 'vfs101', 'vfs301', 'vfs5011', 'upektc_img', 'etes603', 'vfs0050', 'elan' ] -default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301', 'vfs0050', 'etes603', 'vcom5s', 'synaptics'] +default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301', 'vfs0050', 'etes603', 'vcom5s', 'synaptics', 'elan'] all_drivers = default_drivers + virtual_drivers