nfc: nci: Add an additional parameter to identify a connection id
authorChristophe Ricard <christophe.ricard@gmail.com>
Sat, 30 Apr 2016 07:12:51 +0000 (09:12 +0200)
committerSamuel Ortiz <sameo@linux.intel.com>
Tue, 3 May 2016 23:43:21 +0000 (01:43 +0200)
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>
drivers/nfc/fdp/fdp.c
drivers/nfc/st-nci/se.c
include/net/nfc/nci_core.h
net/nfc/nci/core.c
net/nfc/nci/ntf.c
net/nfc/nci/rsp.c

index ccb07a1b153db27f5cadb57d1152d3fdd4b4e8b8..e44a7a2f4061a10a6838dded77c0ecc999abe82a 100644 (file)
@@ -102,7 +102,8 @@ static int fdp_nci_create_conn(struct nci_dev *ndev)
        if (r)
                return r;
 
-       return nci_get_conn_info_by_id(ndev, 0);
+       return nci_get_conn_info_by_dest_type_params(ndev,
+                                                    FDP_PATCH_CONN_DEST, NULL);
 }
 
 static inline int fdp_nci_get_versions(struct nci_dev *ndev)
index e7f25f4e3dc3f465ad4ee32981f1f66fab354fc6..420f019cc42fbf68c9badc81d14e866fb8904c29 100644 (file)
@@ -600,10 +600,12 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
         * HCI will be used here only for proprietary commands.
         */
        if (test_bit(ST_NCI_FACTORY_MODE, &info->flags))
-               r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+               r = nci_nfcee_mode_set(ndev,
+                                      ndev->hci_dev->conn_info->dest_params->id,
                                       NCI_NFCEE_DISABLE);
        else
-               r = nci_nfcee_mode_set(ndev, ndev->hci_dev->conn_info->id,
+               r = nci_nfcee_mode_set(ndev,
+                                      ndev->hci_dev->conn_info->dest_params->id,
                                       NCI_NFCEE_ENABLE);
 
 free_dest_params:
index 57ce24fb0047046d2e12839df1d30df7ce4999d7..ebb50d286ef6d679e77f4be3db798b662cdfa46f 100644 (file)
@@ -109,7 +109,13 @@ struct nci_ops {
 
 struct nci_conn_info {
        struct list_head list;
-       __u8    id; /* can be an RF Discovery ID or an NFCEE ID */
+       /* NCI specification 4.4.2 Connection Creation
+        * The combination of destination type and destination specific
+        * parameters shall uniquely identify a single destination for the
+        * Logical Connection
+        */
+       struct dest_spec_params *dest_params;
+       __u8    dest_type;
        __u8    conn_id;
        __u8    max_pkt_payload_len;
 
@@ -260,7 +266,9 @@ struct nci_dev {
        __u32                   manufact_specific_info;
 
        /* Save RF Discovery ID or NFCEE ID under conn_create */
-       __u8                    cur_id;
+       struct dest_spec_params cur_params;
+       /* Save destination type under conn_create */
+       __u8                    cur_dest_type;
 
        /* stored during nci_data_exchange */
        struct sk_buff          *rx_data_reassembly;
@@ -378,7 +386,8 @@ void nci_clear_target_list(struct nci_dev *ndev);
 void nci_req_complete(struct nci_dev *ndev, int result);
 struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
                                                   int conn_id);
-int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id);
+int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type,
+                                         struct dest_spec_params *params);
 
 /* ----- NCI status code ----- */
 int nci_to_errno(__u8 code);
index 0884f1444817117f3bc0f5d992554d06d52359db..74f2d54df4fc100606ee783e2ad3607fb17fd057 100644 (file)
@@ -64,18 +64,26 @@ struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
        return NULL;
 }
 
