blob: 750f5137b3870e5d6355ceb5d44dd0cfac20b1c7 [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 phFriNfc_Llcp.c
19 * \brief NFC LLCP core
20 *
21 * Project: NFC-FRI
22 *
23 */
24
25/*include files*/
26#include <phNfcTypes.h>
27#include <phNfcHalTypes.h>
28#include <phLibNfcStatus.h>
29#include <phFriNfc_LlcpUtils.h>
30#include <phFriNfc_Llcp.h>
31
32NFCSTATUS phFriNfc_Llcp_DecodeTLV( phNfc_sData_t *psRawData,
33 uint32_t *pOffset,
34 uint8_t *pType,
35 phNfc_sData_t *psValueBuffer )
36{
37 uint8_t type;
38 uint8_t length;
39 uint32_t offset = *pOffset;
40
41 /* Check for NULL pointers */
42 if ((psRawData == NULL) || (pOffset == NULL) || (pType == NULL) || (psValueBuffer == NULL))
43 {
44 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
45 }
46
47 /* Check offset */
48 if (offset > psRawData->length)
49 {
50 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
51 }
52
53 /* Check if enough room for Type and Length (with overflow check) */
54 if ((offset+2 > psRawData->length) && (offset+2 > offset))
55 {
56 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
57 }
58
59 /* Get Type and Length from current TLV, and update offset */
60 type = psRawData->buffer[offset];
61 length = psRawData->buffer[offset+1];
62 offset += 2;
63
64 /* Check if enough room for Value with announced Length (with overflow check) */
65 if ((offset+length > psRawData->length) && (offset+length > offset))
66 {
67 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
68 }
69
70 /* Save response, and update offset */
71 *pType = type;
72 psValueBuffer->buffer = psRawData->buffer + offset;
73 psValueBuffer->length = length;
74 offset += length;
75
76 /* Save updated offset */
77 *pOffset = offset;
78
79 return NFCSTATUS_SUCCESS;
80}
81
82NFCSTATUS phFriNfc_Llcp_EncodeTLV( phNfc_sData_t *psValueBuffer,
83 uint32_t *pOffset,
84 uint8_t type,
85 uint8_t length,
86 uint8_t *pValue)
87{
88 uint32_t offset = *pOffset;
Sunil Jogi7b187e72012-01-16 11:50:07 -080089 uint32_t finalOffset = offset + 2 + length; /* 2 stands for Type and Length fields size */
Nick Pelly5d9927b2010-09-23 12:47:58 -070090 uint8_t i;
91
92 /* Check for NULL pointers */
93 if ((psValueBuffer == NULL) || (pOffset == NULL) || (pValue == NULL))
94 {
95 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
96 }
97
98 /* Check offset */
99 if (offset > psValueBuffer->length)
100 {
101 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
102 }
103
Sunil Jogi7b187e72012-01-16 11:50:07 -0800104 /* Check if enough room for Type, Length and Value (with overflow check) */
105 if ((finalOffset > psValueBuffer->length) || (finalOffset < offset))
Nick Pelly5d9927b2010-09-23 12:47:58 -0700106 {
107 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
108 }
109
110 /* Set the TYPE */
111 psValueBuffer->buffer[offset] = type;
112 offset += 1;
113
114 /* Set the LENGTH */
115 psValueBuffer->buffer[offset] = length;
116 offset += 1;
117
118 /* Set the VALUE */
119 for(i=0;i<length;i++,offset++)
120 {
121 psValueBuffer->buffer[offset] = pValue[i];
122 }
123
124 /* Save updated offset */
125 *pOffset = offset;
126
127 return NFCSTATUS_SUCCESS;
128}
129
Sunil Jogi7b187e72012-01-16 11:50:07 -0800130NFCSTATUS phFriNfc_Llcp_AppendTLV( phNfc_sData_t *psValueBuffer,
131 uint32_t nTlvOffset,
132 uint32_t *pCurrentOffset,
133 uint8_t length,
134 uint8_t *pValue)
135{
136 uint32_t offset = *pCurrentOffset;
137 uint32_t finalOffset = offset + length;
138
139 /* Check for NULL pointers */
140 if ((psValueBuffer == NULL) || (pCurrentOffset == NULL) || (pValue == NULL))
141 {
142 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
143 }
144
145 /* Check offset */
146 if (offset > psValueBuffer->length)
147 {
148 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
149 }
150
151 /* Check if enough room for Type and Length (with overflow check) */
152 if ((finalOffset > psValueBuffer->length) || (finalOffset < offset))
153 {
154 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
155 }
156
157 /* Update the LENGTH */
158 psValueBuffer->buffer[nTlvOffset+1] += length;
159
160 /* Set the VALUE */
161 memcpy(psValueBuffer->buffer + offset, pValue, length);
162 offset += length;
163
164 /* Save updated offset */
165 *pCurrentOffset = offset;
166
167 return NFCSTATUS_SUCCESS;
168}
169
170
Nick Pelly5d9927b2010-09-23 12:47:58 -0700171/* TODO: comment function EncodeMIUX */
Jeff Hamiltone1c9fcf2010-11-01 15:01:42 -0500172void phFriNfc_Llcp_EncodeMIUX(uint16_t miux,
173 uint8_t* pMiuxEncoded)
Nick Pelly5d9927b2010-09-23 12:47:58 -0700174{
Nick Pelly5d9927b2010-09-23 12:47:58 -0700175 /* MASK */
176 miux = miux & PHFRINFC_LLCP_TLV_MIUX_MASK;
177
Jeff Hamiltone1c9fcf2010-11-01 15:01:42 -0500178 pMiuxEncoded[0] = miux >> 8;
179 pMiuxEncoded[1] = miux & 0xff;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700180}
181
182/* TODO: comment function EncodeRW */
183void phFriNfc_Llcp_EncodeRW(uint8_t *pRw)
184{
185 /* MASK */
186 *pRw = *pRw & PHFRINFC_LLCP_TLV_RW_MASK;
187}
188
189/**
190 * Initializes a Fifo Cyclic Buffer to point to some allocated memory.
191 */
192void phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER pUtilFifo,
193 const uint8_t *pBuffStart,
194 uint32_t buffLength)
195{
196 pUtilFifo->pBuffStart = (uint8_t *)pBuffStart;
197 pUtilFifo->pBuffEnd = (uint8_t *)pBuffStart + buffLength-1;
198 pUtilFifo->pIn = (uint8_t *)pBuffStart;
199 pUtilFifo->pOut = (uint8_t *)pBuffStart;
200 pUtilFifo->bFull = FALSE;
201}
202
203/**
204 * Clears the Fifo Cyclic Buffer - loosing any data that was in it.
205 */
206void phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER pUtilFifo)
207{
208 pUtilFifo->pIn = pUtilFifo->pBuffStart;
209 pUtilFifo->pOut = pUtilFifo->pBuffStart;
210 pUtilFifo->bFull = FALSE;
211}
212
213/**
214 * Attempts to write dataLength bytes to the specified Fifo Cyclic Buffer.
215 */
216uint32_t phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER pUtilFifo,
217 uint8_t *pData,
218 uint32_t dataLength)
219{
220 uint32_t dataLengthWritten = 0;
221 uint8_t * pNext;
222
223 while(dataLengthWritten < dataLength)
224 {
225 pNext = (uint8_t*)pUtilFifo->pIn+1;
226
227 if(pNext > pUtilFifo->pBuffEnd)
228 {
229 //Wrap around
230 pNext = pUtilFifo->pBuffStart;
231 }
232
233 if(pUtilFifo->bFull)
234 {
235 //Full
236 break;
237 }
238
239 if(pNext == pUtilFifo->pOut)
240 {
241 // Trigger Full flag
242 pUtilFifo->bFull = TRUE;
243 }
244
245 dataLengthWritten++;
246 *pNext = *pData++;
247 pUtilFifo->pIn = pNext;
248 }
249
250 return dataLengthWritten;
251}
252
253/**
254 * Attempts to read dataLength bytes from the specified Fifo Cyclic Buffer.
255 */
256uint32_t phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER pUtilFifo,
257 uint8_t *pBuffer,
258 uint32_t dataLength)
259{
260 uint32_t dataLengthRead = 0;
261 uint8_t * pNext;
262
263 while(dataLengthRead < dataLength)
264 {
265 if((pUtilFifo->pOut == pUtilFifo->pIn) && (pUtilFifo->bFull == FALSE))
266 {
267 //No more bytes in buffer
268 break;
269 }
270 else
271 {
272 dataLengthRead++;
273
274 if(pUtilFifo->pOut == pUtilFifo->pBuffEnd)
275 {
276 /* Wrap around */
277 pNext = pUtilFifo->pBuffStart;
278 }
279 else
280 {
281 pNext = (uint8_t*)pUtilFifo->pOut + 1;
282 }
283
284 *pBuffer++ = *pNext;
285
286 pUtilFifo->pOut = pNext;
287
288 pUtilFifo->bFull = FALSE;
289 }
290 }
291
292 return dataLengthRead;
293}
294
295/**
296 * Returns the number of bytes currently stored in Fifo Cyclic Buffer.
297 */
298uint32_t phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER pUtilFifo)
299{
300 uint32_t dataLength;
301 uint8_t * pIn = (uint8_t *)pUtilFifo->pIn;
302 uint8_t * pOut = (uint8_t *)pUtilFifo->pOut;
303
304 if (pUtilFifo->bFull)
305 {
306 dataLength = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
307 }
308 else
309 {
310 if(pIn >= pOut)
311 {
312 dataLength = pIn - pOut;
313 }
314 else
315 {
316 dataLength = pUtilFifo->pBuffEnd - pOut;
317 dataLength += (pIn+1) - pUtilFifo->pBuffStart;
318 }
319 }
320
321 return dataLength;
322}
323
324
325/**
326 * Returns the available room for writing in Fifo Cyclic Buffer.
327 */
328uint32_t phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER pUtilFifo)
329{
330 uint32_t dataLength;
331 uint32_t size;
332 uint8_t * pIn = (uint8_t *)pUtilFifo->pIn;
333 uint8_t * pOut = (uint8_t *)pUtilFifo->pOut;
334
335 if (pUtilFifo->bFull)
336 {
337 dataLength = 0;
338 }
339 else
340 {
341 if(pIn >= pOut)
342 {
343 size = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
344 dataLength = size - (pIn - pOut);
345 }
346 else
347 {
348 dataLength = pOut - pIn;
349 }
350 }
351
352 return dataLength;
353}
354
355
356
357uint32_t phFriNfc_Llcp_Header2Buffer( phFriNfc_Llcp_sPacketHeader_t *psHeader, uint8_t *pBuffer, uint32_t nOffset )
358{
359 uint32_t nOriginalOffset = nOffset;
360 pBuffer[nOffset++] = (uint8_t)((psHeader->dsap << 2) | (psHeader->ptype >> 2));
361 pBuffer[nOffset++] = (uint8_t)((psHeader->ptype << 6) | psHeader->ssap);
362 return nOffset - nOriginalOffset;
363}
364
365uint32_t phFriNfc_Llcp_Sequence2Buffer( phFriNfc_Llcp_sPacketSequence_t *psSequence, uint8_t *pBuffer, uint32_t nOffset )
366{
367 uint32_t nOriginalOffset = nOffset;
368 pBuffer[nOffset++] = (uint8_t)((psSequence->ns << 4) | (psSequence->nr));
369 return nOffset - nOriginalOffset;
370}
371
372uint32_t phFriNfc_Llcp_Buffer2Header( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketHeader_t *psHeader )
373{
374 psHeader->dsap = (pBuffer[nOffset] & 0xFC) >> 2;
375 psHeader->ptype = ((pBuffer[nOffset] & 0x03) << 2) | ((pBuffer[nOffset+1] & 0xC0) >> 6);
376 psHeader->ssap = pBuffer[nOffset+1] & 0x3F;
377 return PHFRINFC_LLCP_PACKET_HEADER_SIZE;
378}
379
380uint32_t phFriNfc_Llcp_Buffer2Sequence( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketSequence_t *psSequence )
381{
382 psSequence->ns = pBuffer[nOffset] >> 4;
383 psSequence->nr = pBuffer[nOffset] & 0x0F;
384 return PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
385}
386
387