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
36 uint32_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 *******************************************************************************/
HAL_NfcInitialize(void)49 void 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 *******************************************************************************/
HAL_NfcTerminate(void)82 void 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 *******************************************************************************/
HAL_NfcOpen(tHAL_NFC_CBACK * p_hal_cback,tHAL_NFC_DATA_CBACK * p_data_cback)96 void 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 *******************************************************************************/
HAL_NfcClose(void)121 void 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 *******************************************************************************/
HAL_NfcCoreInitialized(uint16_t data_len,uint8_t * p_core_init_rsp_params)144 void 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 *******************************************************************************/
HAL_NfcWrite(uint16_t data_len,uint8_t * p_data)179 void 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 *******************************************************************************/
HAL_NfcPreDiscover(void)221 bool 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 *******************************************************************************/
HAL_NfcControlGranted(void)261 void 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 *******************************************************************************/
HAL_NfcPowerCycle(void)284 void 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 *******************************************************************************/
HAL_NfcGetMaxNfcee(void)303 uint8_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