drivers: sensor: grow_r502a: move enroll, search, delete to application
Removed fps_enroll, fps_search and fps_delete from
driver code, since they did application usage inside
driver. add the following attributes to achieve the
above functionality from application.
1. SENSOR_ATTR_R502A_CAPTURE
2. SENSOR_ATTR_R502A_TEMPLATE_CREATE
3. SENSOR_ATTR_R502A_RECORD_ADD
4. SENSOR_ATTR_R502A_RECORD_LOAD
5. SENSOR_ATTR_R502A_COMPARE
Signed-off-by: Dinesh Kumar K <dinesh@linumiz.com>
diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c
index 0047f94..69b66ee 100644
--- a/drivers/sensor/grow_r502a/grow_r502a.c
+++ b/drivers/sensor/grow_r502a/grow_r502a.c
@@ -335,8 +335,10 @@
static int fps_store_model(const struct device *dev, uint16_t id)
{
+ struct grow_r502a_data *drv_data = dev->data;
union r502a_packet rx_packet = {0};
char const store_model_len = 4;
+ int ret = 0;
struct led_params led_ctrl = {
.ctrl_code = LED_CTRL_BREATHING,
@@ -351,11 +353,14 @@
};
sys_put_be16(id, &tx_packet.data[2]);
+ k_mutex_lock(&drv_data->lock, K_FOREVER);
+
transceive_packet(dev, &tx_packet, &rx_packet, store_model_len);
if (rx_packet.pid != R502A_ACK_PACKET) {
LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid);
- return -EIO;
+ ret = -EIO;
+ goto unlock;
}
if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) {
@@ -366,16 +371,19 @@
LOG_INF("Fingerprint stored! at ID #%d", id);
} else {
LOG_ERR("Error storing model 0x%X", rx_packet.buf[R502A_CC_IDX]);
- return -EIO;
+ ret = -EIO;
}
-
- return 0;
+unlock:
+ k_mutex_unlock(&drv_data->lock);
+ return ret;
}
static int fps_delete_model(const struct device *dev, uint16_t id, uint16_t count)
{
+ struct grow_r502a_data *drv_data = dev->data;
union r502a_packet rx_packet = {0};
char const delete_model_len = 5;
+ int ret = 0;
union r502a_packet tx_packet = {
.pid = R502A_COMMAND_PACKET,
@@ -384,21 +392,25 @@
sys_put_be16(id, &tx_packet.data[1]);
sys_put_be16(count + R502A_DELETE_COUNT_OFFSET, &tx_packet.data[3]);
+ k_mutex_lock(&drv_data->lock, K_FOREVER);
+
transceive_packet(dev, &tx_packet, &rx_packet, delete_model_len);
if (rx_packet.pid != R502A_ACK_PACKET) {
LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid);
- return -EIO;
+ ret = -EIO;
+ goto unlock;
}
if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) {
LOG_INF("Fingerprint Deleted from ID #%d to #%d", id, (id + count));
} else {
LOG_ERR("Error deleting image 0x%X", rx_packet.buf[R502A_CC_IDX]);
- return -EIO;
+ ret = -EIO;
}
-
- return 0;
+unlock:
+ k_mutex_unlock(&drv_data->lock);
+ return ret;
}
static int fps_empty_db(const struct device *dev)
@@ -429,7 +441,6 @@
LOG_ERR("Error emptying fingerprint library 0x%X",
rx_packet.buf[R502A_CC_IDX]);
ret = -EIO;
- goto unlock;
}
unlock:
@@ -437,11 +448,12 @@
return ret;
}
-static int fps_search(const struct device *dev, uint8_t char_buf_idx)
+static int fps_search(const struct device *dev, struct sensor_value *val)
{
struct grow_r502a_data *drv_data = dev->data;
union r502a_packet rx_packet = {0};
char const search_len = 6;
+ int ret = 0;
struct led_params led_ctrl = {
.ctrl_code = LED_CTRL_BREATHING,
@@ -452,16 +464,19 @@
union r502a_packet tx_packet = {
.pid = R502A_COMMAND_PACKET,
- .data = {R502A_SEARCH, char_buf_idx}
+ .data = {R502A_SEARCH, R502A_CHAR_BUF_1}
};
sys_put_be16(R02A_LIBRARY_START_IDX, &tx_packet.data[2]);
sys_put_be16(R502A_DEFAULT_CAPACITY, &tx_packet.data[4]);
+ k_mutex_lock(&drv_data->lock, K_FOREVER);
+
transceive_packet(dev, &tx_packet, &rx_packet, search_len);
if (rx_packet.pid != R502A_ACK_PACKET) {
LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid);
- return -EIO;
+ ret = -EIO;
+ goto unlock;
}
if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) {
@@ -469,37 +484,120 @@
led_ctrl.color_idx = LED_COLOR_PURPLE;
led_ctrl.cycle = 0x01;
fps_led_control(dev, &led_ctrl);
- drv_data->finger_id = sys_get_be16(&rx_packet.data[1]);
- drv_data->matching_score = sys_get_be16(&rx_packet.data[3]);
- LOG_INF("Found a matching print! at ID #%d", drv_data->finger_id);
- } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND) {
+ val->val1 = sys_get_be16(&rx_packet.data[1]);
+ val->val2 = sys_get_be16(&rx_packet.data[3]);
+ LOG_INF("Found a matching print! at ID #%d", val->val1);
+ } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND_CC) {
led_ctrl.ctrl_code = LED_CTRL_BREATHING;
led_ctrl.color_idx = LED_COLOR_RED;
led_ctrl.cycle = 0x02;
fps_led_control(dev, &led_ctrl);
LOG_ERR("Did not find a match");
- return -ENOENT;
+ ret = -ENOENT;
} else {
led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS;
led_ctrl.color_idx = LED_COLOR_RED;
fps_led_control(dev, &led_ctrl);
LOG_ERR("Error searching for image 0x%X", rx_packet.buf[R502A_CC_IDX]);
- return -EIO;
+ ret = -EIO;
}
-
- return 0;
+unlock:
+ k_mutex_unlock(&drv_data->lock);
+ return ret;
}
-static int fps_enroll(const struct device *dev, const struct sensor_value *val)
+static int fps_load_template(const struct device *dev, uint16_t id)
{
struct grow_r502a_data *drv_data = dev->data;
- int ret = -1;
+ union r502a_packet rx_packet = {0};
+ char const load_tmp_len = 4;
+ int ret = 0;
- if (val->val1 < 0 || val->val1 > R502A_DEFAULT_CAPACITY) {
- LOG_ERR("Invalid ID number");
- return -EINVAL;
+ union r502a_packet tx_packet = {
+ .pid = R502A_COMMAND_PACKET,
+ .data = {R502A_LOAD, R502A_CHAR_BUF_1}
+ };
+ sys_put_be16(id, &tx_packet.data[2]);
+
+ k_mutex_lock(&drv_data->lock, K_FOREVER);
+
+ transceive_packet(dev, &tx_packet, &rx_packet, load_tmp_len);
+
+ if (rx_packet.pid != R502A_ACK_PACKET) {
+ LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid);
+ ret = -EIO;
+ goto unlock;
}
+ if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) {
+ LOG_DBG("Load template data from id #%d to Char_buffer2", id);
+ } else {
+ LOG_ERR("Error Loading template 0x%X",
+ rx_packet.buf[R502A_CC_IDX]);
+ ret = -EIO;
+ }
+
+unlock:
+ k_mutex_unlock(&drv_data->lock);
+ return ret;
+}
+
+static int fps_match_templates(const struct device *dev, struct sensor_value *val)
+{
+ struct grow_r502a_data *drv_data = dev->data;
+ union r502a_packet rx_packet = {0};
+ char const match_templates_len = 1;
+ int ret = 0;
+
+ struct led_params led_ctrl = {
+ .ctrl_code = LED_CTRL_BREATHING,
+ .color_idx = LED_COLOR_BLUE,
+ .speed = LED_SPEED_HALF,
+ .cycle = 0x01,
+ };
+
+ union r502a_packet tx_packet = {
+ .pid = R502A_COMMAND_PACKET,
+ .data = {R502A_MATCH}
+ };
+
+ k_mutex_lock(&drv_data->lock, K_FOREVER);
+
+ transceive_packet(dev, &tx_packet, &rx_packet, match_templates_len);
+
+ if (rx_packet.pid != R502A_ACK_PACKET) {
+ LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid);
+ ret = -EIO;
+ goto unlock;
+ }
+
+ if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) {
+ fps_led_control(dev, &led_ctrl);
+ val->val1 = R502A_FINGER_MATCH_FOUND;
+ val->val2 = sys_get_be16(&rx_packet.data[1]);
+ LOG_INF("Fingerprint matched with a score %d", val->val2);
+ } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_MATCH_CC) {
+ val->val1 = R502A_FINGER_MATCH_NOT_FOUND;
+ LOG_ERR("Fingerprint not matched");
+ ret = -ENOENT;
+ } else {
+ led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS;
+ led_ctrl.color_idx = LED_COLOR_RED;
+ fps_led_control(dev, &led_ctrl);
+ LOG_ERR("Error Matching templates 0x%X",
+ rx_packet.buf[R502A_CC_IDX]);
+ ret = -EIO;
+ }
+unlock:
+ k_mutex_unlock(&drv_data->lock);
+ return ret;
+}
+
+static int fps_capture(const struct device *dev)
+{
+ struct grow_r502a_data *drv_data = dev->data;
+ int ret;
+
k_mutex_lock(&drv_data->lock, K_FOREVER);
ret = fps_get_image(dev);
@@ -518,63 +616,6 @@
}
ret = fps_image_to_char(dev, R502A_CHAR_BUF_2);
- if (ret != 0) {
- goto unlock;
- }
-
- ret = fps_create_model(dev);
- if (ret != 0) {
- goto unlock;
- }
-
- ret = fps_store_model(dev, val->val1);
-
-unlock:
- k_mutex_unlock(&drv_data->lock);
- return ret;
-}
-
-static int fps_delete(const struct device *dev, const struct sensor_value *val)
-{
- struct grow_r502a_data *drv_data = dev->data;
- int ret = -1;
-
- k_mutex_lock(&drv_data->lock, K_FOREVER);
-
- ret = fps_delete_model(dev, val->val1, val->val2);
- if (ret != 0) {
- goto unlock;
- }
-
- ret = fps_get_template_count(dev);
-
-unlock:
- k_mutex_unlock(&drv_data->lock);
- return ret;
-}
-
-static int fps_match(const struct device *dev, struct sensor_value *val)
-{
- struct grow_r502a_data *drv_data = dev->data;
- int ret = -1;
-
- k_mutex_lock(&drv_data->lock, K_FOREVER);
-
- ret = fps_get_image(dev);
- if (ret != 0) {
- goto unlock;
- }
-
- ret = fps_image_to_char(dev, R502A_CHAR_BUF_1);
- if (ret != 0) {
- goto unlock;
- }
-
- ret = fps_search(dev, R502A_CHAR_BUF_1);
- if (ret == 0) {
- val->val1 = drv_data->finger_id;
- val->val2 = drv_data->matching_score;
- }
unlock:
k_mutex_unlock(&drv_data->lock);
@@ -643,12 +684,18 @@
}
switch ((enum sensor_attribute_grow_r502a)attr) {
+ case SENSOR_ATTR_R502A_CAPTURE:
+ return fps_capture(dev);
+ case SENSOR_ATTR_R502A_TEMPLATE_CREATE:
+ return fps_create_model(dev);
case SENSOR_ATTR_R502A_RECORD_ADD:
- return fps_enroll(dev, val);
+ return fps_store_model(dev, val->val1);
case SENSOR_ATTR_R502A_RECORD_DEL:
- return fps_delete(dev, val);
+ return fps_delete_model(dev, val->val1, val->val2);
case SENSOR_ATTR_R502A_RECORD_EMPTY:
return fps_empty_db(dev);
+ case SENSOR_ATTR_R502A_RECORD_LOAD:
+ return fps_load_template(dev, val->val1);
default:
LOG_ERR("Sensor attribute not supported");
return -ENOTSUP;
@@ -660,7 +707,6 @@
enum sensor_attribute attr, struct sensor_value *val)
{
int ret;
- struct grow_r502a_data *drv_data = dev->data;
if ((enum sensor_channel_grow_r502a)chan != SENSOR_CHAN_FINGERPRINT) {
LOG_ERR("Channel not supported");
@@ -669,11 +715,14 @@
switch ((enum sensor_attribute_grow_r502a)attr) {
case SENSOR_ATTR_R502A_RECORD_FIND:
- ret = fps_match(dev, val);
+ ret = fps_search(dev, val);
break;
case SENSOR_ATTR_R502A_RECORD_FREE_IDX:
ret = fps_read_template_table(dev, &val->val1);
break;
+ case SENSOR_ATTR_R502A_COMPARE:
+ ret = fps_match_templates(dev, val);
+ break;
default:
LOG_ERR("Sensor attribute not supported");
ret = -ENOTSUP;
diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h
index f61e7ed..0004435 100644
--- a/drivers/sensor/grow_r502a/grow_r502a.h
+++ b/drivers/sensor/grow_r502a/grow_r502a.h
@@ -61,7 +61,6 @@
*/
#define R502A_OK 0x00 /*commad execution complete*/
-#define R502A_NOT_FOUND 0x09 /*fail to find the matching finger*/
/*Package Identifier's definition*/
#define R502A_COMMAND_PACKET 0x1 /*Command packet*/
@@ -95,6 +94,11 @@
#define R502A_HANDSHAKE 0x40 /*Handshake*/
#define R502A_BADPACKET 0xFE /* Bad packet was sent*/
+#define R502A_NOT_MATCH_CC 0x08 /* templates of two buffers not matching*/
+#define R502A_NOT_FOUND_CC 0x09 /*fail to find the matching finger*/
+#define R502A_FINGER_MATCH_NOT_FOUND 0
+#define R502A_FINGER_MATCH_FOUND 1
+
#define R502A_STARTCODE 0xEF01 /*Fixed value, High byte transferred first*/
#define R502A_DEFAULT_PASSWORD 0x00000000
#define R502A_DEFAULT_ADDRESS 0xFFFFFFFF
@@ -187,8 +191,6 @@
struct k_mutex lock;
struct k_sem uart_rx_sem;
- uint16_t finger_id;
- uint16_t matching_score;
uint16_t template_count;
};
diff --git a/include/zephyr/drivers/sensor/grow_r502a.h b/include/zephyr/drivers/sensor/grow_r502a.h
index 8b0db47..fafcfd7 100644
--- a/include/zephyr/drivers/sensor/grow_r502a.h
+++ b/include/zephyr/drivers/sensor/grow_r502a.h
@@ -24,16 +24,53 @@
};
enum sensor_attribute_grow_r502a {
- /** Add values to the sensor which are having record storage facility */
- SENSOR_ATTR_R502A_RECORD_ADD = SENSOR_ATTR_PRIV_START,
+ /** To capture finger and store as feature file in
+ * RAM buffers char_buf_1 and char_buf_2.
+ */
+ SENSOR_ATTR_R502A_CAPTURE = SENSOR_ATTR_PRIV_START,
+ /** create template from feature files at RAM buffers
+ * char_buf_1 & char_buf_2 and store a template data
+ * back in both RAM buffers char_buf_1 and char_buf_2.
+ */
+ SENSOR_ATTR_R502A_TEMPLATE_CREATE,
+ /** Add template to the sensor record storage */
+ /**
+ * @param val->val1 record index for template to be
+ * stored in the sensor device's flash
+ * library.
+ */
+ SENSOR_ATTR_R502A_RECORD_ADD,
/** To find requested data in record storage */
+ /**
+ * @result val->val1 matched record index.
+ * val->val2 matching score.
+ */
SENSOR_ATTR_R502A_RECORD_FIND,
/** To delete mentioned data from record storage */
+ /**
+ * @param val->val1 record start index to be deleted.
+ * @param val->val2 number of records to be deleted.
+ */
SENSOR_ATTR_R502A_RECORD_DEL,
/** To get available position to store data on record storage */
SENSOR_ATTR_R502A_RECORD_FREE_IDX,
/** To empty the storage record*/
SENSOR_ATTR_R502A_RECORD_EMPTY,
+ /** To load template from storage to RAM buffer of sensor*/
+ /**
+ * @param val->val1 record start index to be loaded in
+ * device internal RAM buffer.
+ */
+ SENSOR_ATTR_R502A_RECORD_LOAD,
+ /** To template data stored in sensor's RAM buffer*/
+ /**
+ * @result
+ * val->val1 match result.
+ * [R502A_FINGER_MATCH_FOUND or
+ * R502A_FINGER_MATCH_NOT_FOUND]
+ * val->val2 matching score.
+ */
+ SENSOR_ATTR_R502A_COMPARE,
};
#ifdef __cplusplus
diff --git a/samples/sensor/grow_r502a/src/main.c b/samples/sensor/grow_r502a/src/main.c
index 583d1ed..573a03a 100644
--- a/samples/sensor/grow_r502a/src/main.c
+++ b/samples/sensor/grow_r502a/src/main.c
@@ -11,32 +11,54 @@
#include <zephyr/drivers/sensor/grow_r502a.h>
static bool enroll;
-static struct sensor_value fid, val;
+static struct sensor_value fid_get, count, find, del;
-static void finger_match(const struct device *dev)
+static void finger_find(const struct device *dev)
{
- struct sensor_value input;
int ret;
- ret = sensor_attr_get(dev, SENSOR_CHAN_FINGERPRINT,
- SENSOR_ATTR_R502A_RECORD_FIND, &input);
+ ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT,
+ SENSOR_ATTR_R502A_CAPTURE, NULL);
if (ret != 0) {
- printk("Sensor attr get failed %d\n", ret);
+ printk("Capture fingerprint failed %d\n", ret);
return;
}
- printk("Matched ID : %d\n", input.val1);
- printk("confidence : %d\n", input.val2);
+
+ ret = sensor_attr_get(dev, SENSOR_CHAN_FINGERPRINT,
+ SENSOR_ATTR_R502A_RECORD_FIND, &find);
+ if (ret != 0) {
+ printk("Find fingerprint failed %d\n", ret);
+ return;
+ }
+ printk("Matched ID : %d\n", find.val1);
+ printk("confidence : %d\n", find.val2);
}
static void finger_enroll(const struct device *dev)
{
int ret;
- ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, SENSOR_ATTR_R502A_RECORD_ADD, &fid);
+ ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT,
+ SENSOR_ATTR_R502A_CAPTURE, NULL);
+ if (ret != 0) {
+ printk("Capture fingerprint failed %d\n", ret);
+ return;
+ }
- if (ret == 0) {
- printk("Fingerprint successfully stored at #%d\n", fid.val1);
+ ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT,
+ SENSOR_ATTR_R502A_TEMPLATE_CREATE, NULL);
+ if (ret != 0) {
+ printk("Create template failed %d\n", ret);
+ return;
+ }
+
+ ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT,
+ SENSOR_ATTR_R502A_RECORD_ADD, &fid_get);
+ if (!ret) {
+ printk("Fingerprint successfully stored at #%d\n", fid_get.val1);
enroll = false;
+ } else {
+ printk("Fingerprint store failed %d\n", ret);
}
}
@@ -49,12 +71,12 @@
printk("Sample Fetch Error %d\n", ret);
return;
}
- ret = sensor_channel_get(dev, SENSOR_CHAN_FINGERPRINT, &val);
+ ret = sensor_channel_get(dev, SENSOR_CHAN_FINGERPRINT, &count);
if (ret < 0) {
printk("Channel Get Error %d\n", ret);
return;
}
- printk("template count : %d\n", val.val1);
+ printk("template count : %d\n", count.val1);
}
static void trigger_handler(const struct device *dev,
@@ -64,13 +86,12 @@
finger_enroll(dev);
} else {
template_count_get(dev);
- finger_match(dev);
+ finger_find(dev);
}
}
int main(void)
{
- static struct sensor_value del, fid_get;
int ret;
const struct device *dev = DEVICE_DT_GET_ONE(hzgrow_r502a);
@@ -103,9 +124,8 @@
}
printk("Fingerprint template free idx at ID #%d\n", fid_get.val1);
- fid.val1 = fid_get.val1;
printk("Waiting for valid finger to enroll as ID #%d\n"
- "Place your finger\n", fid.val1);
+ "Place your finger\n", fid_get.val1);
enroll = true;
if (IS_ENABLED(CONFIG_GROW_R502A_TRIGGER)) {