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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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