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: Julien Lefrique <lefrique@marvell.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
90d78c1396
commit
a99903ec45
|
@ -28,6 +28,8 @@
|
||||||
#ifndef __NCI_H
|
#ifndef __NCI_H
|
||||||
#define __NCI_H
|
#define __NCI_H
|
||||||
|
|
||||||
|
#include <net/nfc/nfc.h>
|
||||||
|
|
||||||
/* NCI constants */
|
/* NCI constants */
|
||||||
#define NCI_MAX_NUM_MAPPING_CONFIGS 10
|
#define NCI_MAX_NUM_MAPPING_CONFIGS 10
|
||||||
#define NCI_MAX_NUM_RF_CONFIGS 10
|
#define NCI_MAX_NUM_RF_CONFIGS 10
|
||||||
|
@ -73,6 +75,8 @@
|
||||||
#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
|
#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
|
||||||
#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
|
#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
|
||||||
|
|
||||||
|
#define NCI_RF_TECH_MODE_LISTEN_MASK 0x80
|
||||||
|
|
||||||
/* NCI RF Technologies */
|
/* NCI RF Technologies */
|
||||||
#define NCI_NFC_RF_TECHNOLOGY_A 0x00
|
#define NCI_NFC_RF_TECHNOLOGY_A 0x00
|
||||||
#define NCI_NFC_RF_TECHNOLOGY_B 0x01
|
#define NCI_NFC_RF_TECHNOLOGY_B 0x01
|
||||||
|
@ -324,26 +328,31 @@ struct nci_core_intf_error_ntf {
|
||||||
struct rf_tech_specific_params_nfca_poll {
|
struct rf_tech_specific_params_nfca_poll {
|
||||||
__u16 sens_res;
|
__u16 sens_res;
|
||||||
__u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */
|
__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_len; /* 0 or 1 Bytes */
|
||||||
__u8 sel_res;
|
__u8 sel_res;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct rf_tech_specific_params_nfcb_poll {
|
struct rf_tech_specific_params_nfcb_poll {
|
||||||
__u8 sensb_res_len;
|
__u8 sensb_res_len;
|
||||||
__u8 sensb_res[12]; /* 11 or 12 Bytes */
|
__u8 sensb_res[NFC_SENSB_RES_MAXSIZE]; /* 11 or 12 Bytes */
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct rf_tech_specific_params_nfcf_poll {
|
struct rf_tech_specific_params_nfcf_poll {
|
||||||
__u8 bit_rate;
|
__u8 bit_rate;
|
||||||
__u8 sensf_res_len;
|
__u8 sensf_res_len;
|
||||||
__u8 sensf_res[18]; /* 16 or 18 Bytes */
|
__u8 sensf_res[NFC_SENSF_RES_MAXSIZE]; /* 16 or 18 Bytes */
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct rf_tech_specific_params_nfcv_poll {
|
struct rf_tech_specific_params_nfcv_poll {
|
||||||
__u8 res_flags;
|
__u8 res_flags;
|
||||||
__u8 dsfid;
|
__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;
|
} __packed;
|
||||||
|
|
||||||
struct nci_rf_discover_ntf {
|
struct nci_rf_discover_ntf {
|
||||||
|
@ -375,7 +384,12 @@ struct activation_params_nfcb_poll_iso_dep {
|
||||||
|
|
||||||
struct activation_params_poll_nfc_dep {
|
struct activation_params_poll_nfc_dep {
|
||||||
__u8 atr_res_len;
|
__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 {
|
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_nfcb_poll nfcb_poll;
|
||||||
struct rf_tech_specific_params_nfcf_poll nfcf_poll;
|
struct rf_tech_specific_params_nfcf_poll nfcf_poll;
|
||||||
struct rf_tech_specific_params_nfcv_poll nfcv_poll;
|
struct rf_tech_specific_params_nfcv_poll nfcv_poll;
|
||||||
|
struct rf_tech_specific_params_nfcf_listen nfcf_listen;
|
||||||
} rf_tech_specific_params;
|
} rf_tech_specific_params;
|
||||||
|
|
||||||
__u8 data_exch_rf_tech_and_mode;
|
__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_nfca_poll_iso_dep nfca_poll_iso_dep;
|
||||||
struct activation_params_nfcb_poll_iso_dep nfcb_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_poll_nfc_dep poll_nfc_dep;
|
||||||
|
struct activation_params_listen_nfc_dep listen_nfc_dep;
|
||||||
} activation_params;
|
} activation_params;
|
||||||
|
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Texas Instruments, Inc.
|
* Copyright (C) 2011 Texas Instruments, Inc.
|
||||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright (C) 2014 Marvell International Ltd.
|
||||||
*
|
*
|
||||||
* Written by Ilan Elias <ilane@ti.com>
|
* Written by Ilan Elias <ilane@ti.com>
|
||||||
*
|
*
|
||||||
|
@ -49,6 +50,8 @@ enum nci_state {
|
||||||
NCI_W4_ALL_DISCOVERIES,
|
NCI_W4_ALL_DISCOVERIES,
|
||||||
NCI_W4_HOST_SELECT,
|
NCI_W4_HOST_SELECT,
|
||||||
NCI_POLL_ACTIVE,
|
NCI_POLL_ACTIVE,
|
||||||
|
NCI_LISTEN_ACTIVE,
|
||||||
|
NCI_LISTEN_SLEEP,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NCI timeouts */
|
/* NCI timeouts */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2011 Instituto Nokia de Tecnologia
|
* Copyright (C) 2011 Instituto Nokia de Tecnologia
|
||||||
|
* Copyright (C) 2014 Marvell International Ltd.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Lauro Ramos Venancio <lauro.venancio@openbossa.org>
|
* Lauro Ramos Venancio <lauro.venancio@openbossa.org>
|
||||||
|
@ -87,6 +88,7 @@ struct nfc_ops {
|
||||||
#define NFC_TARGET_IDX_ANY -1
|
#define NFC_TARGET_IDX_ANY -1
|
||||||
#define NFC_MAX_GT_LEN 48
|
#define NFC_MAX_GT_LEN 48
|
||||||
#define NFC_ATR_RES_GT_OFFSET 15
|
#define NFC_ATR_RES_GT_OFFSET 15
|
||||||
|
#define NFC_ATR_REQ_GT_OFFSET 14
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct nfc_target - NFC target descriptiom
|
* struct nfc_target - NFC target descriptiom
|
||||||
|
|
|
@ -196,15 +196,17 @@ enum nfc_sdp_attr {
|
||||||
};
|
};
|
||||||
#define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1)
|
#define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1)
|
||||||
|
|
||||||
#define NFC_DEVICE_NAME_MAXSIZE 8
|
#define NFC_DEVICE_NAME_MAXSIZE 8
|
||||||
#define NFC_NFCID1_MAXSIZE 10
|
#define NFC_NFCID1_MAXSIZE 10
|
||||||
#define NFC_NFCID2_MAXSIZE 8
|
#define NFC_NFCID2_MAXSIZE 8
|
||||||
#define NFC_NFCID3_MAXSIZE 10
|
#define NFC_NFCID3_MAXSIZE 10
|
||||||
#define NFC_SENSB_RES_MAXSIZE 12
|
#define NFC_SENSB_RES_MAXSIZE 12
|
||||||
#define NFC_SENSF_RES_MAXSIZE 18
|
#define NFC_SENSF_RES_MAXSIZE 18
|
||||||
#define NFC_GB_MAXSIZE 48
|
#define NFC_ATR_REQ_MAXSIZE 64
|
||||||
#define NFC_FIRMWARE_NAME_MAXSIZE 32
|
#define NFC_ATR_RES_MAXSIZE 64
|
||||||
#define NFC_ISO15693_UID_MAXSIZE 8
|
#define NFC_GB_MAXSIZE 48
|
||||||
|
#define NFC_FIRMWARE_NAME_MAXSIZE 32
|
||||||
|
#define NFC_ISO15693_UID_MAXSIZE 8
|
||||||
|
|
||||||
/* NFC protocols */
|
/* NFC protocols */
|
||||||
#define NFC_PROTO_JEWEL 1
|
#define NFC_PROTO_JEWEL 1
|
||||||
|
|
|
@ -167,6 +167,18 @@ static __u8 *nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev,
|
||||||
return data;
|
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)
|
__u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
|
||||||
{
|
{
|
||||||
if (ndev->ops->get_rfprotocol)
|
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 nci_rf_intf_activated_ntf *ntf, __u8 *data)
|
||||||
{
|
{
|
||||||
struct activation_params_poll_nfc_dep *poll;
|
struct activation_params_poll_nfc_dep *poll;
|
||||||
|
struct activation_params_listen_nfc_dep *listen;
|
||||||
|
|
||||||
switch (ntf->activation_rf_tech_and_mode) {
|
switch (ntf->activation_rf_tech_and_mode) {
|
||||||
case NCI_NFC_A_PASSIVE_POLL_MODE:
|
case NCI_NFC_A_PASSIVE_POLL_MODE:
|
||||||
case NCI_NFC_F_PASSIVE_POLL_MODE:
|
case NCI_NFC_F_PASSIVE_POLL_MODE:
|
||||||
poll = &ntf->activation_params.poll_nfc_dep;
|
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);
|
pr_debug("atr_res_len %d\n", poll->atr_res_len);
|
||||||
if (poll->atr_res_len > 0)
|
if (poll->atr_res_len > 0)
|
||||||
memcpy(poll->atr_res, data, poll->atr_res_len);
|
memcpy(poll->atr_res, data, poll->atr_res_len);
|
||||||
break;
|
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:
|
default:
|
||||||
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
|
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
|
||||||
ntf->activation_rf_tech_and_mode);
|
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);
|
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,
|
static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
|
||||||
struct sk_buff *skb)
|
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);
|
&(ntf.rf_tech_specific_params.nfcv_poll), data);
|
||||||
break;
|
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:
|
default:
|
||||||
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
|
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
|
||||||
ntf.activation_rf_tech_and_mode);
|
ntf.activation_rf_tech_and_mode);
|
||||||
|
@ -546,32 +624,39 @@ exit:
|
||||||
|
|
||||||
/* store general bytes to be reported later in dep_link_up */
|
/* store general bytes to be reported later in dep_link_up */
|
||||||
if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
|
if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
|
||||||
ndev->remote_gb_len = 0;
|
err = nci_store_general_bytes_nfc_dep(ndev, &ntf);
|
||||||
|
if (err != NCI_STATUS_OK)
|
||||||
if (ntf.activation_params_len > 0) {
|
pr_err("unable to store general bytes\n");
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
|
if (!(ntf.activation_rf_tech_and_mode & NCI_RF_TECH_MODE_LISTEN_MASK)) {
|
||||||
/* A single target was found and activated automatically */
|
/* Poll mode */
|
||||||
atomic_set(&ndev->state, NCI_POLL_ACTIVE);
|
if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
|
||||||
if (err == NCI_STATUS_OK)
|
/* A single target was found and activated
|
||||||
nci_target_auto_activated(ndev, &ntf);
|
* automatically */
|
||||||
} else { /* ndev->state == NCI_W4_HOST_SELECT */
|
atomic_set(&ndev->state, NCI_POLL_ACTIVE);
|
||||||
/* A selected target was activated, so complete the request */
|
if (err == NCI_STATUS_OK)
|
||||||
atomic_set(&ndev->state, NCI_POLL_ACTIVE);
|
nci_target_auto_activated(ndev, &ntf);
|
||||||
nci_req_complete(ndev, err);
|
} else { /* ndev->state == NCI_W4_HOST_SELECT */
|
||||||
|
/* 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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue