1/******************************************************************************
2 *
3 *  Copyright (C) 2012-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 *  NFC Hardware Abstraction Layer API: Implementation for Broadcom NFC
22 *  controllers
23 *
24 ******************************************************************************/
25#include "nfc_hal_api.h"
26#include <string.h>
27#include "gki.h"
28#include "nfc_hal_int.h"
29#include "nfc_hal_target.h"
30
31/*******************************************************************************
32** NFC_HAL_TASK declarations
33*******************************************************************************/
34#define NFC_HAL_TASK_STR ((int8_t*)"NFC_HAL_TASK")
35#define NFC_HAL_TASK_STACK_SIZE 0x400
36uint32_t nfc_hal_task_stack[(NFC_HAL_TASK_STACK_SIZE + 3) / 4];
37
38/*******************************************************************************
39**
40** Function         HAL_NfcInitialize
41**
42** Description      Called when HAL library is loaded.
43**
44**                  Initialize GKI and start the HCIT task
45**
46** Returns          void
47**
48*******************************************************************************/
49void HAL_NfcInitialize(void) {
50  /* Initialize HAL control block */
51  nfc_hal_main_init();
52
53  HAL_TRACE_API1("HAL_NfcInitialize (): NFC_HAL_TASK id=%i", NFC_HAL_TASK);
54
55#ifndef NFC_HAL_SHARED_GKI
56  /* Initialize GKI (not needed if using shared NFC/HAL GKI resources) */
57  GKI_init();
58  GKI_enable();
59#endif
60
61  /* Create the NCI transport task */
62  GKI_create_task(
63      (TASKPTR)nfc_hal_main_task, NFC_HAL_TASK, NFC_HAL_TASK_STR,
64      (uint16_t*)((uint8_t*)nfc_hal_task_stack + NFC_HAL_TASK_STACK_SIZE),
65      sizeof(nfc_hal_task_stack), NULL, NULL);
66
67#ifndef NFC_HAL_SHARED_GKI
68  /* Start GKI scheduler (not needed if using shared NFC/HAL GKI resources) */
69  GKI_run(0);
70#endif
71}
72
73/*******************************************************************************
74**
75** Function         HAL_NfcTerminate
76**
77** Description      Called to terminate NFC HAL
78**
79** Returns          void
80**
81*******************************************************************************/
82void HAL_NfcTerminate(void) { HAL_TRACE_API0("HAL_NfcTerminate ()"); }
83
84/*******************************************************************************
85**
86** Function         HAL_NfcOpen
87**
88** Description      Open transport and intialize the NFCC, and
89**                  Register callback for HAL event notifications,
90**
91**                  HAL_OPEN_CPLT_EVT will notify when operation is complete.
92**
93** Returns          void
94**
95*******************************************************************************/
96void HAL_NfcOpen(tHAL_NFC_CBACK* p_hal_cback,
97                 tHAL_NFC_DATA_CBACK* p_data_cback) {
98  HAL_TRACE_API0("HAL_NfcOpen ()");
99
100  /* Only handle if HAL is not opened (stack cback is NULL) */
101  if (p_hal_cback) {
102    nfc_hal_dm_init();
103    nfc_hal_cb.p_stack_cback = p_hal_cback;
104    nfc_hal_cb.p_data_cback = p_data_cback;
105
106    /* Send startup event to NFC_HAL_TASK */
107    GKI_send_event(NFC_HAL_TASK, NFC_HAL_TASK_EVT_INITIALIZE);
108  }
109}
110
111/*******************************************************************************
112**
113** Function         HAL_NfcClose
114**
115** Description      Prepare for shutdown. A HAL_CLOSE_DONE_EVENT will be
116**                  reported when complete.
117**
118** Returns          void
119**
120*******************************************************************************/
121void HAL_NfcClose(void) {
122  HAL_TRACE_API0("HAL_NfcClose ()");
123
124  /* Only handle if HAL is opened (stack cback is not-NULL) */
125  if (nfc_hal_cb.p_stack_cback) {
126    /* Send shutdown event to NFC_HAL_TASK */
127    GKI_send_event(NFC_HAL_TASK, NFC_HAL_TASK_EVT_TERMINATE);
128  }
129}
130
131/*******************************************************************************
132**
133** Function         HAL_NfcCoreInitialized
134**
135** Description      Called after the CORE_INIT_RSP is received from the NFCC.
136**                  At this time, the HAL can do any chip-specific
137*configuration,
138**                  and when finished signal the libnfc-nci with event
139**                  HAL_POST_INIT_DONE.
140**
141** Returns          void
142**
143*******************************************************************************/
144void HAL_NfcCoreInitialized(uint16_t data_len,
145                            uint8_t* p_core_init_rsp_params) {
146  NFC_HDR* p_msg;
147  uint16_t size;
148
149  HAL_TRACE_API0("HAL_NfcCoreInitialized ()");
150
151  /* NCI payload len + NCI header size */
152  size = p_core_init_rsp_params[2] + NCI_MSG_HDR_SIZE;
153
154  /* Send message to NFC_HAL_TASK */
155  p_msg = (NFC_HDR*)GKI_getbuf((uint16_t)(size + NFC_HDR_SIZE));
156  if (p_msg != NULL) {
157    p_msg->event = NFC_HAL_EVT_POST_CORE_RESET;
158    p_msg->offset = 0;
159    p_msg->len = size;
160    p_msg->layer_specific = 0;
161    memcpy((uint8_t*)(p_msg + 1) + p_msg->offset, p_core_init_rsp_params, size);
162
163    GKI_send_msg(NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg);
164  }
165}
166
167/*******************************************************************************
168**
169** Function         HAL_NfcWrite
170**
171** Description      Send an NCI control message or data packet to the
172**                  transport. If an NCI command message exceeds the transport
173**                  size, HAL is responsible for fragmenting it, Data packets
174**                  must be of the correct size.
175**
176** Returns          void
177**
178*******************************************************************************/
179void HAL_NfcWrite(uint16_t data_len, uint8_t* p_data) {
180  NFC_HDR* p_msg;
181  uint8_t mt;
182
183  HAL_TRACE_API0("HAL_NfcWrite ()");
184
185  if (data_len > (NCI_MAX_CTRL_SIZE + NCI_MSG_HDR_SIZE)) {
186    HAL_TRACE_ERROR1("HAL_NfcWrite (): too many bytes (%d)", data_len);
187    return;
188  }
189
190  /* Send message to NFC_HAL_TASK */
191  p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_HAL_NCI_POOL_ID);
192  if (p_msg != NULL) {
193    p_msg->event = NFC_HAL_EVT_TO_NFC_NCI;
194    p_msg->offset = NFC_HAL_NCI_MSG_OFFSET_SIZE;
195    p_msg->len = data_len;
196    memcpy((uint8_t*)(p_msg + 1) + p_msg->offset, p_data, data_len);
197
198    /* Check if message is a command or data */
199    mt = (*(p_data)&NCI_MT_MASK) >> NCI_MT_SHIFT;
200    p_msg->layer_specific = (mt == NCI_MT_CMD) ? NFC_HAL_WAIT_RSP_CMD : 0;
201
202    GKI_send_msg(NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg);
203  }
204}
205
206/*******************************************************************************
207**
208** Function         HAL_NfcPreDiscover
209**
210** Description      Perform any vendor-specific pre-discovery actions (if
211*needed)
212**                  If any actions were performed TRUE will be returned, and
213**                  HAL_PRE_DISCOVER_DONE_EVENT will notify when actions are
214**                  completed.
215**
216** Returns          TRUE if vendor-specific pre-discovery actions initialized
217**                  FALSE if no vendor-specific pre-discovery actions are
218*needed.
219**
220*******************************************************************************/
221bool HAL_NfcPreDiscover(void) {
222  bool status = false;
223
224  NFC_HDR* p_msg;
225
226  HAL_TRACE_API0("HAL_NfcPreDiscover ()");
227  if (nfc_hal_cb.pre_discover_done == false) {
228    nfc_hal_cb.pre_discover_done = true;
229    if (p_nfc_hal_pre_discover_cfg && *p_nfc_hal_pre_discover_cfg) {
230      status = true;
231      /* Send message to NFC_HAL_TASK */
232      p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_HAL_NCI_POOL_ID);
233      if (p_msg != NULL) {
234        p_msg->event = NFC_HAL_EVT_PRE_DISCOVER;
235        GKI_send_msg(NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg);
236      }
237    }
238  }
239
240  HAL_TRACE_API1("HAL_NfcPreDiscover status:%d", status);
241  return status;
242}
243
244/*******************************************************************************
245**
246** Function         HAL_NfcControlGranted
247**
248** Description      Grant control to HAL control for sending NCI commands.
249**
250**                  Call in response to HAL_REQUEST_CONTROL_EVENT.
251**
252**                  Must only be called when there are no NCI commands pending.
253**
254**                  HAL_RELEASE_CONTROL_EVENT will notify when HAL no longer
255**                  needs control of NCI.
256**
257**
258** Returns          void
259**
260*******************************************************************************/
261void HAL_NfcControlGranted(void) {
262  NFC_HDR* p_msg;
263  HAL_TRACE_API0("HAL_NfcControlGranted ()");
264
265  /* Send message to NFC_HAL_TASK */
266  p_msg = (NFC_HDR*)GKI_getpoolbuf(NFC_HAL_NCI_POOL_ID);
267  if (p_msg != NULL) {
268    p_msg->event = NFC_HAL_EVT_CONTROL_GRANTED;
269    GKI_send_msg(NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg);
270  }
271}
272
273/*******************************************************************************
274**
275** Function         HAL_NfcPowerCycle
276**
277** Description      Restart NFCC by power cyle
278**
279**                  HAL_OPEN_CPLT_EVT will notify when operation is complete.
280**
281** Returns          void
282**
283*******************************************************************************/
284void HAL_NfcPowerCycle(void) {
285  HAL_TRACE_API0("HAL_NfcPowerCycle ()");
286
287  /* Only handle if HAL is opened (stack cback is not-NULL) */
288  if (nfc_hal_cb.p_stack_cback) {
289    /* Send power cycle event to NFC_HAL_TASK */
290    GKI_send_event(NFC_HAL_TASK, NFC_HAL_TASK_EVT_POWER_CYCLE);
291  }
292}
293
294/*******************************************************************************
295**
296** Function         HAL_NfcGetMaxNfcee
297**
298** Description      Retrieve the maximum number of NFCEEs supported by NFCC
299**
300** Returns          the maximum number of NFCEEs supported by NFCC
301**
302*******************************************************************************/
303uint8_t HAL_NfcGetMaxNfcee(void) {
304  HAL_TRACE_API1("HAL_NfcGetMaxNfcee: %d", nfc_hal_cb.max_ee);
305  return nfc_hal_cb.max_ee;
306}
307