• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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