Commit 9b8d1a4c authored by Christophe Ricard's avatar Christophe Ricard Committed by Samuel Ortiz

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: default avatarChristophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent de5ea851
...@@ -102,7 +102,8 @@ static int fdp_nci_create_conn(struct nci_dev *ndev) ...@@ -102,7 +102,8 @@ static int fdp_nci_create_conn(struct nci_dev *ndev)
if (r) if (r)
return 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) static inline int fdp_nci_get_versions(struct nci_dev *ndev)
......
...@@ -600,10 +600,12 @@ static int st_nci_hci_network_init(struct nci_dev *ndev) ...@@ -600,10 +600,12 @@ static int st_nci_hci_network_init(struct nci_dev *ndev)
* HCI will be used here only for proprietary commands. * HCI will be used here only for proprietary commands.
*/ */
if (test_bit(ST_NCI_FACTORY_MODE, &info->flags)) 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); NCI_NFCEE_DISABLE);
else 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); NCI_NFCEE_ENABLE);
free_dest_params: free_dest_params:
......
...@@ -109,7 +109,13 @@ struct nci_ops { ...@@ -109,7 +109,13 @@ struct nci_ops {
struct nci_conn_info { struct nci_conn_info {
struct list_head list; 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 conn_id;
__u8 max_pkt_payload_len; __u8 max_pkt_payload_len;
...@@ -260,7 +266,9 @@ struct nci_dev { ...@@ -260,7 +266,9 @@ struct nci_dev {
__u32 manufact_specific_info; __u32 manufact_specific_info;
/* Save RF Discovery ID or NFCEE ID under conn_create */ /* 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 */ /* stored during nci_data_exchange */
struct sk_buff *rx_data_reassembly; struct sk_buff *rx_data_reassembly;
...@@ -378,7 +386,8 @@ void nci_clear_target_list(struct nci_dev *ndev); ...@@ -378,7 +386,8 @@ void nci_clear_target_list(struct nci_dev *ndev);
void nci_req_complete(struct nci_dev *ndev, int result); 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, struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
int conn_id); 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 ----- */ /* ----- NCI status code ----- */
int nci_to_errno(__u8 code); int nci_to_errno(__u8 code);
......
...@@ -64,18 +64,26 @@ struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev, ...@@ -64,18 +64,26 @@ struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev,
return NULL; 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; struct nci_conn_info *conn_info;
list_for_each_entry(conn_info, &ndev->conn_info_list, list) { list_for_each_entry(conn_info, &ndev->conn_info_list, list) {
if (conn_info->id == id) if (conn_info->dest_type == dest_type) {
return conn_info->conn_id; 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; return -EINVAL;
} }
EXPORT_SYMBOL(nci_get_conn_info_by_id); EXPORT_SYMBOL(nci_get_conn_info_by_dest_type_params);
/* ---- NCI requests ---- */ /* ---- NCI requests ---- */
...@@ -623,12 +631,15 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, ...@@ -623,12 +631,15 @@ int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type,
if (params) { if (params) {
memcpy(cmd->params, params, params_len); memcpy(cmd->params, params, params_len);
if (params->length > 0) 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 else
ndev->cur_id = 0; ndev->cur_params.id = 0;
} else { } 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, r = __nci_request(ndev, nci_core_conn_create_req, (unsigned long)&data,
msecs_to_jiffies(NCI_CMD_TIMEOUT)); msecs_to_jiffies(NCI_CMD_TIMEOUT));
......
...@@ -734,7 +734,7 @@ static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev, ...@@ -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. * “HCI Access”, even if the HCI Network contains multiple NFCEEs.
*/ */
ndev->hci_dev->nfcee_id = nfcee_ntf->nfcee_id; 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); nci_req_complete(ndev, status);
} }
......
...@@ -226,7 +226,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, ...@@ -226,7 +226,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
__u8 status = skb->data[0]; __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; struct nci_core_conn_create_rsp *rsp;
pr_debug("status 0x%x\n", status); pr_debug("status 0x%x\n", status);
...@@ -241,7 +241,17 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, ...@@ -241,7 +241,17 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
goto exit; 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; conn_info->conn_id = rsp->conn_id;
/* Note: data_exchange_cb and data_exchange_cb_context need to /* 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,7 +261,7 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
INIT_LIST_HEAD(&conn_info->list); INIT_LIST_HEAD(&conn_info->list);
list_add(&conn_info->list, &ndev->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; ndev->hci_dev->conn_info = conn_info;
conn_info->conn_id = rsp->conn_id; conn_info->conn_id = rsp->conn_id;
...@@ -259,7 +269,11 @@ static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, ...@@ -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); 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: exit:
nci_req_complete(ndev, status); nci_req_complete(ndev, status);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment