Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a99903ec authored by Julien Lefrique's avatar Julien Lefrique Committed by Samuel Ortiz
Browse files

NFC: NCI: Handle Target mode activation



Changes:

 * Extract the Listen mode activation parameters from RF_INTF_ACTIVATED_NTF.

 * Store the General Bytes of ATR_REQ.

 * Signal that Target mode is activated in case of an activation in NFC-DEP.

 * Update the NCI state accordingly.

 * Use the various constants defined in nfc.h.

 * Fix the ATR_REQ and ATR_RES maximum size. As per NCI 1.0 and NCI 1.1, the
   Activation Parameters for both Poll and Listen mode contain all the bytes of
   ATR_REQ/ATR_RES starting and including Byte 3 as defined in [DIGITAL].
   In [DIGITAL], the maximum size of ATR_REQ/ATR_RES is 64 bytes and they are
   numbered starting from Byte 1.

Signed-off-by: default avatarJulien Lefrique <lefrique@marvell.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 90d78c13
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
#ifndef __NCI_H
#define __NCI_H

#include <net/nfc/nfc.h>

/* NCI constants */
#define NCI_MAX_NUM_MAPPING_CONFIGS				10
#define NCI_MAX_NUM_RF_CONFIGS					10
@@ -73,6 +75,8 @@
#define NCI_NFC_A_ACTIVE_LISTEN_MODE				0x83
#define NCI_NFC_F_ACTIVE_LISTEN_MODE				0x85

#define NCI_RF_TECH_MODE_LISTEN_MASK				0x80

