Added experimental library for Arduino

The library has not been tested yet on a real Arduino board.
Any improvements would be greatly appreciated.
This commit is contained in:
Andrey Perminov 2021-06-22 13:02:08 -07:00
parent 4bfba0482d
commit decd3073ef
17 changed files with 2423 additions and 0 deletions

View File

@ -0,0 +1,19 @@
= BM-Lite Library for Arduino =
This library allows an Arduino board to access FPC BM-LIte module.
== License ==
Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,330 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <SPI.h>
#include <BMLite.h>
#define BMLITE_PIN_RESET 2
#define BMLITE_PIN_STATUS 4
#define LED1 14
#define LED2 15
#define LED3 16
#define LED4 17
#define BMLITE_BUTTON 3
#define BMLITE_CS_PIN 8
//#define BMLITE_MISO_PIN ARDUINO_12_PIN
//#define BMLITE_MOSI_PIN ARDUINO_11_PIN
//#define BMLITE_CLK_PIN ARDUINO_13_PIN
int leds[4] = {LED1, LED2, LED3, LED4};
#define DATA_BUFFER_SIZE (512)
static uint8_t hcp_txrx_buffer[MTU];
static uint8_t hcp_data_buffer[DATA_BUFFER_SIZE];
static HCP_comm_t hcp_chain;
void setup() {
char *version;
hcp_chain.write = platform_bmlite_spi_send;
hcp_chain.read = platform_bmlite_spi_receive;
hcp_chain.phy_rx_timeout = 2000;
hcp_chain.pkt_buffer = hcp_data_buffer;
hcp_chain.pkt_size_max = sizeof(hcp_data_buffer);
hcp_chain.pkt_size = 0;
hcp_chain.txrx_buffer = hcp_txrx_buffer;
// put your setup code here, to run once:
pinMode(BMLITE_PIN_RESET, OUTPUT);
pinMode(BMLITE_PIN_STATUS, INPUT);
for(int i=0; i<4; i++) {
pinMode(leds[i], OUTPUT);
}
set_leds(0);
pinMode(BMLITE_BUTTON, INPUT);
SPI.begin();
pinMode(BMLITE_CS_PIN, OUTPUT);
platform_init(NULL);
// This block is for debug purpose only and can be safely removed
{
version = (char *)malloc(50);
memset(version, 0, 50);
fpc_bep_result_t res = bep_version(&hcp_chain, version, 99);
free(version);
}
}
uint16_t template_id;
uint32_t current_id = 0;
bool match;
void loop() {
// put your main code here, to run repeatedly:
int res;
uint32_t btn_time = hal_get_button_press_time();
hal_set_leds(BMLITE_LED_STATUS_READY,0);
if (btn_time < 200) {
// nothing hapened
} else if (btn_time < 5000) {
// Enroll
res = bep_enroll_finger(&hcp_chain);
res = bep_template_save(&hcp_chain, current_id++);
} else {
// Erase All templates
hal_set_leds(BMLITE_LED_STATUS_DELETE_TEMPLATES, true);
res = bep_template_remove_all(&hcp_chain);
current_id = 0;
}
res = bep_identify_finger(&hcp_chain, 0, &template_id, &match);
if (res == FPC_BEP_RESULT_TIMEOUT) {
platform_bmlite_reset();
} else if (res != FPC_BEP_RESULT_OK) {
return;
}
hal_set_leds(BMLITE_LED_STATUS_MATCH, match);
res = sensor_wait_finger_not_present(&hcp_chain, 0);
}
void bmlite_on_error(bmlite_error_t error, int32_t value)
{
if(value != FPC_BEP_RESULT_TIMEOUT) {
hal_set_leds(BMLITE_LED_STATUS_ERROR, false);
} else {
// Timeout - not really an error here
hal_set_leds(BMLITE_LED_STATUS_ERROR, true);
}
}
// void bmlite_on_start_capture();
// void bmlite_on_finish_capture();
void bmlite_on_start_enroll()
{
hal_set_leds(BMLITE_LED_STATUS_ENROLL, true);
}
void bmlite_on_finish_enroll()
{
hal_set_leds(BMLITE_LED_STATUS_ENROLL, false);
}
void bmlite_on_start_enrollcapture()
{
hal_set_leds(BMLITE_LED_STATUS_WAITTOUCH, true);
}
void bmlite_on_finish_enrollcapture()
{
hal_set_leds(BMLITE_LED_STATUS_READY, false);
}
void bmlite_on_identify_start()
{
hal_set_leds(BMLITE_LED_STATUS_READY, true);
}
// void bmlite_on_identify_finish();
/*
* Arduino HAL Implementation
*/
fpc_bep_result_t hal_board_init(void *params)
{
(void)params;
return FPC_BEP_RESULT_OK;
}
void hal_bmlite_reset(bool state)
{
if(!state) {
digitalWrite(BMLITE_PIN_RESET, HIGH);
} else {
digitalWrite(BMLITE_PIN_RESET, LOW);
}
}
bool hal_bmlite_get_status(void)
{
return digitalRead(BMLITE_PIN_STATUS);
}
/** LED ON time in ms */
#define LED_SOLID_ON_TIME_MS 700
/** LED blink time in ms */
#define LED_BLINK_TIME_MS 200
static void set_leds(uint8_t color)
{
uint32_t i;
for(i=0; i<4; i++) {
digitalWrite(leds[i], color & 1);
color = color >> 1;
}
}
void hal_set_leds(platform_led_status_t status, uint16_t mode)
{
switch(status) {
case BMLITE_LED_STATUS_READY:
set_leds(0);
break;
case BMLITE_LED_STATUS_MATCH:
if (mode) {
set_leds(1);
} else {
set_leds(2);
}
hal_timebase_busy_wait(500);
break;
case BMLITE_LED_STATUS_WAITTOUCH:
if (mode) {
set_leds(3);
}
break;
case BMLITE_LED_STATUS_ENROLL:
if (mode) {
// Start enroll
set_leds(1);
hal_timebase_busy_wait(500);
set_leds(2);
hal_timebase_busy_wait(500);
} else {
// Finish enroll
set_leds(1);
hal_timebase_busy_wait(100);
set_leds(0);
hal_timebase_busy_wait(100);
set_leds(2);
hal_timebase_busy_wait(100);
}
break;
case BMLITE_LED_STATUS_DELETE_TEMPLATES:
set_leds(4);
hal_timebase_busy_wait(100);
set_leds(0);
hal_timebase_busy_wait(100);
set_leds(4);
hal_timebase_busy_wait(100);
break;
case BMLITE_LED_STATUS_ERROR:
if (mode) {
set_leds(3);
hal_timebase_busy_wait(70);
} else {
set_leds(3);
hal_timebase_busy_wait(500);
set_leds(0);
hal_timebase_busy_wait(500);
set_leds(3);
hal_timebase_busy_wait(500);
}
break;
}
}
fpc_bep_result_t hal_bmlite_spi_write_read(uint8_t *buff, size_t size)
{
digitalWrite(BMLITE_CS_PIN, LOW);
SPI.transfer(buff,size);
digitalWrite(BMLITE_CS_PIN, HIGH);
return FPC_BEP_RESULT_OK;
}
volatile uint32_t button_pressed_time = 0;
static uint32_t btn_press_start;
static uint32_t btn_pressed = 0;
void hal_timebase_init(void)
{
}
void hal_timebase_busy_wait(uint32_t delay)
{
uint32_t start;
uint32_t delay_internal = 0;
/* Ensure minimum delay or skip if delay is zero*/
if (delay) {
delay_internal = delay + 1;
start = micros();
while ((micros() - start) < delay_internal) {
}
}
}
hal_tick_t hal_timebase_get_tick(void)
{
return micros();
}
static void check_buttons()
{
if (digitalRead(BMLITE_BUTTON)) {
if (btn_pressed == 0) {
btn_press_start = micros();
btn_pressed = 1;
}
} else { // Btn released
if (btn_pressed) {
if (micros() > btn_press_start) {
button_pressed_time = micros() - btn_press_start;
} else {
button_pressed_time = micros() + ~btn_press_start + 1;
}
btn_pressed = 0;
}
}
}
uint32_t hal_get_button_press_time()
{
uint32_t time = button_pressed_time;
button_pressed_time = 0;
return time;
}
uint32_t hal_check_button_pressed()
{
uint32_t time = button_pressed_time;
return time;
}

