linux/net/nfc/nci/hci.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 *  This is the HCI over NCI implementation, as specified in the 10.2
   6 *  section of the NCI 1.1 specification.
   7 *
   8 *  Copyright (C) 2014  STMicroelectronics SAS. All rights reserved.
   9 */
  10
  11#include <linux/skbuff.h>
  12
  13#include "../nfc.h"
  14#include <net/nfc/nci.h>
  15#include <net/nfc/nci_core.h>
  16#include <linux/nfc.h>
  17
  18struct nci_data {
  19        u8 conn_id;
  20        u8 pipe;
  21        u8 cmd;
  22        const u8 *data;
  23        u32 data_len;
  24} __packed;
  25
  26struct nci_hci_create_pipe_params {
  27        u8 src_gate;
  28        u8 dest_host;
  29        u8 dest_gate;
  30} __packed;
  31
  32struct nci_hci_create_pipe_resp {
  33        u8 src_host;
  34        u8 src_gate;
  35        u8 dest_host;
  36        u8 dest_gate;
  37        u8 pipe;
  38} __packed;
  39
  40struct nci_hci_delete_pipe_noti {
  41        u8 pipe;
  42} __packed;
  43
  44struct nci_hci_all_pipe_cleared_noti {
  45        u8 host;
  46} __packed;
  47
  48struct nci_hcp_message {
  49        u8 header;      /* type -cmd,evt,rsp- + instruction */
  50        u8 data[];
  51} __packed;
  52
  53struct nci_hcp_packet {
  54        u8 header;      /* cbit+pipe */
  55        struct nci_hcp_message message;
  56} __packed;
  57
  58#define NCI_HCI_ANY_SET_PARAMETER  0x01
  59#define NCI_HCI_ANY_GET_PARAMETER  0x02
  60#define NCI_HCI_ANY_CLOSE_PIPE     0x04
  61#define NCI_HCI_ADM_CLEAR_ALL_PIPE 0x14
  62
  63#define NCI_HFP_NO_CHAINING        0x80
  64
  65#define NCI_NFCEE_ID_HCI                0x80
  66
  67#define NCI_EVT_HOT_PLUG           0x03
  68
  69#define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY       0x01
  70#define NCI_HCI_ADM_CREATE_PIPE                 0x10
  71#define NCI_HCI_ADM_DELETE_PIPE                 0x11
  72
  73/* HCP headers */
  74#define NCI_HCI_HCP_PACKET_HEADER_LEN      1
  75#define NCI_HCI_HCP_MESSAGE_HEADER_LEN     1
  76#define NCI_HCI_HCP_HEADER_LEN             2
  77
  78/* HCP types */
  79#define NCI_HCI_HCP_COMMAND        0x00
  80#define NCI_HCI_HCP_EVENT          0x01
  81#define NCI_HCI_HCP_RESPONSE       0x02
  82
  83#define NCI_HCI_ADM_NOTIFY_PIPE_CREATED     0x12
  84#define NCI_HCI_ADM_NOTIFY_PIPE_DELETED     0x13
  85#define NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED 0x15
  86
  87#define NCI_HCI_FRAGMENT           0x7f
  88#define NCI_HCP_HEADER(type, instr) ((((type) & 0x03) << 6) |\
  89                                      ((instr) & 0x3f))
  90
  91#define NCI_HCP_MSG_GET_TYPE(header) ((header & 0xc0) >> 6)
  92#define NCI_HCP_MSG_GET_CMD(header)  (header & 0x3f)
  93#define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f)
  94
  95static int nci_hci_result_to_errno(u8 result)
  96{
  97        switch (result) {
  98        case NCI_HCI_ANY_OK:
  99                return 0;
 100        case NCI_HCI_ANY_E_REG_PAR_UNKNOWN:
 101                return -EOPNOTSUPP;
 102        case NCI_HCI_ANY_E_TIMEOUT:
 103                return -ETIME;
 104        default:
 105                return -1;
 106        }
 107}
 108
 109/* HCI core */
 110static void nci_hci_reset_pipes(struct nci_hci_dev *hdev)
 111{
 112        int i;
 113
 114        for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
 115                hdev->pipes[i].gate = NCI_HCI_INVALID_GATE;
 116                hdev->pipes[i].host = NCI_HCI_INVALID_HOST;
 117        }
 118        memset(hdev->gate2pipe, NCI_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
 119}
 120
 121static void nci_hci_reset_pipes_per_host(struct nci_dev *ndev, u8 host)
 122{
 123        int i;
 124
 125        for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
 126                if (ndev->hci_dev->pipes[i].host == host) {
 127                        ndev->hci_dev->pipes[i].gate = NCI_HCI_INVALID_GATE;
 128                        ndev->hci_dev->pipes[i].host = NCI_HCI_INVALID_HOST;
 129                }
 130        }
 131}
 132
 133/* Fragment HCI data over NCI packet.
 134 * NFC Forum NCI 10.2.2 Data Exchange:
 135 * The payload of the Data Packets sent on the Logical Connection SHALL be
 136 * valid HCP packets, as defined within [ETSI_102622]. Each Data Packet SHALL
 137 * contain a single HCP packet. NCI Segmentation and Reassembly SHALL NOT be
 138 * applied to Data Messages in either direction. The HCI fragmentation mechanism
 139 * is used if required.
 140 */
 141static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
 142                             const u8 data_type, const u8 *data,
 143                             size_t data_len)
 144{
 145        const struct nci_conn_info *conn_info;
 146        struct sk_buff *skb;
 147        int len, i, r;
 148        u8 cb = pipe;
 149
 150        conn_info = ndev->hci_dev->conn_info;
 151        if (!conn_info)
 152                return -EPROTO;
 153
 154        i = 0;
 155        skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
 156                            NCI_DATA_HDR_SIZE, GFP_KERNEL);
 157        if (!skb)
 158                return -ENOMEM;
 159
 160        skb_reserve(skb, NCI_DATA_HDR_SIZE + 2);
 161        *(u8 *)skb_push(skb, 1) = data_type;
 162
 163        do {
 164                /* If last packet add NCI_HFP_NO_CHAINING */
 165                if (i + conn_info->max_pkt_payload_len -
 166                    (skb->len + 1) >= data_len) {
 167                        cb |= NCI_HFP_NO_CHAINING;
 168                        len = data_len - i;
 169                } else {
 170                        len = conn_info->max_pkt_payload_len - skb->len - 1;
 171                }
 172
 173                *(u8 *)skb_push(skb, 1) = cb;
 174
 175                if (len > 0)
 176                        skb_put_data(skb, data + i, len);
 177
 178                r = nci_send_data(ndev, conn_info->conn_id, skb);
 179                if (r < 0)
 180                        return r;
 181
 182                i += len;
 183
 184                if (i < data_len) {
 185                        skb = nci_skb_alloc(ndev,
 186                                            conn_info->max_pkt_payload_len +
 187                                            NCI_DATA_HDR_SIZE, GFP_KERNEL);
 188                        if (!skb)
 189                                return -ENOMEM;
 190
 191                        skb_reserve(skb, NCI_DATA_HDR_SIZE + 1);
 192                }
 193        } while (i < data_len);
 194
 195        return i;
 196}
 197
 198static void nci_hci_send_data_req(struct nci_dev *ndev, const void *opt)
 199{
 200        const struct nci_data *data = opt;
 201
 202        nci_hci_send_data(ndev, data->pipe, data->cmd,
 203                          data->data, data->data_len);
 204}
 205
 206int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
 207                       const u8 *param, size_t param_len)
 208{
 209        u8 pipe = ndev->hci_dev->gate2pipe[gate];
 210
 211        if (pipe == NCI_HCI_INVALID_PIPE)
 212                return -EADDRNOTAVAIL;
 213
 214        return nci_hci_send_data(ndev, pipe,
 215                        NCI_HCP_HEADER(NCI_HCI_HCP_EVENT, event),
 216                        param, param_len);
 217}
 218EXPORT_SYMBOL(nci_hci_send_event);
 219
 220int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
 221                     const u8 *param, size_t param_len,
 222                     struct sk_buff **skb)
 223{
 224        const struct nci_hcp_message *message;
 225        const struct nci_conn_info *conn_info;
 226        struct nci_data data;
 227        int r;
 228        u8 pipe = ndev->hci_dev->gate2pipe[gate];
 229
 230        if (pipe == NCI_HCI_INVALID_PIPE)
 231                return -EADDRNOTAVAIL;
 232
 233        conn_info = ndev->hci_dev->conn_info;
 234        if (!conn_info)
 235                return -EPROTO;
 236
 237        data.conn_id = conn_info->conn_id;
 238        data.pipe = pipe;
 239        data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND, cmd);
 240        data.data = param;
 241        data.data_len = param_len;
 242
 243        r = nci_request(ndev, nci_hci_send_data_req, &data,
 244                        msecs_to_jiffies(NCI_DATA_TIMEOUT));
 245        if (r == NCI_STATUS_OK) {
 246                message = (struct nci_hcp_message *)conn_info->rx_skb->data;
 247                r = nci_hci_result_to_errno(
 248                        NCI_HCP_MSG_GET_CMD(message->header));
 249                skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
 250
 251                if (!r && skb)
 252                        *skb = conn_info->rx_skb;
 253        }
 254
 255        return r;
 256}
 257EXPORT_SYMBOL(nci_hci_send_cmd);
 258
 259int nci_hci_clear_all_pipes(struct nci_dev *ndev)
 260{
 261        int r;
 262
 263        r = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
 264                             NCI_HCI_ADM_CLEAR_ALL_PIPE, NULL, 0, NULL);
 265        if (r < 0)
 266                return r;
 267
 268        nci_hci_reset_pipes(ndev->hci_dev);
 269        return r;
 270}
 271EXPORT_SYMBOL(nci_hci_clear_all_pipes);
 272
 273static void nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
 274                                   u8 event, struct sk_buff *skb)
 275{
 276        if (ndev->ops->hci_event_received)
 277                ndev->ops->hci_event_received(ndev, pipe, event, skb);
 278}
 279
 280static void nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe,
 281                                 u8 cmd, struct sk_buff *skb)
 282{
 283        u8 gate = ndev->hci_dev->pipes[pipe].gate;
 284        u8 status = NCI_HCI_ANY_OK | ~NCI_HCI_FRAGMENT;
 285        u8 dest_gate, new_pipe;
 286        struct nci_hci_create_pipe_resp *create_info;
 287        struct nci_hci_delete_pipe_noti *delete_info;
 288        struct nci_hci_all_pipe_cleared_noti *cleared_info;
 289
 290        pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
 291
 292        switch (cmd) {
 293        case NCI_HCI_ADM_NOTIFY_PIPE_CREATED:
 294                if (skb->len != 5) {
 295                        status = NCI_HCI_ANY_E_NOK;
 296                        goto exit;
 297                }
 298                create_info = (struct nci_hci_create_pipe_resp *)skb->data;
 299                dest_gate = create_info->dest_gate;
 300                new_pipe = create_info->pipe;
 301                if (new_pipe >= NCI_HCI_MAX_PIPES) {
 302                        status = NCI_HCI_ANY_E_NOK;
 303                        goto exit;
 304                }
 305
 306                /* Save the new created pipe and bind with local gate,
 307                 * the description for skb->data[3] is destination gate id
 308                 * but since we received this cmd from host controller, we
 309                 * are the destination and it is our local gate
 310                 */
 311                ndev->hci_dev->gate2pipe[dest_gate] = new_pipe;
 312                ndev->hci_dev->pipes[new_pipe].gate = dest_gate;
 313                ndev->hci_dev->pipes[new_pipe].host =
 314                                                create_info->src_host;
 315                break;
 316        case NCI_HCI_ANY_OPEN_PIPE:
 317                /* If the pipe is not created report an error */
 318                if (gate == NCI_HCI_INVALID_GATE) {
 319                        status = NCI_HCI_ANY_E_NOK;
 320                        goto exit;
 321                }
 322                break;
 323        case NCI_HCI_ADM_NOTIFY_PIPE_DELETED:
 324                if (skb->len != 1) {
 325                        status = NCI_HCI_ANY_E_NOK;
 326                        goto exit;
 327                }
 328                delete_info = (struct nci_hci_delete_pipe_noti *)skb->data;
 329                if (delete_info->pipe >= NCI_HCI_MAX_PIPES) {
 330                        status = NCI_HCI_ANY_E_NOK;
 331                        goto exit;
 332                }
 333
 334                ndev->hci_dev->pipes[delete_info->pipe].gate =
 335                                                NCI_HCI_INVALID_GATE;
 336                ndev->hci_dev->pipes[delete_info->pipe].host =
 337                                                NCI_HCI_INVALID_HOST;
 338                break;
 339        case NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
 340                if (skb->len != 1) {
 341                        status = NCI_HCI_ANY_E_NOK;
 342                        goto exit;
 343                }
 344
 345                cleared_info =
 346                        (struct nci_hci_all_pipe_cleared_noti *)skb->data;
 347                nci_hci_reset_pipes_per_host(ndev, cleared_info->host);
 348                break;
 349        default:
 350                pr_debug("Discarded unknown cmd %x to gate %x\n", cmd, gate);
 351                break;
 352        }
 353
 354        if (ndev->ops->hci_cmd_received)
 355                ndev->ops->hci_cmd_received(ndev, pipe, cmd, skb);
 356
 357exit:
 358        nci_hci_send_data(ndev, pipe, status, NULL, 0);
 359
 360        kfree_skb(skb);
 361}
 362
 363static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
 364                                  struct sk_buff *skb)
 365{
 366        struct nci_conn_info *conn_info;
 367
 368        conn_info = ndev->hci_dev->conn_info;
 369        if (!conn_info)
 370                goto exit;
 371
 372        conn_info->rx_skb = skb;
 373
 374exit:
 375        nci_req_complete(ndev, NCI_STATUS_OK);
 376}
 377
 378/* Receive hcp message for pipe, with type and cmd.
 379 * skb contains optional message data only.
 380 */
 381static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
 382                                   u8 type, u8 instruction, struct sk_buff *skb)
 383{
 384        switch (type) {
 385        case NCI_HCI_HCP_RESPONSE:
 386                nci_hci_resp_received(ndev, pipe, skb);
 387                break;
 388        case NCI_HCI_HCP_COMMAND:
 389                nci_hci_cmd_received(ndev, pipe, instruction, skb);
 390                break;
 391        case NCI_HCI_HCP_EVENT:
 392                nci_hci_event_received(ndev, pipe, instruction, skb);
 393                break;
 394        default:
 395                pr_err("UNKNOWN MSG Type %d, instruction=%d\n",
 396                       type, instruction);
 397                kfree_skb(skb);
 398                break;
 399        }
 400
 401        nci_req_complete(ndev, NCI_STATUS_OK);
 402}
 403
 404static void nci_hci_msg_rx_work(struct work_struct *work)
 405{
 406        struct nci_hci_dev *hdev =
 407                container_of(work, struct nci_hci_dev, msg_rx_work);
 408        struct sk_buff *skb;
 409        const struct nci_hcp_message *message;
 410        u8 pipe, type, instruction;
 411
 412        while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
 413                pipe = NCI_HCP_MSG_GET_PIPE(skb->data[0]);
 414                skb_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
 415                message = (struct nci_hcp_message *)skb->data;
 416                type = NCI_HCP_MSG_GET_TYPE(message->header);
 417                instruction = NCI_HCP_MSG_GET_CMD(message->header);
 418                skb_pull(skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
 419
 420                nci_hci_hcp_message_rx(hdev->ndev, pipe,
 421                                       type, instruction, skb);
 422        }
 423}
 424
 425void nci_hci_data_received_cb(void *context,
 426                              struct sk_buff *skb, int err)
 427{
 428        struct nci_dev *ndev = (struct nci_dev *)context;
 429        struct nci_hcp_packet *packet;
 430        u8 pipe, type;
 431        struct sk_buff *hcp_skb;
 432        struct sk_buff *frag_skb;
 433        int msg_len;
 434
 435        pr_debug("\n");
 436
 437        if (err) {
 438                nci_req_complete(ndev, err);
 439                return;
 440        }
 441
 442        packet = (struct nci_hcp_packet *)skb->data;
 443        if ((packet->header & ~NCI_HCI_FRAGMENT) == 0) {
 444                skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
 445                return;
 446        }
 447
 448        /* it's the last fragment. Does it need re-aggregation? */
 449        if (skb_queue_len(&ndev->hci_dev->rx_hcp_frags)) {
 450                pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
 451                skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
 452
 453                msg_len = 0;
 454                skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
 455                        msg_len += (frag_skb->len -
 456                                    NCI_HCI_HCP_PACKET_HEADER_LEN);
 457                }
 458
 459                hcp_skb = nfc_alloc_recv_skb(NCI_HCI_HCP_PACKET_HEADER_LEN +
 460                                             msg_len, GFP_KERNEL);
 461                if (!hcp_skb) {
 462                        nci_req_complete(ndev, -ENOMEM);
 463                        return;
 464                }
 465
 466                skb_put_u8(hcp_skb, pipe);
 467
 468                skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
 469                        msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
 470                        skb_put_data(hcp_skb,
 471                                     frag_skb->data + NCI_HCI_HCP_PACKET_HEADER_LEN,
 472                                     msg_len);
 473                }
 474
 475                skb_queue_purge(&ndev->hci_dev->rx_hcp_frags);
 476        } else {
 477                packet->header &= NCI_HCI_FRAGMENT;
 478                hcp_skb = skb;
 479        }
 480
 481        /* if this is a response, dispatch immediately to
 482         * unblock waiting cmd context. Otherwise, enqueue to dispatch
 483         * in separate context where handler can also execute command.
 484         */
 485        packet = (struct nci_hcp_packet *)hcp_skb->data;
 486        type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
 487        if (type == NCI_HCI_HCP_RESPONSE) {
 488                pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
 489                skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
 490                nci_hci_hcp_message_rx(ndev, pipe, type,
 491                                       NCI_STATUS_OK, hcp_skb);
 492        } else {
 493                skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb);
 494                schedule_work(&ndev->hci_dev->msg_rx_work);
 495        }
 496}
 497
 498int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe)
 499{
 500        struct nci_data data;
 501        const struct nci_conn_info *conn_info;
 502
 503        conn_info = ndev->hci_dev->conn_info;
 504        if (!conn_info)
 505                return -EPROTO;
 506
 507        data.conn_id = conn_info->conn_id;
 508        data.pipe = pipe;
 509        data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
 510                                       NCI_HCI_ANY_OPEN_PIPE);
 511        data.data = NULL;
 512        data.data_len = 0;
 513
 514        return nci_request(ndev, nci_hci_send_data_req, &data,
 515                           msecs_to_jiffies(NCI_DATA_TIMEOUT));
 516}
 517EXPORT_SYMBOL(nci_hci_open_pipe);
 518
 519static u8 nci_hci_create_pipe(struct nci_dev *ndev, u8 dest_host,
 520                              u8 dest_gate, int *result)
 521{
 522        u8 pipe;
 523        struct sk_buff *skb;
 524        struct nci_hci_create_pipe_params params;
 525        const struct nci_hci_create_pipe_resp *resp;
 526
 527        pr_debug("gate=%d\n", dest_gate);
 528
 529        params.src_gate = NCI_HCI_ADMIN_GATE;
 530        params.dest_host = dest_host;
 531        params.dest_gate = dest_gate;
 532
 533        *result = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
 534                                   NCI_HCI_ADM_CREATE_PIPE,
 535                                   (u8 *)&params, sizeof(params), &skb);
 536        if (*result < 0)
 537                return NCI_HCI_INVALID_PIPE;
 538
 539        resp = (struct nci_hci_create_pipe_resp *)skb->data;
 540        pipe = resp->pipe;
 541        kfree_skb(skb);
 542
 543        pr_debug("pipe created=%d\n", pipe);
 544
 545        return pipe;
 546}
 547
 548static int nci_hci_delete_pipe(struct nci_dev *ndev, u8 pipe)
 549{
 550        pr_debug("\n");
 551
 552        return nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
 553                                NCI_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL);
 554}
 555
 556int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
 557                      const u8 *param, size_t param_len)
 558{
 559        const struct nci_hcp_message *message;
 560        const struct nci_conn_info *conn_info;
 561        struct nci_data data;
 562        int r;
 563        u8 *tmp;
 564        u8 pipe = ndev->hci_dev->gate2pipe[gate];
 565
 566        pr_debug("idx=%d to gate %d\n", idx, gate);
 567
 568        if (pipe == NCI_HCI_INVALID_PIPE)
 569                return -EADDRNOTAVAIL;
 570
 571        conn_info = ndev->hci_dev->conn_info;
 572        if (!conn_info)
 573                return -EPROTO;
 574
 575        tmp = kmalloc(1 + param_len, GFP_KERNEL);
 576        if (!tmp)
 577                return -ENOMEM;
 578
 579        *tmp = idx;
 580        memcpy(tmp + 1, param, param_len);
 581
 582        data.conn_id = conn_info->conn_id;
 583        data.pipe = pipe;
 584        data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
 585                                       NCI_HCI_ANY_SET_PARAMETER);
 586        data.data = tmp;
 587        data.data_len = param_len + 1;
 588
 589        r = nci_request(ndev, nci_hci_send_data_req, &data,
 590                        msecs_to_jiffies(NCI_DATA_TIMEOUT));
 591        if (r == NCI_STATUS_OK) {
 592                message = (struct nci_hcp_message *)conn_info->rx_skb->data;
 593                r = nci_hci_result_to_errno(
 594                        NCI_HCP_MSG_GET_CMD(message->header));
 595                skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
 596        }
 597
 598        kfree(tmp);
 599        return r;
 600}
 601EXPORT_SYMBOL(nci_hci_set_param);
 602
 603int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
 604                      struct sk_buff **skb)
 605{
 606        const struct nci_hcp_message *message;
 607        const struct nci_conn_info *conn_info;
 608        struct nci_data data;
 609        int r;
 610        u8 pipe = ndev->hci_dev->gate2pipe[gate];
 611
 612        pr_debug("idx=%d to gate %d\n", idx, gate);
 613
 614        if (pipe == NCI_HCI_INVALID_PIPE)
 615                return -EADDRNOTAVAIL;
 616
 617        conn_info = ndev->hci_dev->conn_info;
 618        if (!conn_info)
 619                return -EPROTO;
 620
 621        data.conn_id = conn_info->conn_id;
 622        data.pipe = pipe;
 623        data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
 624                                  NCI_HCI_ANY_GET_PARAMETER);
 625        data.data = &idx;
 626        data.data_len = 1;
 627
 628        r = nci_request(ndev, nci_hci_send_data_req, &data,
 629                        msecs_to_jiffies(NCI_DATA_TIMEOUT));
 630
 631        if (r == NCI_STATUS_OK) {
 632                message = (struct nci_hcp_message *)conn_info->rx_skb->data;
 633                r = nci_hci_result_to_errno(
 634                        NCI_HCP_MSG_GET_CMD(message->header));
 635                skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
 636
 637                if (!r && skb)
 638                        *skb = conn_info->rx_skb;
 639        }
 640
 641        return r;
 642}
 643EXPORT_SYMBOL(nci_hci_get_param);
 644
 645int nci_hci_connect_gate(struct nci_dev *ndev,
 646                         u8 dest_host, u8 dest_gate, u8 pipe)
 647{
 648        bool pipe_created = false;
 649        int r;
 650
 651        if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE)
 652                return 0;
 653
 654        if (ndev->hci_dev->gate2pipe[dest_gate] != NCI_HCI_INVALID_PIPE)
 655                return -EADDRINUSE;
 656
 657        if (pipe != NCI_HCI_INVALID_PIPE)
 658                goto open_pipe;
 659
 660        switch (dest_gate) {
 661        case NCI_HCI_LINK_MGMT_GATE:
 662                pipe = NCI_HCI_LINK_MGMT_PIPE;
 663        break;
 664        case NCI_HCI_ADMIN_GATE:
 665                pipe = NCI_HCI_ADMIN_PIPE;
 666        break;
 667        default:
 668                pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
 669                if (pipe == NCI_HCI_INVALID_PIPE)
 670                        return r;
 671                pipe_created = true;
 672                break;
 673        }
 674
 675open_pipe:
 676        r = nci_hci_open_pipe(ndev, pipe);
 677        if (r < 0) {
 678                if (pipe_created) {
 679                        if (nci_hci_delete_pipe(ndev, pipe) < 0) {
 680                                /* TODO: Cannot clean by deleting pipe...
 681                                 * -> inconsistent state
 682                                 */
 683                        }
 684                }
 685                return r;
 686        }
 687
 688        ndev->hci_dev->pipes[pipe].gate = dest_gate;
 689        ndev->hci_dev->pipes[pipe].host = dest_host;
 690        ndev->hci_dev->gate2pipe[dest_gate] = pipe;
 691
 692        return 0;
 693}
 694EXPORT_SYMBOL(nci_hci_connect_gate);
 695
 696static int nci_hci_dev_connect_gates(struct nci_dev *ndev,
 697                                     u8 gate_count,
 698                                     const struct nci_hci_gate *gates)
 699{
 700        int r;
 701
 702        while (gate_count--) {
 703                r = nci_hci_connect_gate(ndev, gates->dest_host,
 704                                         gates->gate, gates->pipe);
 705                if (r < 0)
 706                        return r;
 707                gates++;
 708        }
 709
 710        return 0;
 711}
 712
 713int nci_hci_dev_session_init(struct nci_dev *ndev)
 714{
 715        struct nci_conn_info *conn_info;
 716        struct sk_buff *skb;
 717        int r;
 718
 719        ndev->hci_dev->count_pipes = 0;
 720        ndev->hci_dev->expected_pipes = 0;
 721
 722        conn_info = ndev->hci_dev->conn_info;
 723        if (!conn_info)
 724                return -EPROTO;
 725
 726        conn_info->data_exchange_cb = nci_hci_data_received_cb;
 727        conn_info->data_exchange_cb_context = ndev;
 728
 729        nci_hci_reset_pipes(ndev->hci_dev);
 730
 731        if (ndev->hci_dev->init_data.gates[0].gate != NCI_HCI_ADMIN_GATE)
 732                return -EPROTO;
 733
 734        r = nci_hci_connect_gate(ndev,
 735                                 ndev->hci_dev->init_data.gates[0].dest_host,
 736                                 ndev->hci_dev->init_data.gates[0].gate,
 737                                 ndev->hci_dev->init_data.gates[0].pipe);
 738        if (r < 0)
 739                return r;
 740
 741        r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
 742                              NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY, &skb);
 743        if (r < 0)
 744                return r;
 745
 746        if (skb->len &&
 747            skb->len == strlen(ndev->hci_dev->init_data.session_id) &&
 748            !memcmp(ndev->hci_dev->init_data.session_id, skb->data, skb->len) &&
 749            ndev->ops->hci_load_session) {
 750                /* Restore gate<->pipe table from some proprietary location. */
 751                r = ndev->ops->hci_load_session(ndev);
 752        } else {
 753                r = nci_hci_clear_all_pipes(ndev);
 754                if (r < 0)
 755                        goto exit;
 756
 757                r = nci_hci_dev_connect_gates(ndev,
 758                                              ndev->hci_dev->init_data.gate_count,
 759                                              ndev->hci_dev->init_data.gates);
 760                if (r < 0)
 761                        goto exit;
 762
 763                r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
 764                                      NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY,
 765                                      ndev->hci_dev->init_data.session_id,
 766                                      strlen(ndev->hci_dev->init_data.session_id));
 767        }
 768
 769exit:
 770        kfree_skb(skb);
 771
 772        return r;
 773}
 774EXPORT_SYMBOL(nci_hci_dev_session_init);
 775
 776struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev)
 777{
 778        struct nci_hci_dev *hdev;
 779
 780        hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
 781        if (!hdev)
 782                return NULL;
 783
 784        skb_queue_head_init(&hdev->rx_hcp_frags);
 785        INIT_WORK(&hdev->msg_rx_work, nci_hci_msg_rx_work);
 786        skb_queue_head_init(&hdev->msg_rx_queue);
 787        hdev->ndev = ndev;
 788
 789        return hdev;
 790}
 791
 792void nci_hci_deallocate(struct nci_dev *ndev)
 793{
 794        kfree(ndev->hci_dev);
 795}
 796