/* 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 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; } }