View File

@ -0,0 +1,15 @@
#######################################
# Syntax Coloring Map BMLite
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -0,0 +1,9 @@
name=BMLite
version=0.1
author=Andrey Perminov
maintainer=
sentence=Allows Arduino/Genuino boards access to FPC BM-Lite module.
paragraph=
category=
url=
architectures=avr,megaavr,sam,samd,nrf52,stm32f4,mbed

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <Arduino.h>
#define BMLITE_USE_CALLBACK
#include "bmlite_if.h"
#include "hcp_tiny.h"
#include "platform.h"
#include "bmlite_hal.h"

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file bmlite_hal.h
* @brief BM-Lite HAL functions.
*
* All functions must be implemented in order to support BM-Lite on a Board
*/
#ifndef BMLITE_H
#define BMLITE_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "fpc_bep_types.h"
#ifdef __arm__
typedef uint32_t hal_tick_t;
#else
typedef uint64_t hal_tick_t;
#endif
/**
* @brief LED status.
*
* Different LED status.
*/
typedef enum {
BMLITE_LED_STATUS_READY = 0,
BMLITE_LED_STATUS_MATCH,
BMLITE_LED_STATUS_WAITTOUCH,
BMLITE_LED_STATUS_ENROLL,
BMLITE_LED_STATUS_DELETE_TEMPLATES,
BMLITE_LED_STATUS_ERROR,
} platform_led_status_t;
/*
* @brief Board initialization
* @param[in] params - pointer to additional parameters
*/
fpc_bep_result_t hal_board_init(void *params);
/*
* @brief Control BM-Lite Reset pin
* @param[in] True - Activate RESET
* False - Deactivate RESET
*/
void hal_bmlite_reset(bool state);
/*
* @brief SPI write-read
* @param[in] Write buffer
* @param[in] Read buffer
* @param[in] Size
* @param[in] Leave CS asserted
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t hal_bmlite_spi_write_read(uint8_t *buff, size_t size);
/*
* @brief Check if BM-Lite IRQ pin is set
* @return ::bool
*/
bool hal_bmlite_get_status(void);
/**
* @brief Initializes timebase. Starts system tick counter.
*/
void hal_timebase_init(void);
/**
* @brief Reads the system tick counter.
*
* @return Tick count since hal_timebase_init() call. [ms]
*/
hal_tick_t hal_timebase_get_tick(void);
/**
* @brief Busy wait.
*
* @param[in] ms Time to wait [ms].
* 0 => return immediately
* 1 => wait at least 1ms etc.
*/
void hal_timebase_busy_wait(uint32_t ms);
/**
* Optional functions for Buttons & Leds control
*/
/**
* @brief Get button press time (msec)
*
* @return ::uint32_t
*/
uint32_t hal_get_button_press_time(void);
/**
* @brief Check if button was pressed and released.
*
* @return Button press time in milli seconds.
*/
uint32_t hal_check_button_pressed(void);
/**
* @brief Set LED(s) status
* @param[in] Status
* @param[in] Status modifier
*/
void hal_set_leds(platform_led_status_t status, uint16_t mode);
#endif /* BMLITE_H */

View File

