Commit e08ce0ed authored by Dinesh Kumar K's avatar Dinesh Kumar K Committed by Anas Nashif
Browse files

drivers: sensor: grow_r502a: add upload and download template

1. Add functionality for upload and download fingerprint
template data of the R502A fingerprint sensor device.
2. change data type for data_len parameter of
transceive_packet function to uint16_t as it may hold
value 256 for dowload template data to sensor.

Signed-off-by: default avatarDinesh Kumar K <dinesh@linumiz.com>
parent 7ae0158e
Loading
Loading
Loading
Loading
+130 −1
Changes for drivers/sensor/grow_r502a/grow_r502a.c: 130 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
LOG_MODULE_REGISTER(GROW_R502A, CONFIG_SENSOR_LOG_LEVEL);

static int transceive_packet(const struct device *dev, union r502a_packet *tx_packet,
				union r502a_packet *rx_packet, char const data_len)
				union r502a_packet *rx_packet, uint16_t data_len)
{
	const struct grow_r502a_config *cfg = dev->config;
	struct grow_r502a_data *drv_data = dev->data;
@@ -784,6 +784,135 @@ unlock:
	return ret;
}

/**
 * @brief	upload template from sensor device's RAM buffer 1 to controller.
 *
 * @result	temp->data	holds the template to be uploaded to controller.
 *		temp->len	holds the length of the template.
 */
int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp)
{
	struct grow_r502a_data *drv_data = dev->data;
	union r502a_packet rx_packet = {0};
	char const upload_temp_len = 2;
	int ret = 0, idx = 0;

	if (!temp->data || (temp->len < R502A_TEMPLATE_MAX_SIZE)) {
		LOG_ERR("Invalid temp data");
		return -EINVAL;
	}

	union r502a_packet tx_packet = {
		.pid = R502A_COMMAND_PACKET,
		.data = {R502A_UPCHAR, R502A_CHAR_BUF_1}
	};

	k_mutex_lock(&drv_data->lock, K_FOREVER);

	ret = transceive_packet(dev, &tx_packet, &rx_packet, upload_temp_len);
	if (ret != 0) {
		goto unlock;
	}

	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("Upload to host controller");
	} else {
		LOG_ERR("Error uploading template 0x%X",
					rx_packet.buf[R502A_CC_IDX]);
		ret = -EIO;
		goto unlock;
	}

	do {
		ret = transceive_packet(dev, NULL, &rx_packet, 0);
		if (ret != 0) {
			goto unlock;
		}

		memcpy(&temp->data[idx], &rx_packet.data,
				sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN);
		idx += sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN;
	} while (rx_packet.pid != R502A_END_DATA_PACKET);

	temp->len = idx;

unlock:
	k_mutex_unlock(&drv_data->lock);
	return ret;
}

/**
 * @brief	download template from controller to sensor device's RAM buffer.
 * @Notes	char_buf_id - other than value 1 will be considered as value 2
 *				by R502A sensor.
 */
int fps_download_char_buf(const struct device *dev, uint8_t char_buf_id,
						const struct r502a_template *temp)
{
	struct grow_r502a_data *drv_data = dev->data;
	union r502a_packet rx_packet = {0};
	char const down_temp_len = 2;
	int ret = 0, i = 0;

	if (!temp->data || (temp->len < R502A_TEMPLATE_MAX_SIZE)) {
		LOG_ERR("Invalid temp data");
		return -EINVAL;
	}

	union r502a_packet tx_packet = {
		.pid = R502A_COMMAND_PACKET,
		.data = {R502A_DOWNCHAR, char_buf_id}
	};

	k_mutex_lock(&drv_data->lock, K_FOREVER);

	ret = transceive_packet(dev, &tx_packet, &rx_packet, down_temp_len);
	if (ret != 0) {
		goto unlock;
	}

	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("Download to R502A sensor");
	} else {
		LOG_ERR("Error downloading template 0x%X",
					rx_packet.buf[R502A_CC_IDX]);
		ret = -EIO;
		goto unlock;
	}

	while (i < (R502A_TEMPLATE_MAX_SIZE - CONFIG_R502A_DATA_PKT_SIZE)) {
		tx_packet.pid = R502A_DATA_PACKET;
		memcpy(tx_packet.data, &temp->data[i], CONFIG_R502A_DATA_PKT_SIZE);

		ret = transceive_packet(dev, &tx_packet, NULL, CONFIG_R502A_DATA_PKT_SIZE);
		if (ret != 0) {
			goto unlock;
		}

		i += CONFIG_R502A_DATA_PKT_SIZE;
	}

	memcpy(tx_packet.data, &temp->data[i], (R502A_TEMPLATE_MAX_SIZE - i));
	tx_packet.pid = R502A_END_DATA_PACKET;
	ret = transceive_packet(dev, &tx_packet, NULL, (R502A_TEMPLATE_MAX_SIZE - i));

unlock:
	k_mutex_unlock(&drv_data->lock);
	return ret;
}

static int fps_init(const struct device *dev)
{
	struct grow_r502a_data *drv_data = dev->data;
+1 −0
Changes for drivers/sensor/grow_r502a/grow_r502a.h: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@

#define R502A_CHAR_BUF_SIZE 384 /* Maximum size of characteristic value buffer*/
#define R502A_TEMPLATE_SIZE 768 /* Maximum size of template, twice of CHAR_BUF*/
#define R502A_TEMPLATE_MAX_SIZE (R502A_CHAR_BUF_TOTAL * R502A_TEMPLATE_SIZE)

#define R502A_MAX_BUF_SIZE  (CONFIG_R502A_DATA_PKT_SIZE + R502A_COMMON_ACK_LEN)

+7 −0
Changes for include/zephyr/drivers/sensor/grow_r502a.h: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -57,6 +57,10 @@ struct r502a_sys_param {
	uint32_t baud;
} __packed;

struct r502a_template {
	uint8_t *data;
	size_t len;
};
enum sensor_channel_grow_r502a {
	/** Fingerprint template count, ID number for enrolling and searching*/
	SENSOR_CHAN_FINGERPRINT = SENSOR_CHAN_PRIV_START,
@@ -127,6 +131,9 @@ enum sensor_attribute_grow_r502a {
};

int r502a_read_sys_param(const struct device *dev, struct r502a_sys_param *val);
int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp);
int fps_download_char_buf(const struct device *dev, uint8_t char_buf_id,
				const struct r502a_template *temp);

#ifdef __cplusplus
}