/* Exec loop sequential state machine */ static void m_loop_state(struct fpi_ssm *ssm) { struct fp_img_dev *dev = ssm->priv; vfs301_dev_t *vdev = dev->priv; switch (ssm->cur_state) { case M_REQUEST_PRINT: vfs301_proto_request_fingerprint(dev->udev, vdev); fpi_ssm_next_state(ssm); break; case M_WAIT_PRINT: /* Wait fingerprint scanning */ async_sleep(200, ssm); break; case M_CHECK_PRINT: if (!vfs301_proto_peek_event(dev->udev, vdev)) fpi_ssm_jump_to_state(ssm, M_WAIT_PRINT); else fpi_ssm_next_state(ssm); break; case M_READ_PRINT_START: fpi_imgdev_report_finger_status(dev, TRUE); vfs301_proto_process_event_start(dev->udev, vdev); fpi_ssm_next_state(ssm); break; case M_READ_PRINT_WAIT: /* Wait fingerprint scanning */ async_sleep(200, ssm); break; case M_READ_PRINT_POLL: { int rv = vfs301_proto_process_event_poll(dev->udev, vdev); assert(rv != VFS301_FAILURE); if (rv == VFS301_ONGOING) fpi_ssm_jump_to_state(ssm, M_READ_PRINT_WAIT); else fpi_ssm_next_state(ssm); } break; case M_SUBMIT_PRINT: if (submit_image(ssm)) { fpi_ssm_mark_completed(ssm); /* NOTE: finger off is expected only after submitting image... */ fpi_imgdev_report_finger_status(dev, FALSE); } else { fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT); } break; } }
static void capture_read_data_cb(struct libusb_transfer *transfer) { struct fpi_ssm *ssm = transfer->user_data; struct fp_img_dev *dev = ssm->priv; unsigned char *data = transfer->buffer; struct fp_img *img; if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { fp_dbg("request is not completed, %d", transfer->status); fpi_ssm_mark_aborted(ssm, -EIO); goto out; } else if (transfer->length != transfer->actual_length) { fp_dbg("expected %d, sent %d bytes", transfer->length, transfer->actual_length); fpi_ssm_mark_aborted(ssm, -EPROTO); goto out; } img = fpi_img_new(IMAGE_SIZE); memcpy(img->data, data, IMAGE_SIZE); fpi_imgdev_image_captured(dev, img); fpi_imgdev_report_finger_status(dev, FALSE); fpi_ssm_mark_completed(ssm); out: g_free(transfer->buffer); libusb_free_transfer(transfer); }
static void finger_det_data_cb(struct libusb_transfer *transfer) { struct fp_img_dev *dev = transfer->user_data; struct upektc_dev *upekdev = dev->priv; unsigned char *data = transfer->buffer; if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { fp_dbg("data transfer status %d\n", transfer->status); fpi_imgdev_session_error(dev, -EIO); goto out; } else if (transfer->length != transfer->actual_length) { fp_dbg("expected %d, got %d bytes", transfer->length, transfer->actual_length); fpi_imgdev_session_error(dev, -EPROTO); } if (finger_present(data, IMAGE_SIZE, upekdev->sum_threshold)) { /* finger present, start capturing */ fpi_imgdev_report_finger_status(dev, TRUE); start_capture(dev); } else { /* no finger, poll for a new histogram */ start_finger_detection(dev); } out: g_free(data); libusb_free_transfer(transfer); }
static void capture_cb(struct libusb_transfer *transfer) { struct fpi_ssm *ssm = transfer->user_data; struct fp_img_dev *dev = ssm->priv; struct v5s_dev *vdev = dev->priv; if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { fpi_ssm_mark_aborted(ssm, -EIO); goto out; } if (++vdev->capture_iteration == NR_REQS) { struct fp_img *img = vdev->capture_img; /* must clear this early, otherwise the call chain takes us into * loopsm_complete where we would free it, when in fact we are * supposed to be handing off this image */ vdev->capture_img = NULL; fpi_imgdev_report_finger_status(dev, finger_is_present(img->data)); fpi_imgdev_image_captured(dev, img); fpi_ssm_next_state(ssm); } else { capture_iterate(ssm); } out: libusb_free_transfer(transfer); }
static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer) { struct fpi_ssm *ssm = transfer->user_data; struct fp_img_dev *dev = ssm->priv; struct aesX660_dev *aesdev = dev->priv; if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && (transfer->length == transfer->actual_length)) { struct fp_img *img; aesdev->strips = g_slist_reverse(aesdev->strips); img = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips, aesdev->strips_len); img->flags |= aesdev->extra_img_flags; g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); g_slist_free(aesdev->strips); aesdev->strips = NULL; aesdev->strips_len = 0; fpi_imgdev_image_captured(dev, img); fpi_imgdev_report_finger_status(dev, FALSE); fpi_ssm_mark_completed(ssm); } else { fpi_ssm_mark_aborted(ssm, -EIO); } libusb_free_transfer(transfer); }
static void et_read_poll_cb(struct libusb_transfer* transfer) { int len; char* br; int r; struct poll_data* adata=transfer->user_data; struct fpi_img_dev* dev=adata->dev; if(transfer->status!=LIBUSB_TRANSFER_COMPLETED) { /*WORKAROUND NEEDED, SOMETIME ALL FREEZES, RESET DEVICE AND REACTIVATE???*/ libusb_free_transfer(transfer); fp_dbg("ERROR"); fpi_imgdev_session_error(dev,-EIO); //return; goto _st; } len=transfer->actual_length-13; if(len!=512) { fp_dbg("Invalid return buffer, length: %d",transfer->actual_length); libusb_free_transfer(transfer); fpi_imgdev_session_error(dev,-EPROTO); return; } libusb_free_transfer(transfer); //Check poll cmd result br=(char*)&ret_buf[len]; r=et_verify_result(br); if(r) { fp_dbg("Invalid result: %s",print_buf(br)); fpi_imgdev_session_error(dev,-EPROTO); return; } //fp_dbg("0x%02hhX,0x%02hhX",ret_buf[0],ret_buf[1]); if((unsigned char)ret_buf[0]==0x82) { if(adata->init->rstage<20) { /*VERY UGLY workaround below, but I don't know how to deal with it. Sometime ret_buf[0] equals 0x82 at the first poll rounds, but really no finger on the scanner */ fp_dbg("POLL WORKAROUND"); goto _st; } //Finger detected //fp_dbg("FINGER DETECTED!"); //fp_dbg("BUF: %s",print_buf(ret_buf)); fpi_imgdev_report_finger_status(dev,TRUE); start_capture(dev); return; } //No finger detected _st: adata->init->rstage++; start_finger_detection(dev,adata); }
static void finger_det_sm_complete(struct fpi_ssm *ssm) { struct fp_img_dev *dev = ssm->priv; struct aesX660_dev *aesdev = dev->priv; int err = ssm->error; fp_dbg("Finger detection completed"); fpi_imgdev_report_finger_status(dev, TRUE); fpi_ssm_free(ssm); if (aesdev->deactivating) complete_deactivation(dev); else if (err) fpi_imgdev_session_error(dev, err); else { fpi_imgdev_report_finger_status(dev, TRUE); start_capture(dev); } }
static void capture_sm_complete(struct fpi_ssm *ssm) { static struct poll_data adata; struct fp_img_dev *dev = ssm->priv; struct etss801u_dev *etdev = dev->priv; fp_dbg(""); if (etdev->deactivating) complete_deactivation(dev); else if (ssm->error) fpi_imgdev_session_error(dev, ssm->error); else /*Done finger enrolling, assemble image and give it to library*/ et_assemble_image(dev); fpi_imgdev_report_finger_status(dev, FALSE); memset(&einit,0,sizeof(struct et_init)); adata.dev=(struct fpi_img_dev*)dev; adata.init=&einit; start_finger_detection(dev,&adata); fpi_ssm_free(ssm); }
static void state_activate(struct fpi_ssm *ssm) { struct libusb_transfer *transfer; struct fp_img_dev *dev = ssm->priv; struct vfs0050_dev *vfs_dev = dev->priv; int to_send; switch (ssm->cur_state) { case M_ACTIVATE_START: vfs_dev->activate_offset = 0; transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_activate1, 64, state_activate_cb, ssm, BULK_TIMEOUT); libusb_submit_transfer(transfer); break; case M_ACTIVATE_1_STEP2: transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_activate1 + 64, 61, state_activate_cb, ssm, BULK_TIMEOUT); libusb_submit_transfer(transfer); break; case M_ACTIVATE_1_SINGLE_READ: transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, state_activate_cb, ssm, BULK_TIMEOUT); libusb_submit_transfer(transfer); break; case M_ACTIVATE_2_SEND: to_send = sizeof(vfs0050_activate2) - vfs_dev->activate_offset; to_send = to_send >= 64 ? 64 : to_send; transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_activate2 + vfs_dev->activate_offset, to_send, state_activate_cb, ssm, BULK_TIMEOUT); libusb_submit_transfer(transfer); break; case M_ACTIVATE_EP1_DRAIN: transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, state_activate_cb, ssm, BULK_TIMEOUT); libusb_submit_transfer(transfer); break; case M_ACTIVATE_EP3_INT1: //first interrupt, should be 5 x 0x00 transfer = libusb_alloc_transfer(0); libusb_fill_interrupt_transfer(transfer, dev->udev, EP3_IN, vfs_dev->tmpbuf, 8, state_activate_cb, ssm, INTERRUPT_TIMEOUT1); libusb_submit_transfer(transfer); break; case M_ACTIVATE_AWAIT_FINGER: //this sets up infinite wait for interrupt. When the interrupt occurs, we're ready to read data on EP2. if (!vfs_dev->is_active) { vfs_dev->is_active = 1; fpi_imgdev_activate_complete(dev, 0); //notify libfprint activation complete. } transfer = libusb_alloc_transfer(0); libusb_fill_interrupt_transfer(transfer, dev->udev, EP3_IN, vfs_dev->tmpbuf, 8, state_activate_cb, ssm, INTERRUPT_TIMEOUT_NONE); libusb_submit_transfer(transfer); break; case M_ACTIVATE_RECEIVE_FINGERPRINT: if (vfs_dev->scanbuf_idx + 64 >= vfs_dev->scanbuf_sz) { vfs_dev->scanbuf_sz <<= 1; vfs_dev->scanbuf = g_realloc(vfs_dev->scanbuf, vfs_dev->scanbuf_sz); } transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, dev->udev, EP2_IN, vfs_dev->scanbuf + vfs_dev->scanbuf_idx, 64, state_activate_cb, ssm, 500); libusb_submit_transfer(transfer); break; case M_ACTIVATE_POST_RECEIVE: submit_image(dev); fpi_imgdev_report_finger_status(dev, FALSE); vfs_dev->activate_offset = 0; vfs_dev->scanbuf_idx = 0; fpi_timeout_add(300, async_sleep_cb, ssm); //wait a bit and see if we're swiping again. break; } }
static void state_activate_cb(struct libusb_transfer *transfer) { struct fpi_ssm *ssm = transfer->user_data; struct fp_img_dev *dev = ssm->priv; struct vfs0050_dev *vfs_dev = dev->priv; switch (ssm->cur_state) { case M_ACTIVATE_1_SINGLE_READ: //check bytes are 0x00 and 0x00 if (vfs_dev->tmpbuf[0] != 0x00 || vfs_dev->tmpbuf[1] != 0x00) { fp_dbg("unexpected bytes back from endpoint in M_ACTIVATE_1_SINGLE_READ"); libusb_free_transfer(transfer); fpi_ssm_jump_to_state(ssm, M_ACTIVATE_START); break; } libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; case M_ACTIVATE_2_SEND: vfs_dev->activate_offset += transfer->actual_length; if (vfs_dev->activate_offset == sizeof(vfs0050_activate2)) { //finished sending this activation section fpi_ssm_next_state(ssm); break; } fpi_ssm_jump_to_state(ssm, M_ACTIVATE_2_SEND); break; case M_ACTIVATE_EP1_DRAIN: //just draining this data, not sure what it does yet. if (transfer->actual_length < 64) { libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; } libusb_free_transfer(transfer); fpi_ssm_jump_to_state(ssm, M_ACTIVATE_EP1_DRAIN); break; case M_ACTIVATE_EP3_INT1: if (transfer->actual_length != 5) { fp_dbg("unexpected length for interrupt transfer in M_ACTIVATE_EP3_INT1"); //TODO: fail here, exit ssm } fpi_ssm_next_state(ssm); break; case M_ACTIVATE_AWAIT_FINGER: //if we got here, it's time to read fingerprint data. //interrupt data should be 02 00 0e 00 f0 if (vfs_dev->is_active) { if (transfer->actual_length != 5) { fp_dbg("unexpected length for interrupt transfer in M_ACTIVATE_AWAIT_FINGER"); //TODO: fail here, exit ssm. } if (memcmp(vfs_dev->tmpbuf, vfs0050_valid_interrupt, 5) != 0) { fp_dbg("invalid interrupt data in M_ACTIVATE_AWAIT_FINGER"); //TODO: fail here, exit ssm. } fpi_imgdev_report_finger_status(dev, TRUE); //report finger on to libfprint fpi_ssm_next_state(ssm); } else { fpi_ssm_mark_completed(ssm); //break fall through } break; case M_ACTIVATE_RECEIVE_FINGERPRINT: if (transfer->actual_length == 0) { libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; } vfs_dev->scanbuf_idx += transfer->actual_length; libusb_free_transfer(transfer); fpi_ssm_jump_to_state(ssm, M_ACTIVATE_RECEIVE_FINGERPRINT); break; default: libusb_free_transfer(transfer); fpi_ssm_next_state(ssm); break; } }