@ -0,0 +1,324 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hcp_tiny.h"
#include "bmlite_if.h"
#include "bmlite_hal.h"
#include <stdio.h>
#include "bmlite_if_callbacks.h"
#define MAX_CAPTURE_ATTEMPTS 15
#define MAX_SINGLE_CAPTURE_ATTEMPTS 3
#define CAPTURE_TIMEOUT 3000
#define exit_if_err(c) { bep_result = c; if(bep_result || chain->bep_result) goto exit; }
#define assert(c) { fpc_bep_result_t res = c; if(res) return res; }
#ifdef BMLITE_USE_CALLBACK
/**
* @brief Mock callback functions
*/
__attribute__((weak)) void bmlite_on_error(bmlite_error_t error, int32_t value) { (void)error; (void)value; }
__attribute__((weak)) void bmlite_on_start_capture() {}
__attribute__((weak)) void bmlite_on_finish_capture() {}
__attribute__((weak)) void bmlite_on_start_enroll() {}
__attribute__((weak)) void bmlite_on_finish_enroll() {}
__attribute__((weak)) void bmlite_on_start_enrollcapture() {}
__attribute__((weak)) void bmlite_on_finish_enrollcapture() {}
__attribute__((weak)) void bmlite_on_identify_start() {}
__attribute__((weak)) void bmlite_on_identify_finish() {}
#endif
fpc_bep_result_t bep_enroll_finger(HCP_comm_t *chain)
{
uint32_t samples_remaining = 0;
fpc_bep_result_t bep_result = FPC_BEP_RESULT_OK;
bool enroll_done = false;
bmlite_on_start_enroll();
/* Enroll start */
exit_if_err(bmlite_send_cmd(chain, CMD_ENROLL, ARG_START));
for (uint8_t i = 0; i < MAX_CAPTURE_ATTEMPTS; ++i) {
bmlite_on_start_enrollcapture();
bep_result = bep_capture(chain, CAPTURE_TIMEOUT);
bmlite_on_finish_enrollcapture();
if (bep_result != FPC_BEP_RESULT_OK) {
continue;
}
/* Enroll add */
bep_result = bmlite_send_cmd(chain, CMD_ENROLL, ARG_ADD);
if (bep_result != FPC_BEP_RESULT_OK) {
continue;
}
bmlite_get_arg(chain, ARG_COUNT);
samples_remaining = *(uint32_t *)chain->arg.data;
// DEBUG("Enroll samples remaining: %d\n", samples_remaining);
/* Break enrolling if we can't collect enough correct images for enroll*/
if (samples_remaining == 0U) {
enroll_done = true;
break;
}
sensor_wait_finger_not_present(chain, 0);
}
bep_result = bmlite_send_cmd(chain, CMD_ENROLL, ARG_FINISH);
exit:
bmlite_on_finish_enroll();
return (!enroll_done) ? FPC_BEP_RESULT_GENERAL_ERROR : bep_result;
}
fpc_bep_result_t bep_identify_finger(HCP_comm_t *chain, uint32_t timeout, uint16_t *template_id, bool *match)
{
fpc_bep_result_t bep_result;
*match = false;
bmlite_on_identify_start();
exit_if_err(bep_capture(chain, timeout));
exit_if_err(bep_image_extract(chain));
exit_if_err(bep_identify(chain));
exit_if_err(bmlite_get_arg(chain, ARG_MATCH));
*match = *(bool *)chain->arg.data;
if(*match) {
bmlite_get_arg(chain, ARG_ID);
*template_id = *(uint16_t *)chain->arg.data;
// Delay for possible updating template on BM-Lite
hal_timebase_busy_wait(50);
}
exit:
bmlite_on_identify_finish();
return bep_result;
}
fpc_bep_result_t sensor_wait_finger_present(HCP_comm_t *chain, uint16_t timeout)
{
fpc_bep_result_t bep_result;
uint32_t prev_timeout = chain->phy_rx_timeout;
bmlite_on_start_capture();
chain->phy_rx_timeout = timeout;
bep_result = bmlite_send_cmd_arg(chain, CMD_WAIT, ARG_FINGER_DOWN, ARG_TIMEOUT, &timeout, sizeof(timeout));
chain->phy_rx_timeout = prev_timeout;
bmlite_on_finish_capture();
return bep_result;
}
fpc_bep_result_t sensor_wait_finger_not_present(HCP_comm_t *chain, uint16_t timeout)
{
fpc_bep_result_t bep_result;
uint32_t prev_timeout = chain->phy_rx_timeout;
chain->phy_rx_timeout = timeout;
bep_result = bmlite_send_cmd_arg(chain, CMD_WAIT, ARG_FINGER_UP, ARG_TIMEOUT, &timeout, sizeof(timeout));
chain->phy_rx_timeout = prev_timeout;
return bep_result;
}
fpc_bep_result_t bep_capture(HCP_comm_t *chain, uint16_t timeout)
{
fpc_bep_result_t bep_result;
uint32_t prev_timeout = chain->phy_rx_timeout;
bmlite_on_start_capture();
chain->phy_rx_timeout = timeout;
for(int i=0; i< MAX_SINGLE_CAPTURE_ATTEMPTS; i++) {
bep_result = bmlite_send_cmd_arg(chain, CMD_CAPTURE, ARG_NONE, ARG_TIMEOUT, &timeout, sizeof(timeout));
if( !(bep_result || chain->bep_result))
break;
}
chain->phy_rx_timeout = prev_timeout;
bmlite_on_finish_capture();
return bep_result;
}
fpc_bep_result_t bep_image_get_size(HCP_comm_t *chain, uint32_t *size)
{
assert(bmlite_send_cmd(chain, CMD_IMAGE, ARG_SIZE));
assert(bmlite_get_arg(chain, ARG_SIZE));
*size = *(uint32_t*)chain->arg.data;
return FPC_BEP_RESULT_OK;
}
fpc_bep_result_t image_create(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_IMAGE, ARG_CREATE);
}
fpc_bep_result_t image_delete(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_IMAGE, ARG_DELETE);
}
fpc_bep_result_t bep_image_get(HCP_comm_t *chain, uint8_t *data, uint32_t size)
{
assert(bmlite_send_cmd(chain, CMD_IMAGE, ARG_UPLOAD));
return bmlite_copy_arg(chain, ARG_DATA, data, size);
}
fpc_bep_result_t bep_image_put(HCP_comm_t *chain, uint8_t *data, uint32_t size)
{
return bmlite_send_cmd_arg(chain, CMD_IMAGE, ARG_DOWNLOAD, ARG_DATA, data, size);
}
fpc_bep_result_t bep_image_extract(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_IMAGE, ARG_EXTRACT);
}
fpc_bep_result_t bep_identify(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_IDENTIFY, ARG_NONE);
}
fpc_bep_result_t bep_template_save(HCP_comm_t *chain, uint16_t template_id)
{
return bmlite_send_cmd_arg(chain, CMD_TEMPLATE, ARG_SAVE, ARG_ID, &template_id, sizeof(template_id));
}
fpc_bep_result_t bep_template_remove_ram(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_TEMPLATE, ARG_DELETE);
}
fpc_bep_result_t bep_template_get(HCP_comm_t *chain, uint8_t *data, uint32_t size)
{
assert(bmlite_send_cmd(chain, CMD_TEMPLATE, ARG_UPLOAD));
return bmlite_copy_arg(chain, ARG_DATA, data, size);
}
fpc_bep_result_t bep_template_put(HCP_comm_t *chain, uint8_t *data, uint16_t length)
{
return bmlite_send_cmd_arg(chain, CMD_TEMPLATE, ARG_DOWNLOAD,
ARG_DATA, data, length);
}
fpc_bep_result_t bep_template_remove(HCP_comm_t *chain, uint16_t template_id)
{
return bmlite_send_cmd_arg(chain, CMD_STORAGE_TEMPLATE, ARG_DELETE,
ARG_ID, &template_id, sizeof(template_id));
}
fpc_bep_result_t bep_template_remove_all(HCP_comm_t *chain)
{
return bmlite_send_cmd_arg(chain, CMD_STORAGE_TEMPLATE, ARG_DELETE,
ARG_ALL, 0, 0);
}
fpc_bep_result_t bep_template_load_storage(HCP_comm_t *chain, uint16_t template_id)
{
return bmlite_send_cmd_arg(chain, CMD_STORAGE_TEMPLATE, ARG_UPLOAD,
ARG_ID, &template_id, sizeof(template_id));
}
fpc_bep_result_t bep_template_get_count(HCP_comm_t *chain, uint16_t *count)
{
assert(bmlite_send_cmd(chain, CMD_STORAGE_TEMPLATE, ARG_COUNT));
assert(bmlite_get_arg(chain, ARG_COUNT));
*count = *(uint16_t*)chain->arg.data;
return FPC_BEP_RESULT_OK;
}
fpc_bep_result_t bep_template_get_ids(HCP_comm_t *chain)
{
assert(bmlite_send_cmd(chain, CMD_STORAGE_TEMPLATE, ARG_ID));
return bmlite_get_arg(chain, ARG_DATA);
}
fpc_bep_result_t bep_sw_reset(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_RESET, ARG_NONE);
}
fpc_bep_result_t bep_sensor_calibrate(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_STORAGE_CALIBRATION, ARG_NONE);
}
fpc_bep_result_t bep_sensor_calibrate_remove(HCP_comm_t *chain)
{
return bmlite_send_cmd(chain, CMD_STORAGE_CALIBRATION, ARG_DELETE);
}
fpc_bep_result_t bep_version(HCP_comm_t *chain, char *version, int len)
{
assert(bmlite_send_cmd_arg(chain, CMD_INFO, ARG_GET, ARG_VERSION, 0, 0));
return bmlite_copy_arg(chain, ARG_VERSION, version, len);
}
fpc_bep_result_t bep_unique_id_get(HCP_comm_t *chain, uint8_t *unique_id)
{
assert(bmlite_send_cmd_arg(chain, CMD_INFO, ARG_GET, ARG_UNIQUE_ID, 0, 0));
return bmlite_copy_arg(chain, ARG_UNIQUE_ID, unique_id, 12);
}
fpc_bep_result_t bep_uart_speed_set(HCP_comm_t *chain, uint32_t speed)
{
assert(bmlite_init_cmd(chain, CMD_COMMUNICATION, ARG_SPEED));
assert(bmlite_add_arg(chain, ARG_SET, 0, 0));
assert(bmlite_add_arg(chain, ARG_DATA, (uint8_t*)&speed, sizeof(speed)));
return bmlite_tranceive(chain);
}
fpc_bep_result_t bep_uart_speed_get(HCP_comm_t *chain, uint32_t *speed)
{
assert(bmlite_init_cmd(chain, CMD_COMMUNICATION, ARG_SPEED));
assert(bmlite_add_arg(chain, ARG_GET, 0, 0));
assert(bmlite_tranceive(chain));
return bmlite_copy_arg(chain, ARG_DATA, speed, sizeof(speed));
}
fpc_bep_result_t bep_sensor_reset(HCP_comm_t *chain)
{
// Delay for possible updating template on BM-Lite
hal_timebase_busy_wait(50);
return bmlite_send_cmd(chain, CMD_SENSOR, ARG_RESET);
}
fpc_bep_result_t bmlite_send_cmd(HCP_comm_t *chain, uint16_t cmd, uint16_t arg_type)
{
assert(bmlite_init_cmd(chain, cmd, arg_type));
return bmlite_tranceive(chain);
}
fpc_bep_result_t bmlite_send_cmd_arg(HCP_comm_t *chain, uint16_t cmd, uint16_t arg1_type, uint16_t arg2_type, void *arg2_data, uint16_t arg2_length)
{
assert(bmlite_init_cmd(chain, cmd, arg1_type));
assert(bmlite_add_arg(chain, arg2_type, arg2_data, arg2_length));
return bmlite_tranceive(chain);
}

View File