/* NCI RF Technologies */
#define NCI_NFC_RF_TECHNOLOGY_A					0x00
#define NCI_NFC_RF_TECHNOLOGY_B					0x01
@@ -324,26 +328,31 @@ struct nci_core_intf_error_ntf {
struct rf_tech_specific_params_nfca_poll {
	__u16	sens_res;
	__u8	nfcid1_len;	/* 0, 4, 7, or 10 Bytes */
	__u8	nfcid1[10];
	__u8	nfcid1[NFC_NFCID1_MAXSIZE];
	__u8	sel_res_len;	/* 0 or 1 Bytes */
	__u8	sel_res;
} __packed;

struct rf_tech_specific_params_nfcb_poll {
	__u8	sensb_res_len;
	__u8	sensb_res[12];	/* 11 or 12 Bytes */
	__u8	sensb_res[NFC_SENSB_RES_MAXSIZE];	/* 11 or 12 Bytes */
} __packed;

struct rf_tech_specific_params_nfcf_poll {
	__u8	bit_rate;
	__u8	sensf_res_len;
	__u8	sensf_res[18];	/* 16 or 18 Bytes */
	__u8	sensf_res[NFC_SENSF_RES_MAXSIZE];	/* 16 or 18 Bytes */
} __packed;

struct rf_tech_specific_params_nfcv_poll {
	__u8	res_flags;
	__u8	dsfid;
	__u8	uid[8];	/* 8 Bytes */
	__u8	uid[NFC_ISO15693_UID_MAXSIZE];	/* 8 Bytes */
} __packed;

struct rf_tech_specific_params_nfcf_listen {
	__u8	local_nfcid2_len;
	__u8	local_nfcid2[NFC_NFCID2_MAXSIZE];	/* 0 or 8 Bytes */
} __packed;

struct nci_rf_discover_ntf {
@@ -375,7 +384,12 @@ struct activation_params_nfcb_poll_iso_dep {

struct activation_params_poll_nfc_dep {
	__u8	atr_res_len;
	__u8	atr_res[63];
	__u8	atr_res[NFC_ATR_RES_MAXSIZE - 2]; /* ATR_RES from byte 3 */
};

struct activation_params_listen_nfc_dep {
	__u8	atr_req_len;
	__u8	atr_req[NFC_ATR_REQ_MAXSIZE - 2]; /* ATR_REQ from byte 3 */
};

struct nci_rf_intf_activated_ntf {
@@ -392,6 +406,7 @@ struct nci_rf_intf_activated_ntf {
		struct rf_tech_specific_params_nfcb_poll nfcb_poll;
		struct rf_tech_specific_params_nfcf_poll nfcf_poll;
		struct rf_tech_specific_params_nfcv_poll nfcv_poll;
		struct rf_tech_specific_params_nfcf_listen nfcf_listen;
	} rf_tech_specific_params;

	__u8	data_exch_rf_tech_and_mode;
@@ -403,6 +418,7 @@ struct nci_rf_intf_activated_ntf {
		struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
		struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep;
		struct activation_params_poll_nfc_dep poll_nfc_dep;
		struct activation_params_listen_nfc_dep listen_nfc_dep;
	} activation_params;

} __packed;
+3 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
 *
 *  Copyright (C) 2011 Texas Instruments, Inc.
 *  Copyright (C) 2013 Intel Corporation. All rights reserved.
 *  Copyright (C) 2014 Marvell International Ltd.
 *
 *  Written by Ilan Elias <ilane@ti.com>
 *
@@ -49,6 +50,8 @@ enum nci_state {
	NCI_W4_ALL_DISCOVERIES,
	NCI_W4_HOST_SELECT,
	NCI_POLL_ACTIVE,
	NCI_LISTEN_ACTIVE,
	NCI_LISTEN_SLEEP,
};

/* NCI timeouts */
+2 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 Instituto Nokia de Tecnologia
 * Copyright (C) 2014 Marvell International Ltd.
 *
 * Authors:
 *    Lauro Ramos Venancio <lauro.venancio@openbossa.org>
@@ -87,6 +88,7 @@ struct nfc_ops {
#define NFC_TARGET_IDX_ANY -1
#define NFC_MAX_GT_LEN 48
#define NFC_ATR_RES_GT_OFFSET 15
#define NFC_ATR_REQ_GT_OFFSET 14

/**
 * struct nfc_target - NFC target descriptiom
+11 −9
Original line number Diff line number Diff line
@@ -202,6 +202,8 @@ enum nfc_sdp_attr {
#define NFC_NFCID3_MAXSIZE		10
#define NFC_SENSB_RES_MAXSIZE		12
#define NFC_SENSF_RES_MAXSIZE		18
#define NFC_ATR_REQ_MAXSIZE		64
#define NFC_ATR_RES_MAXSIZE		64
#define NFC_GB_MAXSIZE			48
#define NFC_FIRMWARE_NAME_MAXSIZE	32
#define NFC_ISO15693_UID_MAXSIZE	8
+109 −24
Original line number Diff line number Diff line
@@ -167,6 +167,18 @@ static __u8 *nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev,
	return data;
}

static __u8 *nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev,
			struct rf_tech_specific_params_nfcf_listen *nfcf_listen,
						     __u8 *data)
{
	nfcf_listen->local_nfcid2_len = min_t(__u8, *data++,
					      NFC_NFCID2_MAXSIZE);
	memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len);
	data += nfcf_listen->local_nfcid2_len;

	return data;
}

__u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
{
	if (ndev->ops->get_rfprotocol)
@@ -401,17 +413,29 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev,
			struct nci_rf_intf_activated_ntf *ntf, __u8 *data)
{
	struct activation_params_poll_nfc_dep *poll;
	struct activation_params_listen_nfc_dep *listen;

	switch (ntf->activation_rf_tech_and_mode) {
	case NCI_NFC_A_PASSIVE_POLL_MODE:
	case NCI_NFC_F_PASSIVE_POLL_MODE:
		poll = &ntf->activation_params.poll_nfc_dep;
		poll->atr_res_len = min_t(__u8, *data++, 63);
		poll->atr_res_len = min_t(__u8, *data++,
					  NFC_ATR_RES_MAXSIZE - 2);
		pr_debug("atr_res_len %d\n", poll->atr_res_len);
		if (poll->atr_res_len > 0)
			memcpy(poll->atr_res, data, poll->atr_res_len);
		break;

	case NCI_NFC_A_PASSIVE_LISTEN_MODE:
	case NCI_NFC_F_PASSIVE_LISTEN_MODE:
		listen = &ntf->activation_params.listen_nfc_dep;
		listen->atr_req_len = min_t(__u8, *data++,
					    NFC_ATR_REQ_MAXSIZE - 2);
		pr_debug("atr_req_len %d\n", listen->atr_req_len);
		if (listen->atr_req_len > 0)
			memcpy(listen->atr_req, data, listen->atr_req_len);
		break;

	default:
		pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
		       ntf->activation_rf_tech_and_mode);
@@ -444,6 +468,50 @@ static void nci_target_auto_activated(struct nci_dev *ndev,
	nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets);
}

static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev,
		struct nci_rf_intf_activated_ntf *ntf)
{
	ndev->remote_gb_len = 0;

	if (ntf->activation_params_len <= 0)
		return NCI_STATUS_OK;

	switch (ntf->activation_rf_tech_and_mode) {
	case NCI_NFC_A_PASSIVE_POLL_MODE:
	case NCI_NFC_F_PASSIVE_POLL_MODE:
		/* ATR_RES general bytes at offset 15 */
		ndev->remote_gb_len = min_t(__u8,
			(ntf->activation_params.poll_nfc_dep.atr_res_len
						- NFC_ATR_RES_GT_OFFSET),
			NFC_MAX_GT_LEN);
		memcpy(ndev->remote_gb,
		       (ntf->activation_params.poll_nfc_dep .atr_res
						+ NFC_ATR_RES_GT_OFFSET),
		       ndev->remote_gb_len);
		break;

	case NCI_NFC_A_PASSIVE_LISTEN_MODE:
	case NCI_NFC_F_PASSIVE_LISTEN_MODE:
		/* ATR_REQ general bytes at offset 14 */
		ndev->remote_gb_len = min_t(__u8,
			(ntf->activation_params.listen_nfc_dep.atr_req_len
						- NFC_ATR_REQ_GT_OFFSET),
			NFC_MAX_GT_LEN);
		memcpy(ndev->remote_gb,
		       (ntf->activation_params.listen_nfc_dep.atr_req
						+ NFC_ATR_REQ_GT_OFFSET),
		       ndev->remote_gb_len);
		break;

	default:
		pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
		       ntf->activation_rf_tech_and_mode);
		return NCI_STATUS_RF_PROTOCOL_ERROR;
	}

	return NCI_STATUS_OK;
}

static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
					     struct sk_buff *skb)
{
@@ -493,6 +561,16 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
				&(ntf.rf_tech_specific_params.nfcv_poll), data);
			break;

		case NCI_NFC_A_PASSIVE_LISTEN_MODE:
			/* no RF technology specific parameters */
			break;

		case NCI_NFC_F_PASSIVE_LISTEN_MODE:
			data = nci_extract_rf_params_nfcf_passive_listen(ndev,
				&(ntf.rf_tech_specific_params.nfcf_listen),
				data);
			break;

		default:
			pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
			       ntf.activation_rf_tech_and_mode);
