1/******************************************************************************
2 *
3 *  Copyright (C) 2010-2014 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 *  NFA interface to HCI
22 *
23 ******************************************************************************/
24#include <android-base/stringprintf.h>
25#include <base/logging.h>
26
27#include "nfa_hci_api.h"
28#include "nfa_hci_defs.h"
29#include "nfa_hci_int.h"
30
31using android::base::StringPrintf;
32
33extern bool nfc_debug_enabled;
34
35/*******************************************************************************
36**
37** Function         NFA_HciRegister
38**
39** Description      This function will register an application with hci and
40**                  returns an application handle and provides a mechanism to
41**                  register a callback with HCI to receive NFA HCI event
42**                  notification. When the application is registered (or if an
43**                  error occurs), the app will be notified with
44**                  NFA_HCI_REGISTER_EVT. Previous session information including
45**                  allocated gates, created pipes and pipes states will be
46**                  returned as part of tNFA_HCI_REGISTER data.
47**
48** Returns          NFA_STATUS_OK if successfully initiated
49**                  NFA_STATUS_FAILED otherwise
50**
51*******************************************************************************/
52tNFA_STATUS NFA_HciRegister(char* p_app_name, tNFA_HCI_CBACK* p_cback,
53                            bool b_send_conn_evts) {
54  tNFA_HCI_API_REGISTER_APP* p_msg;
55  uint8_t app_name_len;
56
57  if (p_app_name == NULL) {
58    DLOG_IF(INFO, nfc_debug_enabled)
59        << StringPrintf("Invalid Application name");
60    return (NFA_STATUS_FAILED);
61  }
62
63  if (p_cback == NULL) {
64    DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
65        "Application should provide callback function to "
66        "register!");
67    return (NFA_STATUS_FAILED);
68  }
69
70  DLOG_IF(INFO, nfc_debug_enabled)
71      << StringPrintf("Application Name: %s", p_app_name);
72
73  app_name_len = (uint8_t)strlen(p_app_name);
74
75  /* Register the application with HCI */
76  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
77      (p_app_name != NULL) && (app_name_len <= NFA_MAX_HCI_APP_NAME_LEN) &&
78      ((p_msg = (tNFA_HCI_API_REGISTER_APP*)GKI_getbuf(
79            sizeof(tNFA_HCI_API_REGISTER_APP))) != NULL)) {
80    p_msg->hdr.event = NFA_HCI_API_REGISTER_APP_EVT;
81
82    /* Save application name and callback */
83    memset(p_msg->app_name, 0, sizeof(p_msg->app_name));
84    strncpy(p_msg->app_name, p_app_name, NFA_MAX_HCI_APP_NAME_LEN);
85    p_msg->p_cback = p_cback;
86    p_msg->b_send_conn_evts = b_send_conn_evts;
87
88    nfa_sys_sendmsg(p_msg);
89    return (NFA_STATUS_OK);
90  }
91
92  return (NFA_STATUS_FAILED);
93}
94
95/*******************************************************************************
96**
97** Function         NFA_HciGetGateAndPipeList
98**
99** Description      This function will get the list of gates allocated to the
100**                  application and list of dynamic pipes created by the
101**                  application. The app will be notified with
102**                  NFA_HCI_GET_GATE_PIPE_LIST_EVT. List of allocated dynamic
103**                  gates to the application and list of pipes created by the
104**                  application will be returned as part of
105**                  tNFA_HCI_GET_GATE_PIPE_LIST data.
106**
107** Returns          NFA_STATUS_OK if successfully initiated
108**                  NFA_STATUS_FAILED otherwise
109**
110*******************************************************************************/
111tNFA_STATUS NFA_HciGetGateAndPipeList(tNFA_HANDLE hci_handle) {
112  tNFA_HCI_API_GET_APP_GATE_PIPE* p_msg;
113
114  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
115    DLOG_IF(INFO, nfc_debug_enabled)
116        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
117    return (NFA_STATUS_FAILED);
118  }
119
120  DLOG_IF(INFO, nfc_debug_enabled)
121      << StringPrintf("hci_handle:0x%04x", hci_handle);
122
123  /* Register the application with HCI */
124  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
125      ((p_msg = (tNFA_HCI_API_GET_APP_GATE_PIPE*)GKI_getbuf(
126            sizeof(tNFA_HCI_API_GET_APP_GATE_PIPE))) != NULL)) {
127    p_msg->hdr.event = NFA_HCI_API_GET_APP_GATE_PIPE_EVT;
128    p_msg->hci_handle = hci_handle;
129
130    nfa_sys_sendmsg(p_msg);
131    return (NFA_STATUS_OK);
132  }
133
134  return (NFA_STATUS_FAILED);
135}
136
137/*******************************************************************************
138**
139** Function         NFA_HciDeregister
140**
141** Description      This function is called to deregister an application
142**                  from HCI. The app will be notified by NFA_HCI_DEREGISTER_EVT
143**                  after deleting all the pipes owned by the app and
144**                  deallocating all the gates allocated to the app or if an
145**                  error occurs. Even if deregistration fails, the app has to
146**                  register again to provide a new cback function.
147**
148** Returns          NFA_STATUS_OK if the application is deregistered
149**                  successfully
150**                  NFA_STATUS_FAILED otherwise
151
152*******************************************************************************/
153tNFA_STATUS NFA_HciDeregister(char* p_app_name) {
154  tNFA_HCI_API_DEREGISTER_APP* p_msg;
155  int xx;
156  uint8_t app_name_len;
157
158  if (p_app_name == NULL) {
159    DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("Invalid Application");
160    return (NFA_STATUS_FAILED);
161  }
162
163  DLOG_IF(INFO, nfc_debug_enabled)
164      << StringPrintf("Application Name: %s", p_app_name);
165  app_name_len = (uint8_t)strlen(p_app_name);
166
167  if (app_name_len > NFA_MAX_HCI_APP_NAME_LEN) return (NFA_STATUS_FAILED);
168
169  /* Find the application registration */
170  for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
171    if ((nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) &&
172        (!strncmp(p_app_name, &nfa_hci_cb.cfg.reg_app_names[xx][0],
173                  app_name_len)))
174      break;
175  }
176
177  if (xx == NFA_HCI_MAX_APP_CB) {
178    LOG(ERROR) << StringPrintf("Application Name: %s  NOT FOUND", p_app_name);
179    return (NFA_STATUS_FAILED);
180  }
181
182  /* Deregister the application with HCI */
183  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
184      ((p_msg = (tNFA_HCI_API_DEREGISTER_APP*)GKI_getbuf(
185            sizeof(tNFA_HCI_API_DEREGISTER_APP))) != NULL)) {
186    p_msg->hdr.event = NFA_HCI_API_DEREGISTER_APP_EVT;
187
188    memset(p_msg->app_name, 0, sizeof(p_msg->app_name));
189    strncpy(p_msg->app_name, p_app_name, NFA_MAX_HCI_APP_NAME_LEN);
190
191    nfa_sys_sendmsg(p_msg);
192    return (NFA_STATUS_OK);
193  }
194
195  return (NFA_STATUS_FAILED);
196}
197
198/*******************************************************************************
199**
200** Function         NFA_HciAllocGate
201**
202** Description      This function will allocate the gate if any specified or an
203**                  available generic gate for the app to provide an entry point
204**                  for a particular service to other host or to establish
205**                  communication with other host. When the gate is
206**                  allocated (or if an error occurs), the app will be notified
207**                  with NFA_HCI_ALLOCATE_GATE_EVT with the gate id. The
208**                  allocated Gate information will be stored in non volatile
209**                  memory.
210**
211** Returns          NFA_STATUS_OK if this API started
212**                  NFA_STATUS_FAILED if no generic gate is available
213**
214*******************************************************************************/
215tNFA_STATUS NFA_HciAllocGate(tNFA_HANDLE hci_handle, uint8_t gate) {
216  tNFA_HCI_API_ALLOC_GATE* p_msg;
217
218  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
219    DLOG_IF(INFO, nfc_debug_enabled)
220        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
221    return (NFA_STATUS_FAILED);
222  }
223
224  if ((gate) && ((gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) ||
225                 (gate > NFA_HCI_LAST_PROP_GATE) ||
226                 (gate == NFA_HCI_CONNECTIVITY_GATE))) {
227    DLOG_IF(INFO, nfc_debug_enabled)
228        << StringPrintf("Cannot allocate gate:0x%02x", gate);
229    return (NFA_STATUS_FAILED);
230  }
231
232  DLOG_IF(INFO, nfc_debug_enabled)
233      << StringPrintf("hci_handle:0x%04x, Gate:0x%02x", hci_handle, gate);
234
235  /* Request HCI to allocate gate to the application */
236  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
237      ((p_msg = (tNFA_HCI_API_ALLOC_GATE*)GKI_getbuf(
238            sizeof(tNFA_HCI_API_ALLOC_GATE))) != NULL)) {
239    p_msg->hdr.event = NFA_HCI_API_ALLOC_GATE_EVT;
240    p_msg->hci_handle = hci_handle;
241    p_msg->gate = gate;
242
243    nfa_sys_sendmsg(p_msg);
244    return (NFA_STATUS_OK);
245  }
246  return (NFA_STATUS_FAILED);
247}
248
249/*******************************************************************************
250**
251** Function         NFA_HciDeallocGate
252**
253** Description      This function will release the specified gate that was
254**                  previously allocated to the application. When the generic
255**                  gate is released (or if an error occurs), the app will be
256**                  notified with NFA_HCI_DEALLOCATE_GATE_EVT with the gate id.
257**
258** Returns          NFA_STATUS_OK if successfully initiated
259**                  NFA_STATUS_FAILED otherwise
260**
261*******************************************************************************/
262tNFA_STATUS NFA_HciDeallocGate(tNFA_HANDLE hci_handle, uint8_t gate) {
263  tNFA_HCI_API_DEALLOC_GATE* p_msg;
264
265  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
266    DLOG_IF(INFO, nfc_debug_enabled)
267        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
268    return (NFA_STATUS_FAILED);
269  }
270
271  if ((gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) ||
272      (gate > NFA_HCI_LAST_PROP_GATE) || (gate == NFA_HCI_CONNECTIVITY_GATE)) {
273    DLOG_IF(INFO, nfc_debug_enabled)
274        << StringPrintf("Cannot deallocate the gate:0x%02x", gate);
275    return (NFA_STATUS_FAILED);
276  }
277
278  DLOG_IF(INFO, nfc_debug_enabled)
279      << StringPrintf("hci_handle:0x%04x, gate:0x%02X", hci_handle, gate);
280
281  /* Request HCI to deallocate the gate that was previously allocated to the
282   * application */
283  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
284      ((p_msg = (tNFA_HCI_API_DEALLOC_GATE*)GKI_getbuf(
285            sizeof(tNFA_HCI_API_DEALLOC_GATE))) != NULL)) {
286    p_msg->hdr.event = NFA_HCI_API_DEALLOC_GATE_EVT;
287    p_msg->hci_handle = hci_handle;
288    p_msg->gate = gate;
289
290    nfa_sys_sendmsg(p_msg);
291    return (NFA_STATUS_OK);
292  }
293  return (NFA_STATUS_FAILED);
294}
295
296/*******************************************************************************
297**
298** Function         NFA_HciGetHostList
299**
300** Description      This function will request the host controller to return the
301**                  list of hosts that are present in the host network. When
302**                  host controller responds with the host list (or if an error
303**                  occurs), the app will be notified with NFA_HCI_HOST_LIST_EVT
304**
305** Returns          NFA_STATUS_OK if successfully initiated
306**                  NFA_STATUS_FAILED otherwise
307**
308*******************************************************************************/
309tNFA_STATUS NFA_HciGetHostList(tNFA_HANDLE hci_handle) {
310  tNFA_HCI_API_GET_HOST_LIST* p_msg;
311
312  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
313    DLOG_IF(INFO, nfc_debug_enabled)
314        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
315    return (NFA_STATUS_FAILED);
316  }
317
318  DLOG_IF(INFO, nfc_debug_enabled)
319      << StringPrintf("hci_handle:0x%04x", hci_handle);
320
321  /* Request HCI to get list of host in the hci network */
322  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
323      ((p_msg = (tNFA_HCI_API_GET_HOST_LIST*)GKI_getbuf(
324            sizeof(tNFA_HCI_API_GET_HOST_LIST))) != NULL)) {
325    p_msg->hdr.event = NFA_HCI_API_GET_HOST_LIST_EVT;
326    p_msg->hci_handle = hci_handle;
327
328    nfa_sys_sendmsg(p_msg);
329    return (NFA_STATUS_OK);
330  }
331
332  return (NFA_STATUS_FAILED);
333}
334
335/*******************************************************************************
336**
337** Function         NFA_HciCreatePipe
338**
339** Description      This function is called to create a dynamic pipe with the
340**                  specified host. When the dynamic pipe is created (or
341**                  if an error occurs), the app will be notified with
342**                  NFA_HCI_CREATE_PIPE_EVT with the pipe id. If a pipe exists
343**                  between the two gates passed as argument and if it was
344**                  created earlier by the calling application then the pipe
345**                  id of the existing pipe will be returned and a new pipe
346**                  will not be created. After successful creation of pipe,
347**                  registry entry will be created for the dynamic pipe and
348**                  all information related to the pipe will be stored in non
349**                  volatile memory.
350**
351** Returns          NFA_STATUS_OK if successfully initiated
352**                  NFA_STATUS_FAILED otherwise
353**
354*******************************************************************************/
355tNFA_STATUS NFA_HciCreatePipe(tNFA_HANDLE hci_handle, uint8_t source_gate_id,
356                              uint8_t dest_host, uint8_t dest_gate) {
357  tNFA_HCI_API_CREATE_PIPE_EVT* p_msg;
358  uint8_t xx;
359
360  DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
361      "hci_handle:0x%04x, source gate:0x%02X, "
362      "destination host:0x%02X , destination gate:0x%02X",
363      hci_handle, source_gate_id, dest_host, dest_gate);
364
365  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
366    DLOG_IF(INFO, nfc_debug_enabled)
367        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
368    return (NFA_STATUS_FAILED);
369  }
370
371  if ((source_gate_id < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) ||
372      (source_gate_id > NFA_HCI_LAST_PROP_GATE)) {
373    DLOG_IF(INFO, nfc_debug_enabled)
374        << StringPrintf("Invalid local Gate:0x%02x", source_gate_id);
375    return (NFA_STATUS_FAILED);
376  }
377
378  if (((dest_gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE) &&
379       (dest_gate != NFA_HCI_LOOP_BACK_GATE) &&
380       (dest_gate != NFA_HCI_IDENTITY_MANAGEMENT_GATE)) ||
381      (dest_gate > NFA_HCI_LAST_PROP_GATE)) {
382    DLOG_IF(INFO, nfc_debug_enabled)
383        << StringPrintf("Invalid Destination Gate:0x%02x", dest_gate);
384    return (NFA_STATUS_FAILED);
385  }
386
387  for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
388    if (nfa_hci_cb.inactive_host[xx] == dest_host) break;
389
390  if (xx != NFA_HCI_MAX_HOST_IN_NETWORK) {
391    DLOG_IF(INFO, nfc_debug_enabled)
392        << StringPrintf("Host not active:0x%02x", dest_host);
393    return (NFA_STATUS_FAILED);
394  }
395
396  /* Request HCI to create a pipe between two specified gates */
397  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
398      (!nfa_hci_cb.b_low_power_mode) &&
399      ((p_msg = (tNFA_HCI_API_CREATE_PIPE_EVT*)GKI_getbuf(
400            sizeof(tNFA_HCI_API_CREATE_PIPE_EVT))) != NULL)) {
401    p_msg->hdr.event = NFA_HCI_API_CREATE_PIPE_EVT;
402    p_msg->hci_handle = hci_handle;
403    p_msg->source_gate = source_gate_id;
404    p_msg->dest_host = dest_host; /* Host id of the destination host */
405    p_msg->dest_gate = dest_gate; /* Gate id of the destination gate */
406
407    nfa_sys_sendmsg(p_msg);
408    return (NFA_STATUS_OK);
409  }
410  return (NFA_STATUS_FAILED);
411}
412
413/*******************************************************************************
414**
415** Function         NFA_HciOpenPipe
416**
417** Description      This function is called to open a dynamic pipe.
418**                  When the dynamic pipe is opened (or
419**                  if an error occurs), the app will be notified with
420**                  NFA_HCI_OPEN_PIPE_EVT with the pipe id.
421**
422** Returns          NFA_STATUS_OK if successfully initiated
423**                  NFA_STATUS_FAILED otherwise
424**
425*******************************************************************************/
426tNFA_STATUS NFA_HciOpenPipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
427  tNFA_HCI_API_OPEN_PIPE_EVT* p_msg;
428
429  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
430    DLOG_IF(INFO, nfc_debug_enabled)
431        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
432    return (NFA_STATUS_FAILED);
433  }
434
435  if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
436      (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
437    DLOG_IF(INFO, nfc_debug_enabled)
438        << StringPrintf("Invalid Pipe:0x%02x", pipe);
439    return (NFA_STATUS_FAILED);
440  }
441
442  DLOG_IF(INFO, nfc_debug_enabled)
443      << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
444
445  /* Request HCI to open a pipe if it is in closed state */
446  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
447      (!nfa_hci_cb.b_low_power_mode) &&
448      ((p_msg = (tNFA_HCI_API_OPEN_PIPE_EVT*)GKI_getbuf(
449            sizeof(tNFA_HCI_API_OPEN_PIPE_EVT))) != NULL)) {
450    p_msg->hdr.event = NFA_HCI_API_OPEN_PIPE_EVT;
451    p_msg->hci_handle = hci_handle;
452    p_msg->pipe = pipe; /* Pipe ID of the pipe to open */
453
454    nfa_sys_sendmsg(p_msg);
455    return (NFA_STATUS_OK);
456  }
457  return (NFA_STATUS_FAILED);
458}
459
460/*******************************************************************************
461**
462** Function         NFA_HciGetRegistry
463**
464** Description      This function requests a peer host to return the desired
465**                  registry field value for the gate that the pipe is on.
466**
467**                  When the peer host responds,the app is notified with
468**                  NFA_HCI_GET_REG_RSP_EVT or
469**                  if an error occurs in sending the command the app will be
470**                  notified by NFA_HCI_CMD_SENT_EVT
471**
472** Returns          NFA_STATUS_OK if successfully initiated
473**                  NFA_STATUS_FAILED otherwise
474**
475*******************************************************************************/
476tNFA_STATUS NFA_HciGetRegistry(tNFA_HANDLE hci_handle, uint8_t pipe,
477                               uint8_t reg_inx) {
478  tNFA_HCI_API_GET_REGISTRY* p_msg;
479
480  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
481    DLOG_IF(INFO, nfc_debug_enabled)
482        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
483    return (NFA_STATUS_FAILED);
484  }
485
486  if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
487    DLOG_IF(INFO, nfc_debug_enabled)
488        << StringPrintf("Invalid Pipe:0x%02x", pipe);
489    return (NFA_STATUS_FAILED);
490  }
491
492  DLOG_IF(INFO, nfc_debug_enabled)
493      << StringPrintf("hci_handle:0x%04x  Pipe: 0x%02x", hci_handle, pipe);
494
495  /* Request HCI to get list of gates supported by the specified host */
496  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
497      ((p_msg = (tNFA_HCI_API_GET_REGISTRY*)GKI_getbuf(
498            sizeof(tNFA_HCI_API_GET_REGISTRY))) != NULL)) {
499    p_msg->hdr.event = NFA_HCI_API_GET_REGISTRY_EVT;
500    p_msg->hci_handle = hci_handle;
501    p_msg->pipe = pipe;
502    p_msg->reg_inx = reg_inx;
503
504    nfa_sys_sendmsg(p_msg);
505    return (NFA_STATUS_OK);
506  }
507
508  return (NFA_STATUS_FAILED);
509}
510
511/*******************************************************************************
512**
513** Function         NFA_HciSendCommand
514**
515** Description      This function is called to send a command on a pipe created
516**                  by the application.
517**                  The app will be notified by NFA_HCI_CMD_SENT_EVT if an error
518**                  occurs.
519**                  When the peer host responds,the app is notified with
520**                  NFA_HCI_RSP_RCVD_EVT
521**
522** Returns          NFA_STATUS_OK if successfully initiated
523**                  NFA_STATUS_FAILED otherwise
524**
525*******************************************************************************/
526tNFA_STATUS NFA_HciSendCommand(tNFA_HANDLE hci_handle, uint8_t pipe,
527                               uint8_t cmd_code, uint16_t cmd_size,
528                               uint8_t* p_data) {
529  tNFA_HCI_API_SEND_CMD_EVT* p_msg;
530
531  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
532    DLOG_IF(INFO, nfc_debug_enabled)
533        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
534    return (NFA_STATUS_FAILED);
535  }
536
537  if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
538    DLOG_IF(INFO, nfc_debug_enabled)
539        << StringPrintf("Invalid Pipe:0x%02x", pipe);
540    return (NFA_STATUS_FAILED);
541  }
542
543  if ((cmd_size && (p_data == NULL)) || (cmd_size > NFA_MAX_HCI_CMD_LEN)) {
544    DLOG_IF(INFO, nfc_debug_enabled)
545        << StringPrintf("Invalid cmd size:0x%02x", cmd_size);
546    return (NFA_STATUS_FAILED);
547  }
548
549  DLOG_IF(INFO, nfc_debug_enabled)
550      << StringPrintf("hci_handle:0x%04x, pipe:0x%02x  Code: 0x%02x",
551                      hci_handle, pipe, cmd_code);
552
553  /* Request HCI to post event data on a particular pipe */
554  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
555      ((p_msg = (tNFA_HCI_API_SEND_CMD_EVT*)GKI_getbuf(
556            sizeof(tNFA_HCI_API_SEND_CMD_EVT))) != NULL)) {
557    p_msg->hdr.event = NFA_HCI_API_SEND_CMD_EVT;
558    p_msg->hci_handle = hci_handle;
559    p_msg->pipe = pipe;
560    p_msg->cmd_code = cmd_code;
561    p_msg->cmd_len = cmd_size;
562
563    if (cmd_size) memcpy(p_msg->data, p_data, cmd_size);
564
565    nfa_sys_sendmsg(p_msg);
566    return (NFA_STATUS_OK);
567  }
568
569  return (NFA_STATUS_FAILED);
570}
571
572/*******************************************************************************
573**
574** Function         NFA_HciSendEvent
575**
576** Description      This function is called to send any event on a pipe created
577**                  by the application.
578**                  The app will be notified by NFA_HCI_EVENT_SENT_EVT
579**                  after successfully sending the event on the specified pipe
580**                  or if an error occurs. The application should wait for this
581**                  event before releasing event buffer passed as argument.
582**                  If the app is expecting a response to the event then it can
583**                  provide response buffer for collecting the response. If it
584**                  provides a response buffer it can also provide response
585**                  timeout indicating maximum timeout for the response.
586**                  Maximum of NFA_MAX_HCI_EVENT_LEN bytes APDU can be received
587**                  using internal buffer if no response buffer is provided by
588**                  the application. The app will be notified by
589**                  NFA_HCI_EVENT_RCVD_EVT after receiving the response event
590**                  or on timeout if app provided response buffer and response
591**                  timeout. If response buffer and response timeout is provided
592**                  by the application, it should wait for this event before
593**                  releasing the response buffer. If the application did not
594**                  provide response timeout then it should not release the
595**                  response buffer until it receives NFA_HCI_EVENT_RCVD_EVT or
596**                  after timeout it sends next event on the same pipe
597**                  and receives NFA_HCI_EVENT_SENT_EVT for that event.
598**
599** Returns          NFA_STATUS_OK if successfully initiated
600**                  NFA_STATUS_FAILED otherwise
601**
602*******************************************************************************/
603tNFA_STATUS NFA_HciSendEvent(tNFA_HANDLE hci_handle, uint8_t pipe,
604                             uint8_t evt_code, uint16_t evt_size,
605                             uint8_t* p_data, uint16_t rsp_size,
606                             uint8_t* p_rsp_buf, uint16_t rsp_timeout) {
607  tNFA_HCI_API_SEND_EVENT_EVT* p_msg;
608
609  DLOG_IF(INFO, nfc_debug_enabled)
610      << StringPrintf("hci_handle:0x%04x, pipe:0x%02x  Code: 0x%02x",
611                      hci_handle, pipe, evt_code);
612
613  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
614    DLOG_IF(INFO, nfc_debug_enabled)
615        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
616    return (NFA_STATUS_FAILED);
617  }
618
619  if (pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) {
620    DLOG_IF(INFO, nfc_debug_enabled)
621        << StringPrintf("Invalid Pipe:0x%02x", pipe);
622    return (NFA_STATUS_FAILED);
623  }
624
625  if (evt_size && (p_data == NULL)) {
626    DLOG_IF(INFO, nfc_debug_enabled)
627        << StringPrintf("Invalid Event size:0x%02x", evt_size);
628    return (NFA_STATUS_FAILED);
629  }
630
631  if (rsp_size && (p_rsp_buf == NULL)) {
632    DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
633        "No Event buffer, but invalid event buffer size "
634        ":%u",
635        rsp_size);
636    return (NFA_STATUS_FAILED);
637  }
638
639  /* Request HCI to post event data on a particular pipe */
640  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
641      ((p_msg = (tNFA_HCI_API_SEND_EVENT_EVT*)GKI_getbuf(
642            sizeof(tNFA_HCI_API_SEND_EVENT_EVT))) != NULL)) {
643    p_msg->hdr.event = NFA_HCI_API_SEND_EVENT_EVT;
644    p_msg->hci_handle = hci_handle;
645    p_msg->pipe = pipe;
646    p_msg->evt_code = evt_code;
647    p_msg->evt_len = evt_size;
648    p_msg->p_evt_buf = p_data;
649    p_msg->rsp_len = rsp_size;
650    p_msg->p_rsp_buf = p_rsp_buf;
651    p_msg->rsp_timeout = rsp_timeout;
652
653    nfa_sys_sendmsg(p_msg);
654    return (NFA_STATUS_OK);
655  }
656
657  return (NFA_STATUS_FAILED);
658}
659
660/*******************************************************************************
661**
662** Function         NFA_HciClosePipe
663**
664** Description      This function is called to close a dynamic pipe.
665**                  When the dynamic pipe is closed (or
666**                  if an error occurs), the app will be notified with
667**                  NFA_HCI_CLOSE_PIPE_EVT with the pipe id.
668**
669** Returns          NFA_STATUS_OK if successfully initiated
670**                  NFA_STATUS_FAILED otherwise
671**
672*******************************************************************************/
673tNFA_STATUS NFA_HciClosePipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
674  tNFA_HCI_API_CLOSE_PIPE_EVT* p_msg;
675
676  DLOG_IF(INFO, nfc_debug_enabled)
677      << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
678
679  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
680    DLOG_IF(INFO, nfc_debug_enabled)
681        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
682    return (NFA_STATUS_FAILED);
683  }
684
685  if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
686      (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
687    DLOG_IF(INFO, nfc_debug_enabled)
688        << StringPrintf("Invalid Pipe:0x%02x", pipe);
689    return (NFA_STATUS_FAILED);
690  }
691
692  /* Request HCI to close a pipe if it is in opened state */
693  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
694      (!nfa_hci_cb.b_low_power_mode) &&
695      ((p_msg = (tNFA_HCI_API_CLOSE_PIPE_EVT*)GKI_getbuf(
696            sizeof(tNFA_HCI_API_CLOSE_PIPE_EVT))) != NULL)) {
697    p_msg->hdr.event = NFA_HCI_API_CLOSE_PIPE_EVT;
698    p_msg->hci_handle = hci_handle;
699    p_msg->pipe = pipe;
700
701    nfa_sys_sendmsg(p_msg);
702    return (NFA_STATUS_OK);
703  }
704  return (NFA_STATUS_FAILED);
705}
706
707/*******************************************************************************
708**
709** Function         NFA_HciDeletePipe
710**
711** Description      This function is called to delete a particular dynamic pipe.
712**                  When the dynamic pipe is deleted (or if an error occurs),
713**                  the app will be notified with NFA_HCI_DELETE_PIPE_EVT with
714**                  the pipe id. After successful deletion of pipe, registry
715**                  entry will be deleted for the dynamic pipe and all
716**                  information related to the pipe will be deleted from non
717**                  volatile memory.
718**
719** Returns          NFA_STATUS_OK if successfully initiated
720**                  NFA_STATUS_FAILED otherwise
721**
722*******************************************************************************/
723tNFA_STATUS NFA_HciDeletePipe(tNFA_HANDLE hci_handle, uint8_t pipe) {
724  tNFA_HCI_API_DELETE_PIPE_EVT* p_msg;
725
726  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
727    DLOG_IF(INFO, nfc_debug_enabled)
728        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
729    return (NFA_STATUS_FAILED);
730  }
731
732  if ((pipe < NFA_HCI_FIRST_DYNAMIC_PIPE) ||
733      (pipe > NFA_HCI_LAST_DYNAMIC_PIPE)) {
734    DLOG_IF(INFO, nfc_debug_enabled)
735        << StringPrintf("Invalid Pipe:0x%02x", pipe);
736    return (NFA_STATUS_FAILED);
737  }
738
739  DLOG_IF(INFO, nfc_debug_enabled)
740      << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
741
742  /* Request HCI to delete a pipe created by the application identified by hci
743   * handle */
744  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
745      (!nfa_hci_cb.b_low_power_mode) &&
746      ((p_msg = (tNFA_HCI_API_DELETE_PIPE_EVT*)GKI_getbuf(
747            sizeof(tNFA_HCI_API_DELETE_PIPE_EVT))) != NULL)) {
748    p_msg->hdr.event = NFA_HCI_API_DELETE_PIPE_EVT;
749    p_msg->hci_handle = hci_handle;
750    p_msg->pipe = pipe;
751
752    nfa_sys_sendmsg(p_msg);
753    return (NFA_STATUS_OK);
754  }
755  return (NFA_STATUS_FAILED);
756}
757
758/*******************************************************************************
759**
760** Function         NFA_HciAddStaticPipe
761**
762** Description      This function is called to add a static pipe for sending
763**                  7816 APDUs. When the static pipe is added (or if an error
764**                  occurs), the app will be notified with
765**                  NFA_HCI_ADD_STATIC_PIPE_EVT with the status.
766**
767** Returns          NFA_STATUS_OK if successfully initiated
768**                  NFA_STATUS_FAILED otherwise
769**
770*******************************************************************************/
771tNFA_STATUS NFA_HciAddStaticPipe(tNFA_HANDLE hci_handle, uint8_t host,
772                                 uint8_t gate, uint8_t pipe) {
773  tNFA_HCI_API_ADD_STATIC_PIPE_EVT* p_msg;
774  uint8_t xx;
775
776  if ((NFA_HANDLE_GROUP_MASK & hci_handle) != NFA_HANDLE_GROUP_HCI) {
777    DLOG_IF(INFO, nfc_debug_enabled)
778        << StringPrintf("Invalid hci_handle:0x%04x", hci_handle);
779    return (NFA_STATUS_FAILED);
780  }
781
782  for (xx = 0; xx < NFA_HCI_MAX_HOST_IN_NETWORK; xx++)
783    if (nfa_hci_cb.inactive_host[xx] == host) break;
784
785  if (xx != NFA_HCI_MAX_HOST_IN_NETWORK) {
786    DLOG_IF(INFO, nfc_debug_enabled)
787        << StringPrintf("Host not active:0x%02x", host);
788    return (NFA_STATUS_FAILED);
789  }
790
791  if (gate <= NFA_HCI_LAST_HOST_SPECIFIC_GATE) {
792    DLOG_IF(INFO, nfc_debug_enabled)
793        << StringPrintf("Invalid Gate:0x%02x", gate);
794    return (NFA_STATUS_FAILED);
795  }
796
797  if (pipe <= NFA_HCI_LAST_DYNAMIC_PIPE) {
798    DLOG_IF(INFO, nfc_debug_enabled)
799        << StringPrintf("Invalid Pipe:0x%02x", pipe);
800    return (NFA_STATUS_FAILED);
801  }
802
803  DLOG_IF(INFO, nfc_debug_enabled)
804      << StringPrintf("hci_handle:0x%04x, pipe:0x%02X", hci_handle, pipe);
805
806  /* Request HCI to delete a pipe created by the application identified by hci
807   * handle */
808  if ((nfa_hci_cb.hci_state != NFA_HCI_STATE_DISABLED) &&
809      ((p_msg = (tNFA_HCI_API_ADD_STATIC_PIPE_EVT*)GKI_getbuf(
810            sizeof(tNFA_HCI_API_ADD_STATIC_PIPE_EVT))) != NULL)) {
811    p_msg->hdr.event = NFA_HCI_API_ADD_STATIC_PIPE_EVT;
812    p_msg->hci_handle = hci_handle;
813    p_msg->host = host;
814    p_msg->gate = gate;
815    p_msg->pipe = pipe;
816
817    nfa_sys_sendmsg(p_msg);
818    return (NFA_STATUS_OK);
819  }
820  /* Unable to add static pipe */
821  return (NFA_STATUS_FAILED);
822}
823
824/*******************************************************************************
825**
826** Function         NFA_HciDebug
827**
828** Description      Debug function.
829**
830*******************************************************************************/
831void NFA_HciDebug(uint8_t action, uint8_t size, uint8_t* p_data) {
832  int xx;
833  tNFA_HCI_DYN_GATE* pg = nfa_hci_cb.cfg.dyn_gates;
834  tNFA_HCI_DYN_PIPE* pp = nfa_hci_cb.cfg.dyn_pipes;
835  NFC_HDR* p_msg;
836  uint8_t* p;
837
838  switch (action) {
839    case NFA_HCI_DEBUG_DISPLAY_CB:
840      DLOG_IF(INFO, nfc_debug_enabled)
841          << StringPrintf("NFA_HciDebug  Host List:");
842      for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++) {
843        if (nfa_hci_cb.cfg.reg_app_names[xx][0] != 0) {
844          DLOG_IF(INFO, nfc_debug_enabled)
845              << StringPrintf("              Host Inx:  %u   Name: %s", xx,
846                              &nfa_hci_cb.cfg.reg_app_names[xx][0]);
847        }
848      }
849
850      DLOG_IF(INFO, nfc_debug_enabled)
851          << StringPrintf("NFA_HciDebug  Gate List:");
852      for (xx = 0; xx < NFA_HCI_MAX_GATE_CB; xx++, pg++) {
853        if (pg->gate_id != 0) {
854          DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
855              "              Gate Inx: %x  ID: 0x%02x  Owner: 0x%04x  "
856              "PipeInxMask: 0x%08x",
857              xx, pg->gate_id, pg->gate_owner, pg->pipe_inx_mask);
858        }
859      }
860
861      DLOG_IF(INFO, nfc_debug_enabled)
862          << StringPrintf("NFA_HciDebug  Pipe List:");
863      for (xx = 0; xx < NFA_HCI_MAX_PIPE_CB; xx++, pp++) {
864        if (pp->pipe_id != 0) {
865          DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
866              "              Pipe Inx: %x  ID: 0x%02x  State: %u  "
867              "LocalGate: "
868              "0x%02x  Dest Gate: 0x%02x  Host: 0x%02x",
869              xx, pp->pipe_id, pp->pipe_state, pp->local_gate, pp->dest_gate,
870              pp->dest_host);
871        }
872      }
873      break;
874
875    case NFA_HCI_DEBUG_SIM_HCI_EVENT:
876      p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
877      if (p_msg != NULL) {
878        p = (uint8_t*)(p_msg + 1);
879
880        p_msg->event = NFA_HCI_CHECK_QUEUE_EVT;
881        p_msg->len = size;
882        p_msg->offset = 0;
883
884        memcpy(p, p_data, size);
885
886        nfa_sys_sendmsg(p_msg);
887      }
888      break;
889
890    case NFA_HCI_DEBUG_ENABLE_LOOPBACK:
891      DLOG_IF(INFO, nfc_debug_enabled)
892          << StringPrintf("NFA_HciDebug  HCI_LOOPBACK_DEBUG = TRUE");
893      HCI_LOOPBACK_DEBUG = NFA_HCI_DEBUG_ON;
894      break;
895
896    case NFA_HCI_DEBUG_DISABLE_LOOPBACK:
897      DLOG_IF(INFO, nfc_debug_enabled)
898          << StringPrintf("NFA_HciDebug  HCI_LOOPBACK_DEBUG = FALSE");
899      HCI_LOOPBACK_DEBUG = NFA_HCI_DEBUG_OFF;
900      break;
901  }
902}
903