aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2016-04-30 03:12:51 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2016-05-03 19:43:21 -0400
commit9b8d1a4cf2aa819d606b4e423a6523fc0d4460a2 (patch)
tree5862df9d18bb3e54f90b6fb81a23ac68ea0107a8
parentde5ea8517c2ae40785fe5d0a2d02fc71bef1761b (diff)
nfc: nci: Add an additional parameter to identify a connection id
According to NCI specification, destination type and destination specific parameters shall uniquely identify a single destination for the Logical Connection. Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/nfc/fdp/fdp.c3
-rw-r--r--drivers/nfc/st-nci/se.c6
-rw-r--r--include/net/nfc/nci_core.h15
-rw-r--r--net/nfc/nci/core.c25
-rw-r--r--net/nfc/nci/ntf.c2
-rw-r--r--net/nfc/nci/rsp.c20
6 files changed, 54 insertions, 17 deletions
diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c
index ccb07a1b153d..e44a7a2f4061 100644
--- a/drivers/nfc/fdp/fdp.c
+++ b/drivers/nfc/fdp/fdp.c
@@ -102,7 +102,8 @@ static int fdp_nci_create_conn(struct nci_dev *ndev)
102 if (r) 102 if (r)
103 return r; 103 return r;
104 104
105 return nci_get_conn_info_by_id(ndev, 0); 105 return nci_get_conn_info_by_dest_type_params(ndev,
106 FDP_PATCH_CONN_DEST, NULL);
106} 107}
107 108
108static inline int fdp_nci_get_versions(struct nci_dev *ndev) 109static inline int fdp_nci_get_versions(struct nci_dev *ndev)
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c
index e7f25f4e3dc3..420f019cc42f 100644
--- a/drivers/nfc/st-nci/se.c
+++ b/drivers/nfc/st-nci/se.c
@@ -600,10 +600,12 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
600 * HCI will be used here only for proprietary commands. 600 * HCI will be used here only for proprietary commands.
601 */ 601 */
602 if (test_bit(ST_NCI_FACTORY_MODE, &info->flags)) 602 if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
603 r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id, 603 r = nci_nfcee_mode_set(ndev,
604 ndev->hci_dev->conn_info->dest_params->id,
604 NCI_NFCEE_DISABLE); 605 NCI_NFCEE_DISABLE);
605 else 606 else
606 r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id, 607 r = nci_nfcee_mode_set(ndev,
608 ndev->hci_dev->conn_info->dest_params->id,
607 NCI_NFCEE_ENABLE); 609 NCI_NFCEE_ENABLE);
608 610
609free_dest_params: 611free_dest_params:
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 57ce24fb0047..ebb50d286ef6 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -109,7 +109,13 @@ struct nci_ops {
109 109
110struct nci_conn_info { 110struct nci_conn_info {
111 struct list_head list; 111 struct list_head list;
112 __u8 id; /* can be an RF Discovery ID or an NFCEE ID */ 112 /* NCI specification 4.4.2 Connection Creation
113 * The combination of destination type and destination specific
114 * parameters shall uniquely identify a single destination for the
115 * Logical Connection
116 */
117 struct dest_spec_params *dest_params;
118 __u8 dest_type;
113 __u8 conn_id; 119 __u8 conn_id;
114 __u8 max_pkt_payload_len; 120 __u8 max_pkt_payload_len;
115 121
@@ -260,7 +266,9 @@ struct nci_dev {
260 __u32 manufact_specific_info; 266 __u32 manufact_specific_info;
261 267
262 /* Save RF Discovery ID or NFCEE ID under conn_create */ 268 /* Save RF Discovery ID or NFCEE ID under conn_create */
263 __u8 cur_id; 269 struct dest_spec_params cur_params;
270 /* Save destination type under conn_create */
271 __u8 cur_dest_type;
264 272
265 /* stored during nci_data_exchange */ 273 /* stored during nci_data_exchange */
266 struct sk_buff *rx_data_reassembly; 274 struct sk_buff *rx_data_reassembly;
@@ -378,7 +386,8 @@ void nci_clear_target_list(struct nci_dev *ndev);
378void nci_req_complete(struct nci_dev *ndev, int result); 386void nci_req_complete(struct nci_dev *ndev, int result);
379struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev, 387struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
380 int conn_id); 388 int conn_id);
381int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id); 389int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type,
390 struct dest_spec_params *params);
382 391
383/* ----- NCI status code ----- */ 392/* ----- NCI status code ----- */
384int nci_to_errno(__u8 code); 393int nci_to_errno(__u8 code);
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 0884f1444817..74f2d54df4fc 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -64,18 +64,26 @@ struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
64 return NULL; 64 return NULL;
65} 65}
66 66
67int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id) 67int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type,
68 struct dest_spec_params *params)
68{ 69{
69 struct nci_conn_info *conn_info; 70 struct nci_conn_info *conn_info;
70 71
71 list_for_each_entry(conn_info, &ndev->conn_info_list, list) { 72 list_for_each_entry(conn_info, &ndev->conn_info_list, list) {
72 if (conn_info->id == id) 73 if (conn_info->dest_type == dest_type) {
73 return conn_info->conn_id; 74 if (!params)
75 return conn_info->conn_id;
76 if (conn_info) {
77 if (params->id == conn_info->dest_params->id &&
78 params->protocol == conn_info->dest_params->protocol)
79 return conn_info->conn_id;
80 }
81 }
74 } 82 }
75 83
76 return -EINVAL; 84 return -EINVAL;
77} 85}
78EXPORT_SYMBOL(nci_get_conn_info_by_id); 86EXPORT_SYMBOL(nci_get_conn_info_by_dest_type_params);
79 87
80/* ---- NCI requests ---- */ 88/* ---- NCI requests ---- */
81 89
@@ -623,12 +631,15 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
623 if (params) { 631 if (params) {
624 memcpy(cmd->params, params, params_len); 632 memcpy(cmd->params, params, params_len);
625 if (params->length > 0) 633 if (params->length > 0)
626 ndev->cur_id = params->value[DEST_SPEC_PARAMS_ID_INDEX]; 634 memcpy(&ndev->cur_params,
635 &params->value[DEST_SPEC_PARAMS_ID_INDEX],
636 sizeof(struct dest_spec_params));
627 else 637 else
628 ndev->cur_id = 0; 638 ndev->cur_params.id = 0;
629 } else { 639 } else {
630 ndev->cur_id = 0; 640 ndev->cur_params.id = 0;
631 } 641 }
642 ndev->cur_dest_type = destination_type;
632 643
633 r = __nci_request(ndev, nci_core_conn_create_req, (unsigned long)&data, 644 r = __nci_request(ndev, nci_core_conn_create_req, (unsigned long)&data,
634 msecs_to_jiffies(NCI_CMD_TIMEOUT)); 645 msecs_to_jiffies(NCI_CMD_TIMEOUT));
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 2ada2b39e355..1e8c1a12aaec 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -734,7 +734,7 @@ static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev,
734 * “HCI Access”, even if the HCI Network contains multiple NFCEEs. 734 * “HCI Access”, even if the HCI Network contains multiple NFCEEs.
735 */ 735 */
736 ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id; 736 ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id;
737 ndev->cur_id = nfcee_ntf->nfcee_id; 737 ndev->cur_params.id = nfcee_ntf->nfcee_id;
738 738
739 nci_req_complete(ndev, status); 739 nci_req_complete(ndev, status);
740} 740}
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index 69fe163b7350..e3bbf1937d0e 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -226,7 +226,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
226 struct sk_buff *skb) 226 struct sk_buff *skb)
227{ 227{
228 __u8 status = skb->data[0]; 228 __u8 status = skb->data[0];
229 struct nci_conn_info *conn_info; 229 struct nci_conn_info *conn_info = NULL;
230 struct nci_core_conn_create_rsp *rsp; 230 struct nci_core_conn_create_rsp *rsp;
231 231
232 pr_debug("status 0x%x\n", status); 232 pr_debug("status 0x%x\n", status);
@@ -241,7 +241,17 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
241 goto exit; 241 goto exit;
242 } 242 }
243 243
244 conn_info->id = ndev->cur_id; 244 conn_info->dest_params = devm_kzalloc(&ndev->nfc_dev->dev,
245 sizeof(struct dest_spec_params),
246 GFP_KERNEL);
247 if (!conn_info->dest_params) {
248 status = NCI_STATUS_REJECTED;
249 goto free_conn_info;
250 }
251
252 conn_info->dest_type = ndev->cur_dest_type;
253 conn_info->dest_params->id = ndev->cur_params.id;
254 conn_info->dest_params->protocol = ndev->cur_params.protocol;
245 conn_info->conn_id = rsp->conn_id; 255 conn_info->conn_id = rsp->conn_id;
246 256
247 /* Note: data_exchange_cb and data_exchange_cb_context need to 257 /* Note: data_exchange_cb and data_exchange_cb_context need to
@@ -251,7 +261,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
251 INIT_LIST_HEAD(&conn_info->list); 261 INIT_LIST_HEAD(&conn_info->list);
252 list_add(&conn_info->list, &ndev->conn_info_list); 262 list_add(&conn_info->list, &ndev->conn_info_list);
253 263
254 if (ndev->cur_id == ndev->hci_dev->nfcee_id) 264 if (ndev->cur_params.id == ndev->hci_dev->nfcee_id)
255 ndev->hci_dev->conn_info = conn_info; 265 ndev->hci_dev->conn_info = conn_info;
256 266
257 conn_info->conn_id = rsp->conn_id; 267 conn_info->conn_id = rsp->conn_id;
@@ -259,7 +269,11 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
259 atomic_set(&conn_info->credits_cnt, rsp->credits_cnt); 269 atomic_set(&conn_info->credits_cnt, rsp->credits_cnt);
260 } 270 }
261 271
272free_conn_info:
273 if (status == NCI_STATUS_REJECTED)
274 devm_kfree(&ndev->nfc_dev->dev, conn_info);
262exit: 275exit:
276
263 nci_req_complete(ndev, status); 277 nci_req_complete(ndev, status);
264} 278}
265 279