@@ -546,33 +624,40 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,

		/* store general bytes to be reported later in dep_link_up */
		if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
			ndev->remote_gb_len = 0;

			if (ntf.activation_params_len > 0) {
				/* ATR_RES general bytes at offset 15 */
				ndev->remote_gb_len = min_t(__u8,
					(ntf.activation_params
					.poll_nfc_dep.atr_res_len
					- NFC_ATR_RES_GT_OFFSET),
					NFC_MAX_GT_LEN);
				memcpy(ndev->remote_gb,
				       (ntf.activation_params.poll_nfc_dep
				       .atr_res + NFC_ATR_RES_GT_OFFSET),
				       ndev->remote_gb_len);
			}
			err = nci_store_general_bytes_nfc_dep(ndev, &ntf);
			if (err != NCI_STATUS_OK)
				pr_err("unable to store general bytes\n");
		}
	}

	if (!(ntf.activation_rf_tech_and_mode & NCI_RF_TECH_MODE_LISTEN_MASK)) {
		/* Poll mode */
		if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
		/* A single target was found and activated automatically */
			/* A single target was found and activated
			 * automatically */
			atomic_set(&ndev->state, NCI_POLL_ACTIVE);
			if (err == NCI_STATUS_OK)
				nci_target_auto_activated(ndev, &ntf);
		} else {	/* ndev->state == NCI_W4_HOST_SELECT */
		/* A selected target was activated, so complete the request */
			/* A selected target was activated, so complete the
			 * request */
			atomic_set(&ndev->state, NCI_POLL_ACTIVE);
			nci_req_complete(ndev, err);
		}
	} else {
		/* Listen mode */
		atomic_set(&ndev->state, NCI_LISTEN_ACTIVE);
		if (err == NCI_STATUS_OK &&
		    ntf.rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) {
			err = nfc_tm_activated(ndev->nfc_dev,
					       NFC_PROTO_NFC_DEP_MASK,
					       NFC_COMM_PASSIVE,
					       ndev->remote_gb,
					       ndev->remote_gb_len);
			if (err != NCI_STATUS_OK)
				pr_err("error when signaling tm activation\n");
		}
	}
}

static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,