linux/net/nfc/nci/rsp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  The NFC Controller Interface is the communication protocol between an
   4 *  NFC Controller (NFCC) and a Device Host (DH).
   5 *
   6 *  Copyright (C) 2011 Texas Instruments, Inc.
   7 *
   8 *  Written by Ilan Elias <ilane@ti.com>
   9 *
  10 *  Acknowledgements:
  11 *  This file is based on hci_event.c, which was written
  12 *  by Maxim Krasnyansky.
  13 */
  14
  15#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
  16
  17#include <linux/types.h>
  18#include <linux/interrupt.h>
  19#include <linux/bitops.h>
  20#include <linux/skbuff.h>
  21
  22#include "../nfc.h"
  23#include <net/nfc/nci.h>
  24#include <net/nfc/nci_core.h>
  25
  26/* Handle NCI Response packets */
  27
  28static void nci_core_reset_rsp_packet(struct nci_dev *ndev,
  29                                      const struct sk_buff *skb)
  30{
  31        const struct nci_core_reset_rsp *rsp = (void *)skb->data;
  32
  33        pr_debug("status 0x%x\n", rsp->status);
  34
  35        /* Handle NCI 1.x ver */
  36        if (skb->len != 1) {
  37                if (rsp->status == NCI_STATUS_OK) {
  38                        ndev->nci_ver = rsp->nci_ver;
  39                        pr_debug("nci_ver 0x%x, config_status 0x%x\n",
  40                                 rsp->nci_ver, rsp->config_status);
  41                }
  42
  43                nci_req_complete(ndev, rsp->status);
  44        }
  45}
  46
  47static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev,
  48                                      const struct sk_buff *skb)
  49{
  50        const struct nci_core_init_rsp_1 *rsp_1 = (void *)skb->data;
  51        const struct nci_core_init_rsp_2 *rsp_2;
  52
  53        pr_debug("status 0x%x\n", rsp_1->status);
  54
  55        if (rsp_1->status != NCI_STATUS_OK)
  56                return rsp_1->status;
  57
  58        ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
  59        ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
  60
  61        ndev->num_supported_rf_interfaces =
  62                min((int)ndev->num_supported_rf_interfaces,
  63                    NCI_MAX_SUPPORTED_RF_INTERFACES);
  64
  65        memcpy(ndev->supported_rf_interfaces,
  66               rsp_1->supported_rf_interfaces,
  67               ndev->num_supported_rf_interfaces);
  68
  69        rsp_2 = (void *) (skb->data + 6 + rsp_1->num_supported_rf_interfaces);
  70
  71        ndev->max_logical_connections = rsp_2->max_logical_connections;
  72        ndev->max_routing_table_size =
  73                __le16_to_cpu(rsp_2->max_routing_table_size);
  74        ndev->max_ctrl_pkt_payload_len =
  75                rsp_2->max_ctrl_pkt_payload_len;
  76        ndev->max_size_for_large_params =
  77                __le16_to_cpu(rsp_2->max_size_for_large_params);
  78        ndev->manufact_id =
  79                rsp_2->manufact_id;
  80        ndev->manufact_specific_info =
  81                __le32_to_cpu(rsp_2->manufact_specific_info);
  82
  83        return NCI_STATUS_OK;
  84}
  85
  86static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev,
  87                                      const struct sk_buff *skb)
  88{
  89        const struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
  90        const u8 *supported_rf_interface = rsp->supported_rf_interfaces;
  91        u8 rf_interface_idx = 0;
  92        u8 rf_extension_cnt = 0;
  93
  94        pr_debug("status %x\n", rsp->status);
  95
  96        if (rsp->status != NCI_STATUS_OK)
  97                return rsp->status;
  98
  99        ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features);
 100        ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces;
 101
 102        ndev->num_supported_rf_interfaces =
 103                min((int)ndev->num_supported_rf_interfaces,
 104                    NCI_MAX_SUPPORTED_RF_INTERFACES);
 105
 106        while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
 107                ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++;
 108
 109                /* skip rf extension parameters */
 110                rf_extension_cnt = *supported_rf_interface++;
 111                supported_rf_interface += rf_extension_cnt;
 112        }
 113
 114        ndev->max_logical_connections = rsp->max_logical_connections;
 115        ndev->max_routing_table_size =
 116                        __le16_to_cpu(rsp->max_routing_table_size);
 117        ndev->max_ctrl_pkt_payload_len =
 118                        rsp->max_ctrl_pkt_payload_len;
 119        ndev->max_size_for_large_params = NCI_MAX_LARGE_PARAMS_NCI_v2;
 120
 121        return NCI_STATUS_OK;
 122}
 123
 124static void nci_core_init_rsp_packet(struct nci_dev *ndev, const struct sk_buff *skb)
 125{
 126        u8 status = 0;
 127
 128        if (!(ndev->nci_ver & NCI_VER_2_MASK))
 129                status = nci_core_init_rsp_packet_v1(ndev, skb);
 130        else
 131                status = nci_core_init_rsp_packet_v2(ndev, skb);
 132
 133        if (status != NCI_STATUS_OK)
 134                goto exit;
 135
 136        pr_debug("nfcc_features 0x%x\n",
 137                 ndev->nfcc_features);
 138        pr_debug("num_supported_rf_interfaces %d\n",
 139                 ndev->num_supported_rf_interfaces);
 140        pr_debug("supported_rf_interfaces[0] 0x%x\n",
 141                 ndev->supported_rf_interfaces[0]);
 142        pr_debug("supported_rf_interfaces[1] 0x%x\n",
 143                 ndev->supported_rf_interfaces[1]);
 144        pr_debug("supported_rf_interfaces[2] 0x%x\n",
 145                 ndev->supported_rf_interfaces[2]);
 146        pr_debug("supported_rf_interfaces[3] 0x%x\n",
 147                 ndev->supported_rf_interfaces[3]);
 148        pr_debug("max_logical_connections %d\n",
 149                 ndev->max_logical_connections);
 150        pr_debug("max_routing_table_size %d\n",
 151                 ndev->max_routing_table_size);
 152        pr_debug("max_ctrl_pkt_payload_len %d\n",
 153                 ndev->max_ctrl_pkt_payload_len);
 154        pr_debug("max_size_for_large_params %d\n",
 155                 ndev->max_size_for_large_params);
 156        pr_debug("manufact_id 0x%x\n",
 157                 ndev->manufact_id);
 158        pr_debug("manufact_specific_info 0x%x\n",
 159                 ndev->manufact_specific_info);
 160
 161exit:
 162        nci_req_complete(ndev, status);
 163}
 164
 165static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
 166                                           const struct sk_buff *skb)
 167{
 168        const struct nci_core_set_config_rsp *rsp = (void *)skb->data;
 169
 170        pr_debug("status 0x%x\n", rsp->status);
 171
 172        nci_req_complete(ndev, rsp->status);
 173}
 174
 175static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
 176                                       const struct sk_buff *skb)
 177{
 178        __u8 status = skb->data[0];
 179
 180        pr_debug("status 0x%x\n", status);
 181
 182        nci_req_complete(ndev, status);
 183}
 184
 185static void nci_rf_disc_rsp_packet(struct nci_dev *ndev,
 186                                   const struct sk_buff *skb)
 187{
 188        struct nci_conn_info *conn_info;
 189        __u8 status = skb->data[0];
 190
 191        pr_debug("status 0x%x\n", status);
 192
 193        if (status == NCI_STATUS_OK) {
 194                atomic_set(&ndev->state, NCI_DISCOVERY);
 195
 196                conn_info = ndev->rf_conn_info;
 197                if (!conn_info) {
 198                        conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
 199                                                 sizeof(struct nci_conn_info),
 200                                                 GFP_KERNEL);
 201                        if (!conn_info) {
 202                                status = NCI_STATUS_REJECTED;
 203                                goto exit;
 204                        }
 205                        conn_info->conn_id = NCI_STATIC_RF_CONN_ID;
 206                        INIT_LIST_HEAD(&conn_info->list);
 207                        list_add(&conn_info->list, &ndev->conn_info_list);
 208                        ndev->rf_conn_info = conn_info;
 209                }
 210        }
 211
 212exit:
 213        nci_req_complete(ndev, status);
 214}
 215
 216static void nci_rf_disc_select_rsp_packet(struct nci_dev *ndev,
 217                                          const struct sk_buff *skb)
 218{
 219        __u8 status = skb->data[0];
 220
 221        pr_debug("status 0x%x\n", status);
 222
 223        /* Complete the request on intf_activated_ntf or generic_error_ntf */
 224        if (status != NCI_STATUS_OK)
 225                nci_req_complete(ndev, status);
 226}
 227
 228static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev,
 229                                         const struct sk_buff *skb)
 230{
 231        __u8 status = skb->data[0];
 232
 233        pr_debug("status 0x%x\n", status);
 234
 235        /* If target was active, complete the request only in deactivate_ntf */
 236        if ((status != NCI_STATUS_OK) ||
 237            (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
 238                nci_clear_target_list(ndev);
 239                atomic_set(&ndev->state, NCI_IDLE);
 240                nci_req_complete(ndev, status);
 241        }
 242}
 243
 244static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev,
 245                                          const struct sk_buff *skb)
 246{
 247        const struct nci_nfcee_discover_rsp *discover_rsp;
 248
 249        if (skb->len != 2) {
 250                nci_req_complete(ndev, NCI_STATUS_NFCEE_PROTOCOL_ERROR);
 251                return;
 252        }
 253
 254        discover_rsp = (struct nci_nfcee_discover_rsp *)skb->data;
 255
 256        if (discover_rsp->status != NCI_STATUS_OK ||
 257            discover_rsp->num_nfcee == 0)
 258                nci_req_complete(ndev, discover_rsp->status);
 259}
 260
 261static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev,
 262                                          const struct sk_buff *skb)
 263{
 264        __u8 status = skb->data[0];
 265
 266        pr_debug("status 0x%x\n", status);
 267        nci_req_complete(ndev, status);
 268}
 269
 270static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev,
 271                                            const struct sk_buff *skb)
 272{
 273        __u8 status = skb->data[0];
 274        struct nci_conn_info *conn_info = NULL;
 275        const struct nci_core_conn_create_rsp *rsp;
 276
 277        pr_debug("status 0x%x\n", status);
 278
 279        if (status == NCI_STATUS_OK) {
 280                rsp = (struct nci_core_conn_create_rsp *)skb->data;
 281
 282                conn_info = devm_kzalloc(&ndev->nfc_dev->dev,
 283                                         sizeof(*conn_info), GFP_KERNEL);
 284                if (!conn_info) {
 285                        status = NCI_STATUS_REJECTED;
 286                        goto exit;
 287                }
 288
 289                conn_info->dest_params = devm_kzalloc(&ndev->nfc_dev->dev,
 290                                                sizeof(struct dest_spec_params),
 291                                                GFP_KERNEL);
 292                if (!conn_info->dest_params) {
 293                        status = NCI_STATUS_REJECTED;
 294                        goto free_conn_info;
 295                }
 296
 297                conn_info->dest_type = ndev->cur_dest_type;
 298                conn_info->dest_params->id = ndev->cur_params.id;
 299                conn_info->dest_params->protocol = ndev->cur_params.protocol;
 300                conn_info->conn_id = rsp->conn_id;
 301
 302                /* Note: data_exchange_cb and data_exchange_cb_context need to
 303                 * be specify out of nci_core_conn_create_rsp_packet
 304                 */
 305
 306                INIT_LIST_HEAD(&conn_info->list);
 307                list_add(&conn_info->list, &ndev->conn_info_list);
 308
 309                if (ndev->cur_params.id == ndev->hci_dev->nfcee_id)
 310                        ndev->hci_dev->conn_info = conn_info;
 311
 312                conn_info->conn_id = rsp->conn_id;
 313                conn_info->max_pkt_payload_len = rsp->max_ctrl_pkt_payload_len;
 314                atomic_set(&conn_info->credits_cnt, rsp->credits_cnt);
 315        }
 316
 317free_conn_info:
 318        if (status == NCI_STATUS_REJECTED)
 319                devm_kfree(&ndev->nfc_dev->dev, conn_info);
 320exit:
 321
 322        nci_req_complete(ndev, status);
 323}
 324
 325static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
 326                                           const struct sk_buff *skb)
 327{
 328        struct nci_conn_info *conn_info;
 329        __u8 status = skb->data[0];
 330
 331        pr_debug("status 0x%x\n", status);
 332        if (status == NCI_STATUS_OK) {
 333                conn_info = nci_get_conn_info_by_conn_id(ndev,
 334                                                         ndev->cur_conn_id);
 335                if (conn_info) {
 336                        list_del(&conn_info->list);
 337                        if (conn_info == ndev->rf_conn_info)
 338                                ndev->rf_conn_info = NULL;
 339                        devm_kfree(&ndev->nfc_dev->dev, conn_info);
 340                }
 341        }
 342        nci_req_complete(ndev, status);
 343}
 344
 345void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 346{
 347        __u16 rsp_opcode = nci_opcode(skb->data);
 348
 349        /* we got a rsp, stop the cmd timer */
 350        del_timer(&ndev->cmd_timer);
 351
 352        pr_debug("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n",
 353                 nci_pbf(skb->data),
 354                 nci_opcode_gid(rsp_opcode),
 355                 nci_opcode_oid(rsp_opcode),
 356                 nci_plen(skb->data));
 357
 358        /* strip the nci control header */
 359        skb_pull(skb, NCI_CTRL_HDR_SIZE);
 360
 361        if (nci_opcode_gid(rsp_opcode) == NCI_GID_PROPRIETARY) {
 362                if (nci_prop_rsp_packet(ndev, rsp_opcode, skb) == -ENOTSUPP) {
 363                        pr_err("unsupported rsp opcode 0x%x\n",
 364                               rsp_opcode);
 365                }
 366
 367                goto end;
 368        }
 369
 370        switch (rsp_opcode) {
 371        case NCI_OP_CORE_RESET_RSP:
 372                nci_core_reset_rsp_packet(ndev, skb);
 373                break;
 374
 375        case NCI_OP_CORE_INIT_RSP:
 376                nci_core_init_rsp_packet(ndev, skb);
 377                break;
 378
 379        case NCI_OP_CORE_SET_CONFIG_RSP:
 380                nci_core_set_config_rsp_packet(ndev, skb);
 381                break;
 382
 383        case NCI_OP_CORE_CONN_CREATE_RSP:
 384                nci_core_conn_create_rsp_packet(ndev, skb);
 385                break;
 386
 387        case NCI_OP_CORE_CONN_CLOSE_RSP:
 388                nci_core_conn_close_rsp_packet(ndev, skb);
 389                break;
 390
 391        case NCI_OP_RF_DISCOVER_MAP_RSP:
 392                nci_rf_disc_map_rsp_packet(ndev, skb);
 393                break;
 394
 395        case NCI_OP_RF_DISCOVER_RSP:
 396                nci_rf_disc_rsp_packet(ndev, skb);
 397                break;
 398
 399        case NCI_OP_RF_DISCOVER_SELECT_RSP:
 400                nci_rf_disc_select_rsp_packet(ndev, skb);
 401                break;
 402
 403        case NCI_OP_RF_DEACTIVATE_RSP:
 404                nci_rf_deactivate_rsp_packet(ndev, skb);
 405                break;
 406
 407        case NCI_OP_NFCEE_DISCOVER_RSP:
 408                nci_nfcee_discover_rsp_packet(ndev, skb);
 409                break;
 410
 411        case NCI_OP_NFCEE_MODE_SET_RSP:
 412                nci_nfcee_mode_set_rsp_packet(ndev, skb);
 413                break;
 414
 415        default:
 416                pr_err("unknown rsp opcode 0x%x\n", rsp_opcode);
 417                break;
 418        }
 419
 420        nci_core_rsp_packet(ndev, rsp_opcode, skb);
 421end:
 422        kfree_skb(skb);
 423
 424        /* trigger the next cmd */
 425        atomic_set(&ndev->cmd_cnt, 1);
 426        if (!skb_queue_empty(&ndev->cmd_q))
 427                queue_work(ndev->cmd_wq, &ndev->cmd_work);
 428}
 429