Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Christophe Ricard and committed by
Samuel Ortiz
9b8d1a4c de5ea851

+54 -17
+2 -1
drivers/nfc/fdp/fdp.c
··· 102 102 if (r) 103 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 108 109 static inline int fdp_nci_get_versions(struct nci_dev *ndev)
+4 -2
drivers/nfc/st-nci/se.c
··· 600 600 * HCI will be used here only for proprietary commands. 601 601 */ 602 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 605 NCI_NFCEE_DISABLE); 605 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 609 NCI_NFCEE_ENABLE); 608 610 609 611 free_dest_params:
+12 -3
include/net/nfc/nci_core.h
··· 109 109 110 110 struct nci_conn_info { 111 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 119 __u8 conn_id; 114 120 __u8 max_pkt_payload_len; 115 121 ··· 266 260 __u32 manufact_specific_info; 267 261 268 262 /* Save RF Discovery ID or NFCEE ID under conn_create */ 269 - __u8 cur_id; 263 + struct dest_spec_params cur_params; 264 + /* Save destination type under conn_create */ 265 + __u8 cur_dest_type; 270 266 271 267 /* stored during nci_data_exchange */ 272 268 struct sk_buff *rx_data_reassembly; ··· 386 378 void nci_req_complete(struct nci_dev *ndev, int result); 387 379 struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev, 388 380 int conn_id); 389 - int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id); 381 + int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type, 382 + struct dest_spec_params *params); 390 383 391 384 /* ----- NCI status code ----- */ 392 385 int nci_to_errno(__u8 code);
+18 -7
net/nfc/nci/core.c
··· 64 64 return NULL; 65 65 } 66 66 67 - int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id) 67 + int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type, 68 + struct dest_spec_params *params) 68 69 { 69 70 struct nci_conn_info *conn_info; 70 71 71 72 list_for_each_entry(conn_info, &ndev->conn_info_list, list) { 72 - if (conn_info->id == id) 73 - return conn_info->conn_id; 73 + if (conn_info->dest_type == dest_type) { 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 84 return -EINVAL; 77 85 } 78 - EXPORT_SYMBOL(nci_get_conn_info_by_id); 86 + EXPORT_SYMBOL(nci_get_conn_info_by_dest_type_params); 79 87 80 88 /* ---- NCI requests ---- */ 81 89 ··· 631 623 if (params) { 632 624 memcpy(cmd->params, params, params_len); 633 625 if (params->length > 0) 634 - ndev->cur_id = params->value[DEST_SPEC_PARAMS_ID_INDEX]; 626 + memcpy(&ndev->cur_params, 627 + &params->value[DEST_SPEC_PARAMS_ID_INDEX], 628 + sizeof(struct dest_spec_params)); 635 629 else 636 - ndev->cur_id = 0; 630 + ndev->cur_params.id = 0; 637 631 } else { 638 - ndev->cur_id = 0; 632 + ndev->cur_params.id = 0; 639 633 } 634 + ndev->cur_dest_type = destination_type; 640 635 641 636 r = __nci_request(ndev, nci_core_conn_create_req, (unsigned long)&data, 642 637 msecs_to_jiffies(NCI_CMD_TIMEOUT));
+1 -1
net/nfc/nci/ntf.c
··· 734 734 * “HCI Access”, even if the HCI Network contains multiple NFCEEs. 735 735 */ 736 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 739 nci_req_complete(ndev, status); 740 740 }
+17 -3
net/nfc/nci/rsp.c
··· 226 226 struct sk_buff *skb) 227 227 { 228 228 __u8 status = skb->data[0]; 229 - struct nci_conn_info *conn_info; 229 + struct nci_conn_info *conn_info = NULL; 230 230 struct nci_core_conn_create_rsp *rsp; 231 231 232 232 pr_debug("status 0x%x\n", status); ··· 241 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 255 conn_info->conn_id = rsp->conn_id; 246 256 247 257 /* Note: data_exchange_cb and data_exchange_cb_context need to ··· 261 251 INIT_LIST_HEAD(&conn_info->list); 262 252 list_add(&conn_info->list, &ndev->conn_info_list); 263 253 264 - if (ndev->cur_id == ndev->hci_dev->nfcee_id) 254 + if (ndev->cur_params.id == ndev->hci_dev->nfcee_id) 265 255 ndev->hci_dev->conn_info = conn_info; 266 256 267 257 conn_info->conn_id = rsp->conn_id; ··· 269 259 atomic_set(&conn_info->credits_cnt, rsp->credits_cnt); 270 260 } 271 261 262 + free_conn_info: 263 + if (status == NCI_STATUS_REJECTED) 264 + devm_kfree(&ndev->nfc_dev->dev, conn_info); 272 265 exit: 266 + 273 267 nci_req_complete(ndev, status); 274 268 } 275 269