root/net/nfc/hci/command.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfc_hci_execute_cmd_async
  2. nfc_hci_execute_cb
  3. nfc_hci_execute_cmd
  4. nfc_hci_send_event
  5. nfc_hci_send_cmd
  6. nfc_hci_send_cmd_async
  7. nfc_hci_set_param
  8. nfc_hci_get_param
  9. nfc_hci_open_pipe
  10. nfc_hci_close_pipe
  11. nfc_hci_create_pipe
  12. nfc_hci_delete_pipe
  13. nfc_hci_clear_all_pipes
  14. nfc_hci_disconnect_gate
  15. nfc_hci_disconnect_all_gates
  16. nfc_hci_connect_gate

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2012  Intel Corporation. All rights reserved.
   4  */
   5 
   6 #define pr_fmt(fmt) "hci: %s: " fmt, __func__
   7 
   8 #include <linux/init.h>
   9 #include <linux/kernel.h>
  10 #include <linux/sched.h>
  11 #include <linux/module.h>
  12 
  13 #include <net/nfc/hci.h>
  14 
  15 #include "hci.h"
  16 
  17 #define MAX_FWI 4949
  18 
  19 static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
  20                                const u8 *param, size_t param_len,
  21                                data_exchange_cb_t cb, void *cb_context)
  22 {
  23         pr_debug("exec cmd async through pipe=%d, cmd=%d, plen=%zd\n", pipe,
  24                  cmd, param_len);
  25 
  26         /* TODO: Define hci cmd execution delay. Should it be the same
  27          * for all commands?
  28          */
  29         return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_COMMAND, cmd,
  30                                       param, param_len, cb, cb_context, MAX_FWI);
  31 }
  32 
  33 /*
  34  * HCI command execution completion callback.
  35  * err will be a standard linux error (may be converted from HCI response)
  36  * skb contains the response data and must be disposed, or may be NULL if
  37  * an error occured
  38  */
  39 static void nfc_hci_execute_cb(void *context, struct sk_buff *skb, int err)
  40 {
  41         struct hcp_exec_waiter *hcp_ew = (struct hcp_exec_waiter *)context;
  42 
  43         pr_debug("HCI Cmd completed with result=%d\n", err);
  44 
  45         hcp_ew->exec_result = err;
  46         if (hcp_ew->exec_result == 0)
  47                 hcp_ew->result_skb = skb;
  48         else
  49                 kfree_skb(skb);
  50         hcp_ew->exec_complete = true;
  51 
  52         wake_up(hcp_ew->wq);
  53 }
  54 
  55 static int nfc_hci_execute_cmd(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
  56                                const u8 *param, size_t param_len,
  57                                struct sk_buff **skb)
  58 {
  59         DECLARE_WAIT_QUEUE_HEAD_ONSTACK(ew_wq);
  60         struct hcp_exec_waiter hcp_ew;
  61         hcp_ew.wq = &ew_wq;
  62         hcp_ew.exec_complete = false;
  63         hcp_ew.result_skb = NULL;
  64 
  65         pr_debug("exec cmd sync through pipe=%d, cmd=%d, plen=%zd\n", pipe,
  66                  cmd, param_len);
  67 
  68         /* TODO: Define hci cmd execution delay. Should it be the same
  69          * for all commands?
  70          */
  71         hcp_ew.exec_result = nfc_hci_hcp_message_tx(hdev, pipe,
  72                                                     NFC_HCI_HCP_COMMAND, cmd,
  73                                                     param, param_len,
  74                                                     nfc_hci_execute_cb, &hcp_ew,
  75                                                     MAX_FWI);
  76         if (hcp_ew.exec_result < 0)
  77                 return hcp_ew.exec_result;
  78 
  79         wait_event(ew_wq, hcp_ew.exec_complete == true);
  80 
  81         if (hcp_ew.exec_result == 0) {
  82                 if (skb)
  83                         *skb = hcp_ew.result_skb;
  84                 else
  85                         kfree_skb(hcp_ew.result_skb);
  86         }
  87 
  88         return hcp_ew.exec_result;
  89 }
  90 
  91 int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
  92                        const u8 *param, size_t param_len)
  93 {
  94         u8 pipe;
  95 
  96         pr_debug("%d to gate %d\n", event, gate);
  97 
  98         pipe = hdev->gate2pipe[gate];
  99         if (pipe == NFC_HCI_INVALID_PIPE)
 100                 return -EADDRNOTAVAIL;
 101 
 102         return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_EVENT, event,
 103                                       param, param_len, NULL, NULL, 0);
 104 }
 105 EXPORT_SYMBOL(nfc_hci_send_event);
 106 
 107 /*
 108  * Execute an hci command sent to gate.
 109  * skb will contain response data if success. skb can be NULL if you are not
 110  * interested by the response.
 111  */
 112 int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
 113                      const u8 *param, size_t param_len, struct sk_buff **skb)
 114 {
 115         u8 pipe;
 116 
 117         pr_debug("\n");
 118 
 119         pipe = hdev->gate2pipe[gate];
 120         if (pipe == NFC_HCI_INVALID_PIPE)
 121                 return -EADDRNOTAVAIL;
 122 
 123         return nfc_hci_execute_cmd(hdev, pipe, cmd, param, param_len, skb);
 124 }
 125 EXPORT_SYMBOL(nfc_hci_send_cmd);
 126 
 127 int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
 128                            const u8 *param, size_t param_len,
 129                            data_exchange_cb_t cb, void *cb_context)
 130 {
 131         u8 pipe;
 132 
 133         pr_debug("\n");
 134 
 135         pipe = hdev->gate2pipe[gate];
 136         if (pipe == NFC_HCI_INVALID_PIPE)
 137                 return -EADDRNOTAVAIL;
 138 
 139         return nfc_hci_execute_cmd_async(hdev, pipe, cmd, param, param_len,
 140                                          cb, cb_context);
 141 }
 142 EXPORT_SYMBOL(nfc_hci_send_cmd_async);
 143 
 144 int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
 145                       const u8 *param, size_t param_len)
 146 {
 147         int r;
 148         u8 *tmp;
 149 
 150         /* TODO ELa: reg idx must be inserted before param, but we don't want
 151          * to ask the caller to do it to keep a simpler API.
 152          * For now, just create a new temporary param buffer. This is far from
 153          * optimal though, and the plan is to modify APIs to pass idx down to
 154          * nfc_hci_hcp_message_tx where the frame is actually built, thereby
 155          * eliminating the need for the temp allocation-copy here.
 156          */
 157 
 158         pr_debug("idx=%d to gate %d\n", idx, gate);
 159 
 160         tmp = kmalloc(1 + param_len, GFP_KERNEL);
 161         if (tmp == NULL)
 162                 return -ENOMEM;
 163 
 164         *tmp = idx;
 165         memcpy(tmp + 1, param, param_len);
 166 
 167         r = nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_SET_PARAMETER,
 168                              tmp, param_len + 1, NULL);
 169 
 170         kfree(tmp);
 171 
 172         return r;
 173 }
 174 EXPORT_SYMBOL(nfc_hci_set_param);
 175 
 176 int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx,
 177                       struct sk_buff **skb)
 178 {
 179         pr_debug("gate=%d regidx=%d\n", gate, idx);
 180 
 181         return nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_GET_PARAMETER,
 182                                 &idx, 1, skb);
 183 }
 184 EXPORT_SYMBOL(nfc_hci_get_param);
 185 
 186 static int nfc_hci_open_pipe(struct nfc_hci_dev *hdev, u8 pipe)
 187 {
 188         struct sk_buff *skb;
 189         int r;
 190 
 191         pr_debug("pipe=%d\n", pipe);
 192 
 193         r = nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_OPEN_PIPE,
 194                                 NULL, 0, &skb);
 195         if (r == 0) {
 196                 /* dest host other than host controller will send
 197                  * number of pipes already open on this gate before
 198                  * execution. The number can be found in skb->data[0]
 199                  */
 200                 kfree_skb(skb);
 201         }
 202 
 203         return r;
 204 }
 205 
 206 static int nfc_hci_close_pipe(struct nfc_hci_dev *hdev, u8 pipe)
 207 {
 208         pr_debug("\n");
 209 
 210         return nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_CLOSE_PIPE,
 211                                    NULL, 0, NULL);
 212 }
 213 
 214 static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host,
 215                               u8 dest_gate, int *result)
 216 {
 217         struct sk_buff *skb;
 218         struct hci_create_pipe_params params;
 219         struct hci_create_pipe_resp *resp;
 220         u8 pipe;
 221 
 222         pr_debug("gate=%d\n", dest_gate);
 223 
 224         params.src_gate = NFC_HCI_ADMIN_GATE;
 225         params.dest_host = dest_host;
 226         params.dest_gate = dest_gate;
 227 
 228         *result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
 229                                       NFC_HCI_ADM_CREATE_PIPE,
 230                                       (u8 *) &params, sizeof(params), &skb);
 231         if (*result < 0)
 232                 return NFC_HCI_INVALID_PIPE;
 233 
 234         resp = (struct hci_create_pipe_resp *)skb->data;
 235         pipe = resp->pipe;
 236         kfree_skb(skb);
 237 
 238         pr_debug("pipe created=%d\n", pipe);
 239 
 240         return pipe;
 241 }
 242 
 243 static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe)
 244 {
 245         pr_debug("\n");
 246 
 247         return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
 248                                    NFC_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL);
 249 }
 250 
 251 static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev)
 252 {
 253         u8 param[2];
 254         size_t param_len = 2;
 255 
 256         /* TODO: Find out what the identity reference data is
 257          * and fill param with it. HCI spec 6.1.3.5 */
 258 
 259         pr_debug("\n");
 260 
 261         if (test_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &hdev->quirks))
 262                 param_len = 0;
 263 
 264         return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE,
 265                                    NFC_HCI_ADM_CLEAR_ALL_PIPE, param, param_len,
 266                                    NULL);
 267 }
 268 
 269 int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate)
 270 {
 271         int r;
 272         u8 pipe = hdev->gate2pipe[gate];
 273 
 274         pr_debug("\n");
 275 
 276         if (pipe == NFC_HCI_INVALID_PIPE)
 277                 return -EADDRNOTAVAIL;
 278 
 279         r = nfc_hci_close_pipe(hdev, pipe);
 280         if (r < 0)
 281                 return r;
 282 
 283         if (pipe != NFC_HCI_LINK_MGMT_PIPE && pipe != NFC_HCI_ADMIN_PIPE) {
 284                 r = nfc_hci_delete_pipe(hdev, pipe);
 285                 if (r < 0)
 286                         return r;
 287         }
 288 
 289         hdev->gate2pipe[gate] = NFC_HCI_INVALID_PIPE;
 290 
 291         return 0;
 292 }
 293 EXPORT_SYMBOL(nfc_hci_disconnect_gate);
 294 
 295 int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev)
 296 {
 297         int r;
 298 
 299         pr_debug("\n");
 300 
 301         r = nfc_hci_clear_all_pipes(hdev);
 302         if (r < 0)
 303                 return r;
 304 
 305         nfc_hci_reset_pipes(hdev);
 306 
 307         return 0;
 308 }
 309 EXPORT_SYMBOL(nfc_hci_disconnect_all_gates);
 310 
 311 int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
 312                          u8 pipe)
 313 {
 314         bool pipe_created = false;
 315         int r;
 316 
 317         pr_debug("\n");
 318 
 319         if (pipe == NFC_HCI_DO_NOT_CREATE_PIPE)
 320                 return 0;
 321 
 322         if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
 323                 return -EADDRINUSE;
 324 
 325         if (pipe != NFC_HCI_INVALID_PIPE)
 326                 goto open_pipe;
 327 
 328         switch (dest_gate) {
 329         case NFC_HCI_LINK_MGMT_GATE:
 330                 pipe = NFC_HCI_LINK_MGMT_PIPE;
 331                 break;
 332         case NFC_HCI_ADMIN_GATE:
 333                 pipe = NFC_HCI_ADMIN_PIPE;
 334                 break;
 335         default:
 336                 pipe = nfc_hci_create_pipe(hdev, dest_host, dest_gate, &r);
 337                 if (pipe == NFC_HCI_INVALID_PIPE)
 338                         return r;
 339                 pipe_created = true;
 340                 break;
 341         }
 342 
 343 open_pipe:
 344         r = nfc_hci_open_pipe(hdev, pipe);
 345         if (r < 0) {
 346                 if (pipe_created)
 347                         if (nfc_hci_delete_pipe(hdev, pipe) < 0) {
 348                                 /* TODO: Cannot clean by deleting pipe...
 349                                  * -> inconsistent state */
 350                         }
 351                 return r;
 352         }
 353 
 354         hdev->pipes[pipe].gate = dest_gate;
 355         hdev->pipes[pipe].dest_host = dest_host;
 356         hdev->gate2pipe[dest_gate] = pipe;
 357 
 358         return 0;
 359 }
 360 EXPORT_SYMBOL(nfc_hci_connect_gate);

/* [<][>][^][v][top][bottom][index][help] */