-int nci_get_conn_info_by_id(struct nci_dev *ndev, u8 id)
+int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type,
+                                         struct dest_spec_params *params)
 {
        struct nci_conn_info *conn_info;
 
        list_for_each_entry(conn_info, &ndev->conn_info_list, list) {
-               if (conn_info->id == id)
-                       return conn_info->conn_id;
+               if (conn_info->dest_type == dest_type) {
+                       if (!params)
+                               return conn_info->conn_id;
+                       if (conn_info) {
+                               if (params->id == conn_info->dest_params->id &&
+                                   params->protocol == conn_info->dest_params->protocol)
+                                       return conn_info->conn_id;
+                       }
+               }
        }
 
        return -EINVAL;
 }
-EXPORT_SYMBOL(nci_get_conn_info_by_id);
+EXPORT_SYMBOL(nci_get_conn_info_by_dest_type_params);
 
 /* ---- NCI requests ---- */
 
@@ -623,12 +631,15 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
        if (params) {
                memcpy(cmd->params, params, params_len);
                if (params->length > 0)
-                       ndev->cur_id = params->value[DEST_SPEC_PARAMS_ID_INDEX];
+                       memcpy(&ndev->cur_params,
+                              &params->value[DEST_SPEC_PARAMS_ID_INDEX],
+                              sizeof(struct dest_spec_params));
                else
-                       ndev->cur_id = 0;
+                       ndev->cur_params.id = 0;
        } else {
-               ndev->cur_id = 0;
+               ndev->cur_params.id = 0;
        }
+       ndev->cur_dest_type = destination_type;
 
        r = __nci_request(ndev, nci_core_conn_create_req, (unsigned long)&data,
                          msecs_to_jiffies(NCI_CMD_TIMEOUT));
index 2ada2b39e355efa7fd0e4aa154115bec580aadd7..1e8c1a12aaec35c0f14ad44740e904c03060f05f 100644 (file)
@@ -734,7 +734,7 @@ static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev,
         * “HCI Access”, even if the HCI Network contains multiple NFCEEs.
         */
        ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id;
-       ndev->cur_id = nfcee_ntf->nfcee_id;
+       ndev->cur_params.id = nfcee_ntf->nfcee_id;
 
        nci_req_complete(ndev, status);
 }
index 69fe163b7350825f1a4731a8357ac99c45da385f..e3bbf1937d0e96e0af5e4df215f89548fb2b5686 100644 (file)
@@ -226,7 +226,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
                                            struct sk_buff *skb)
 {
        __u8 status = skb->data[0];
-       struct nci_conn_info *conn_info;
+       struct nci_conn_info *conn_info = NULL;
        struct nci_core_conn_create_rsp *rsp;
 
        pr_debug("status 0x%x\n", status);
@@ -241,7 +241,17 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
                        goto exit;
                }
 
-               conn_info->id = ndev->cur_id;
+               conn_info->dest_params = devm_kzalloc(&ndev->nfc_dev->dev,
+                                               sizeof(struct dest_spec_params),
+                                               GFP_KERNEL);
+               if (!conn_info->dest_params) {
+                       status = NCI_STATUS_REJECTED;
+                       goto free_conn_info;
+               }
+
+               conn_info->dest_type = ndev->cur_dest_type;
+               conn_info->dest_params->id = ndev->cur_params.id;
+               conn_info->dest_params->protocol = ndev->cur_params.protocol;
                conn_info->conn_id = rsp->conn_id;
 
                /* 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,
                INIT_LIST_HEAD(&conn_info->list);
                list_add(&conn_info->list, &ndev->conn_info_list);
 
-               if (ndev->cur_id == ndev->hci_dev->nfcee_id)
+               if (ndev->cur_params.id == ndev->hci_dev->nfcee_id)
                        ndev->hci_dev->conn_info = conn_info;
 
                conn_info->conn_id = rsp->conn_id;
@@ -259,7 +269,11 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
                atomic_set(&conn_info->credits_cnt, rsp->credits_cnt);
        }
 
+free_conn_info:
+       if (status == NCI_STATUS_REJECTED)
+               devm_kfree(&ndev->nfc_dev->dev, conn_info);
 exit:
+
        nci_req_complete(ndev, status);
 }