1 /*
2 * Copyright (C) 2010 NXP Semiconductors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*!
18 * \file phLlcNfc.c
19 * \brief Common LLC for the upper layer.
20 *
21 * Project: NFC-FRI-1.1
22 *
23 * $Date: Wed Apr 28 17:07:03 2010 $
24 * $Author: ing02260 $
25 * $Revision: 1.59 $
26 * $Aliases: NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $
27 *
28 */
29
30 /*************************** Includes *******************************/
31 #include <phNfcTypes.h>
32 #include <phNfcStatus.h>
33 #include <phOsalNfc.h>
34 #include <phNfcInterface.h>
35 #include <phLlcNfc_DataTypes.h>
36 #include <phLlcNfc.h>
37 #include <phLlcNfc_Frame.h>
38 #include <phLlcNfc_Interface.h>
39 #include <phLlcNfc_Timer.h>
40
41 /*********************** End of includes ****************************/
42
43 /***************************** Macros *******************************/
44
45 /************************ End of macros *****************************/
46
47 /***************************** Global variables *******************************/
48
49 #ifdef LLC_RELEASE_FLAG
50 uint8_t g_release_flag;
51 #endif /* #ifdef LLC_RELEASE_FLAG */
52
53 /************************ End of global variables *****************************/
54
55
56
57 /*********************** Local functions ****************************/
58 /**
59 * \ingroup grp_hal_nfc_llc
60 *
61 * \brief \b Init function
62 *
63 * \copydoc page_reg Initialise all variables of the LLC component (Asynchronous function).
64 *
65 * \param[in] pContext LLC context provided by the upper layer. The LLC
66 * context will be given to the upper layer through the
67 * \ref phLlcNfc_Register function
68 * \param[in] pLinkInfo Link information of the hardware
69 *
70 * \retval NFCSTATUS_PENDING If the command is yet to be processed.
71 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid.
72 * \retval Other errors Errors related to the lower layers
73 *
74 */
75 static
76 NFCSTATUS
77 phLlcNfc_Init (
78 void *pContext,
79 void *pLinkInfo
80 );
81
82 /**
83 * \ingroup grp_hal_nfc_llc
84 *
85 * \brief \b Send function
86 *
87 * \copydoc page_reg This asynchronous function gets the information from the upper layer and creates the
88 * proper LLC packet to send the information it to the hardware. The number of
89 * bytes written is obtained from the send response callback which has been
90 * registered in \ref phLlcNfc_Register function
91 *
92 * \param[in] pContext LLC context is provided by the upper layer. The LLC
93 * context earlier was given to the upper layer through the
94 * \ref phLlcNfc_Register function
95 * \param[in] pLinkInfo Link information of the hardware.
96 * \param[in] pLlc_Buf The information given by the upper layer to send it to
97 * the lower layer
98 * \param[in] llcBufLength the length of pLlc_Buf, that needs to be sent to the
99 * lower layer is given by the upper layer
100 *
101 * \retval NFCSTATUS_PENDING If the command is yet to be process.
102 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid.
103 * \retval Other errors Errors related to the lower layers
104 *
105 */
106 static
107 NFCSTATUS
108 phLlcNfc_Send (
109 void *pContext,
110 void *pLinkInfo,
111 uint8_t *pLlcBuf,
112 uint16_t llcBufLength
113 );
114
115 /**
116 * \ingroup grp_hal_nfc_llc
117 *
118 * \brief \b Receive function
119 *
120 * \copydoc page_reg This asynchronous function gets the length and the required buffer from
121 * the upper layer to receive the information from the the hardware. The
122 * received data will be given through the receive response callback
123 * which has been registered in the \b phLlcNfc_Register function
124 *
125 * \param[in] pContext LLC context is provided by the upper layer. The LLC
126 * context earlier was given to the upper layer through the
127 * \b phLlcNfc_Register function
128 * \param[in] pLinkInfo Link information of the hardware
129 * \param[in] pLlc_Buf The information given by the upper layer to receive data from
130 * the lower layer
131 * \param[in] llcBufLength The length of pLlc_Buf given by the upper layer
132 *
133 * \retval NFCSTATUS_PENDING If the command is yet to be process.
134 * \retval NFCSTATUS_INVALID_PARAMETER At least one parameter of the function is invalid.
135 * \retval Other errors Errors related to the lower layers
136 *
137 */
138 static
139 NFCSTATUS
140 phLlcNfc_Receive (
141 void *pContext,
142 void *pLinkInfo,
143 uint8_t *pLlcBuf,
144 uint16_t llcBufLength
145 );
146 /******************** End of Local functions ************************/
147
148 /********************** Global variables ****************************/
149
150 /******************** End of Global Variables ***********************/
151
152 NFCSTATUS
phLlcNfc_Register(phNfcIF_sReference_t * psReference,phNfcIF_sCallBack_t if_callback,void * psIFConfig)153 phLlcNfc_Register (
154 phNfcIF_sReference_t *psReference,
155 phNfcIF_sCallBack_t if_callback,
156 void *psIFConfig
157 )
158 {
159 NFCSTATUS result = NFCSTATUS_SUCCESS;
160 phLlcNfc_Context_t *ps_llc_ctxt = NULL;
161 phNfcLayer_sCfg_t *psconfig = (phNfcLayer_sCfg_t *)psIFConfig;
162
163 PH_LLCNFC_PRINT("Llc Register called\n");
164 if ((NULL == psReference) || (NULL == psIFConfig) ||
165 (NULL == psReference->plower_if) ||
166 #if 0
167 (NULL == if_callback.pif_ctxt) ||
168 #endif
169 (NULL == if_callback.notify) ||
170 (NULL == if_callback.receive_complete) ||
171 (NULL == if_callback.send_complete))
172 {
173 result = PHNFCSTVAL(CID_NFC_LLC,
174 NFCSTATUS_INVALID_PARAMETER);
175 }
176 else
177 {
178 /* Now LLC is in RESET state */
179 ps_llc_ctxt = (phLlcNfc_Context_t*)phOsalNfc_GetMemory(
180 sizeof(phLlcNfc_Context_t));
181 if (NULL == ps_llc_ctxt)
182 {
183 /* Memory allocation failed */
184 result = PHNFCSTVAL(CID_NFC_LLC,
185 NFCSTATUS_INSUFFICIENT_RESOURCES);
186 }
187 else
188 {
189 result = NFCSTATUS_SUCCESS;
190
191 (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t));
192
193 /* Register the LLC functions to the upper layer */
194 psReference->plower_if->init = (pphNfcIF_Interface_t)&phLlcNfc_Init;
195 psReference->plower_if->release = (pphNfcIF_Interface_t)&phLlcNfc_Release;
196 psReference->plower_if->send = (pphNfcIF_Transact_t)&phLlcNfc_Send;
197 psReference->plower_if->receive = (pphNfcIF_Transact_t)&phLlcNfc_Receive;
198 /* Copy the LLC context to the upper layer */
199 psReference->plower_if->pcontext = ps_llc_ctxt;
200
201 /* Register the callback function from the upper layer */
202 ps_llc_ctxt->cb_for_if.receive_complete = if_callback.receive_complete;
203 ps_llc_ctxt->cb_for_if.send_complete = if_callback.send_complete;
204 ps_llc_ctxt->cb_for_if.notify = if_callback.notify;
205 /* Get the upper layer context */
206 ps_llc_ctxt->cb_for_if.pif_ctxt = if_callback.pif_ctxt;
207
208 result = phLlcNfc_Interface_Register(ps_llc_ctxt, psconfig);
209
210 if (NFCSTATUS_SUCCESS == result)
211 {
212 #ifdef LLC_RELEASE_FLAG
213 g_release_flag = FALSE;
214 #endif /* #ifdef LLC_RELEASE_FLAG */
215 }
216 }
217 }
218 PH_LLCNFC_DEBUG("Llc Register result : 0x%x\n", result);
219 return result;
220 }
221
222 static
223 NFCSTATUS
phLlcNfc_Init(void * pContext,void * pLinkInfo)224 phLlcNfc_Init (
225 void *pContext,
226 void *pLinkInfo
227 )
228 {
229 NFCSTATUS result = NFCSTATUS_SUCCESS;
230 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
231 phLlcNfc_LlcPacket_t s_packet_info;
232
233 PH_LLCNFC_PRINT("Llc Init called\n");
234 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo))
235 {
236 result = PHNFCSTVAL(CID_NFC_LLC,
237 NFCSTATUS_INVALID_PARAMETER);
238 }
239 else
240 {
241 /* Initialisation */
242 ps_llc_ctxt->phwinfo = pLinkInfo;
243 /* Call the internal frame initialise */
244 phLlcNfc_H_Frame_Init(ps_llc_ctxt);
245 /* Call the internal LLC TL interface initialise */
246 result = phLlcNfc_Interface_Init(ps_llc_ctxt);
247 if (NFCSTATUS_SUCCESS == result)
248 {
249 /* Call the internal LLC timer initialise */
250 result = phLlcNfc_TimerInit(ps_llc_ctxt);
251 }
252
253 if (NFCSTATUS_SUCCESS == result)
254 {
255 /* Create the static timer */
256 phLlcNfc_CreateTimers();
257
258 /* Create a U frame */
259 result = phLlcNfc_H_CreateUFramePayload(ps_llc_ctxt,
260 &s_packet_info,
261 &(s_packet_info.llcbuf_len),
262 phLlcNfc_e_rset);
263 }
264 if (NFCSTATUS_SUCCESS == result)
265 {
266 /* Call DAL write */
267 result = phLlcNfc_Interface_Write(ps_llc_ctxt,
268 (uint8_t*)&(s_packet_info.s_llcbuf),
269 (uint32_t)s_packet_info.llcbuf_len);
270 }
271 if (NFCSTATUS_PENDING == result)
272 {
273 /* Start the timer */
274 result = phLlcNfc_StartTimers(PH_LLCNFC_CONNECTIONTIMER, 0);
275 if (NFCSTATUS_SUCCESS == result)
276 {
277 ps_llc_ctxt->s_frameinfo.sent_frame_type =
278 init_u_rset_frame;
279 result = NFCSTATUS_PENDING;
280 }
281 }
282
283 if (NFCSTATUS_PENDING != result)
284 {
285 (void)phLlcNfc_Release(ps_llc_ctxt, pLinkInfo);
286 }
287 }
288 PH_LLCNFC_DEBUG("Llc Init result : 0x%x\n", result);
289 return result;
290 }
291
292 NFCSTATUS
phLlcNfc_Release(void * pContext,void * pLinkInfo)293 phLlcNfc_Release(
294 void *pContext,
295 void *pLinkInfo
296 )
297 {
298 NFCSTATUS result = PHNFCSTVAL(CID_NFC_LLC,
299 NFCSTATUS_INVALID_PARAMETER);
300 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
301 /*
302 1. Free all the memory allocated in initialise
303 */
304 PH_LLCNFC_PRINT("Llc release called\n");
305
306 if ((NULL != ps_llc_ctxt) && (NULL != pLinkInfo))
307 {
308 result = NFCSTATUS_SUCCESS;
309 ps_llc_ctxt->phwinfo = pLinkInfo;
310 #ifdef INCLUDE_DALINIT_DEINIT
311 if (NULL != ps_llc_ctxt->lower_if.release)
312 {
313 result = ps_llc_ctxt->lower_if.release(
314 ps_llc_ctxt->lower_if.pcontext,
315 pLinkInfo);
316 }
317 #endif
318 if (NULL != ps_llc_ctxt->lower_if.transact_abort)
319 {
320 result = ps_llc_ctxt->lower_if.transact_abort(
321 ps_llc_ctxt->lower_if.pcontext,
322 pLinkInfo);
323 }
324 if (NULL != ps_llc_ctxt->lower_if.unregister)
325 {
326 result = ps_llc_ctxt->lower_if.unregister(
327 ps_llc_ctxt->lower_if.pcontext,
328 pLinkInfo);
329 }
330
331 /* Call the internal LLC timer un-initialise */
332 phLlcNfc_TimerUnInit(ps_llc_ctxt);
333 phLlcNfc_H_Frame_DeInit(&ps_llc_ctxt->s_frameinfo);
334 (void)memset(ps_llc_ctxt, 0, sizeof(phLlcNfc_Context_t));
335 phOsalNfc_FreeMemory(ps_llc_ctxt);
336 ps_llc_ctxt = NULL;
337
338 #ifdef LLC_RELEASE_FLAG
339 g_release_flag = TRUE;
340 #endif /* #ifdef LLC_RELEASE_FLAG */
341
342 }
343 PH_LLCNFC_DEBUG("Llc release result : 0x%04X\n", result);
344 return result;
345 }
346
347 static
348 NFCSTATUS
phLlcNfc_Send(void * pContext,void * pLinkInfo,uint8_t * pLlcBuf,uint16_t llcBufLength)349 phLlcNfc_Send (
350 void *pContext,
351 void *pLinkInfo,
352 uint8_t *pLlcBuf,
353 uint16_t llcBufLength
354 )
355 {
356 /*
357 1. Check the function parameters for valid values
358 2. Create the I frame llc payload using the upper layer buffer
359 3. Send the updated buffer to the below layer
360 4. Store the I frame in a list, till acknowledge is received
361 */
362 NFCSTATUS result = NFCSTATUS_SUCCESS;
363 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
364 phLlcNfc_Frame_t *ps_frame_info = NULL;
365 phLlcNfc_LlcPacket_t s_packet_info;
366 phLlcNfc_StoreIFrame_t *ps_store_frame = NULL;
367 #if 0
368 uint8_t count = 1;
369 #endif /* #if 0 */
370
371 PH_LLCNFC_PRINT ("Llc Send called\n");
372 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) ||
373 (NULL == pLlcBuf) || (0 == llcBufLength) ||
374 (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN))
375 {
376 /* Parameter check failed */
377 result = PHNFCSTVAL(CID_NFC_LLC,
378 NFCSTATUS_INVALID_PARAMETER);
379 }
380 else if (ps_llc_ctxt->s_frameinfo.s_send_store.winsize_cnt >=
381 ps_llc_ctxt->s_frameinfo.window_size)
382 {
383 /* Window size check failed */
384 result = PHNFCSTVAL(CID_NFC_LLC,
385 NFCSTATUS_NOT_ALLOWED);
386 }
387 else
388 {
389 ps_frame_info = &(ps_llc_ctxt->s_frameinfo);
390 ps_store_frame = &(ps_frame_info->s_send_store);
391
392 PH_LLCNFC_DEBUG ("Buffer length : 0x%04X\n", llcBufLength);
393 PH_LLCNFC_PRINT_BUFFER (pLlcBuf, llcBufLength);
394
395 /* Copy the hardware information */
396 ps_llc_ctxt->phwinfo = pLinkInfo;
397
398 /* Create I frame with the user buffer */
399 (void)phLlcNfc_H_CreateIFramePayload (
400 &(ps_llc_ctxt->s_frameinfo),
401 &s_packet_info,
402 pLlcBuf, (uint8_t)llcBufLength);
403
404
405 /* Store the I frame in the send list */
406 (void)phLlcNfc_H_StoreIFrame (ps_store_frame, s_packet_info);
407 result = NFCSTATUS_PENDING;
408
409 #ifdef CTRL_WIN_SIZE_COUNT
410
411 /* No check required */
412 if ((TRUE != ps_frame_info->write_pending) &&
413 (PH_LLCNFC_READPEND_REMAIN_BYTE !=
414 ps_frame_info->read_pending))
415
416 #else /* #ifdef CTRL_WIN_SIZE_COUNT */
417
418 if (1 == ps_frame_info->s_send_store.winsize_cnt)
419
420 #endif /* #ifdef CTRL_WIN_SIZE_COUNT */
421 {
422 /* Call write to the below layer, only if previous write
423 is completed */
424 result = phLlcNfc_Interface_Write (ps_llc_ctxt,
425 (uint8_t *)&(s_packet_info.s_llcbuf),
426 (uint32_t)s_packet_info.llcbuf_len);
427
428 if ((NFCSTATUS_PENDING == result) ||
429 (NFCSTATUS_BUSY == PHNFCSTATUS (result)))
430 {
431 ps_frame_info->write_status = result;
432 if (NFCSTATUS_BUSY == PHNFCSTATUS(result))
433 {
434 result = NFCSTATUS_PENDING;
435 ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t)
436 ((resend_i_frame == ps_frame_info->write_wait_call) ?
437 ps_frame_info->write_wait_call : user_i_frame);
438 }
439 else
440 {
441 /* Start the timer */
442 (void)phLlcNfc_StartTimers (PH_LLCNFC_GUARDTIMER,
443 ps_frame_info->n_s);
444
445 /* "sent_frame_type is updated" only if the data is
446 written to the lower layer */
447 ps_frame_info->sent_frame_type = user_i_frame;
448 }
449 }
450 #if 0
451 /* Get the added frame array count */
452 count = (uint8_t)((((ps_store_frame->start_pos +
453 ps_store_frame->winsize_cnt) - count)) %
454 PH_LLCNFC_MOD_NS_NR);
455 #endif /* #if 0 */
456 }
457 else
458 {
459 ps_frame_info->write_status = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY);
460 ps_frame_info->write_wait_call = (phLlcNfc_eSentFrameType_t)
461 ((resend_i_frame == ps_frame_info->write_wait_call) ?
462 ps_frame_info->write_wait_call : user_i_frame);
463 }
464 }
465
466
467 PH_LLCNFC_DEBUG ("Llc Send result : 0x%04X\n", result);
468 return result;
469 }
470
471 static
472 NFCSTATUS
phLlcNfc_Receive(void * pContext,void * pLinkInfo,uint8_t * pLlcBuf,uint16_t llcBufLength)473 phLlcNfc_Receive (
474 void *pContext,
475 void *pLinkInfo,
476 uint8_t *pLlcBuf,
477 uint16_t llcBufLength
478 )
479 {
480 NFCSTATUS result = NFCSTATUS_SUCCESS;
481 phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext;
482 phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL;
483
484 PH_LLCNFC_PRINT("Llc Receive called\n");
485 if ((NULL == ps_llc_ctxt) || (NULL == pLinkInfo) ||
486 (NULL == pLlcBuf) || (0 == llcBufLength) ||
487 (llcBufLength > PH_LLCNFC_MAX_IFRAME_BUFLEN))
488 {
489 result = PHNFCSTVAL(CID_NFC_LLC,
490 NFCSTATUS_INVALID_PARAMETER);
491 }
492 else
493 {
494 ps_llc_ctxt->phwinfo = pLinkInfo;
495
496 ps_recv_pkt = &(ps_llc_ctxt->s_frameinfo.s_recvpacket);
497 /* Always read the first byte to read the length, then
498 read the entire data later using the 1 byte buffer */
499 llcBufLength = PH_LLCNFC_BYTES_INIT_READ;
500 /* Call write to the below layer */
501 result = phLlcNfc_Interface_Read(ps_llc_ctxt,
502 PH_LLCNFC_READWAIT_OFF,
503 &(ps_recv_pkt->s_llcbuf.llc_length_byte),
504 llcBufLength);
505
506 ps_llc_ctxt->s_frameinfo.upper_recv_call = TRUE;
507 if (NFCSTATUS_PENDING != result)
508 {
509 ps_llc_ctxt->state = phLlcNfc_Initialised_State;
510 }
511 }
512 PH_LLCNFC_DEBUG("Llc Receive result : 0x%04X\n", result);
513 return result;
514 }
515