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 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
phFriNfc_Llcp_DecodeTLV(phNfc_sData_t * psRawData,uint32_t * pOffset,uint8_t * pType,phNfc_sData_t * psValueBuffer)32 NFCSTATUS 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
phFriNfc_Llcp_EncodeTLV(phNfc_sData_t * psValueBuffer,uint32_t * pOffset,uint8_t type,uint8_t length,uint8_t * pValue)82 NFCSTATUS 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;
89 uint8_t i;
90
91 /* Check for NULL pointers */
92 if ((psValueBuffer == NULL) || (pOffset == NULL) || (pValue == NULL))
93 {
94 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
95 }
96
97 /* Check offset */
98 if (offset > psValueBuffer->length)
99 {
100 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
101 }
102
103 /* Check if enough room for Type and Length (with overflow check) */
104 if ((offset+2 > psValueBuffer->length) && (offset+2 > offset))
105 {
106 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
107 }
108
109 /* Set the TYPE */
110 psValueBuffer->buffer[offset] = type;
111 offset += 1;
112
113 /* Set the LENGTH */
114 psValueBuffer->buffer[offset] = length;
115 offset += 1;
116
117 /* Set the VALUE */
118 for(i=0;i<length;i++,offset++)
119 {
120 psValueBuffer->buffer[offset] = pValue[i];
121 }
122
123 /* Save updated offset */
124 *pOffset = offset;
125
126 return NFCSTATUS_SUCCESS;
127 }
128
129 /* TODO: comment function EncodeMIUX */
phFriNfc_Llcp_EncodeMIUX(uint16_t miux,uint8_t * pMiuxEncoded)130 void phFriNfc_Llcp_EncodeMIUX(uint16_t miux,
131 uint8_t* pMiuxEncoded)
132 {
133 /* MASK */
134 miux = miux & PHFRINFC_LLCP_TLV_MIUX_MASK;
135
136 pMiuxEncoded[0] = miux >> 8;
137 pMiuxEncoded[1] = miux & 0xff;
138 }
139
140 /* TODO: comment function EncodeRW */
phFriNfc_Llcp_EncodeRW(uint8_t * pRw)141 void phFriNfc_Llcp_EncodeRW(uint8_t *pRw)
142 {
143 /* MASK */
144 *pRw = *pRw & PHFRINFC_LLCP_TLV_RW_MASK;
145 }
146
147 /**
148 * Initializes a Fifo Cyclic Buffer to point to some allocated memory.
149 */
phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER pUtilFifo,const uint8_t * pBuffStart,uint32_t buffLength)150 void phFriNfc_Llcp_CyclicFifoInit(P_UTIL_FIFO_BUFFER pUtilFifo,
151 const uint8_t *pBuffStart,
152 uint32_t buffLength)
153 {
154 pUtilFifo->pBuffStart = (uint8_t *)pBuffStart;
155 pUtilFifo->pBuffEnd = (uint8_t *)pBuffStart + buffLength-1;
156 pUtilFifo->pIn = (uint8_t *)pBuffStart;
157 pUtilFifo->pOut = (uint8_t *)pBuffStart;
158 pUtilFifo->bFull = FALSE;
159 }
160
161 /**
162 * Clears the Fifo Cyclic Buffer - loosing any data that was in it.
163 */
phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER pUtilFifo)164 void phFriNfc_Llcp_CyclicFifoClear(P_UTIL_FIFO_BUFFER pUtilFifo)
165 {
166 pUtilFifo->pIn = pUtilFifo->pBuffStart;
167 pUtilFifo->pOut = pUtilFifo->pBuffStart;
168 pUtilFifo->bFull = FALSE;
169 }
170
171 /**
172 * Attempts to write dataLength bytes to the specified Fifo Cyclic Buffer.
173 */
phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER pUtilFifo,uint8_t * pData,uint32_t dataLength)174 uint32_t phFriNfc_Llcp_CyclicFifoWrite(P_UTIL_FIFO_BUFFER pUtilFifo,
175 uint8_t *pData,
176 uint32_t dataLength)
177 {
178 uint32_t dataLengthWritten = 0;
179 uint8_t * pNext;
180
181 while(dataLengthWritten < dataLength)
182 {
183 pNext = (uint8_t*)pUtilFifo->pIn+1;
184
185 if(pNext > pUtilFifo->pBuffEnd)
186 {
187 //Wrap around
188 pNext = pUtilFifo->pBuffStart;
189 }
190
191 if(pUtilFifo->bFull)
192 {
193 //Full
194 break;
195 }
196
197 if(pNext == pUtilFifo->pOut)
198 {
199 // Trigger Full flag
200 pUtilFifo->bFull = TRUE;
201 }
202
203 dataLengthWritten++;
204 *pNext = *pData++;
205 pUtilFifo->pIn = pNext;
206 }
207
208 return dataLengthWritten;
209 }
210
211 /**
212 * Attempts to read dataLength bytes from the specified Fifo Cyclic Buffer.
213 */
phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER pUtilFifo,uint8_t * pBuffer,uint32_t dataLength)214 uint32_t phFriNfc_Llcp_CyclicFifoFifoRead(P_UTIL_FIFO_BUFFER pUtilFifo,
215 uint8_t *pBuffer,
216 uint32_t dataLength)
217 {
218 uint32_t dataLengthRead = 0;
219 uint8_t * pNext;
220
221 while(dataLengthRead < dataLength)
222 {
223 if((pUtilFifo->pOut == pUtilFifo->pIn) && (pUtilFifo->bFull == FALSE))
224 {
225 //No more bytes in buffer
226 break;
227 }
228 else
229 {
230 dataLengthRead++;
231
232 if(pUtilFifo->pOut == pUtilFifo->pBuffEnd)
233 {
234 /* Wrap around */
235 pNext = pUtilFifo->pBuffStart;
236 }
237 else
238 {
239 pNext = (uint8_t*)pUtilFifo->pOut + 1;
240 }
241
242 *pBuffer++ = *pNext;
243
244 pUtilFifo->pOut = pNext;
245
246 pUtilFifo->bFull = FALSE;
247 }
248 }
249
250 return dataLengthRead;
251 }
252
253 /**
254 * Returns the number of bytes currently stored in Fifo Cyclic Buffer.
255 */
phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER pUtilFifo)256 uint32_t phFriNfc_Llcp_CyclicFifoUsage(P_UTIL_FIFO_BUFFER pUtilFifo)
257 {
258 uint32_t dataLength;
259 uint8_t * pIn = (uint8_t *)pUtilFifo->pIn;
260 uint8_t * pOut = (uint8_t *)pUtilFifo->pOut;
261
262 if (pUtilFifo->bFull)
263 {
264 dataLength = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
265 }
266 else
267 {
268 if(pIn >= pOut)
269 {
270 dataLength = pIn - pOut;
271 }
272 else
273 {
274 dataLength = pUtilFifo->pBuffEnd - pOut;
275 dataLength += (pIn+1) - pUtilFifo->pBuffStart;
276 }
277 }
278
279 return dataLength;
280 }
281
282
283 /**
284 * Returns the available room for writing in Fifo Cyclic Buffer.
285 */
phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER pUtilFifo)286 uint32_t phFriNfc_Llcp_CyclicFifoAvailable(P_UTIL_FIFO_BUFFER pUtilFifo)
287 {
288 uint32_t dataLength;
289 uint32_t size;
290 uint8_t * pIn = (uint8_t *)pUtilFifo->pIn;
291 uint8_t * pOut = (uint8_t *)pUtilFifo->pOut;
292
293 if (pUtilFifo->bFull)
294 {
295 dataLength = 0;
296 }
297 else
298 {
299 if(pIn >= pOut)
300 {
301 size = pUtilFifo->pBuffEnd - pUtilFifo->pBuffStart + 1;
302 dataLength = size - (pIn - pOut);
303 }
304 else
305 {
306 dataLength = pOut - pIn;
307 }
308 }
309
310 return dataLength;
311 }
312
313
314
phFriNfc_Llcp_Header2Buffer(phFriNfc_Llcp_sPacketHeader_t * psHeader,uint8_t * pBuffer,uint32_t nOffset)315 uint32_t phFriNfc_Llcp_Header2Buffer( phFriNfc_Llcp_sPacketHeader_t *psHeader, uint8_t *pBuffer, uint32_t nOffset )
316 {
317 uint32_t nOriginalOffset = nOffset;
318 pBuffer[nOffset++] = (uint8_t)((psHeader->dsap << 2) | (psHeader->ptype >> 2));
319 pBuffer[nOffset++] = (uint8_t)((psHeader->ptype << 6) | psHeader->ssap);
320 return nOffset - nOriginalOffset;
321 }
322
phFriNfc_Llcp_Sequence2Buffer(phFriNfc_Llcp_sPacketSequence_t * psSequence,uint8_t * pBuffer,uint32_t nOffset)323 uint32_t phFriNfc_Llcp_Sequence2Buffer( phFriNfc_Llcp_sPacketSequence_t *psSequence, uint8_t *pBuffer, uint32_t nOffset )
324 {
325 uint32_t nOriginalOffset = nOffset;
326 pBuffer[nOffset++] = (uint8_t)((psSequence->ns << 4) | (psSequence->nr));
327 return nOffset - nOriginalOffset;
328 }
329
phFriNfc_Llcp_Buffer2Header(uint8_t * pBuffer,uint32_t nOffset,phFriNfc_Llcp_sPacketHeader_t * psHeader)330 uint32_t phFriNfc_Llcp_Buffer2Header( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketHeader_t *psHeader )
331 {
332 psHeader->dsap = (pBuffer[nOffset] & 0xFC) >> 2;
333 psHeader->ptype = ((pBuffer[nOffset] & 0x03) << 2) | ((pBuffer[nOffset+1] & 0xC0) >> 6);
334 psHeader->ssap = pBuffer[nOffset+1] & 0x3F;
335 return PHFRINFC_LLCP_PACKET_HEADER_SIZE;
336 }
337
phFriNfc_Llcp_Buffer2Sequence(uint8_t * pBuffer,uint32_t nOffset,phFriNfc_Llcp_sPacketSequence_t * psSequence)338 uint32_t phFriNfc_Llcp_Buffer2Sequence( uint8_t *pBuffer, uint32_t nOffset, phFriNfc_Llcp_sPacketSequence_t *psSequence )
339 {
340 psSequence->ns = pBuffer[nOffset] >> 4;
341 psSequence->nr = pBuffer[nOffset] & 0x0F;
342 return PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
343 }
344
345
346