command.c (8335B)
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 19static 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 occurred 38 */ 39static 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 55static 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 91int 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} 105EXPORT_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 */ 112int 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 pipe = hdev->gate2pipe[gate]; 118 if (pipe == NFC_HCI_INVALID_PIPE) 119 return -EADDRNOTAVAIL; 120 121 return nfc_hci_execute_cmd(hdev, pipe, cmd, param, param_len, skb); 122} 123EXPORT_SYMBOL(nfc_hci_send_cmd); 124 125int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, 126 const u8 *param, size_t param_len, 127 data_exchange_cb_t cb, void *cb_context) 128{ 129 u8 pipe; 130 131 pipe = hdev->gate2pipe[gate]; 132 if (pipe == NFC_HCI_INVALID_PIPE) 133 return -EADDRNOTAVAIL; 134 135 return nfc_hci_execute_cmd_async(hdev, pipe, cmd, param, param_len, 136 cb, cb_context); 137} 138EXPORT_SYMBOL(nfc_hci_send_cmd_async); 139 140int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, 141 const u8 *param, size_t param_len) 142{ 143 int r; 144 u8 *tmp; 145 146 /* TODO ELa: reg idx must be inserted before param, but we don't want 147 * to ask the caller to do it to keep a simpler API. 148 * For now, just create a new temporary param buffer. This is far from 149 * optimal though, and the plan is to modify APIs to pass idx down to 150 * nfc_hci_hcp_message_tx where the frame is actually built, thereby 151 * eliminating the need for the temp allocation-copy here. 152 */ 153 154 pr_debug("idx=%d to gate %d\n", idx, gate); 155 156 tmp = kmalloc(1 + param_len, GFP_KERNEL); 157 if (tmp == NULL) 158 return -ENOMEM; 159 160 *tmp = idx; 161 memcpy(tmp + 1, param, param_len); 162 163 r = nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_SET_PARAMETER, 164 tmp, param_len + 1, NULL); 165 166 kfree(tmp); 167 168 return r; 169} 170EXPORT_SYMBOL(nfc_hci_set_param); 171 172int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, 173 struct sk_buff **skb) 174{ 175 pr_debug("gate=%d regidx=%d\n", gate, idx); 176 177 return nfc_hci_send_cmd(hdev, gate, NFC_HCI_ANY_GET_PARAMETER, 178 &idx, 1, skb); 179} 180EXPORT_SYMBOL(nfc_hci_get_param); 181 182static int nfc_hci_open_pipe(struct nfc_hci_dev *hdev, u8 pipe) 183{ 184 struct sk_buff *skb; 185 int r; 186 187 pr_debug("pipe=%d\n", pipe); 188 189 r = nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_OPEN_PIPE, 190 NULL, 0, &skb); 191 if (r == 0) { 192 /* dest host other than host controller will send 193 * number of pipes already open on this gate before 194 * execution. The number can be found in skb->data[0] 195 */ 196 kfree_skb(skb); 197 } 198 199 return r; 200} 201 202static int nfc_hci_close_pipe(struct nfc_hci_dev *hdev, u8 pipe) 203{ 204 return nfc_hci_execute_cmd(hdev, pipe, NFC_HCI_ANY_CLOSE_PIPE, 205 NULL, 0, NULL); 206} 207 208static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host, 209 u8 dest_gate, int *result) 210{ 211 struct sk_buff *skb; 212 struct hci_create_pipe_params params; 213 struct hci_create_pipe_resp *resp; 214 u8 pipe; 215 216 pr_debug("gate=%d\n", dest_gate); 217 218 params.src_gate = NFC_HCI_ADMIN_GATE; 219 params.dest_host = dest_host; 220 params.dest_gate = dest_gate; 221 222 *result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, 223 NFC_HCI_ADM_CREATE_PIPE, 224 (u8 *) ¶ms, sizeof(params), &skb); 225 if (*result < 0) 226 return NFC_HCI_INVALID_PIPE; 227 228 resp = (struct hci_create_pipe_resp *)skb->data; 229 pipe = resp->pipe; 230 kfree_skb(skb); 231 232 pr_debug("pipe created=%d\n", pipe); 233 234 return pipe; 235} 236 237static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) 238{ 239 return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, 240 NFC_HCI_ADM_DELETE_PIPE, &pipe, 1, NULL); 241} 242 243static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) 244{ 245 u8 param[2]; 246 size_t param_len = 2; 247 248 /* TODO: Find out what the identity reference data is 249 * and fill param with it. HCI spec 6.1.3.5 */ 250 251 if (test_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &hdev->quirks)) 252 param_len = 0; 253 254 return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, 255 NFC_HCI_ADM_CLEAR_ALL_PIPE, param, param_len, 256 NULL); 257} 258 259int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) 260{ 261 int r; 262 u8 pipe = hdev->gate2pipe[gate]; 263 264 if (pipe == NFC_HCI_INVALID_PIPE) 265 return -EADDRNOTAVAIL; 266 267 r = nfc_hci_close_pipe(hdev, pipe); 268 if (r < 0) 269 return r; 270 271 if (pipe != NFC_HCI_LINK_MGMT_PIPE && pipe != NFC_HCI_ADMIN_PIPE) { 272 r = nfc_hci_delete_pipe(hdev, pipe); 273 if (r < 0) 274 return r; 275 } 276 277 hdev->gate2pipe[gate] = NFC_HCI_INVALID_PIPE; 278 279 return 0; 280} 281EXPORT_SYMBOL(nfc_hci_disconnect_gate); 282 283int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev) 284{ 285 int r; 286 287 r = nfc_hci_clear_all_pipes(hdev); 288 if (r < 0) 289 return r; 290 291 nfc_hci_reset_pipes(hdev); 292 293 return 0; 294} 295EXPORT_SYMBOL(nfc_hci_disconnect_all_gates); 296 297int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, 298 u8 pipe) 299{ 300 bool pipe_created = false; 301 int r; 302 303 if (pipe == NFC_HCI_DO_NOT_CREATE_PIPE) 304 return 0; 305 306 if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) 307 return -EADDRINUSE; 308 309 if (pipe != NFC_HCI_INVALID_PIPE) 310 goto open_pipe; 311 312 switch (dest_gate) { 313 case NFC_HCI_LINK_MGMT_GATE: 314 pipe = NFC_HCI_LINK_MGMT_PIPE; 315 break; 316 case NFC_HCI_ADMIN_GATE: 317 pipe = NFC_HCI_ADMIN_PIPE; 318 break; 319 default: 320 pipe = nfc_hci_create_pipe(hdev, dest_host, dest_gate, &r); 321 if (pipe == NFC_HCI_INVALID_PIPE) 322 return r; 323 pipe_created = true; 324 break; 325 } 326 327open_pipe: 328 r = nfc_hci_open_pipe(hdev, pipe); 329 if (r < 0) { 330 if (pipe_created) 331 if (nfc_hci_delete_pipe(hdev, pipe) < 0) { 332 /* TODO: Cannot clean by deleting pipe... 333 * -> inconsistent state */ 334 } 335 return r; 336 } 337 338 hdev->pipes[pipe].gate = dest_gate; 339 hdev->pipes[pipe].dest_host = dest_host; 340 hdev->gate2pipe[dest_gate] = pipe; 341 342 return 0; 343} 344EXPORT_SYMBOL(nfc_hci_connect_gate);