@ -0,0 +1,365 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BMLITE_IF_H
#define BMLITE_IF_H
#include "hcp_tiny.h"
#include "bmlite_if_callbacks.h"
/**
* @brief Enroll finger. Created template must be saved to FLASH storage
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_enroll_finger(HCP_comm_t *chain);
/**
* @brief Capture and identify finger against existing templates in Flash storage
*
* @param[in] chain - HCP com chain
* @param[in] timeout - timeout (msec). Maximum timeout 65535 msec
* set to 0 for waiting indefinitely
*
* @param[out] template_id - pointer for matched template ID
* @param[out] match - pointer to match result
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_identify_finger(HCP_comm_t *chain, uint32_t timeout,
uint16_t *template_id, bool *match);
/**
* @brief Wait for finger present on sensor"
*
* @param[in] chain - HCP com chain
* @param[in] timeout - timeout (msec). Maximum timeout 65535 msec
* set to 0 for waiting indefinitely
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t sensor_wait_finger_present(HCP_comm_t *chain, uint16_t timeout);
/**
* @brief Wait for finger not present on sensor"
*
* @param[in] chain - HCP com chain
* @param[in] timeout - timeout (msec). Maximum timeout 65535 msec
* set to 0 for waiting indefinitely
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t sensor_wait_finger_not_present(HCP_comm_t *chain, uint16_t timeout);
/**
* @brief Wait for finger present on sensor and capture image"
*
* @param[in] chain - HCP com chain
* @param[in] timeout - timeout (msec). Maximum timeout 65535 msec
* set to 0 for waiting indefinitely
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_capture(HCP_comm_t *chain, uint16_t timeout);
/**
* @brief Get size of captured image
*
* @param[in] chain - HCP com chain
*
* @param[out] size
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_image_get_size(HCP_comm_t *chain, uint32_t *size);
/**
* @brief Allocates image buffer on FPC BM-LIte
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t image_create(HCP_comm_t *chain);
/**
* @brief Deletes image buffer on FPC BM-LIte
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t image_delete(HCP_comm_t *chain);
/**
* @brief Pull captured image from FPC BM-Lite
*
* @param[in] chain - HCP com chain
*
* @param[in] data - pointer to image buffer
* @param[in] size - size of the image buffer
* if buffer size is not enough the image
* will be truncated
* chain->arg.size will contain real size of the image
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_image_get(HCP_comm_t *chain, uint8_t *data, uint32_t size);
/**
* @brief Push image to FPC BM-Lite
*
* @param[in] chain - HCP com chain
*
* @param[in] data - pointer to image buffer
* @param[in] size - size of the image buffer
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_image_put(HCP_comm_t *chain, uint8_t *data, uint32_t size);
/**
* @brief Extract image features to prepare image for enrolling or matching
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_image_extract(HCP_comm_t *chain);
/**
* @brief Identify prepared image against existing templates in Flash storage
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_identify(HCP_comm_t *chain);
/**
* @brief Save template after enroll is finished to FLASH storage
*
* @param[in] chain - HCP com chain
* @param[out] template_id - template ID
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_save(HCP_comm_t *chain, uint16_t template_id);
/**
* @brief Remove template from RAM
*
* @param[in] chain - HCP com chain
* @param[in] template_id - template ID
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_remove_ram(HCP_comm_t *chain);
/**
* @brief Pull template stored in RAM from FPC BM-Lite
*
* @param[in] chain - HCP com chain
*
* @param[in] data - pointer to template buffer
* @param[in] size - size of the template buffer
* if buffer size is not enough the template
* will be truncated
* chain->arg.size will contain real size of the template
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_get(HCP_comm_t *chain, uint8_t *data, uint32_t size);
/**
* @brief Push template to FPC BM-Lite and stored it to RAM
*
* @param[in] chain - HCP com chain
*
* @param[in] data - pointer to template buffer
* @param[in] size - size of the template buffer
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_put(HCP_comm_t *chain, uint8_t *data, uint16_t length);
/**
* @brief Remove template from FLASH storage
*
* @param[in] chain - HCP com chain
* @param[in] template_id - template ID
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_remove(HCP_comm_t *chain, uint16_t template_id);
/**
* @brief Remove all templates from FLASH storage
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_remove_all(HCP_comm_t *chain);
/**
* @brief Copy template from FLASH storage to RAM
*
* @param[in] chain - HCP com chain
* @param[in] template_id - template ID
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_load_storage(HCP_comm_t *chain, uint16_t template_id);
/**
* @brief Remove template from FLASH storage
*
* @param[in] chain - HCP com chain
* @param[out] template_id - template ID
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_template_get_count(HCP_comm_t *chain, uint16_t *count);
/**
* @brief Get array of template ID stored on FPC BM-LIte
*
* @param[in] chain - HCP com chain
* @return ::fpc_bep_result_t
* chain->arg.data - pointer to array of uint16_t of IDs
* chain->arg.size - length of the array (in bytes). For calculating
* number of templates divide the arg.size by 2
*/
fpc_bep_result_t bep_template_get_ids(HCP_comm_t *chain);
/**
* @brief Software reset of FCP BM-Lite
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_sw_reset(HCP_comm_t *chain);
/**
* @brief Calibrate FPC BM-LIte sensor and store calibration data to FLASH storage
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*
* FPC BM-Lite must be restarted to activate new calibration data
*/
fpc_bep_result_t bep_sensor_calibrate(HCP_comm_t *chain);
/**
* @brief Remove FPC BM-LIte sensor calibration data from FLASH storage
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*
* FPC BM-Lite must be restarted to activate
*/
fpc_bep_result_t bep_sensor_calibrate_remove(HCP_comm_t *chain);
/**
* @brief Get version of FPC BM-LIte firmware
*
* @param[in] chain - HCP com chain
* @param[in] version - pointer to data buffer
* @param[in] size - size of the data buffer
* if buffer size is not enough the data
* will be truncated
* chain->arg.size will contain real size of the data
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_version(HCP_comm_t *chain, char *version, int len);
/**
* @brief Get version of FPC BM-LIte firmware
*
* @param[in] chain - HCP com chain
* @param[in] unique_id - pointer to data buffer
* chain->arg.size will contain real size of the data
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_unique_id_get(HCP_comm_t *chain, uint8_t *unique_id);
/**
* @brief Set requested UART communication speed
*
* @param[in] chain - HCP com chain
* @param[in] speed - UART speed
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_uart_speed_set(HCP_comm_t *chain, uint32_t speed);
/**
* @brief Get current UART communication speed
*
* @param[in] chain - HCP com chain
* @param[out] speed - UART speed
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_uart_speed_get(HCP_comm_t *chain, uint32_t *speed);
/**
* @brief Reset FPC BM-Lite fingerprint sensor
*
* @param[in] chain - HCP com chain
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bep_sensor_reset(HCP_comm_t *chain);
/**
* @brief Build and send command to FPC BM-Lite and receive answer
*
* @param[in] chain - HCP com chain
* @param[in] cmd - BM-Lite command
* @param[in] arg_type - Argument without parameters
* set to ARG_NONE if the command has no argument
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_send_cmd(HCP_comm_t *chain, uint16_t cmd, uint16_t arg_type);
/**
* @brief Build and send command with additiona argument with parameters
*
* @param[in] chain - HCP com chain
* @param[in] cmd - BM-Lite command
* @param[in] arg1_type - argument 1 without parameters
* set to ARG_NONE if the command has no argument without paramener
* @param[in] arg2_type - argument 2
* @param[in] arg2_data - data pointer for argument 2
* set to 0 if argument 2 has no parameter
* @param[in] arg2_length - length of data for argument 2
* set to 0 if argument 2 has no parameter
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_send_cmd_arg(HCP_comm_t *chain, uint16_t cmd, uint16_t arg1_type, uint16_t arg2_type, void *arg2_data, uint16_t arg2_length);
#endif

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BMLITE_IF_CALLBACKS_H
#define BMLITE_IF_CALLBACKS_H
#include <stdint.h>
#ifndef BMLITE_USE_CALLBACK
#define bmlite_on_error(error, value)
#define bmlite_on_start_capture()
#define bmlite_on_finish_capture()
#define bmlite_on_finish_enroll()
#define bmlite_on_start_enroll()
#define bmlite_on_start_enrollcapture()
#define bmlite_on_finish_enrollcapture()
#define bmlite_on_identify_start()
#define bmlite_on_identify_finish()
#else
typedef enum {
BMLITE_ERROR_OK = 0,
BMLITE_ERROR_CAPTURE,
BMLITE_ERROR_CAPTURE_START,
BMLITE_ERROR_ENROLL_START,
BMLITE_ERROR_ENROLL_ADD,
BMLITE_ERROR_ENROLL_FINISH,
BMLITE_ERROR_WRONG_ANSWER,
BMLITE_ERROR_FINGER_WAIT,
BMLITE_ERROR_IDENTYFY,
BMLITE_ERROR_TEMPLATE_SAVE,
BMLITE_ERROR_TEMPLATE_DELETE,
BMLITE_ERROR_TEMPLATE_COUNT,
BMLITE_ERROR_TEMPLATE_GETIDS,
BMLITE_ERROR_IMAGE_EXTRACT,
BMLITE_ERROR_IMAGE_GETSIZE,
BMLITE_ERROR_IMAGE_GET,
BMLITE_ERROR_GETVERSION,
BMLITE_ERROR_SW_RESET,
BMLITE_ERROR_CALIBRATE,
BMLITE_ERROR_CALIBRATE_DELETE,
BMLITE_ERROR_SEND_CMD,
BMLITE_ERROR_GET_ARG,
} bmlite_error_t;
/**
* @brief Error Callback function
*
* @param[in] Callback Error Code
* @param[in] BEP result code
*/
void bmlite_on_error(bmlite_error_t error, int32_t value);
/**
* @brief Starting Capture Callback function
*/
void bmlite_on_start_capture();
/**
* @brief Finishing Capture Callback function
*/
void bmlite_on_finish_capture();
/**
* @brief Starting Enroll Callback function
*/
void bmlite_on_start_enroll();
/**
* @brief Finishing Enroll Callback function
*/
void bmlite_on_finish_enroll();
/**
* @brief Starting Capture for Enroll Callback function
*/
void bmlite_on_start_enrollcapture();
/**
* @brief Finishing Capture for Enroll Callback function
*/
void bmlite_on_finish_enrollcapture();
/**
* @brief Starting Identify Callback function
*/
void bmlite_on_identify_start();
/**
* @brief Finishing Identify Callback function
*/
void bmlite_on_identify_finish();
#endif // BMLITE_USE_CALLBACK
#endif

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2020 Fingerprint Cards AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FPC_BEP_TYPES_H
#define FPC_BEP_TYPES_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/**
* @file fpc_bep_types.h
* @brief Biometric Embedded Platform types.
*
* This is the common types used by Biometric Embedded Platform (BEP) library.
*
* @note This is a work-in-progress specification. Implementers are informed
* that this API may change without providing any backward compatibility.
* However it is FPC's ambition that the API shall remain compatible between
* releases.
*/
/** @brief Common result returned by BEP functions. */
typedef enum {
/** No errors occurred. */
FPC_BEP_RESULT_OK = 0,
/** General error. */
FPC_BEP_RESULT_GENERAL_ERROR = -1,
/** Internal error. */
FPC_BEP_RESULT_INTERNAL_ERROR = -2,
/** Invalid argument. */
FPC_BEP_RESULT_INVALID_ARGUMENT = -3,
/** The functionality is not implemented. */
FPC_BEP_RESULT_NOT_IMPLEMENTED = -4,
/** The operation was cancelled. */
FPC_BEP_RESULT_CANCELLED = -5,
/** Out of memory. */
FPC_BEP_RESULT_NO_MEMORY = -6,
/** Resources are not available. */
FPC_BEP_RESULT_NO_RESOURCE = -7,
/** An I/O error occurred. */
FPC_BEP_RESULT_IO_ERROR = -8,
/** Sensor is broken. */
FPC_BEP_RESULT_BROKEN_SENSOR = -9,
/** The operation cannot be performed in the current state. */
FPC_BEP_RESULT_WRONG_STATE = -10,
/** The operation timed out. */
FPC_BEP_RESULT_TIMEOUT = -11,
/** The ID is not unique. */
FPC_BEP_RESULT_ID_NOT_UNIQUE = -12,
/** The ID is not found. */
FPC_BEP_RESULT_ID_NOT_FOUND = -13,
/** The format is invalid. */
FPC_BEP_RESULT_INVALID_FORMAT = -14,
/** An image capture error occurred. */
FPC_BEP_RESULT_IMAGE_CAPTURE_ERROR = -15,
/** Sensor hardware id or sensor configuration mismatch. */
FPC_BEP_RESULT_SENSOR_MISMATCH = -16,
/** Invalid parameter. */
FPC_BEP_RESULT_INVALID_PARAMETER = -17,
/** Missing Template. */
FPC_BEP_RESULT_MISSING_TEMPLATE = -18,
/** Invalid Calibration.*/
FPC_BEP_RESULT_INVALID_CALIBRATION = -19,
/** Calibration/template storage not formatted.*/
FPC_BEP_RESULT_STORAGE_NOT_FORMATTED = -20,
/** Sensor hasn't been initialized. */
FPC_BEP_RESULT_SENSOR_NOT_INITIALIZED = -21,
/** Enroll fail after too many bad images. */
FPC_BEP_RESULT_TOO_MANY_BAD_IMAGES = -22,
/** Cryptographic operation failed. */
FPC_BEP_RESULT_CRYPTO_ERROR = -23,
/** The functionality is not supported. */
FPC_BEP_RESULT_NOT_SUPPORTED = -24,
/** Finger not stable during image capture. */
FPC_BEP_FINGER_NOT_STABLE = -25,
/** The functionality could not be used before it's initialized. */
FPC_BEP_RESULT_NOT_INITIALIZED = -26,
} fpc_bep_result_t;
#endif /* FPC_BEP_TYPES_H */

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2020 Fingerprint Cards AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file fpc_crc.c
* @brief CRC32 calculation.
*/
#include <stdint.h>
#include "fpc_crc.h"
/**
* The constants here are for the CRC-32 generator polynomial, as defined in
* the Microsoft Systems Journal, March 1995, pp. 107-108.
*/
static const uint32_t crc32_table[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t fpc_crc(uint32_t crc, const void *buf, uint32_t size)
{
const uint8_t *p;
p = (const uint8_t *)buf;
crc = crc ^ ~0U;
while (size--) {
crc = crc32_table[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
return crc ^ ~0U;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 Fingerprint Cards AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FPC_CRC_H
#define FPC_CRC_H
/**
* @file fpc_crc.h
* @brief Functionality for calculating CRC-32.
*/
#include <stdint.h>
/**
* @brief Calculates CRC-32 value for the data in the buffer.
*
* @param crc Accumulated CRC-32 value, must be 0 on first call.
* @param buf Buffer with data to calculate CRC-32 for.
* @param size Size of buffer in number of bytes.
* @return CRC-32 value for the data in buffer.
*/
uint32_t fpc_crc(uint32_t crc, const void *buf, uint32_t size);
#endif /* FPC_CRC_H */

View File

@ -0,0 +1,223 @@
/*
* Copyright (c) 2020 Fingerprint Cards AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file fpc_hcp_common.h
* @brief Host Communication Protocol common type definitions.
*/
#ifndef FPC_HCP_COMMON_H
#define FPC_HCP_COMMON_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** Returns the smallest of two values. */
#define HCP_MIN(x, y) (((x) < (y)) ? (x) : (y))
/** Program specific commands base number */
#define CMD_APP_BASE_VAL 0xE000
/** Program specific arguments base number */
#define ARG_APP_BASE_VAL 0x7000
/** HCP Command definitions */
enum fpc_hcp_cmd {
CMD_NONE = 0x0000,
/* Biometry */
CMD_CAPTURE = 0x0001,
CMD_ENROLL = 0x0002,
CMD_IDENTIFY = 0x0003,
CMD_MATCH = 0x0004,
CMD_IMAGE = 0x0005,
CMD_TEMPLATE = 0x0006,
CMD_WAIT = 0x0007,
CMD_SETTINGS = 0x0008,
/* Sensor */
CMD_NAVIGATE = 0x1001,
CMD_SENSOR = 0x1002,
CMD_DEADPIXELS = 0x1003,
/* Security */
CMD_CONNECT = 0x2001,
CMD_RECONNECT = 0x2002,
/* Firmware */
CMD_RESET = 0x3002,
CMD_CANCEL = 0x3003,
CMD_INFO = 0x3004,
/* Storage */
CMD_STORAGE_TEMPLATE = 0x4002,
CMD_STORAGE_CALIBRATION = 0x4003,
CMD_STORAGE_LOG = 0x4004,
CMD_STORAGE_SETTINGS = 0x4005,
/* Hardware */
CMD_TEST = 0x5001,
CMD_MCU = 0x5002,
CMD_GPIO = 0x5003,
/* Communication */
CMD_COMMUNICATION = 0x6001,
/* Application specific commands */
CMD_APP_BASE = CMD_APP_BASE_VAL,
/* Debug */
CMD_DIAG = 0xF003,
CMD_FFFF = 0xFFFF,
};
/** HCP Command type */
typedef uint16_t fpc_hcp_cmd_t;
/** HCP Argument definitions */
enum fpc_hcp_arg {
ARG_NONE = 0x0000,
/* Biometry */
ARG_FINGER_DOWN = 0x0001,
ARG_FINGER_UP = 0x0002,
ARG_START = 0x0003,
ARG_ADD = 0x0004,
ARG_FINISH = 0x0005,
ARG_ID = 0x0006,
ARG_ALL = 0x0007,
ARG_EXTRACT = 0x0008,
ARG_MATCH_IMAGE = 0x0009,
ARG_MATCH = 0x000A,
/* Data */
ARG_ACQUIRE = 0x1001,
ARG_RELEASE = 0x1002,
ARG_SET = 0x1003,
ARG_GET = 0x1004,
ARG_UPLOAD = 0x1005,
ARG_DOWNLOAD = 0x1006,
ARG_CREATE = 0x1007,
ARG_SAVE = 0x1008,
ARG_DELETE = 0x1009,
ARG_DATA = 0x100A,
ARG_UPDATE = 0x100B,
ARG_SEQ_NR = 0x100C,
ARG_SEQ_LEN = 0x100D,
/* Results */
ARG_RESULT = 0x2001,
ARG_COUNT = 0x2002,
ARG_SIZE = 0x2003,
ARG_LEVEL = 0x2004,
ARG_FORMAT = 0x2005,
ARG_FLAG = 0x2006,
ARG_PROPERTIES = 0x2007,
ARG_SPEED = 0x2008,
ARG_PROD_TEST = 0x2009,
/* Sensor */
ARG_SENSOR_TYPE = 0x3001,
ARG_WIDTH = 0x3002,
ARG_HEIGHT = 0x3003,
ARG_RESET = 0x3004,
ARG_DPI = 0x3005,
ARG_MAX_SPI_CLOCK = 0x3006,
ARG_NUM_SUB_AREAS_WIDTH = 0x3007,
ARG_NUM_SUB_AREAS_HEIGHT = 0x3008,
ARG_IRQ_STATUS = 0x3009,
ARG_RESET_HARD = 0x300A,
/* MCU */
ARG_IDLE = 0x4001,
ARG_SLEEP = 0x4002,
ARG_DEEP_SLEEP = 0x4003,
ARG_POWER_MODE = 0x4004,
ARG_BUSY_WAIT = 0x4005,
/* Misc */
ARG_TIMEOUT = 0x5001,
ARG_DONE = 0x5002,
/* Info */
ARG_BOOT = 0x6001,
ARG_STATUS = 0x6002,
ARG_VERSION = 0x6003,
ARG_UNIQUE_ID = 0x6004,
/* Application specific arguments */
ARG_APP_BASE = ARG_APP_BASE_VAL,
/* VSM */
ARG_NONCE = 0x8001,
ARG_MAC = 0x8002,
ARG_RANDOM = 0x8003,
ARG_CLAIM = 0x8004,
ARG_PUBLIC_KEY = 0x8005,
ARG_CIPHERTEXT = 0x8006,
/* Communication */
ARG_MTU = 0x9001,
/* Debug */
ARG_STACK = 0xE001,
ARG_FILL = 0xE002,
ARG_HEAP = 0xE003,
/* Log */
ARG_MODE = 0xF001,
ARG_DEBUG = 0xF002,
ARG_FFFF = 0xFFFF,
};
/** HCP Argument type */
typedef uint16_t fpc_hcp_arg_t;
/**
* @brief Command Argument
*/
typedef struct fpc_hcp_arg_data {
/** Argument */
fpc_hcp_arg_t arg;
/** Size of data */
uint16_t size;
/** Free data inside HCP */
bool free_data;
/** Pointer to data */
uint8_t *data;
} fpc_hcp_arg_data_t;
/**
* @brief Application Command Packet
*/
typedef struct fpc_hcp_packet {
/** Command ID */
fpc_hcp_cmd_t id;
/** Number of arguments */
uint16_t num_args;
/** Pointer to argument data */
fpc_hcp_arg_data_t *arguments;
} fpc_hcp_packet_t;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* FPC_HCP_COMMON_H */

View File

@ -0,0 +1,305 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include "fpc_crc.h"
#include "hcp_tiny.h"
#include "bmlite_if_callbacks.h"
#ifdef DEBUG
#include <stdio.h>
#include <stdlib.h>
#define LOG_DEBUG(...) printf(__VA_ARGS__)
#else
#define LOG_DEBUG(...)
#endif
static uint32_t fpc_com_ack = FPC_BEP_ACK;
static fpc_bep_result_t _rx_link(HCP_comm_t *hcp_comm);
static fpc_bep_result_t _tx_link(HCP_comm_t *hcp_comm);
typedef struct {
uint16_t cmd;
uint16_t args_nr;
uint8_t args[];
} _HCP_cmd_t;
typedef struct {
uint16_t arg;
uint16_t size;
uint8_t pld[];
} _CMD_arg_t;
typedef struct {
uint16_t lnk_chn;
uint16_t lnk_size;
uint16_t t_size;
uint16_t t_seq_nr;
uint16_t t_seq_len;
_HCP_cmd_t t_pld;
} _HPC_pkt_t;
fpc_bep_result_t bmlite_init_cmd(HCP_comm_t *hcp_comm, uint16_t cmd, uint16_t arg_key)
{
fpc_bep_result_t bep_result;
_HCP_cmd_t *out = (_HCP_cmd_t *)hcp_comm->pkt_buffer;
out->cmd = cmd;
out->args_nr = 0;
hcp_comm->pkt_size = 4;
if(arg_key != ARG_NONE) {
bep_result = bmlite_add_arg(hcp_comm, arg_key, NULL, 0);
if(bep_result) {
bmlite_on_error(BMLITE_ERROR_SEND_CMD, bep_result);
return bep_result;
}
}
return FPC_BEP_RESULT_OK;
}
fpc_bep_result_t bmlite_add_arg(HCP_comm_t *hcp_comm, uint16_t arg_type, void *arg_data, uint16_t arg_size)
{
if(hcp_comm->pkt_size + 4 + arg_size > hcp_comm->pkt_size_max) {
bmlite_on_error(BMLITE_ERROR_SEND_CMD, FPC_BEP_RESULT_NO_MEMORY);
return FPC_BEP_RESULT_NO_MEMORY;
}
((_HCP_cmd_t *)hcp_comm->pkt_buffer)->args_nr++;
_CMD_arg_t *args = (_CMD_arg_t *)(&hcp_comm->pkt_buffer[hcp_comm->pkt_size]);
args->arg = arg_type;
args->size = arg_size;
if(arg_size) {
memcpy(&args->pld, arg_data, arg_size);
}
hcp_comm->pkt_size += 4 + arg_size;
return FPC_BEP_RESULT_OK;
}
fpc_bep_result_t bmlite_get_arg(HCP_comm_t *hcp_comm, uint16_t arg_type)
{
uint16_t i = 0;
uint8_t *buffer = hcp_comm->pkt_buffer;
uint16_t args_nr = ((_HCP_cmd_t *)(buffer))->args_nr;
uint8_t *pdata = (uint8_t *)&((_HCP_cmd_t *)(buffer))->args;
while (i < args_nr && (uint32_t)(pdata - buffer) <= hcp_comm->pkt_size) {
_CMD_arg_t *parg = (_CMD_arg_t *)pdata;
if(parg->arg == arg_type) {
hcp_comm->arg.size = parg->size;
hcp_comm->arg.data = parg->pld;
return FPC_BEP_RESULT_OK;
} else {
i++;
pdata += 4 + parg->size;
}
}
// Ignore missing ARG_RESULT because some command return result other way
// if (arg_type != ARG_RESULT) {
bmlite_on_error(BMLITE_ERROR_GET_ARG, FPC_BEP_RESULT_INVALID_ARGUMENT);
// }
return FPC_BEP_RESULT_INVALID_ARGUMENT;
}
fpc_bep_result_t bmlite_copy_arg(HCP_comm_t *hcp_comm, uint16_t arg_key, void *arg_data, uint16_t arg_data_size)
{
fpc_bep_result_t bep_result;
bep_result = bmlite_get_arg(hcp_comm, arg_key);
if(bep_result == FPC_BEP_RESULT_OK) {
if(arg_data == NULL) {
bmlite_on_error(BMLITE_ERROR_GET_ARG, FPC_BEP_RESULT_NO_MEMORY);
return FPC_BEP_RESULT_NO_MEMORY;
}
memcpy(arg_data, hcp_comm->arg.data, HCP_MIN(arg_data_size, hcp_comm->arg.size));
} else {
bmlite_on_error(BMLITE_ERROR_GET_ARG, FPC_BEP_RESULT_INVALID_ARGUMENT);
return FPC_BEP_RESULT_INVALID_ARGUMENT;
}
return bep_result;
}
fpc_bep_result_t bmlite_tranceive(HCP_comm_t *hcp_comm)
{
fpc_bep_result_t bep_result;
bep_result = bmlite_send(hcp_comm);
if (bep_result == FPC_BEP_RESULT_OK) {
bep_result = bmlite_receive(hcp_comm);
if (bmlite_get_arg(hcp_comm, ARG_RESULT) == FPC_BEP_RESULT_OK) {
hcp_comm->bep_result = (fpc_bep_result_t)*(int8_t*)hcp_comm->arg.data;
} else {
hcp_comm->bep_result = FPC_BEP_RESULT_OK;
}
}
return bep_result;
}
fpc_bep_result_t bmlite_receive(HCP_comm_t *hcp_comm)
{
fpc_bep_result_t bep_result = FPC_BEP_RESULT_OK;
fpc_bep_result_t com_result = FPC_BEP_RESULT_OK;
uint16_t seq_nr = 0;
uint16_t seq_len = 1;
uint8_t *p = hcp_comm->pkt_buffer;
_HPC_pkt_t *pkt = (_HPC_pkt_t *)hcp_comm->txrx_buffer;
uint16_t buf_len = 0;
while(seq_nr < seq_len) {
bep_result = _rx_link(hcp_comm);
if (!bep_result) {
seq_nr = pkt->t_seq_nr;
seq_len = pkt->t_seq_len;
if(pkt->t_size != pkt->lnk_size - 6) {
com_result = FPC_BEP_RESULT_IO_ERROR;
continue;
}
if(buf_len + pkt->t_size < hcp_comm->pkt_size_max) {
memcpy(p, &pkt->t_pld, pkt->t_size);
p += pkt->t_size;
buf_len += pkt->t_size;
} else {
com_result = FPC_BEP_RESULT_NO_MEMORY;
}
#ifdef DEBUG
if (seq_len > 1)
LOG_DEBUG("Received data chunk %d of %d\n", seq_nr, seq_len);
#endif
} else {
bmlite_on_error(BMLITE_ERROR_SEND_CMD, bep_result);
return bep_result;
}
}
hcp_comm->pkt_size = buf_len;
if(com_result != FPC_BEP_RESULT_OK) {
bmlite_on_error(BMLITE_ERROR_SEND_CMD, com_result);
}
return com_result;
}
static fpc_bep_result_t _rx_link(HCP_comm_t *hcp_comm)
{
// Get size, msg and CRC
fpc_bep_result_t result = hcp_comm->read(4, hcp_comm->txrx_buffer, hcp_comm->phy_rx_timeout, NULL);
_HPC_pkt_t *pkt = (_HPC_pkt_t *)hcp_comm->txrx_buffer;
uint16_t size;
if (result) {
LOG_DEBUG("Timed out waiting for response.\n");
return result;
}
size = pkt->lnk_size;
// Check if size plus header and crc is larger than max package size.
if (MTU < size + 8) {
// LOG_DEBUG("S: Invalid size %d, larger than MTU %d.\n", size, MTU);
bmlite_on_error(BMLITE_ERROR_SEND_CMD, FPC_BEP_RESULT_IO_ERROR);
return FPC_BEP_RESULT_IO_ERROR;
}
hcp_comm->read(size + 4, hcp_comm->txrx_buffer + 4, 100, NULL);
uint32_t crc = *(uint32_t *)(hcp_comm->txrx_buffer + 4 + size);
uint32_t crc_calc = fpc_crc(0, hcp_comm->txrx_buffer+4, size);
if (crc_calc != crc) {
LOG_DEBUG("CRC mismatch. Calculated %04X, received %04X\n",
(unsigned int)crc_calc, (unsigned int)crc);
bmlite_on_error(BMLITE_ERROR_SEND_CMD, FPC_BEP_RESULT_IO_ERROR);
return FPC_BEP_RESULT_IO_ERROR;
}
// Send Ack
hcp_comm->write(4, (uint8_t *)&fpc_com_ack, 0, NULL);
return FPC_BEP_RESULT_OK;
}
fpc_bep_result_t bmlite_send(HCP_comm_t *hcp_comm)
{
uint16_t seq_nr = 1;
fpc_bep_result_t bep_result = FPC_BEP_RESULT_OK;
uint16_t data_left = hcp_comm->pkt_size;
uint8_t *p = hcp_comm->pkt_buffer;
_HPC_pkt_t *phy_frm = (_HPC_pkt_t *)hcp_comm->txrx_buffer;
// Application MTU size is PHY MTU - (Transport and Link overhead)
uint16_t app_mtu = MTU - 6 - 8;
// Calculate sequence length
uint16_t seq_len = (data_left / app_mtu) + 1;
phy_frm->lnk_chn = 0;
phy_frm->t_seq_len = seq_len;
for (seq_nr = 1; seq_nr <= seq_len && !bep_result; seq_nr++) {
phy_frm->t_seq_nr = seq_nr;
if (data_left < app_mtu) {
phy_frm->t_size = data_left;
} else {
phy_frm->t_size = app_mtu;
}
memcpy(&phy_frm->t_pld, p, phy_frm->t_size);
phy_frm->lnk_size = phy_frm->t_size + 6;
p += phy_frm->t_size;
data_left -= phy_frm->t_size;
bep_result = _tx_link(hcp_comm);
}
if(bep_result) {
bmlite_on_error(BMLITE_ERROR_SEND_CMD, bep_result);
}
return bep_result;
}
static fpc_bep_result_t _tx_link(HCP_comm_t *hcp_comm)
{
fpc_bep_result_t bep_result;
_HPC_pkt_t *pkt = (_HPC_pkt_t *)hcp_comm->txrx_buffer;
uint32_t crc_calc = fpc_crc(0, &pkt->t_size, pkt->lnk_size);
*(uint32_t *)(hcp_comm->txrx_buffer + pkt->lnk_size + 4) = crc_calc;
uint16_t size = pkt->lnk_size + 8;
bep_result = hcp_comm->write(size, hcp_comm->txrx_buffer, 0, NULL);
// Wait for ACK
uint32_t ack;
bep_result = hcp_comm->read(4, (uint8_t *)&ack, 500, NULL);
if (bep_result == FPC_BEP_RESULT_TIMEOUT) {
LOG_DEBUG("ASK read timeout\n");
bmlite_on_error(BMLITE_ERROR_SEND_CMD, FPC_BEP_RESULT_TIMEOUT);
return FPC_BEP_RESULT_IO_ERROR;
}
if(ack != fpc_com_ack) {
return FPC_BEP_RESULT_IO_ERROR;
}
return FPC_BEP_RESULT_OK;
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef HCP_H
#define HCP_H
#include "fpc_bep_types.h"
#include "fpc_hcp_common.h"
/** MTU for HCP physical layer */
#define MTU 256
/** Communication acknowledge definition */
#define FPC_BEP_ACK 0x7f01ff7f
typedef struct {
uint32_t size;
uint8_t *data;
} HCP_arg_t;
typedef struct {
/** Send data to BM-Lite */
fpc_bep_result_t (*write) (uint16_t, const uint8_t *, uint32_t, void *);
/** Receive data from BM-Lite */
fpc_bep_result_t (*read)(uint16_t, uint8_t *, uint32_t, void *);
/** Receive timeout (msec). Applys ONLY to receiving packet from BM-Lite on physical layer */
uint32_t phy_rx_timeout;
/** Data buffer for application layer */
uint8_t *pkt_buffer;
/** Size of data buffer */
uint32_t pkt_size_max;
/** Current size of incoming or outcoming command packet */
uint32_t pkt_size;
/** Buffer of MTU size for transport layer */
uint8_t *txrx_buffer;
/** Values of last argument pulled by bmlite_get_arg
Values are valid only right after bmlite_get_arg() call */
HCP_arg_t arg;
/** Result of execution command on BM-Lite */
fpc_bep_result_t bep_result;
} HCP_comm_t;
/**
* @brief Send prepared command packet to FPC BM-LIte
*
* @param[in] hcp_comm - pointer to HCP_comm struct
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_send(HCP_comm_t *hcp_comm);
/**
* @brief Receive answer from FPC BM-LIte
*
* @param[in] hcp_comm - pointer to HCP_comm struct
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_receive(HCP_comm_t *hcp_comm);
/**
* @brief Send prepared command packet to FPC BM-LIte and receive answer
*
* @param[in] hcp_comm - pointer to HCP_comm struct
*
* Returns result of executing command in BM-LIte in hcp_comm->bep_result
* if communication with BM-Lite was successful.
* Please not that some BM-Lite command does not return result in ARG_RESULT.
* They return data with some other argument instead.
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_tranceive(HCP_comm_t *hcp_comm);
/**
* @brief Initialize new command for BM-Lite
*
* @param[in] hcp_comm - pointer to HCP_comm struct
* @param[in] cmd - command to send
* @param[in] arg - Argument for the command without parameterd
* Use ARG_NONE and add arguments by bmlite_add_arg() if
* you need to add argument with parameter
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_init_cmd(HCP_comm_t *hcp_comm, uint16_t cmd, uint16_t arg);
/**
* @brief Add argument to command.
* Must be used only after command buffer is initialized by bmlite_init_cmd()
*
* @param[in] hcp_comm - pointer to HCP_comm struct
* @param[in] arg_type - argument key
* @param[in] arg_data - argument data
* @param[in] arg_size - argument data length
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_add_arg(HCP_comm_t *hcp_comm, uint16_t arg_type, void *arg_data, uint16_t arg_size);
/**
* @brief Search for argument in received answer.
*
* @param[in] hcp_comm - pointer to HCP_comm struct
* @param[in] arg_type - argument key
*
* If found, place pointer to argument data in receiving buffer to hcp_comm->arg.data
* and size of the argument in hcp_comm->arg.size
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_get_arg(HCP_comm_t *hcp_comm, uint16_t arg_type);
/**
* @brief Search for argument in received answer and copy argument's data
* to arg_data
*
* @param[in] hcp_comm - pointer to HCP_comm struct
* @param[in] arg_type - argument key
* @param[out] arg_data - pointer for memory to copy argument value
* @param[out] arg_data_size - size of data area for copying argument value
*
* If found, argument's data will be copyed to arg_data
* If received argument's size greater that arg_data_size, the copyed data will be
* truncated to arg_data_size.
* Still hcp_comm->arg.data will be pointed to argument's data in receiving buffer
* and real size of the argument will be hcp_comm->arg.size
*
* @return ::fpc_bep_result_t
*/
fpc_bep_result_t bmlite_copy_arg(HCP_comm_t *hcp_comm, uint16_t arg_key, void *arg_data, uint16_t arg_data_size);
#endif

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2020 Fingerprint Cards AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modified by Andrey Perminov <andrey.ppp@gmail.com>
* for BM-Lite applications
*/
/**
* @file platform.c
* @brief Platform specific functions
*/
#ifdef DEBUG_COMM
#include <stdio.h>
#define LOG_DEBUG(...) printf(__VA_ARGS__)
#else
#define LOG_DEBUG(...)
#endif
#include "fpc_bep_types.h"
#include "platform.h"
#include "bmlite_hal.h"
fpc_bep_result_t platform_init(void *params)
{
fpc_bep_result_t result;
result = hal_board_init(params);
if(result == FPC_BEP_RESULT_OK) {
hal_timebase_init();
platform_bmlite_reset();
}
return result;
}
void platform_bmlite_reset(void)
{
hal_bmlite_reset(true);
hal_timebase_busy_wait(100);
hal_bmlite_reset(false);
hal_timebase_busy_wait(100);
}
fpc_bep_result_t platform_bmlite_spi_send(uint16_t size, const uint8_t *data, uint32_t timeout,
void *session)
{
#ifdef DEBUG_COMM
LOG_DEBUG("-> ");
for (int i=0; i<size; i++)
LOG_DEBUG("%02X ", data[i]);
LOG_DEBUG("\n");
#endif
return hal_bmlite_spi_write_read((uint8_t *)data, size);
}
fpc_bep_result_t platform_bmlite_spi_receive(uint16_t size, uint8_t *data, uint32_t timeout,
void *session)
{
volatile uint32_t start_time = hal_timebase_get_tick();
volatile uint32_t curr_time = start_time;
// Wait for BM_Lite Ready for timeout or indefinitely if timeout is 0
while (!hal_bmlite_get_status() &&
(!timeout || (curr_time = hal_timebase_get_tick()) - start_time < timeout)) {
if(hal_check_button_pressed()) {
return FPC_BEP_RESULT_TIMEOUT;
}
}
if(timeout && curr_time - start_time >= timeout) {
return FPC_BEP_RESULT_TIMEOUT;
}
fpc_bep_result_t res = hal_bmlite_spi_write_read(data, size);
#ifdef DEBUG_COMM
LOG_DEBUG("<- ");
for (int i=0; i<size; i++)
LOG_DEBUG("%02X ", data[i]);
LOG_DEBUG("\n");
#endif
return res;
}
__attribute__((weak)) uint32_t hal_check_button_pressed()
{
return 0;
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2020 Fingerprint Cards AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Modified by Andrey Perminov <andrey.ppp@gmail.com>
* for FPC BM-Lite applications
*/
#ifndef PLATFORM_H
#define PLATFORM_H
/**
* @file platform.h
* @brief Platform specific function interface
*/
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "fpc_bep_types.h"
/**
* @brief Initializes board
*
* @param[in] params - pointer to additional parameters.
*/
fpc_bep_result_t platform_init(void *params);
/**
* @brief Does BM-Lite HW Reset
*
*/
void platform_bmlite_reset(void);
/**
* @brief Sends data over SPI port in blocking mode.
*
* @param[in] size Number of bytes to send.
* @param[in] data Data buffer to send.
* @param[in] timeout Timeout in ms. Use 0 for infinity.
*
* @return ::fpc_com_result_t
*/
fpc_bep_result_t platform_bmlite_spi_send(uint16_t size, const uint8_t *data, uint32_t timeout,
void *session);
/**
* @brief Sends data over UART port in blocking mode.
*
* @param[in] size Number of bytes to send.
* @param[in] data Data buffer to send.
* @param[in] timeout Timeout in ms. Use 0 for infinity.
*
* @return ::fpc_com_result_t
*/
fpc_bep_result_t platform_bmlite_uart_send(uint16_t size, const uint8_t *data, uint32_t timeout,
void *session);
/**
* @brief Receives data from SPI port in blocking mode.
*
* @param[in] size Number of bytes to receive.
* @param[in, out] data Data buffer to fill.
* @param[in] timeout Timeout in ms. Use 0 for infinity.
*
* @return ::fpc_com_result_t
*/
fpc_bep_result_t platform_bmlite_spi_receive(uint16_t size, uint8_t *data, uint32_t timeout,
void *session);
/**
* @brief Receives data from UART port in blocking mode.
*
* @param[in] size Number of bytes to receive.
* @param[in, out] data Data buffer to fill.
* @param[in] timeout Timeout in ms. Use 0 for infinity.
*
* @return ::fpc_com_result_t
*/
fpc_bep_result_t platform_bmlite_uart_receive(uint16_t size, uint8_t *data, uint32_t timeout,
void *session);
/**
* @brief Stops execution if a debug interface is attached.
*/
void platform_halt_if_debug(void);
/**
* @brief Performs a software reset.
*/
void platform_sw_reset(void) __attribute__((__noreturn__));
#endif /* PLATFORM_H */