aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/nci/rsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/nci/rsp.c')
-rw-r--r--net/nfc/nci/rsp.c121
1 files changed, 90 insertions, 31 deletions
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index a48297b79f34..b911ab78bed9 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -25,39 +25,42 @@
/* Handle NCI Response packets */
-static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+static void nci_core_reset_rsp_packet(struct nci_dev *ndev,
+ const struct sk_buff *skb)
{
- struct nci_core_reset_rsp *rsp = (void *) skb->data;
+ const struct nci_core_reset_rsp *rsp = (void *)skb->data;
pr_debug("status 0x%x\n", rsp->status);
- if (rsp->status == NCI_STATUS_OK) {
- ndev->nci_ver = rsp->nci_ver;
- pr_debug("nci_ver 0x%x, config_status 0x%x\n",
- rsp->nci_ver, rsp->config_status);
- }
+ /* Handle NCI 1.x ver */
+ if (skb->len != 1) {
+ if (rsp->status == NCI_STATUS_OK) {
+ ndev->nci_ver = rsp->nci_ver;
+ pr_debug("nci_ver 0x%x, config_status 0x%x\n",
+ rsp->nci_ver, rsp->config_status);
+ }
- nci_req_complete(ndev, rsp->status);
+ nci_req_complete(ndev, rsp->status);
+ }
}
-static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev,
+ const struct sk_buff *skb)
{
- struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data;
- struct nci_core_init_rsp_2 *rsp_2;
+ const struct nci_core_init_rsp_1 *rsp_1 = (void *)skb->data;
+ const struct nci_core_init_rsp_2 *rsp_2;
pr_debug("status 0x%x\n", rsp_1->status);
if (rsp_1->status != NCI_STATUS_OK)
- goto exit;
+ return rsp_1->status;
ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
- if (ndev->num_supported_rf_interfaces >
- NCI_MAX_SUPPORTED_RF_INTERFACES) {
- ndev->num_supported_rf_interfaces =
- NCI_MAX_SUPPORTED_RF_INTERFACES;
- }
+ ndev->num_supported_rf_interfaces =
+ min((int)ndev->num_supported_rf_interfaces,
+ NCI_MAX_SUPPORTED_RF_INTERFACES);
memcpy(ndev->supported_rf_interfaces,
rsp_1->supported_rf_interfaces,
@@ -77,6 +80,59 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
ndev->manufact_specific_info =
__le32_to_cpu(rsp_2->manufact_specific_info);
+ return NCI_STATUS_OK;
+}
+
+static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev,
+ const struct sk_buff *skb)
+{
+ const struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
+ const u8 *supported_rf_interface = rsp->supported_rf_interfaces;
+ u8 rf_interface_idx = 0;
+ u8 rf_extension_cnt = 0;
+
+ pr_debug("status %x\n", rsp->status);
+
+ if (rsp->status != NCI_STATUS_OK)
+ return rsp->status;
+
+ ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features);
+ ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces;
+
+ ndev->num_supported_rf_interfaces =
+ min((int)ndev->num_supported_rf_interfaces,
+ NCI_MAX_SUPPORTED_RF_INTERFACES);
+
+ while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
+ ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++;
+
+ /* skip rf extension parameters */
+ rf_extension_cnt = *supported_rf_interface++;
+ supported_rf_interface += rf_extension_cnt;
+ }
+
+ ndev->max_logical_connections = rsp->max_logical_connections;
+ ndev->max_routing_table_size =
+ __le16_to_cpu(rsp->max_routing_table_size);
+ ndev->max_ctrl_pkt_payload_len =
+ rsp->max_ctrl_pkt_payload_len;
+ ndev->max_size_for_large_params = NCI_MAX_LARGE_PARAMS_NCI_v2;
+
+ return NCI_STATUS_OK;
+}
+
+static void nci_core_init_rsp_packet(struct nci_dev *ndev, const struct sk_buff *skb)
+{
+ u8 status = 0;
+
+ if (!(ndev->nci_ver & NCI_VER_2_MASK))
+ status = nci_core_init_rsp_packet_v1(ndev, skb);
+ else
+ status = nci_core_init_rsp_packet_v2(ndev, skb);
+
+ if (status != NCI_STATUS_OK)
+ goto exit;
+
pr_debug("nfcc_features 0x%x\n",
ndev->nfcc_features);
pr_debug("num_supported_rf_interfaces %d\n",
@@ -103,13 +159,13 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
ndev->manufact_specific_info);
exit:
- nci_req_complete(ndev, rsp_1->status);
+ nci_req_complete(ndev, status);
}
static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
- struct nci_core_set_config_rsp *rsp = (void *) skb->data;
+ const struct nci_core_set_config_rsp *rsp = (void *)skb->data;
pr_debug("status 0x%x\n", rsp->status);
@@ -117,7 +173,7 @@ static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
}
static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -126,9 +182,10 @@ static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
nci_req_complete(ndev, status);
}
-static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+static void nci_rf_disc_rsp_packet(struct nci_dev *ndev,
+ const struct sk_buff *skb)
{
- struct nci_conn_info *conn_info;
+ struct nci_conn_info *conn_info;
__u8 status = skb->data[0];
pr_debug("status 0x%x\n", status);
@@ -157,7 +214,7 @@ exit:
}
static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -169,7 +226,7 @@ static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
}
static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -185,9 +242,9 @@ static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
}
static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
- struct nci_nfcee_discover_rsp *discover_rsp;
+ const struct nci_nfcee_discover_rsp *discover_rsp;
if (skb->len != 2) {
nci_req_complete(ndev, NCI_STATUS_NFCEE_PROTOCOL_ERROR);
@@ -202,7 +259,7 @@ static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev,
}
static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
__u8 status = skb->data[0];
@@ -211,11 +268,11 @@ static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev,
}
static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
__u8 status = skb->data[0];
struct nci_conn_info *conn_info = NULL;
- struct nci_core_conn_create_rsp *rsp;
+ const struct nci_core_conn_create_rsp *rsp;
pr_debug("status 0x%x\n", status);
@@ -266,7 +323,7 @@ exit:
}
static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
struct nci_conn_info *conn_info;
__u8 status = skb->data[0];
@@ -277,6 +334,8 @@ static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
ndev->cur_conn_id);
if (conn_info) {
list_del(&conn_info->list);
+ if (conn_info == ndev->rf_conn_info)
+ ndev->rf_conn_info = NULL;
devm_kfree(&ndev->nfc_dev->dev, conn_info);
}
}