blob: 36b442b786edfebf57ac7fc727ad602ee978df4a [file] [log] [blame]
Nick Pelly5d9927b2010-09-23 12:47:58 -07001/*
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*/
75static
76NFCSTATUS
77phLlcNfc_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*/
106static
107NFCSTATUS
108phLlcNfc_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*/
138static
139NFCSTATUS
140phLlcNfc_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
152NFCSTATUS
153phLlcNfc_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
222static
223NFCSTATUS
224phLlcNfc_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;
Daniel Tomasb313c3d2011-05-26 15:52:17 +0200231 phLlcNfc_LlcPacket_t s_packet_info;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700232
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 */
Nick Pelly5d9927b2010-09-23 12:47:58 -0700242 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 */
Daniel Tomasb313c3d2011-05-26 15:52:17 +0200259 result = phLlcNfc_H_CreateUFramePayload(ps_llc_ctxt,
260 &s_packet_info,
261 &(s_packet_info.llcbuf_len),
Nick Pelly5d9927b2010-09-23 12:47:58 -0700262 phLlcNfc_e_rset);
263 }
264 if (NFCSTATUS_SUCCESS == result)
265 {
266 /* Call DAL write */
267 result = phLlcNfc_Interface_Write(ps_llc_ctxt,
Daniel Tomasb313c3d2011-05-26 15:52:17 +0200268 (uint8_t*)&(s_packet_info.s_llcbuf),
269 (uint32_t)s_packet_info.llcbuf_len);
Nick Pelly5d9927b2010-09-23 12:47:58 -0700270 }
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
292NFCSTATUS
293phLlcNfc_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
347static
348NFCSTATUS
349phLlcNfc_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;
Daniel Tomasb313c3d2011-05-26 15:52:17 +0200365 phLlcNfc_LlcPacket_t s_packet_info;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700366 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
Nick Pelly5d9927b2010-09-23 12:47:58 -0700404
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 {
Nick Pelly5d9927b2010-09-23 12:47:58 -0700422 /* Call write to the below layer, only if previous write
423 is completed */
424 result = phLlcNfc_Interface_Write (ps_llc_ctxt,
Daniel Tomasb313c3d2011-05-26 15:52:17 +0200425 (uint8_t *)&(s_packet_info.s_llcbuf),
426 (uint32_t)s_packet_info.llcbuf_len);
Nick Pelly5d9927b2010-09-23 12:47:58 -0700427
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
471static
472NFCSTATUS
473phLlcNfc_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}