Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  The NFC Controller Interface is the communication protocol between an
0004  *  NFC Controller (NFCC) and a Device Host (DH).
0005  *  This is the HCI over NCI implementation, as specified in the 10.2
0006  *  section of the NCI 1.1 specification.
0007  *
0008  *  Copyright (C) 2014  STMicroelectronics SAS. All rights reserved.
0009  */
0010 
0011 #include <linux/skbuff.h>
0012 
0013 #include "../nfc.h"
0014 #include <net/nfc/nci.h>
0015 #include <net/nfc/nci_core.h>
0016 #include <linux/nfc.h>
0017 
0018 struct nci_data {
0019     u8 conn_id;
0020     u8 pipe;
0021     u8 cmd;
0022     const u8 *data;
0023     u32 data_len;
0024 } __packed;
0025 
0026 struct nci_hci_create_pipe_params {
0027     u8 src_gate;
0028     u8 dest_host;
0029     u8 dest_gate;
0030 } __packed;
0031 
0032 struct nci_hci_create_pipe_resp {
0033     u8 src_host;
0034     u8 src_gate;
0035     u8 dest_host;
0036     u8 dest_gate;
0037     u8 pipe;
0038 } __packed;
0039 
0040 struct nci_hci_delete_pipe_noti {
0041     u8 pipe;
0042 } __packed;
0043 
0044 struct nci_hci_all_pipe_cleared_noti {
0045     u8 host;
0046 } __packed;
0047 
0048 struct nci_hcp_message {
0049     u8 header;      /* type -cmd,evt,rsp- + instruction */
0050     u8 data[];
0051 } __packed;
0052 
0053 struct nci_hcp_packet {
0054     u8 header;      /* cbit+pipe */
0055     struct nci_hcp_message message;
0056 } __packed;
0057 
0058 #define NCI_HCI_ANY_SET_PARAMETER  0x01
0059 #define NCI_HCI_ANY_GET_PARAMETER  0x02
0060 #define NCI_HCI_ANY_CLOSE_PIPE     0x04
0061 #define NCI_HCI_ADM_CLEAR_ALL_PIPE 0x14
0062 
0063 #define NCI_HFP_NO_CHAINING        0x80
0064 
0065 #define NCI_NFCEE_ID_HCI                0x80
0066 
0067 #define NCI_EVT_HOT_PLUG           0x03
0068 
0069 #define NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY       0x01
0070 #define NCI_HCI_ADM_CREATE_PIPE         0x10
0071 #define NCI_HCI_ADM_DELETE_PIPE         0x11
0072 
0073 /* HCP headers */
0074 #define NCI_HCI_HCP_PACKET_HEADER_LEN      1
0075 #define NCI_HCI_HCP_MESSAGE_HEADER_LEN     1
0076 #define NCI_HCI_HCP_HEADER_LEN             2
0077 
0078 /* HCP types */
0079 #define NCI_HCI_HCP_COMMAND        0x00
0080 #define NCI_HCI_HCP_EVENT          0x01
0081 #define NCI_HCI_HCP_RESPONSE       0x02
0082 
0083 #define NCI_HCI_ADM_NOTIFY_PIPE_CREATED     0x12
0084 #define NCI_HCI_ADM_NOTIFY_PIPE_DELETED     0x13
0085 #define NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED 0x15
0086 
0087 #define NCI_HCI_FRAGMENT           0x7f
0088 #define NCI_HCP_HEADER(type, instr) ((((type) & 0x03) << 6) |\
0089                       ((instr) & 0x3f))
0090 
0091 #define NCI_HCP_MSG_GET_TYPE(header) ((header & 0xc0) >> 6)
0092 #define NCI_HCP_MSG_GET_CMD(header)  (header & 0x3f)
0093 #define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f)
0094 
0095 static int nci_hci_result_to_errno(u8 result)
0096 {
0097     switch (result) {
0098     case NCI_HCI_ANY_OK:
0099         return 0;
0100     case NCI_HCI_ANY_E_REG_PAR_UNKNOWN:
0101         return -EOPNOTSUPP;
0102     case NCI_HCI_ANY_E_TIMEOUT:
0103         return -ETIME;
0104     default:
0105         return -1;
0106     }
0107 }
0108 
0109 /* HCI core */
0110 static void nci_hci_reset_pipes(struct nci_hci_dev *hdev)
0111 {
0112     int i;
0113 
0114     for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
0115         hdev->pipes[i].gate = NCI_HCI_INVALID_GATE;
0116         hdev->pipes[i].host = NCI_HCI_INVALID_HOST;
0117     }
0118     memset(hdev->gate2pipe, NCI_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe));
0119 }
0120 
0121 static void nci_hci_reset_pipes_per_host(struct nci_dev *ndev, u8 host)
0122 {
0123     int i;
0124 
0125     for (i = 0; i < NCI_HCI_MAX_PIPES; i++) {
0126         if (ndev->hci_dev->pipes[i].host == host) {
0127             ndev->hci_dev->pipes[i].gate = NCI_HCI_INVALID_GATE;
0128             ndev->hci_dev->pipes[i].host = NCI_HCI_INVALID_HOST;
0129         }
0130     }
0131 }
0132 
0133 /* Fragment HCI data over NCI packet.
0134  * NFC Forum NCI 10.2.2 Data Exchange:
0135  * The payload of the Data Packets sent on the Logical Connection SHALL be
0136  * valid HCP packets, as defined within [ETSI_102622]. Each Data Packet SHALL
0137  * contain a single HCP packet. NCI Segmentation and Reassembly SHALL NOT be
0138  * applied to Data Messages in either direction. The HCI fragmentation mechanism
0139  * is used if required.
0140  */
0141 static int nci_hci_send_data(struct nci_dev *ndev, u8 pipe,
0142                  const u8 data_type, const u8 *data,
0143                  size_t data_len)
0144 {
0145     const struct nci_conn_info *conn_info;
0146     struct sk_buff *skb;
0147     int len, i, r;
0148     u8 cb = pipe;
0149 
0150     conn_info = ndev->hci_dev->conn_info;
0151     if (!conn_info)
0152         return -EPROTO;
0153 
0154     i = 0;
0155     skb = nci_skb_alloc(ndev, conn_info->max_pkt_payload_len +
0156                 NCI_DATA_HDR_SIZE, GFP_ATOMIC);
0157     if (!skb)
0158         return -ENOMEM;
0159 
0160     skb_reserve(skb, NCI_DATA_HDR_SIZE + 2);
0161     *(u8 *)skb_push(skb, 1) = data_type;
0162 
0163     do {
0164         /* If last packet add NCI_HFP_NO_CHAINING */
0165         if (i + conn_info->max_pkt_payload_len -
0166             (skb->len + 1) >= data_len) {
0167             cb |= NCI_HFP_NO_CHAINING;
0168             len = data_len - i;
0169         } else {
0170             len = conn_info->max_pkt_payload_len - skb->len - 1;
0171         }
0172 
0173         *(u8 *)skb_push(skb, 1) = cb;
0174 
0175         if (len > 0)
0176             skb_put_data(skb, data + i, len);
0177 
0178         r = nci_send_data(ndev, conn_info->conn_id, skb);
0179         if (r < 0)
0180             return r;
0181 
0182         i += len;
0183 
0184         if (i < data_len) {
0185             skb = nci_skb_alloc(ndev,
0186                         conn_info->max_pkt_payload_len +
0187                         NCI_DATA_HDR_SIZE, GFP_ATOMIC);
0188             if (!skb)
0189                 return -ENOMEM;
0190 
0191             skb_reserve(skb, NCI_DATA_HDR_SIZE + 1);
0192         }
0193     } while (i < data_len);
0194 
0195     return i;
0196 }
0197 
0198 static void nci_hci_send_data_req(struct nci_dev *ndev, const void *opt)
0199 {
0200     const struct nci_data *data = opt;
0201 
0202     nci_hci_send_data(ndev, data->pipe, data->cmd,
0203               data->data, data->data_len);
0204 }
0205 
0206 int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
0207                const u8 *param, size_t param_len)
0208 {
0209     u8 pipe = ndev->hci_dev->gate2pipe[gate];
0210 
0211     if (pipe == NCI_HCI_INVALID_PIPE)
0212         return -EADDRNOTAVAIL;
0213 
0214     return nci_hci_send_data(ndev, pipe,
0215             NCI_HCP_HEADER(NCI_HCI_HCP_EVENT, event),
0216             param, param_len);
0217 }
0218 EXPORT_SYMBOL(nci_hci_send_event);
0219 
0220 int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
0221              const u8 *param, size_t param_len,
0222              struct sk_buff **skb)
0223 {
0224     const struct nci_hcp_message *message;
0225     const struct nci_conn_info *conn_info;
0226     struct nci_data data;
0227     int r;
0228     u8 pipe = ndev->hci_dev->gate2pipe[gate];
0229 
0230     if (pipe == NCI_HCI_INVALID_PIPE)
0231         return -EADDRNOTAVAIL;
0232 
0233     conn_info = ndev->hci_dev->conn_info;
0234     if (!conn_info)
0235         return -EPROTO;
0236 
0237     data.conn_id = conn_info->conn_id;
0238     data.pipe = pipe;
0239     data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND, cmd);
0240     data.data = param;
0241     data.data_len = param_len;
0242 
0243     r = nci_request(ndev, nci_hci_send_data_req, &data,
0244             msecs_to_jiffies(NCI_DATA_TIMEOUT));
0245     if (r == NCI_STATUS_OK) {
0246         message = (struct nci_hcp_message *)conn_info->rx_skb->data;
0247         r = nci_hci_result_to_errno(
0248             NCI_HCP_MSG_GET_CMD(message->header));
0249         skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0250 
0251         if (!r && skb)
0252             *skb = conn_info->rx_skb;
0253     }
0254 
0255     return r;
0256 }
0257 EXPORT_SYMBOL(nci_hci_send_cmd);
0258 
0259 int nci_hci_clear_all_pipes(struct nci_dev *ndev)
0260 {
0261     int r;
0262 
0263     r = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
0264                  NCI_HCI_ADM_CLEAR_ALL_PIPE, NULL, 0, NULL);
0265     if (r < 0)
0266         return r;
0267 
0268     nci_hci_reset_pipes(ndev->hci_dev);
0269     return r;
0270 }
0271 EXPORT_SYMBOL(nci_hci_clear_all_pipes);
0272 
0273 static void nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
0274                    u8 event, struct sk_buff *skb)
0275 {
0276     if (ndev->ops->hci_event_received)
0277         ndev->ops->hci_event_received(ndev, pipe, event, skb);
0278 }
0279 
0280 static void nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe,
0281                  u8 cmd, struct sk_buff *skb)
0282 {
0283     u8 gate = ndev->hci_dev->pipes[pipe].gate;
0284     u8 status = NCI_HCI_ANY_OK | ~NCI_HCI_FRAGMENT;
0285     u8 dest_gate, new_pipe;
0286     struct nci_hci_create_pipe_resp *create_info;
0287     struct nci_hci_delete_pipe_noti *delete_info;
0288     struct nci_hci_all_pipe_cleared_noti *cleared_info;
0289 
0290     pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
0291 
0292     switch (cmd) {
0293     case NCI_HCI_ADM_NOTIFY_PIPE_CREATED:
0294         if (skb->len != 5) {
0295             status = NCI_HCI_ANY_E_NOK;
0296             goto exit;
0297         }
0298         create_info = (struct nci_hci_create_pipe_resp *)skb->data;
0299         dest_gate = create_info->dest_gate;
0300         new_pipe = create_info->pipe;
0301         if (new_pipe >= NCI_HCI_MAX_PIPES) {
0302             status = NCI_HCI_ANY_E_NOK;
0303             goto exit;
0304         }
0305 
0306         /* Save the new created pipe and bind with local gate,
0307          * the description for skb->data[3] is destination gate id
0308          * but since we received this cmd from host controller, we
0309          * are the destination and it is our local gate
0310          */
0311         ndev->hci_dev->gate2pipe[dest_gate] = new_pipe;
0312         ndev->hci_dev->pipes[new_pipe].gate = dest_gate;
0313         ndev->hci_dev->pipes[new_pipe].host =
0314                         create_info->src_host;
0315         break;
0316     case NCI_HCI_ANY_OPEN_PIPE:
0317         /* If the pipe is not created report an error */
0318         if (gate == NCI_HCI_INVALID_GATE) {
0319             status = NCI_HCI_ANY_E_NOK;
0320             goto exit;
0321         }
0322         break;
0323     case NCI_HCI_ADM_NOTIFY_PIPE_DELETED:
0324         if (skb->len != 1) {
0325             status = NCI_HCI_ANY_E_NOK;
0326             goto exit;
0327         }
0328         delete_info = (struct nci_hci_delete_pipe_noti *)skb->data;
0329         if (delete_info->pipe >= NCI_HCI_MAX_PIPES) {
0330             status = NCI_HCI_ANY_E_NOK;
0331             goto exit;
0332         }
0333 
0334         ndev->hci_dev->pipes[delete_info->pipe].gate =
0335                         NCI_HCI_INVALID_GATE;
0336         ndev->hci_dev->pipes[delete_info->pipe].host =
0337                         NCI_HCI_INVALID_HOST;
0338         break;
0339     case NCI_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
0340         if (skb->len != 1) {
0341             status = NCI_HCI_ANY_E_NOK;
0342             goto exit;
0343         }
0344 
0345         cleared_info =
0346             (struct nci_hci_all_pipe_cleared_noti *)skb->data;
0347         nci_hci_reset_pipes_per_host(ndev, cleared_info->host);
0348         break;
0349     default:
0350         pr_debug("Discarded unknown cmd %x to gate %x\n", cmd, gate);
0351         break;
0352     }
0353 
0354     if (ndev->ops->hci_cmd_received)
0355         ndev->ops->hci_cmd_received(ndev, pipe, cmd, skb);
0356 
0357 exit:
0358     nci_hci_send_data(ndev, pipe, status, NULL, 0);
0359 
0360     kfree_skb(skb);
0361 }
0362 
0363 static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
0364                   struct sk_buff *skb)
0365 {
0366     struct nci_conn_info *conn_info;
0367 
0368     conn_info = ndev->hci_dev->conn_info;
0369     if (!conn_info)
0370         goto exit;
0371 
0372     conn_info->rx_skb = skb;
0373 
0374 exit:
0375     nci_req_complete(ndev, NCI_STATUS_OK);
0376 }
0377 
0378 /* Receive hcp message for pipe, with type and cmd.
0379  * skb contains optional message data only.
0380  */
0381 static void nci_hci_hcp_message_rx(struct nci_dev *ndev, u8 pipe,
0382                    u8 type, u8 instruction, struct sk_buff *skb)
0383 {
0384     switch (type) {
0385     case NCI_HCI_HCP_RESPONSE:
0386         nci_hci_resp_received(ndev, pipe, skb);
0387         break;
0388     case NCI_HCI_HCP_COMMAND:
0389         nci_hci_cmd_received(ndev, pipe, instruction, skb);
0390         break;
0391     case NCI_HCI_HCP_EVENT:
0392         nci_hci_event_received(ndev, pipe, instruction, skb);
0393         break;
0394     default:
0395         pr_err("UNKNOWN MSG Type %d, instruction=%d\n",
0396                type, instruction);
0397         kfree_skb(skb);
0398         break;
0399     }
0400 
0401     nci_req_complete(ndev, NCI_STATUS_OK);
0402 }
0403 
0404 static void nci_hci_msg_rx_work(struct work_struct *work)
0405 {
0406     struct nci_hci_dev *hdev =
0407         container_of(work, struct nci_hci_dev, msg_rx_work);
0408     struct sk_buff *skb;
0409     const struct nci_hcp_message *message;
0410     u8 pipe, type, instruction;
0411 
0412     while ((skb = skb_dequeue(&hdev->msg_rx_queue)) != NULL) {
0413         pipe = NCI_HCP_MSG_GET_PIPE(skb->data[0]);
0414         skb_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
0415         message = (struct nci_hcp_message *)skb->data;
0416         type = NCI_HCP_MSG_GET_TYPE(message->header);
0417         instruction = NCI_HCP_MSG_GET_CMD(message->header);
0418         skb_pull(skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0419 
0420         nci_hci_hcp_message_rx(hdev->ndev, pipe,
0421                        type, instruction, skb);
0422     }
0423 }
0424 
0425 void nci_hci_data_received_cb(void *context,
0426                   struct sk_buff *skb, int err)
0427 {
0428     struct nci_dev *ndev = (struct nci_dev *)context;
0429     struct nci_hcp_packet *packet;
0430     u8 pipe, type;
0431     struct sk_buff *hcp_skb;
0432     struct sk_buff *frag_skb;
0433     int msg_len;
0434 
0435     if (err) {
0436         nci_req_complete(ndev, err);
0437         return;
0438     }
0439 
0440     packet = (struct nci_hcp_packet *)skb->data;
0441     if ((packet->header & ~NCI_HCI_FRAGMENT) == 0) {
0442         skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
0443         return;
0444     }
0445 
0446     /* it's the last fragment. Does it need re-aggregation? */
0447     if (skb_queue_len(&ndev->hci_dev->rx_hcp_frags)) {
0448         pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
0449         skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
0450 
0451         msg_len = 0;
0452         skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
0453             msg_len += (frag_skb->len -
0454                     NCI_HCI_HCP_PACKET_HEADER_LEN);
0455         }
0456 
0457         hcp_skb = nfc_alloc_recv_skb(NCI_HCI_HCP_PACKET_HEADER_LEN +
0458                          msg_len, GFP_KERNEL);
0459         if (!hcp_skb) {
0460             nci_req_complete(ndev, -ENOMEM);
0461             return;
0462         }
0463 
0464         skb_put_u8(hcp_skb, pipe);
0465 
0466         skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
0467             msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
0468             skb_put_data(hcp_skb,
0469                      frag_skb->data + NCI_HCI_HCP_PACKET_HEADER_LEN,
0470                      msg_len);
0471         }
0472 
0473         skb_queue_purge(&ndev->hci_dev->rx_hcp_frags);
0474     } else {
0475         packet->header &= NCI_HCI_FRAGMENT;
0476         hcp_skb = skb;
0477     }
0478 
0479     /* if this is a response, dispatch immediately to
0480      * unblock waiting cmd context. Otherwise, enqueue to dispatch
0481      * in separate context where handler can also execute command.
0482      */
0483     packet = (struct nci_hcp_packet *)hcp_skb->data;
0484     type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
0485     if (type == NCI_HCI_HCP_RESPONSE) {
0486         pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
0487         skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
0488         nci_hci_hcp_message_rx(ndev, pipe, type,
0489                        NCI_STATUS_OK, hcp_skb);
0490     } else {
0491         skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb);
0492         schedule_work(&ndev->hci_dev->msg_rx_work);
0493     }
0494 }
0495 
0496 int nci_hci_open_pipe(struct nci_dev *ndev, u8 pipe)
0497 {
0498     struct nci_data data;
0499     const struct nci_conn_info *conn_info;
0500 
0501     conn_info = ndev->hci_dev->conn_info;
0502     if (!conn_info)
0503         return -EPROTO;
0504 
0505     data.conn_id = conn_info->conn_id;
0506     data.pipe = pipe;
0507     data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
0508                        NCI_HCI_ANY_OPEN_PIPE);
0509     data.data = NULL;
0510     data.data_len = 0;
0511 
0512     return nci_request(ndev, nci_hci_send_data_req, &data,
0513                msecs_to_jiffies(NCI_DATA_TIMEOUT));
0514 }
0515 EXPORT_SYMBOL(nci_hci_open_pipe);
0516 
0517 static u8 nci_hci_create_pipe(struct nci_dev *ndev, u8 dest_host,
0518                   u8 dest_gate, int *result)
0519 {
0520     u8 pipe;
0521     struct sk_buff *skb;
0522     struct nci_hci_create_pipe_params params;
0523     const struct nci_hci_create_pipe_resp *resp;
0524 
0525     pr_debug("gate=%d\n", dest_gate);
0526 
0527     params.src_gate = NCI_HCI_ADMIN_GATE;
0528     params.dest_host = dest_host;
0529     params.dest_gate = dest_gate;
0530 
0531     *result = nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
0532                    NCI_HCI_ADM_CREATE_PIPE,
0533                    (u8 *)&params, sizeof(params), &skb);
0534     if (*result < 0)
0535         return NCI_HCI_INVALID_PIPE;
0536 
0537     resp = (struct nci_hci_create_pipe_resp *)skb->data;
0538     pipe = resp->pipe;
0539     kfree_skb(skb);
0540 
0541     pr_debug("pipe created=%d\n", pipe);
0542 
0543     return pipe;
0544 }
0545 
0546 static int nci_hci_delete_pipe(struct nci_dev *ndev, u8 pipe)
0547 {
0548     return nci_hci_send_cmd(ndev, NCI_HCI_ADMIN_GATE,
0549                 NCI_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL);
0550 }
0551 
0552 int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
0553               const u8 *param, size_t param_len)
0554 {
0555     const struct nci_hcp_message *message;
0556     const struct nci_conn_info *conn_info;
0557     struct nci_data data;
0558     int r;
0559     u8 *tmp;
0560     u8 pipe = ndev->hci_dev->gate2pipe[gate];
0561 
0562     pr_debug("idx=%d to gate %d\n", idx, gate);
0563 
0564     if (pipe == NCI_HCI_INVALID_PIPE)
0565         return -EADDRNOTAVAIL;
0566 
0567     conn_info = ndev->hci_dev->conn_info;
0568     if (!conn_info)
0569         return -EPROTO;
0570 
0571     tmp = kmalloc(1 + param_len, GFP_KERNEL);
0572     if (!tmp)
0573         return -ENOMEM;
0574 
0575     *tmp = idx;
0576     memcpy(tmp + 1, param, param_len);
0577 
0578     data.conn_id = conn_info->conn_id;
0579     data.pipe = pipe;
0580     data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
0581                        NCI_HCI_ANY_SET_PARAMETER);
0582     data.data = tmp;
0583     data.data_len = param_len + 1;
0584 
0585     r = nci_request(ndev, nci_hci_send_data_req, &data,
0586             msecs_to_jiffies(NCI_DATA_TIMEOUT));
0587     if (r == NCI_STATUS_OK) {
0588         message = (struct nci_hcp_message *)conn_info->rx_skb->data;
0589         r = nci_hci_result_to_errno(
0590             NCI_HCP_MSG_GET_CMD(message->header));
0591         skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0592     }
0593 
0594     kfree(tmp);
0595     return r;
0596 }
0597 EXPORT_SYMBOL(nci_hci_set_param);
0598 
0599 int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
0600               struct sk_buff **skb)
0601 {
0602     const struct nci_hcp_message *message;
0603     const struct nci_conn_info *conn_info;
0604     struct nci_data data;
0605     int r;
0606     u8 pipe = ndev->hci_dev->gate2pipe[gate];
0607 
0608     pr_debug("idx=%d to gate %d\n", idx, gate);
0609 
0610     if (pipe == NCI_HCI_INVALID_PIPE)
0611         return -EADDRNOTAVAIL;
0612 
0613     conn_info = ndev->hci_dev->conn_info;
0614     if (!conn_info)
0615         return -EPROTO;
0616 
0617     data.conn_id = conn_info->conn_id;
0618     data.pipe = pipe;
0619     data.cmd = NCI_HCP_HEADER(NCI_HCI_HCP_COMMAND,
0620                   NCI_HCI_ANY_GET_PARAMETER);
0621     data.data = &idx;
0622     data.data_len = 1;
0623 
0624     r = nci_request(ndev, nci_hci_send_data_req, &data,
0625             msecs_to_jiffies(NCI_DATA_TIMEOUT));
0626 
0627     if (r == NCI_STATUS_OK) {
0628         message = (struct nci_hcp_message *)conn_info->rx_skb->data;
0629         r = nci_hci_result_to_errno(
0630             NCI_HCP_MSG_GET_CMD(message->header));
0631         skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
0632 
0633         if (!r && skb)
0634             *skb = conn_info->rx_skb;
0635     }
0636 
0637     return r;
0638 }
0639 EXPORT_SYMBOL(nci_hci_get_param);
0640 
0641 int nci_hci_connect_gate(struct nci_dev *ndev,
0642              u8 dest_host, u8 dest_gate, u8 pipe)
0643 {
0644     bool pipe_created = false;
0645     int r;
0646 
0647     if (pipe == NCI_HCI_DO_NOT_OPEN_PIPE)
0648         return 0;
0649 
0650     if (ndev->hci_dev->gate2pipe[dest_gate] != NCI_HCI_INVALID_PIPE)
0651         return -EADDRINUSE;
0652 
0653     if (pipe != NCI_HCI_INVALID_PIPE)
0654         goto open_pipe;
0655 
0656     switch (dest_gate) {
0657     case NCI_HCI_LINK_MGMT_GATE:
0658         pipe = NCI_HCI_LINK_MGMT_PIPE;
0659     break;
0660     case NCI_HCI_ADMIN_GATE:
0661         pipe = NCI_HCI_ADMIN_PIPE;
0662     break;
0663     default:
0664         pipe = nci_hci_create_pipe(ndev, dest_host, dest_gate, &r);
0665         if (pipe == NCI_HCI_INVALID_PIPE)
0666             return r;
0667         pipe_created = true;
0668         break;
0669     }
0670 
0671 open_pipe:
0672     r = nci_hci_open_pipe(ndev, pipe);
0673     if (r < 0) {
0674         if (pipe_created) {
0675             if (nci_hci_delete_pipe(ndev, pipe) < 0) {
0676                 /* TODO: Cannot clean by deleting pipe...
0677                  * -> inconsistent state
0678                  */
0679             }
0680         }
0681         return r;
0682     }
0683 
0684     ndev->hci_dev->pipes[pipe].gate = dest_gate;
0685     ndev->hci_dev->pipes[pipe].host = dest_host;
0686     ndev->hci_dev->gate2pipe[dest_gate] = pipe;
0687 
0688     return 0;
0689 }
0690 EXPORT_SYMBOL(nci_hci_connect_gate);
0691 
0692 static int nci_hci_dev_connect_gates(struct nci_dev *ndev,
0693                      u8 gate_count,
0694                      const struct nci_hci_gate *gates)
0695 {
0696     int r;
0697 
0698     while (gate_count--) {
0699         r = nci_hci_connect_gate(ndev, gates->dest_host,
0700                      gates->gate, gates->pipe);
0701         if (r < 0)
0702             return r;
0703         gates++;
0704     }
0705 
0706     return 0;
0707 }
0708 
0709 int nci_hci_dev_session_init(struct nci_dev *ndev)
0710 {
0711     struct nci_conn_info *conn_info;
0712     struct sk_buff *skb;
0713     int r;
0714 
0715     ndev->hci_dev->count_pipes = 0;
0716     ndev->hci_dev->expected_pipes = 0;
0717 
0718     conn_info = ndev->hci_dev->conn_info;
0719     if (!conn_info)
0720         return -EPROTO;
0721 
0722     conn_info->data_exchange_cb = nci_hci_data_received_cb;
0723     conn_info->data_exchange_cb_context = ndev;
0724 
0725     nci_hci_reset_pipes(ndev->hci_dev);
0726 
0727     if (ndev->hci_dev->init_data.gates[0].gate != NCI_HCI_ADMIN_GATE)
0728         return -EPROTO;
0729 
0730     r = nci_hci_connect_gate(ndev,
0731                  ndev->hci_dev->init_data.gates[0].dest_host,
0732                  ndev->hci_dev->init_data.gates[0].gate,
0733                  ndev->hci_dev->init_data.gates[0].pipe);
0734     if (r < 0)
0735         return r;
0736 
0737     r = nci_hci_get_param(ndev, NCI_HCI_ADMIN_GATE,
0738                   NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY, &skb);
0739     if (r < 0)
0740         return r;
0741 
0742     if (skb->len &&
0743         skb->len == strlen(ndev->hci_dev->init_data.session_id) &&
0744         !memcmp(ndev->hci_dev->init_data.session_id, skb->data, skb->len) &&
0745         ndev->ops->hci_load_session) {
0746         /* Restore gate<->pipe table from some proprietary location. */
0747         r = ndev->ops->hci_load_session(ndev);
0748     } else {
0749         r = nci_hci_clear_all_pipes(ndev);
0750         if (r < 0)
0751             goto exit;
0752 
0753         r = nci_hci_dev_connect_gates(ndev,
0754                           ndev->hci_dev->init_data.gate_count,
0755                           ndev->hci_dev->init_data.gates);
0756         if (r < 0)
0757             goto exit;
0758 
0759         r = nci_hci_set_param(ndev, NCI_HCI_ADMIN_GATE,
0760                       NCI_HCI_ADMIN_PARAM_SESSION_IDENTITY,
0761                       ndev->hci_dev->init_data.session_id,
0762                       strlen(ndev->hci_dev->init_data.session_id));
0763     }
0764 
0765 exit:
0766     kfree_skb(skb);
0767 
0768     return r;
0769 }
0770 EXPORT_SYMBOL(nci_hci_dev_session_init);
0771 
0772 struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev)
0773 {
0774     struct nci_hci_dev *hdev;
0775 
0776     hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
0777     if (!hdev)
0778         return NULL;
0779 
0780     skb_queue_head_init(&hdev->rx_hcp_frags);
0781     INIT_WORK(&hdev->msg_rx_work, nci_hci_msg_rx_work);
0782     skb_queue_head_init(&hdev->msg_rx_queue);
0783     hdev->ndev = ndev;
0784 
0785     return hdev;
0786 }
0787 
0788 void nci_hci_deallocate(struct nci_dev *ndev)
0789 {
0790     kfree(ndev->hci_dev);
0791 }