Can we use PN7160 NFC Reader instead of PN532 Adafruit NFC Reader

Hello,

In my project, I want to use PN7160 NFC Reader instead of PN532 NFC Reader because in nRF SDK had a library for PN532 but the library is comfortable for PN7160 or not .??

Yes, i can go for PN532 also but they are not recommended for a new design by anybody. So Please let us know if it's comfortable or not.??

Thank You.

Parents Reply Children
  • Are these build errors when trying to build the project? If so, can you show me the error log, and please let me know what SDK version you're using, as the guide was written for NCS 1.7.1, so you will need to do some steps to migrate to newer SDK versions. The steps should be covered in the release notes of each version of the SDK.

    Best regards,

    Simon

  • Hello simonr,

    Thanks for the reply, i tried another blog, and 

    i got working on the write custom service but for the read custom service whatever the data received from the ST25's reader, i couldn't send it to the mobile app. i don' know where exactly the data stored in the custom service. 

    when i debug it i got to know that the NFC Tag data received in the zephyr.lst file and I couldn't store any buffer and use it in the main.c 

    this is the code ,

    main.c
    
    
    /* main.c - Application main entry point */
    
    /*
     * Copyright (c) 2019 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <stdbool.h>
    #include <string.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <st25r3911b_nfca.h>
    #include <nfc/ndef/msg_parser.h>
    #include <nfc/ndef/le_oob_rec_parser.h>
    #include <nfc/t2t/parser.h>
    #include <nfc/t4t/ndef_file.h>
    #include <nfc/t4t/isodep.h>
    #include <nfc/t4t/hl_procedure.h>
    #include <nfc/ndef/ch_rec_parser.h>
    #include <zephyr/sys/byteorder.h>
    #include <errno.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/drivers/gpio.h>
    #include <soc.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <my_service.h>
    
    #define NFCA_BD 128
    #define BITS_IN_BYTE 8
    #define MAX_TLV_BLOCKS 10
    #define MAX_NDEF_RECORDS 10
    #define NFCA_T2T_BUFFER_SIZE 1024
    #define NFCA_LAST_BIT_MASK 0x80
    #define NFCA_FDT_ALIGN_84 84
    #define NFCA_FDT_ALIGN_20 20
    
    #define NFC_T2T_READ_CMD 0x30
    #define NFC_T2T_READ_CMD_LEN 0x02
    
    #define NFC_T4T_ISODEP_FSD 256
    #define NFC_T4T_ISODEP_RX_DATA_MAX_SIZE 1024
    #define NFC_T4T_APDU_MAX_SIZE 1024
    
    #define NFC_NDEF_REC_PARSER_BUFF_SIZE 128
    
    #define NFC_TX_DATA_LEN NFC_T4T_ISODEP_FSD
    #define NFC_RX_DATA_LEN NFC_T4T_ISODEP_FSD
    
    #define T2T_MAX_DATA_EXCHANGE 16
    #define TAG_TYPE_2_DATA_AREA_MULTIPLICATOR 8
    #define TAG_TYPE_2_DATA_AREA_SIZE_OFFSET (NFC_T2T_CC_BLOCK_OFFSET + 2)
    #define TAG_TYPE_2_BLOCKS_PER_EXCHANGE (T2T_MAX_DATA_EXCHANGE / NFC_T2T_BLOCK_SIZE)
    
    #define TRANSMIT_DELAY 3000
    #define ALL_REQ_DELAY 2000
    
    #define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)
    int flag=0;
    static K_SEM_DEFINE(ble_init_ok, 0, 1);
    static const struct bt_data ad[] = 
    {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = 
    {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, MY_SERVICE_UUID),
    };
    
    struct bt_conn *my_connection;
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	my_connection = conn;
    
    	if (err) 
    	{
    		printk("Connection failed (err %u)\n", err);
    		return;
    	}
    	else if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection established!		\n\
    		Connected to: %s					\n\
    		Role: %u							\n\
    		Connection interval: %u				\n\
    		Slave latency: %u					\n\
    		Connection supervisory timeout: %u	\n"
    		, addr, info.role, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason %u)\n", reason);
    }
    
    static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
    {
    	//If acceptable params, return true, otherwise return false.
    	return true; 
    }
    
    static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency, uint16_t timeout)
    {
    	struct bt_conn_info info; 
    	char addr[BT_ADDR_LE_STR_LEN];
    	
    	if(bt_conn_get_info(conn, &info))
    	{
    		printk("Could not parse connection info\n");
    	}
    	else
    	{
    		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    		
    		printk("Connection parameters updated!	\n\
    		Connected to: %s						\n\
    		New Connection Interval: %u				\n\
    		New Slave Latency: %u					\n\
    		New Connection Supervisory Timeout: %u	\n"
    		, addr, info.le.interval, info.le.latency, info.le.timeout);
    	}
    }
    
    static struct bt_conn_cb conn_callbacks = 
    {
    	.connected				= connected,
    	.disconnected   		= disconnected,
    	.le_param_req			= le_param_req,
    	.le_param_updated		= le_param_updated
    };
    
    static void bt_ready(int err)
    {
    	if (err) 
    	{
    		printk("BLE init failed with error code %d\n", err);
    		return;
    	}
    
    	//Configure connection callbacks
    	bt_conn_cb_register(&conn_callbacks);
    
    	//Initalize services
    	err = my_service_init();
    
    	if (err) 
    	{
    		printk("Failed to init LBS (err:%d)\n", err);
    		return;
    	}
    
    	//Start advertising
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    			      sd, ARRAY_SIZE(sd));
    	if (err) 
    	{
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Advertising successfully started\n");
    
    	k_sem_give(&ble_init_ok);
    }
    
    
    static void error(void)
    {
    	while (true) {
    		printk("Error!\n");
    		/* Spin for ever */
    		k_sleep(K_MSEC(1000)); //1000ms
    	}
    }
    
    void on_data_received(struct bt_conn *conn, const uint8_t *const data, uint16_t len)
    {
        uint8_t temp_str[len+1];
        memcpy(temp_str, data, len);
        temp_str[len] = 0x00;
    }
    
    static uint8_t tx_data[NFC_TX_DATA_LEN];
    static uint8_t rx_data[NFC_RX_DATA_LEN];
    
    static struct k_poll_event events[ST25R3911B_NFCA_EVENT_CNT];
    static struct k_work_delayable transmit_work;
    
    NFC_T4T_CC_DESC_DEF(t4t_cc, MAX_TLV_BLOCKS);
    
    static struct st25r3911b_nfca_buf tx_buf = {
    	.data = tx_data,
    	.len = sizeof(tx_data)
    };
    
    static const struct st25r3911b_nfca_buf rx_buf = {
    	.data = rx_data,
    	.len = sizeof(rx_data)
    };
    
    enum nfc_tag_type {
    	NFC_TAG_TYPE_UNSUPPORTED = 0,
    	NFC_TAG_TYPE_T2T,
    	NFC_TAG_TYPE_T4T
    };
    
    enum t2t_state {
    	T2T_IDLE,
    	T2T_HEADER_READ,
    	T2T_DATA_READ
    };
    
    struct t2t_tag {
    	enum t2t_state state;
    	uint16_t data_bytes;
    	uint8_t data[NFCA_T2T_BUFFER_SIZE];
    };
    
    struct t4t_tag {
    	uint8_t data[NFC_T4T_ISODEP_RX_DATA_MAX_SIZE];
    	uint8_t ndef[MAX_TLV_BLOCKS][NFC_T4T_APDU_MAX_SIZE];
    	uint8_t tlv_index;
    };
    
    static enum nfc_tag_type tag_type;
    static struct t2t_tag t2t;
    static struct t4t_tag t4t;
    
    static void nfc_tag_detect(bool all_request)
    {
    	int err;
    	enum st25r3911b_nfca_detect_cmd cmd;
    
    	tag_type = NFC_TAG_TYPE_UNSUPPORTED;
    
    	cmd = all_request ? ST25R3911B_NFCA_DETECT_CMD_ALL_REQ :
    		ST25R3911B_NFCA_DETECT_CMD_SENS_REQ;
    
    	err = st25r3911b_nfca_tag_detect(cmd);
    	if (err) {
    		printk("Tag detect error: %d.\n", err);
    	}
    }
    
    static int ftd_calculate(uint8_t *data, size_t len)
    {
    	uint8_t ftd_align;
    
    	ftd_align = (data[len - 1] & NFCA_LAST_BIT_MASK) ?
    		NFCA_FDT_ALIGN_84 : NFCA_FDT_ALIGN_20;
    
    	return len * NFCA_BD * BITS_IN_BYTE + ftd_align;
    }
    
    static int nfc_t2t_read_block_cmd_make(uint8_t *tx_data,
    				       size_t tx_data_size,
    				       uint8_t block_num)
    {
    	if (!tx_data) {
    		return -EINVAL;
    	}
    
    	if (tx_data_size < NFC_T2T_READ_CMD_LEN) {
    		return -ENOMEM;
    	}
    
    	tx_data[0] = NFC_T2T_READ_CMD;
    	tx_data[1] = block_num;
    
    	return 0;
    }
    
    static int t2t_header_read(void)
    {
    	int err;
    	int ftd;
    
    	err = nfc_t2t_read_block_cmd_make(tx_data, sizeof(tx_data), 0);
    	if (err) {
    		return err;
    	}
    
    	tx_buf.data = tx_data;
    	tx_buf.len = NFC_T2T_READ_CMD_LEN;
    
    	ftd = ftd_calculate(tx_data, NFC_T2T_READ_CMD_LEN);
    
    	t2t.state = T2T_HEADER_READ;
    
    	err = st25r3911b_nfca_transfer_with_crc(&tx_buf, &rx_buf, ftd);
    
    	return err;
    }
    
    /** .. include_startingpoint_le_oob_rec_parser_rst */
    static void ndef_le_oob_rec_analyze(const struct nfc_ndef_record_desc *le_oob_rec_desc)
    {
    	int err;
    	uint8_t desc_buf[NFC_NDEF_REC_PARSER_BUFF_SIZE];
    	uint32_t desc_buf_len = sizeof(desc_buf);
    
    	err = nfc_ndef_le_oob_rec_parse(le_oob_rec_desc, desc_buf,
    					&desc_buf_len);
    	if (err) {
    		printk("Error during NDEF LE OOB Record parsing, err: %d.\n",
    			err);
    	} else {
    		nfc_ndef_le_oob_rec_printout(
    			(struct nfc_ndef_le_oob_rec_payload_desc *) desc_buf);
    	}
    }
    /** .. include_endpoint_le_oob_rec_parser_rst */
    
    /** .. include_startingpoint_ch_rec_parser_rst */
    static void ndef_ch_rec_analyze(const struct nfc_ndef_record_desc *ndef_rec_desc)
    {
    	int err;
    	uint8_t hs_buf[NFC_NDEF_REC_PARSER_BUFF_SIZE];
    	uint32_t hs_buf_len = sizeof(hs_buf);
    	uint8_t ac_buf[NFC_NDEF_REC_PARSER_BUFF_SIZE];
    	uint32_t ac_buf_len = sizeof(ac_buf);
    	struct nfc_ndef_ch_rec *ch_rec;
    	struct nfc_ndef_ch_ac_rec *ac_rec;
    
    	err = nfc_ndef_ch_rec_parse(ndef_rec_desc, hs_buf, &hs_buf_len);
    	if (err) {
    		printk("Error during parsing Handover Select record: %d\n",
    		       err);
    		return;
    	}
    
    	ch_rec = (struct nfc_ndef_ch_rec *)hs_buf;
    
    	printk("Handover Select Record payload");
    
    	nfc_ndef_ch_rec_printout(ch_rec);
    	for (size_t i = 0; i < ch_rec->local_records->record_count; i++) 
    	{
    		
    		if (nfc_ndef_ch_ac_rec_check(ch_rec->local_records->record[i])) 
    		{
    			err = nfc_ndef_ch_ac_rec_parse(ch_rec->local_records->record[i],
    						       ac_buf, &ac_buf_len);
    			if (err) {
    				printk("Error during parsing AC record: %d\n",
    				       err);
    				return;
    			}
    
    			ac_rec = (struct nfc_ndef_ch_ac_rec *)ac_buf;
    
    			nfc_ndef_ac_rec_printout(ac_rec);
    		}
    	}
    }
    /** .. include_endpoint_ch_rec_parser_rst */
    
    static void ndef_rec_analyze(const struct nfc_ndef_record_desc *ndef_rec_desc)
    {
    	/* Match NDEF Record with specific NDEF Record parser. */
    	if (nfc_ndef_ch_rec_check(ndef_rec_desc,
    				  NFC_NDEF_CH_REC_TYPE_HANDOVER_SELECT)) {
    		ndef_ch_rec_analyze(ndef_rec_desc);
    	} else if (nfc_ndef_le_oob_rec_check(ndef_rec_desc)) {
    		ndef_le_oob_rec_analyze(ndef_rec_desc);
    	} else {
    		/* Do nothing */
    	}
    }
    
    static void ndef_data_analyze(const uint8_t *ndef_msg_buff, size_t nfc_data_len)
    {
    	int  err;
    	struct nfc_ndef_msg_desc *ndef_msg_desc;
    	uint8_t desc_buf[NFC_NDEF_PARSER_REQUIRED_MEM(MAX_NDEF_RECORDS)];
    	size_t desc_buf_len = sizeof(desc_buf);
    
    	err = nfc_ndef_msg_parse(desc_buf,
    				 &desc_buf_len,
    				 ndef_msg_buff,
    				 &nfc_data_len);
    	if (err) {
    		printk("Error during parsing a NDEF message, err: %d.\n", err);
    		return;
    	}
    
    	ndef_msg_desc = (struct nfc_ndef_msg_desc *) desc_buf;
    
    	nfc_ndef_msg_printout(ndef_msg_desc);
    
    	for (size_t i = 0; i < ndef_msg_desc->record_count; i++) {
    		ndef_rec_analyze(ndef_msg_desc->record[i]);
    	}
    }
    
    static void t2t_data_read_complete(uint8_t *data)
    {
    	int err;
    
    	if (!data) {
    		printk("No T2T data read.\n");
    		return;
    	}
    
    	/* Declaration of Type 2 Tag structure. */
    	NFC_T2T_DESC_DEF(tag_data, MAX_TLV_BLOCKS);
    	struct nfc_t2t *t2t = &NFC_T2T_DESC(tag_data);
    
    	err = nfc_t2t_parse(t2t, data);
    	if (err) {
    		printk("Not enought memory to read whole tag. Printing what have been read.\n");
    	}
    
    	nfc_t2t_printout(t2t);
    
    	struct nfc_t2t_tlv_block *tlv_block = t2t->tlv_block_array;
    
    	for (size_t i = 0; i < t2t->tlv_count; i++) {
    		if (tlv_block->tag == NFC_T2T_TLV_NDEF_MESSAGE) {
    			ndef_data_analyze(tlv_block->value, tlv_block->length);
    			tlv_block++;
    		}
    	}
    
    	st25r3911b_nfca_tag_sleep();
    
    	k_work_reschedule(&transmit_work, K_MSEC(TRANSMIT_DELAY));
    }
    
    static int t2t_on_data_read(const uint8_t *data, size_t data_len,
    			    void (*t2t_read_complete)(uint8_t *))
    {
    	int err;
    	int ftd;
    	uint8_t block_to_read;
    	uint16_t offset = 0;
    	static uint8_t block_num;
    
    	block_to_read = t2t.data_bytes / NFC_T2T_BLOCK_SIZE;
    	offset = block_num * NFC_T2T_BLOCK_SIZE;
    
    	memcpy(t2t.data + offset, data, data_len);
    
    	block_num += TAG_TYPE_2_BLOCKS_PER_EXCHANGE;
    
    	if (block_num > block_to_read) {
    		block_num = 0;
    		t2t.state = T2T_IDLE;
    
    		if (t2t_read_complete) {
    			t2t_read_complete(t2t.data);
    		}
    
    		return 0;
    	}
    
    	err = nfc_t2t_read_block_cmd_make(tx_data, sizeof(tx_data), block_num);
    	if (err) {
    		return err;
    	}
    
    	tx_buf.data = tx_data;
    	tx_buf.len = NFC_T2T_READ_CMD_LEN;
    
    	ftd = ftd_calculate(tx_data, NFC_T2T_READ_CMD_LEN);
    
    	err = st25r3911b_nfca_transfer_with_crc(&tx_buf, &rx_buf, ftd);
    
    	return err;
    }
    
    static int on_t2t_transfer_complete(const uint8_t *data, size_t len)
    {
    	switch (t2t.state) {
    	case T2T_HEADER_READ:
    		t2t.data_bytes = TAG_TYPE_2_DATA_AREA_MULTIPLICATOR *
    				 data[TAG_TYPE_2_DATA_AREA_SIZE_OFFSET];
    
    		if ((t2t.data_bytes + NFC_T2T_FIRST_DATA_BLOCK_OFFSET) > sizeof(t2t.data)) {
    			return -ENOMEM;
    		}
    
    		t2t.state = T2T_DATA_READ;
    
    		return t2t_on_data_read(data, len, t2t_data_read_complete);
    
    	case T2T_DATA_READ:
    		return t2t_on_data_read(data, len, t2t_data_read_complete);
    
    	default:
    		return -EFAULT;
    	}
    }
    
    static void transfer_handler(struct k_work *work)
    {
    	nfc_tag_detect(false);
    }
    
    static void nfc_field_on(void)
    {
    	printk("NFC field on.\n");
    
    	nfc_tag_detect(false);
    }
    
    static void nfc_timeout(bool tag_sleep)
    {
    	if (tag_sleep) {
    		printk("Tag sleep or no detected, sending ALL Request.\n");
    	} else if (tag_type == NFC_TAG_TYPE_T4T) {
    		nfc_t4t_isodep_on_timeout();
    
    		return;
    	} else {
    		/* Do nothing. */
    	}
    
    	/* Sleep will block processing loop. Accepted as it is short. */
    	k_sleep(K_MSEC(ALL_REQ_DELAY));
    
    	nfc_tag_detect(true);
    }
    
    static void nfc_field_off(void)
    {
    	printk("NFC field off.\n");
    }
    
    static void tag_detected(const struct st25r3911b_nfca_sens_resp *sens_resp)
    {
    	printk("Anticollision: 0x%x Platform: 0x%x.\n",
    		sens_resp->anticollison,
    		sens_resp->platform_info);
    
    	int err = st25r3911b_nfca_anticollision_start();
    
    	if (err) {
    		printk("Anticollision error: %d.\n", err);
    	}
    }
    
    static void anticollision_completed(const struct st25r3911b_nfca_tag_info *tag_info,
    				    int err)
    {
    	if (err) {
    		printk("Error during anticollision avoidance.\n");
    
    		nfc_tag_detect(false);
    
    		return;
    	}
    
    	printk("Tag info, type: %d.\n", tag_info->type);
    
    	if (tag_info->type == ST25R3911B_NFCA_TAG_TYPE_T2T) {
    		printk("Type 2 Tag.\n");
    
    		tag_type = NFC_TAG_TYPE_T2T;
    
    		err = t2t_header_read();
    		if (err) {
    			printk("Type 2 Tag data read error %d.\n", err);
    		}
    	} else if (tag_info->type == ST25R3911B_NFCA_TAG_TYPE_T4T) {
    		printk("Type 4 Tag.\n");
    
    		tag_type = NFC_TAG_TYPE_T4T;
    
    		/* Send RATS command */
    		err = nfc_t4t_isodep_rats_send(NFC_T4T_ISODEP_FSD_256, 0);
    		if (err) {
    			printk("Type 4 Tag RATS sending error %d.\n", err);
    		}
    	} else {
    		printk("Unsupported tag type.\n");
    
    		tag_type = NFC_TAG_TYPE_UNSUPPORTED;
    
    		nfc_tag_detect(false);
    
    		return;
    	}
    }
    
    static void transfer_completed(const uint8_t *data, size_t len, int err)
    {
    	if (err) {
    		printk("NFC Transfer error: %d.\n", err);
    		return;
    	}
    
    	switch (tag_type) {
    	case NFC_TAG_TYPE_T2T:
    		err = on_t2t_transfer_complete(data, len);
    		if (err) {
    			printk("NFC-A T2T read error: %d.\n", err);
    		}
    		break;
    
    	case NFC_TAG_TYPE_T4T:
    		err = nfc_t4t_isodep_data_received(data, len, err);
    		if (err) {
    			printk("NFC-A T4T read error: %d.\n", err);
    		}
    		break;
    
    	default:
    		break;
    	}
    	
    }
    
    static void tag_sleep(void)
    {
    	flag=1;
    	printk("Tag entered the Sleep state.\n");
    }
    
    static const struct st25r3911b_nfca_cb cb = {
    	.field_on = nfc_field_on,
    	.field_off = nfc_field_off,
    	.tag_detected = tag_detected,
    	.anticollision_completed = anticollision_completed,
    	.rx_timeout = nfc_timeout,
    	.transfer_completed = transfer_completed,
    	.tag_sleep = tag_sleep
    };
    
    static void t4t_isodep_selected(const struct nfc_t4t_isodep_tag *t4t_tag)
    {
    	int err;
    
    	printk("NFC T4T selected.\n");
    
    	if ((t4t_tag->lp_divisor != 0) &&
    	    (t4t_tag->lp_divisor != t4t_tag->pl_divisor)) {
    		printk("Unsupported bitrate divisor by Reader/Writer.\n");
    	}
    
    	err = nfc_t4t_hl_procedure_ndef_tag_app_select();
    	if (err) {
    		printk("NFC T4T app select err %d.\n", err);
    		return;
    	}
    }
    
    static void t4t_isodep_error(int err)
    {
    	printk("ISO-DEP Protocol error %d.\n", err);
    	nfc_tag_detect(false);
    }
    
    static void t4t_isodep_data_send(uint8_t *data, size_t data_len, uint32_t ftd)
    {
    	int err;
    
    	tx_buf.data = data;
    	tx_buf.len = data_len;
    
    	err = st25r3911b_nfca_transfer_with_crc(&tx_buf, &rx_buf, ftd);
    	if (err) {
    		printk("NFC T4T ISO-DEP transfer error: %d.\n", err);
    	}
    }
    
    static void t4t_isodep_received(const uint8_t *data, size_t data_len)
    {
    	int err;
    
    	err = nfc_t4t_hl_procedure_on_data_received(data, data_len);
    	if (err) {
    		printk("NFC Type 4 Tag HL data received error: %d.\n", err);
    	}
    }
    
    static void t4t_isodep_deselected(void)
    {
    	st25r3911b_nfca_tag_sleep();
    
    	k_work_reschedule(&transmit_work, K_MSEC(TRANSMIT_DELAY));
    }
    
    static const struct nfc_t4t_isodep_cb t4t_isodep_cb = {
    	.selected = t4t_isodep_selected,
    	.deselected = t4t_isodep_deselected,
    	.error = t4t_isodep_error,
    	.ready_to_send = t4t_isodep_data_send,
    	.data_received = t4t_isodep_received
    };
    
    static void t4t_hl_selected(enum nfc_t4t_hl_procedure_select type)
    {
    	int err = 0;
    
    	switch (type) {
    	case NFC_T4T_HL_PROCEDURE_NDEF_APP_SELECT:
    		printk("NFC T4T NDEF Application selected.\n");
    
    		err = nfc_t4t_hl_procedure_cc_select();
    		if (err) {
    			printk("NFC T4T Capability Container select error: %d.\n",
    				err);
    		}
    
    		break;
    
    	case NFC_T4T_HL_PROCEDURE_CC_SELECT:
    		printk("NFC T4T Capability Container file selected.\n");
    
    		err = nfc_t4t_hl_procedure_cc_read(&NFC_T4T_CC_DESC(t4t_cc));
    		if (err) {
    			printk("Capability Container read error: %d.\n", err);
    		}
    
    		break;
    
    	case NFC_T4T_HL_PROCEDURE_NDEF_FILE_SELECT:
    		printk("NFC T4T NDEF file selected.\n");
    
    
    		err = nfc_t4t_hl_procedure_ndef_read(&NFC_T4T_CC_DESC(t4t_cc),
    						     t4t.ndef[t4t.tlv_index], NFC_T4T_APDU_MAX_SIZE);
    		if (err) {
    			printk("NFC T4T NDEF file read error %d.\n", err);
    		}
    
    		break;
    
    	default:
    		break;
    	}
    
    	if (err) {
    		st25r3911b_nfca_tag_sleep();
    
    		k_work_reschedule(&transmit_work, K_MSEC(TRANSMIT_DELAY));
    	}
    }
    
    static void t4t_hl_cc_read(struct nfc_t4t_cc_file *cc)
    {
    	printk("NFC T4T Capability Container file read.\n");
    
    	for (size_t i = 0; i < cc->tlv_count; i++) {
    		int err;
    		struct nfc_t4t_tlv_block *tlv_block = &cc->tlv_block_array[i];
    
    		if ((tlv_block->type == NFC_T4T_TLV_BLOCK_TYPE_NDEF_FILE_CONTROL_TLV) &&
    		    (tlv_block->value.read_access == NFC_T4T_TLV_BLOCK_CONTROL_FILE_READ_ACCESS_GRANTED)) {
    			err = nfc_t4t_hl_procedure_ndef_file_select(tlv_block->value.file_id);
    			if (err) {
    				printk("NFC T4T NDEF file select error: %d.\n", err);
    			}
    
    			return;
    		}
    	}
    
    	printk("No NDEF File TLV in Capability Container.");
    }
    
    static void t4t_hl_ndef_read(uint16_t file_id, const uint8_t *data, size_t len)
    {
    	int err;
    	struct nfc_t4t_cc_file *cc;
    	struct nfc_t4t_tlv_block *tlv_block;
    
    	printk("NDEF file read, id: 0x%x.\n", file_id);
    
    	t4t.tlv_index++;
    	cc = &NFC_T4T_CC_DESC(t4t_cc);
    
    	for (size_t i = t4t.tlv_index; i < cc->tlv_count; i++) {
    		tlv_block = &cc->tlv_block_array[i];
    
    		if ((tlv_block->type == NFC_T4T_TLV_BLOCK_TYPE_NDEF_FILE_CONTROL_TLV) &&
    		    (tlv_block->value.read_access == NFC_T4T_TLV_BLOCK_CONTROL_FILE_READ_ACCESS_GRANTED)) {
    
    			err = nfc_t4t_hl_procedure_ndef_file_select(tlv_block->value.file_id);
    			if (err) {
    				printk("NFC T4T NDEF file select error: %d.\n", err);
    			}
    
    			return;
    		}
    
    		t4t.tlv_index++;
    	}
    
    	nfc_t4t_cc_file_printout(cc);
    
    	tlv_block = cc->tlv_block_array;
    	for (size_t i = 0; i < cc->tlv_count; i++) {
    		if ((tlv_block[i].type == NFC_T4T_TLV_BLOCK_TYPE_NDEF_FILE_CONTROL_TLV) ||
    		    (tlv_block[i].value.file.content != NULL)) {
    			ndef_data_analyze(nfc_t4t_ndef_file_msg_get(tlv_block[i].value.file.content),
    					  nfc_t4t_ndef_file_msg_size_get(tlv_block[i].value.file.len));
    		}
    	}
    
    	t4t.tlv_index = 0;
    	err = nfc_t4t_isodep_tag_deselect();
    	if (err) {
    		printk("NFC T4T Deselect error: %d.\n", err);
    	}
    }
    
    static const struct nfc_t4t_hl_procedure_cb t4t_hl_procedure_cb = {
    	.selected = t4t_hl_selected,
    	.cc_read = t4t_hl_cc_read,
    	.ndef_read = t4t_hl_ndef_read
    };
    
    
    void main(void)
    {
    	int err;
    	uint32_t number = 0;
    
    	printk("Starting Nordic BLE peripheral tutorial\n");
    
    	
    	err = bt_enable(bt_ready);
    
    	if (err) 
    	{
    		printk("BLE initialization failed\n");
    		error(); //Catch error
    	}
    	
    	/* 	Bluetooth stack should be ready in less than 100 msec. 								\
    																							\
    		We use this semaphore to wait for bt_enable to call bt_ready before we proceed 		\
    		to the main loop. By using the semaphore to block execution we allow the RTOS to 	\
    		execute other tasks while we wait. */	
    	err = k_sem_take(&ble_init_ok, K_MSEC(500));
    
    	if (!err) 
    	{
    		printk("Bluetooth initialized\n");
    	} else 
    	{
    		printk("BLE initialization did not complete in time\n");
    		error(); //Catch error
    	}
    
    	err = my_service_init();
    
    	printk("Starting NFC TAG Reader example\n");
    	nfc_t4t_hl_procedure_cb_register(&t4t_hl_procedure_cb);
    
    	k_work_init_delayable(&transmit_work, transfer_handler);
    
    	err = nfc_t4t_isodep_init(tx_data, sizeof(tx_data),
    				  t4t.data, sizeof(t4t.data),
    				  &t4t_isodep_cb);
    	if (err) {
    		printk("NFC T4T ISO-DEP Protocol initialization failed err: %d.\n",
    		       err);
    		return;
    	}
    
    	err = st25r3911b_nfca_init(events, ARRAY_SIZE(events), &cb);
    	if (err) {
    		printk("NFCA initialization failed err: %d.\n", err);
    		return;
    	}
    
    	err = st25r3911b_nfca_field_on();
    	if (err) {
    		printk("Field on error %d.", err);
    		return;
    	}
    
    	while (true) {
    		k_poll(events, ARRAY_SIZE(events), K_FOREVER);
    		err = st25r3911b_nfca_process();
    		
    		if (flag)
    		{
    		my_service_send(my_connection,&tx_buf, strlen(&tx_buf));
    		number++;
    		k_msleep(1000); // 1000ms
    		flag=0;
    		}
    		else
    		{
    			// printk("no data pushed to BLE\n");
    		}
    		
    		if (err)
    		{
    			printk("NFC-A process failed, err: %d.\n", err);
    			return;
    		}
    	}
    }
    

    my_service.c

    my_service.c
    
    #include <my_service.h>
    #include <zephyr/kernel.h>
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/drivers/gpio.h>
    #include <soc.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    
    #define BT_UUID_MY_SERVICE      BT_UUID_DECLARE_128(MY_SERVICE_UUID)
    #define BT_UUID_MY_SERVICE_RX   BT_UUID_DECLARE_128(RX_CHARACTERISTIC_UUID)
    #define BT_UUID_MY_SERVICE_TX   BT_UUID_DECLARE_128(TX_CHARACTERISTIC_UUID)
    
    #define MAX_TRANSMIT_SIZE 240//TODO figure this out
    
    uint8_t data_rx[MAX_TRANSMIT_SIZE];
    uint8_t data_tx[MAX_TRANSMIT_SIZE];
    
    int my_service_init(void)
    {
        int err = 0;
    
        memset(&data_rx, 0, MAX_TRANSMIT_SIZE);
        memset(&data_tx, 0, MAX_TRANSMIT_SIZE);
    
        return err;
    }
    
    /* This function is called whenever the RX Characteristic has been written to by a Client */
    static ssize_t on_receive(struct bt_conn *conn,
    			  const struct bt_gatt_attr *attr,
    			  const void *buf,
    			  uint16_t len,
    			  uint16_t offset,
    			  uint8_t flags)
    {
        const uint8_t * buffer = buf;
    	printk("Received data, handle %d, conn %p, data: 0x", attr->handle, conn);
        for(uint8_t i = 0; i < len; i++){
            printk("%d", buffer[i]);
        }
        printk("\n");
    	return len;
    }
    
    /* This function is called whenever a Notification has been sent by the TX Characteristic */
    static void on_sent(struct bt_conn *conn, void *user_data)
    {
    	ARG_UNUSED(user_data);
    
        const bt_addr_le_t * addr = bt_conn_get_dst(conn);
            
    	printk("Data sent to Address 0x %02X %02X %02X %02X %02X %02X \n", addr->a.val[0]
                                                                        , addr->a.val[1]
                                                                        , addr->a.val[2]
                                                                        , addr->a.val[3]
                                                                        , addr->a.val[4]
                                                                        , addr->a.val[5]);
    }
    
    /* This function is called whenever the CCCD register has been changed by the client*/
    void on_cccd_changed(const struct bt_gatt_attr *attr, uint16_t value)
    {
        ARG_UNUSED(attr);
        switch(value)
        {
            case BT_GATT_CCC_NOTIFY: 
                // Start sending stuff!
                break;
    
            case BT_GATT_CCC_INDICATE: 
                // Start sending stuff via indications
                break;
    
            case 0: 
                // Stop sending stuff
                break;
            
            default: 
                printk("Error, CCCD has been set to an invalid value");     
        }
    }
                            
    
    /* LED Button Service Declaration and Registration */
    BT_GATT_SERVICE_DEFINE(my_service,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_MY_SERVICE),
    BT_GATT_CHARACTERISTIC(BT_UUID_MY_SERVICE_RX,
    			       BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
    			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, 
                       NULL, on_receive, NULL),
    BT_GATT_CHARACTERISTIC(BT_UUID_MY_SERVICE_TX,
    			       BT_GATT_CHRC_NOTIFY,
    			       BT_GATT_PERM_READ,
                       NULL, NULL, NULL),
    BT_GATT_CCC(on_cccd_changed,
            BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
    );
    
    /* This function sends a notification to a Client with the provided data,
    given that the Client Characteristic Control Descripter has been set to Notify (0x1).
    It also calls the on_sent() callback if successful*/
    void my_service_send(struct bt_conn *conn, const char *data, uint16_t len)
    {
        /* 
        The attribute for the TX characteristic is used with bt_gatt_is_subscribed 
        to check whether notification has been enabled by the peer or not.
        Attribute table: 0 = Service, 1 = Primary service, 2 = RX, 3 = TX, 4 = CCC.
        */
        const struct bt_gatt_attr *attr = &my_service.attrs[3]; 
    
        struct bt_gatt_notify_params params = 
        {
            .uuid   = BT_UUID_MY_SERVICE_TX,
            .attr   = attr,
            .data   = data,
            .len    = len,
            .func   = on_sent
        };
    
        // Check whether notifications are enabled or not
        if(bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY)) 
        {
            // Send the notification
    	    if(bt_gatt_notify_cb(conn, &params))
            {
                printk("Error, unable to send notification\n");
            }
        }
        else
        {
            printk("Warning, notification not enabled on the selected attribute\n");
        }
    }
    
    
    
    

    my_service.h

    my_service.h
    
    #include <zephyr/kernel.h>
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/drivers/gpio.h>
    #include <soc.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    
    
    // 30cb6c29-afc3-4af0-b6d5-1b0e6a2df99e
    
    #define MY_SERVICE_UUID 0x9e, 0xf9, 0x2d, 0x6a, 0x0e, 0x1b, 0xd5,   0xb6, \
    			 	0xf0, 0x4a, 0xc3, 0xaf, 0x29, 0x6c, 0xcb, 0x30
    
    // bb126ce2-b86b-4287-9d72-cd7382f1d829 //RX
    // b89f16c5-e6c6-4fc0-a211-47ab3e4deb89 //TX
    
    #define RX_CHARACTERISTIC_UUID 0x29, 0xd8, 0xf1, 0x82, 0x73, 0xcd, 0x72, 0x9d, \
    0x87, 0x42, 0x6b, 0xb8, 0xe2, 0x6c, 0x12, 0xbb
    
    #define TX_CHARACTERISTIC_UUID 0x89, 0xeb, 0x4d, 0x3e, 0xab, 0x47, 0x11, 0xa2, \
    0xc0, 0x4f, 0xc6, 0xe6, 0xc5, 0x16, 0x9f, 0xb8
    
    
    typedef void (*data_rx_cb_t)(uint8_t *data, uint8_t length);
    
    /** @brief Callback struct used by the my_service Service. */
    struct my_service_cb 
    {
    	/** Data received callback. */
    	data_rx_cb_t    data_rx_cb;
    };
    
    
    int my_service_init(void);
    void my_service_send(struct bt_conn *conn, const char *data, uint16_t len);
    
    

Related