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 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 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 uint32_t finalOffset = offset + 2 + length; /* 2 stands for Type and Length fields size */ 90 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 104 /* Check if enough room for Type, Length and Value (with overflow check) */ 105 if ((finalOffset > psValueBuffer->length) || (finalOffset < offset)) 106 { 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 130 NFCSTATUS 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 171 /* TODO: comment function EncodeMIUX */ 172 void phFriNfc_Llcp_EncodeMIUX(uint16_t miux, 173 uint8_t* pMiuxEncoded) 174 { 175 /* MASK */ 176 miux = miux & PHFRINFC_LLCP_TLV_MIUX_MASK; 177 178 pMiuxEncoded[0] = miux >> 8; 179 pMiuxEncoded[1] = miux & 0xff; 180 } 181 182 /* TODO: comment function EncodeRW */ 183 void 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 */ 192 void 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 */ 206 void 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 */ 216 uint32_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 */ 256 uint32_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 */ 298 uint32_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 */ 328 uint32_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 357 uint32_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 365 uint32_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 372 uint32_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 380 uint32_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 388