NFC: nci: Add HCI over NCI protocol support

According to the NCI specification, one can use HCI over NCI
to talk with specific NFCEE. The HCI network is viewed as one
logical NFCEE.
This is needed to support secure element running HCI only
firmwares embedded on an NCI capable chipset, like e.g. the
st21nfcb.
There is some duplication between this piece of code and the
HCI core code, but the latter would need to be abstracted even
more to be able to use NCI as a logical transport for HCP packets.

Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Christophe Ricard
2015-02-01 22:26:14 +01:00
committed by Samuel Ortiz
parent 736bb95774
commit 11f54f2286
5 changed files with 816 additions and 19 deletions
+1 -1
View File
@@ -4,6 +4,6 @@
obj-$(CONFIG_NFC_NCI) += nci.o
nci-objs := core.o data.o lib.o ntf.o rsp.o
nci-objs := core.o data.o lib.o ntf.o rsp.o hci.o
nci-$(CONFIG_NFC_NCI_SPI) += spi.o
+13 -7
View File
@@ -122,10 +122,10 @@ static int __nci_request(struct nci_dev *ndev,
return rc;
}
static inline int nci_request(struct nci_dev *ndev,
void (*req)(struct nci_dev *ndev,
unsigned long opt),
unsigned long opt, __u32 timeout)
inline int nci_request(struct nci_dev *ndev,
void (*req)(struct nci_dev *ndev,
unsigned long opt),
unsigned long opt, __u32 timeout)
{
int rc;
@@ -901,7 +901,6 @@ static struct nfc_ops nci_nfc_ops = {
};
/* ---- Interface to NCI drivers ---- */
/**
* nci_allocate_device - allocate a new nci device
*
@@ -936,13 +935,20 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
tx_headroom + NCI_DATA_HDR_SIZE,
tx_tailroom);
if (!ndev->nfc_dev)
goto free_exit;
goto free_nci;
ndev->hci_dev = nci_hci_allocate(ndev);
if (!ndev->hci_dev)
goto free_nfc;
nfc_set_drvdata(ndev->nfc_dev, ndev);
return ndev;
free_exit:
free_nfc:
kfree(ndev->nfc_dev);
free_nci:
kfree(ndev);
return NULL;
}
+686
View File
File diff suppressed because it is too large Load Diff
+23 -11
View File
@@ -723,19 +723,31 @@ static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev,
pr_debug("\n");
conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
sizeof(struct nci_conn_info), GFP_KERNEL);
if (!conn_info) {
status = NCI_STATUS_REJECTED;
goto exit;
/* NFCForum NCI 9.2.1 HCI Network Specific Handling
* If the NFCC supports the HCI Network, it SHALL return one,
* and only one, NFCEE_DISCOVER_NTF with a Protocol type of
* “HCI Access”, even if the HCI Network contains multiple NFCEEs.
*/
if (!ndev->hci_dev->conn_info) {
conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
sizeof(*conn_info), GFP_KERNEL);
if (!conn_info) {
status = NCI_STATUS_REJECTED;
goto exit;
}
conn_info->id = nfcee_ntf->nfcee_id;
conn_info->conn_id = NCI_INVALID_CONN_ID;
conn_info->data_exchange_cb = nci_hci_data_received_cb;
conn_info->data_exchange_cb_context = ndev;
INIT_LIST_HEAD(&conn_info->list);
list_add(&conn_info->list, &ndev->conn_info_list);
ndev->hci_dev->conn_info = conn_info;
}
conn_info->id = nfcee_ntf->nfcee_id;
conn_info->conn_id = NCI_INVALID_CONN_ID;
INIT_LIST_HEAD(&conn_info->list);
list_add(&conn_info->list, &ndev->conn_info_list);
exit:
nci_req_complete(ndev, status);
}