Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 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 phLlcNfc_Interface.c |
| 19 | * \brief Interface for both LLC and transport layer |
| 20 | * |
| 21 | * Project: NFC-FRI-1.1 |
| 22 | * |
| 23 | * $Date: Tue Jun 1 14:41:26 2010 $ |
| 24 | * $Author: ing02260 $ |
| 25 | * $Revision: 1.75 $ |
| 26 | * $Aliases: NFC_FRI1.1_WK1023_R35_1 $ |
| 27 | * |
| 28 | */ |
| 29 | |
| 30 | /*************************** Includes *******************************/ |
| 31 | #include <phNfcTypes.h> |
| 32 | #include <phNfcStatus.h> |
| 33 | #include <phOsalNfc.h> |
| 34 | #include <phNfcInterface.h> |
| 35 | #include <phLlcNfc_DataTypes.h> |
| 36 | #include <phLlcNfc_Timer.h> |
| 37 | #include <phLlcNfc_Frame.h> |
| 38 | #include <phLlcNfc.h> |
| 39 | #include <phLlcNfc_Interface.h> |
| 40 | #ifdef PH_LLCNFC_STUB |
| 41 | #include <phDalNfc_Stub.h> |
| 42 | #endif |
| 43 | #ifdef PH_LLCNFC_DALINT |
| 44 | #include <phDal4Nfc.h> |
| 45 | #endif |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 46 | #define LOG_TAG "NFC-LLC" |
| 47 | |
| 48 | #include <utils/Log.h> |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 49 | /*********************** End of includes ****************************/ |
| 50 | |
| 51 | /***************************** Macros *******************************/ |
| 52 | #define PH_LLCNFC_APPEND_LEN (4) |
| 53 | #define LLC_NS_FRAME_HEADER_MASK (0x38U) |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 54 | /************************ End of macros *****************************/ |
| 55 | |
| 56 | /*********************** Local functions ****************************/ |
| 57 | static |
| 58 | void |
| 59 | phLlcNfc_WrResp_Cb( |
| 60 | void *pContext, |
| 61 | void *pHwInfo, |
| 62 | phNfc_sTransactionInfo_t *pCompInfo |
| 63 | ); |
| 64 | |
| 65 | static |
| 66 | void |
| 67 | phLlcNfc_RdResp_Cb( |
| 68 | void *pContext, |
| 69 | void *pHwInfo, |
| 70 | phNfc_sTransactionInfo_t *pCompInfo |
| 71 | ); |
| 72 | |
| 73 | /******************** End of Local functions ************************/ |
| 74 | |
| 75 | /********************** Global variables ****************************/ |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 76 | int libnfc_llc_error_count = 0; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 77 | |
| 78 | /******************** End of Global Variables ***********************/ |
| 79 | |
| 80 | NFCSTATUS |
| 81 | phLlcNfc_Interface_Register( |
| 82 | phLlcNfc_Context_t *psLlcCtxt, |
| 83 | phNfcLayer_sCfg_t *psIFConfig |
| 84 | ) |
| 85 | { |
| 86 | NFCSTATUS result = NFCSTATUS_SUCCESS; |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 87 | phNfcIF_sCallBack_t if_cb = {0,0,0,0}; |
| 88 | phNfcIF_sReference_t sreference = {0,0,0}; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 89 | |
| 90 | if ((NULL == psLlcCtxt) || (NULL == psIFConfig)) |
| 91 | { |
| 92 | result = PHNFCSTVAL(CID_NFC_LLC, |
| 93 | NFCSTATUS_INVALID_PARAMETER); |
| 94 | } |
| 95 | else |
| 96 | { |
| 97 | result = NFCSTATUS_SUCCESS; |
| 98 | if_cb.notify = NULL; |
| 99 | if_cb.receive_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_RdResp_Cb; |
| 100 | if_cb.send_complete = (pphNfcIF_Transact_Completion_CB_t)&phLlcNfc_WrResp_Cb; |
| 101 | if_cb.pif_ctxt = psLlcCtxt; |
| 102 | sreference.plower_if = &(psLlcCtxt->lower_if); |
| 103 | result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); |
| 104 | #ifdef PH_LLCNFC_STUB |
| 105 | result = phDalNfc_StubRegister(&sreference, if_cb, psIFConfig->layer_next); |
| 106 | #endif /* #ifdef PH_LLCNFC_STUB */ |
| 107 | #ifdef PH_LLCNFC_DALINT |
| 108 | result = phDal4Nfc_Register(&sreference, if_cb, psIFConfig->layer_next); |
| 109 | #else |
| 110 | if ((NULL != psIFConfig->layer_next) && |
| 111 | (NULL != psIFConfig->layer_next->layer_registry)) |
| 112 | { |
| 113 | result = psIFConfig->layer_next->layer_registry( |
| 114 | &sreference, |
| 115 | if_cb, |
| 116 | (void *)&psIFConfig[(psIFConfig->layer_index - 1)]); |
| 117 | } |
| 118 | #endif /* #ifdef PH_LLCNFC_DALINT */ |
| 119 | } |
| 120 | PH_LLCNFC_DEBUG("Llc Dal Interface Register result : 0x%x\n", result); |
| 121 | return result; |
| 122 | } |
| 123 | |
| 124 | NFCSTATUS |
| 125 | phLlcNfc_Interface_Init( |
| 126 | phLlcNfc_Context_t *psLlcCtxt |
| 127 | ) |
| 128 | { |
| 129 | /* |
| 130 | 1. Get the pointer of the main llc context |
| 131 | */ |
| 132 | NFCSTATUS result = NFCSTATUS_SUCCESS; |
| 133 | if ((NULL == psLlcCtxt) || |
| 134 | (NULL == psLlcCtxt->lower_if.init)) |
| 135 | { |
| 136 | result = PHNFCSTVAL(CID_NFC_LLC, |
| 137 | NFCSTATUS_INVALID_PARAMETER); |
| 138 | } |
| 139 | else |
| 140 | { |
| 141 | /* Initialise the main context */ |
| 142 | result = psLlcCtxt->lower_if.init( psLlcCtxt->lower_if.pcontext, |
| 143 | psLlcCtxt->phwinfo); |
| 144 | } |
| 145 | PH_LLCNFC_DEBUG("Llc Dal Interface Init result : 0x%x\n", result); |
| 146 | return result; |
| 147 | } |
| 148 | |
| 149 | NFCSTATUS |
| 150 | phLlcNfc_Interface_Read( |
| 151 | phLlcNfc_Context_t *psLlcCtxt, |
| 152 | uint8_t readWaitOn, |
| 153 | uint8_t *pLlcBuffer, |
| 154 | uint32_t llcBufferLength |
| 155 | ) |
| 156 | { |
| 157 | NFCSTATUS result = NFCSTATUS_PENDING; |
| 158 | /* |
| 159 | 1. Call DAL or TL read with "phLlcNfc_LlcTl_RdResp_Cb" as |
| 160 | callback function |
| 161 | */ |
| 162 | PH_LLCNFC_PRINT("Llc Dal Interface Read called\n"); |
| 163 | if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) || |
| 164 | (0 == llcBufferLength) || (NULL == psLlcCtxt->lower_if.receive) || |
| 165 | (readWaitOn > PH_LLCNFC_READWAIT_ON)) |
| 166 | { |
| 167 | result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); |
| 168 | } |
| 169 | else if (PH_LLCNFC_READPEND_FLAG_OFF != |
| 170 | psLlcCtxt->s_frameinfo.read_pending) |
| 171 | { |
| 172 | /* do nothing */ |
| 173 | } |
| 174 | else |
| 175 | { |
| 176 | if (PH_LLCNFC_READWAIT_OFF == readWaitOn) |
| 177 | { |
| 178 | result = psLlcCtxt->lower_if.receive( |
| 179 | psLlcCtxt->lower_if.pcontext, |
| 180 | psLlcCtxt->phwinfo, |
| 181 | pLlcBuffer, |
| 182 | (uint8_t)llcBufferLength); |
| 183 | } |
| 184 | else |
| 185 | { |
| 186 | result = psLlcCtxt->lower_if.receive_wait( |
| 187 | psLlcCtxt->lower_if.pcontext, |
| 188 | psLlcCtxt->phwinfo, |
| 189 | pLlcBuffer, |
| 190 | (uint16_t)llcBufferLength); |
| 191 | } |
| 192 | |
| 193 | if(NFCSTATUS_PENDING == result) |
| 194 | { |
| 195 | if (PH_LLCNFC_READPEND_ONE_BYTE == llcBufferLength) |
| 196 | { |
| 197 | psLlcCtxt->s_frameinfo.read_pending = |
| 198 | PH_LLCNFC_READPEND_ONE_BYTE; |
| 199 | } |
| 200 | else |
| 201 | { |
| 202 | psLlcCtxt->s_frameinfo.read_pending = |
| 203 | PH_LLCNFC_READPEND_REMAIN_BYTE; |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | PH_LLCNFC_DEBUG("Llc Dal Interface Read result : 0x%x\n", result); |
| 208 | return result; |
| 209 | } |
| 210 | |
| 211 | NFCSTATUS |
| 212 | phLlcNfc_Interface_Write( |
| 213 | phLlcNfc_Context_t *psLlcCtxt, |
| 214 | uint8_t *pLlcBuffer, |
| 215 | uint32_t llcBufferLength |
| 216 | ) |
| 217 | { |
| 218 | NFCSTATUS result = NFCSTATUS_PENDING; |
| 219 | |
| 220 | PH_LLCNFC_PRINT("Llc Dal Interface Write called\n"); |
| 221 | /* |
| 222 | 1. Call DAL or TL write with "phLlcNfc_LlcTl_WrResp_Cb" as |
| 223 | callback function |
| 224 | */ |
| 225 | if ((NULL == psLlcCtxt) || (NULL == pLlcBuffer) || |
| 226 | (0 == llcBufferLength) || |
| 227 | (NULL == psLlcCtxt->lower_if.send)) |
| 228 | { |
Nick Pelly | 34ff48f | 2011-06-27 09:01:51 -0700 | [diff] [blame] | 229 | PH_LLCNFC_DEBUG ("psLlcCtxt : 0x%p\n", psLlcCtxt); |
| 230 | PH_LLCNFC_DEBUG ("pLlcBuffer : 0x%p\n", pLlcBuffer); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 231 | PH_LLCNFC_DEBUG ("llcBufferLength : 0x%08X\n", llcBufferLength); |
| 232 | result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_INVALID_PARAMETER); |
| 233 | } |
| 234 | else |
| 235 | { |
| 236 | PH_LLCNFC_PRINT("Buffer to be send to Dal : \n"); |
| 237 | PH_LLCNFC_PRINT_BUFFER(pLlcBuffer, llcBufferLength); |
| 238 | |
| 239 | if ((TRUE == psLlcCtxt->s_frameinfo.write_pending) || |
| 240 | (PH_LLCNFC_READPEND_REMAIN_BYTE == |
| 241 | psLlcCtxt->s_frameinfo.read_pending)) |
| 242 | { |
| 243 | result = PHNFCSTVAL(CID_NFC_LLC, NFCSTATUS_BUSY); |
| 244 | } |
| 245 | else |
| 246 | { |
| 247 | #ifdef LLC_DATA_BYTES |
| 248 | |
| 249 | PH_LLCNFC_PRINT_DATA (pLlcBuffer, llcBufferLength); |
| 250 | PH_LLCNFC_STRING (";\n"); |
| 251 | |
| 252 | #endif /* LLC_DATA_BYTES */ |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 253 | |
| 254 | psLlcCtxt->s_frameinfo.s_llcpacket.llcbuf_len = (uint8_t)llcBufferLength; |
| 255 | (void)memcpy ((void *)&(psLlcCtxt->s_frameinfo.s_llcpacket.s_llcbuf), |
| 256 | (void *)pLlcBuffer, llcBufferLength); |
| 257 | |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 258 | result = psLlcCtxt->lower_if.send(psLlcCtxt->lower_if.pcontext, |
| 259 | psLlcCtxt->phwinfo, |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 260 | (uint8_t *)&(psLlcCtxt->s_frameinfo.s_llcpacket.s_llcbuf), |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 261 | (uint16_t)llcBufferLength); |
| 262 | if(NFCSTATUS_PENDING == result) |
| 263 | { |
| 264 | psLlcCtxt->s_frameinfo.write_pending = TRUE; |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 265 | #ifdef PIGGY_BACK |
| 266 | /* Stop the ACK timer, as the ACK or I frame is sent */ |
| 267 | phLlcNfc_StopTimers (PH_LLCNFC_ACKTIMER, 0); |
| 268 | /* ACK is sent, so reset the response received count */ |
| 269 | psLlcCtxt->s_frameinfo.resp_recvd_count = 0; |
| 270 | #endif /* #ifdef PIGGY_BACK */ |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 271 | } |
| 272 | } |
| 273 | } |
| 274 | PH_LLCNFC_DEBUG("Llc Dal Interface Write result : 0x%x\n", result); |
| 275 | return result; |
| 276 | } |
| 277 | |
| 278 | static |
| 279 | void |
| 280 | phLlcNfc_WrResp_Cb( |
| 281 | void *pContext, |
| 282 | void *pHwInfo, |
| 283 | phNfc_sTransactionInfo_t *pCompInfo |
| 284 | ) |
| 285 | { |
| 286 | /* |
| 287 | 1. Check the window size, if window size = windows |
| 288 | 1. Call the send callback, which has been registered by upper |
| 289 | layer |
| 290 | */ |
| 291 | NFCSTATUS result = NFCSTATUS_SUCCESS; |
| 292 | phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; |
| 293 | phLlcNfc_Frame_t *ps_frame_info = NULL; |
| 294 | phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; |
| 295 | phLlcNfc_StoreIFrame_t *ps_store_frame = NULL; |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 296 | phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 297 | uint8_t count = 0; |
| 298 | |
| 299 | PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB CALLED\n\n"); |
| 300 | |
| 301 | if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo)) |
| 302 | { |
| 303 | ps_llc_ctxt->s_frameinfo.write_pending = FALSE; |
| 304 | |
| 305 | PHNFC_UNUSED_VARIABLE(result); |
| 306 | |
| 307 | if(NFCSTATUS_SUCCESS == pCompInfo->status) |
| 308 | { |
| 309 | ps_frame_info = &(ps_llc_ctxt->s_frameinfo); |
| 310 | ps_recv_pkt = &(ps_frame_info->s_recvpacket); |
| 311 | ps_store_frame = &(ps_frame_info->s_send_store); |
| 312 | count = ps_frame_info->s_send_store.start_pos; |
| 313 | |
| 314 | PH_LLCNFC_DEBUG("RECEIVE length : 0x%02X\n", ps_recv_pkt->llcbuf_len); |
| 315 | PH_LLCNFC_DEBUG("SENT frame type : 0x%02X\n", ps_frame_info->sent_frame_type); |
| 316 | PH_LLCNFC_DEBUG("WRITE PENDING : 0x%02X\n", ps_frame_info->write_pending); |
| 317 | PH_LLCNFC_DEBUG("WRITE PENDING status : 0x%04X\n", ps_frame_info->write_status); |
| 318 | PH_LLCNFC_DEBUG("WRITE wait frame type : 0x%02X\n", ps_frame_info->write_wait_call); |
| 319 | PH_LLCNFC_DEBUG("NS START POS : 0x%02X\n", ps_store_frame->start_pos); |
| 320 | PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_store_frame->winsize_cnt); |
| 321 | |
| 322 | switch(ps_frame_info->sent_frame_type) |
| 323 | { |
| 324 | case init_u_rset_frame: |
| 325 | { |
| 326 | /* First U frame sent properly, update sent frame type |
| 327 | in the callback */ |
| 328 | result = phLlcNfc_Interface_Read (ps_llc_ctxt, |
| 329 | PH_LLCNFC_READWAIT_OFF, |
| 330 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 331 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 332 | |
| 333 | if (NFCSTATUS_BUSY == |
| 334 | PHNFCSTATUS (ps_frame_info->write_status)) |
| 335 | { |
| 336 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 337 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 338 | } |
| 339 | break; |
| 340 | } |
| 341 | |
| 342 | case init_u_a_frame: |
| 343 | { |
| 344 | /* First UA frame sent properly, update sent frame type |
| 345 | in the callback. Send the notification to the |
| 346 | upper layer */ |
| 347 | ps_frame_info->sent_frame_type = write_resp_received; |
| 348 | result = phLlcNfc_Interface_Read (ps_llc_ctxt, |
| 349 | PH_LLCNFC_READWAIT_OFF, |
| 350 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 351 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 352 | |
| 353 | if(NULL != ps_llc_ctxt->cb_for_if.notify) |
| 354 | { |
| 355 | notifyinfo.status = NFCSTATUS_SUCCESS; |
| 356 | ps_llc_ctxt->cb_for_if.notify ( |
| 357 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 358 | ps_llc_ctxt->phwinfo, |
| 359 | NFC_NOTIFY_INIT_COMPLETED, |
| 360 | ¬ifyinfo); |
| 361 | } |
| 362 | break; |
| 363 | } |
| 364 | |
| 365 | case u_rset_frame: |
| 366 | { |
| 367 | /* Retries has failed to work, so U frame is sent */ |
| 368 | ps_frame_info->sent_frame_type = write_resp_received; |
| 369 | |
| 370 | if (NFCSTATUS_BUSY == |
| 371 | PHNFCSTATUS (ps_frame_info->write_status)) |
| 372 | { |
| 373 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 374 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 375 | } |
| 376 | break; |
| 377 | } |
| 378 | |
| 379 | case user_i_frame: |
| 380 | { |
| 381 | /* Send complete */ |
| 382 | count = ps_frame_info->n_s; |
| 383 | |
| 384 | ps_store_frame->s_llcpacket[count].frame_to_send = |
| 385 | ps_frame_info->sent_frame_type = write_resp_received; |
| 386 | |
| 387 | /* N(S) shall be incremented now, because, this callback |
| 388 | ensures that packet is sent */ |
| 389 | count = |
| 390 | ps_frame_info->n_s = ((ps_frame_info->n_s + 1) % |
| 391 | PH_LLCNFC_MOD_NS_NR); |
| 392 | |
| 393 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 394 | PH_LLCNFC_READWAIT_OFF, |
| 395 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 396 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 397 | |
| 398 | if (NFCSTATUS_BUSY == |
| 399 | PHNFCSTATUS (ps_frame_info->write_status)) |
| 400 | { |
| 401 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 402 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 403 | } |
| 404 | |
| 405 | |
| 406 | if ((((ps_store_frame->start_pos + ps_store_frame->winsize_cnt) % |
| 407 | PH_LLCNFC_MOD_NS_NR) == ps_frame_info->n_s) && |
| 408 | (ps_frame_info->window_size == ps_store_frame->winsize_cnt)) |
| 409 | { |
| 410 | /* Don't call the upper layer send completion callback, |
| 411 | because last sent frame is the maximum that can be |
| 412 | held by LLC due to windowing |
| 413 | store the callback info, call send completion shall |
| 414 | be sent to upper layer only after the ACK is received for the |
| 415 | I frames */ |
| 416 | ps_llc_ctxt->send_cb_len = (pCompInfo->length - |
| 417 | PH_LLCNFC_APPEND_LEN); |
| 418 | } |
| 419 | else |
| 420 | { |
| 421 | /* Send completion is sent to upper layer |
| 422 | Actually, this allows the upper layer to send data, if any |
| 423 | */ |
| 424 | if (NULL != ps_llc_ctxt->cb_for_if.send_complete) |
| 425 | { |
| 426 | pCompInfo->length = (pCompInfo->length - |
| 427 | PH_LLCNFC_APPEND_LEN); |
| 428 | ps_llc_ctxt->cb_for_if.send_complete ( |
| 429 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 430 | pHwInfo, pCompInfo); |
| 431 | } |
| 432 | } |
| 433 | break; |
| 434 | } |
| 435 | |
| 436 | case s_frame: |
| 437 | { |
| 438 | #if 0 |
| 439 | uint8_t i_frame_ns_value = 0; |
| 440 | #endif /* #if 0 */ |
| 441 | /* S frame is only sent when ever a I frame is received from |
| 442 | the PN544 in the read response callback, so the received I |
| 443 | frame is acknowledged with S frame. The write response |
| 444 | callback for sent S frame is in progress. */ |
| 445 | ps_frame_info->sent_frame_type = write_resp_received; |
| 446 | |
| 447 | #if 0 |
| 448 | i_frame_ns_value = |
| 449 | ((ps_store_frame->s_llcpacket[count].s_llcbuf.sllcpayload.llcheader |
| 450 | & LLC_NS_FRAME_HEADER_MASK) >> PH_LLCNFC_NS_START_BIT_POS); |
| 451 | |
| 452 | |
| 453 | PH_LLCNFC_DEBUG("Actual ns value : 0x%02X\n", |
| 454 | i_frame_ns_value); |
| 455 | #endif /* #if 0 */ |
| 456 | |
| 457 | PH_LLCNFC_DEBUG("Window size : 0x%02X\n", |
| 458 | ps_frame_info->s_send_store.winsize_cnt); |
| 459 | PH_LLCNFC_DEBUG("frame to send : 0x%02X\n", |
| 460 | ps_store_frame->s_llcpacket[count].frame_to_send); |
| 461 | |
| 462 | if (NFCSTATUS_BUSY == |
| 463 | PHNFCSTATUS(ps_frame_info->write_status)) |
| 464 | { |
| 465 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 466 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 467 | } |
| 468 | #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB |
| 469 | phLlcNfc_H_SendInfo (ps_llc_ctxt); |
| 470 | #endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ |
| 471 | break; |
| 472 | } |
| 473 | |
| 474 | #ifdef LLC_RR_INSTEAD_OF_REJ |
| 475 | case rej_rr_s_frame: |
| 476 | { |
| 477 | if (NFCSTATUS_BUSY == |
| 478 | PHNFCSTATUS(ps_frame_info->write_status)) |
| 479 | { |
| 480 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 481 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 482 | } |
| 483 | break; |
| 484 | } |
| 485 | #endif /* #ifdef LLC_RR_INSTEAD_OF_REJ */ |
| 486 | |
| 487 | case resend_i_frame: |
| 488 | { |
| 489 | /* The code reaches here, only if stored I frame is sent |
| 490 | No changes here, but send next I frame from the stored list, |
| 491 | in the read response callback, only if proper S or I frame |
| 492 | is received from the PN544 */ |
| 493 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 494 | PH_LLCNFC_READWAIT_OFF, |
| 495 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 496 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 497 | |
| 498 | if (NFCSTATUS_BUSY == PHNFCSTATUS(ps_frame_info->write_status)) |
| 499 | { |
| 500 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 501 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 502 | } |
| 503 | |
| 504 | if (ps_store_frame->winsize_cnt == |
| 505 | ps_frame_info->window_size) |
| 506 | { |
| 507 | /* Don't call the upper layer send completion callback, |
| 508 | store the callback info, call send completion after |
| 509 | ack for written frame |
| 510 | ps_llc_ctxt->send_cb_len = pCompInfo->length; */ |
| 511 | } |
| 512 | else |
| 513 | { |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 514 | /* ***** This notification needs to be disabled ***** */ |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 515 | if(NULL != ps_llc_ctxt->cb_for_if.send_complete) |
| 516 | { |
| 517 | pCompInfo->length = (pCompInfo->length - |
| 518 | PH_LLCNFC_APPEND_LEN); |
| 519 | ps_llc_ctxt->cb_for_if.send_complete( |
| 520 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 521 | pHwInfo, pCompInfo); |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | if(user_i_frame == |
| 526 | ps_store_frame->s_llcpacket[count].frame_to_send) |
| 527 | { |
| 528 | /* Send complete */ |
| 529 | ps_store_frame->s_llcpacket[count].frame_to_send = |
| 530 | resend_i_frame; |
| 531 | } |
| 532 | break; |
| 533 | } |
| 534 | |
| 535 | case rejected_i_frame: |
| 536 | { |
| 537 | /* Update the sent frame type, if window size count is 0 */ |
| 538 | ps_frame_info->sent_frame_type = write_resp_received; |
| 539 | /* The code enters here, whenever a I frame is resent and for |
| 540 | this resent I frame, an I frame received from PN544. |
| 541 | So the S frame is sent as the acknowledgment */ |
| 542 | if (NFCSTATUS_BUSY == |
| 543 | PHNFCSTATUS(ps_frame_info->write_status)) |
| 544 | { |
| 545 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 546 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 547 | } |
| 548 | break; |
| 549 | } |
| 550 | |
| 551 | case resend_s_frame: |
| 552 | { |
| 553 | /* Update the sent frame type, if window size count is 0 */ |
| 554 | ps_frame_info->sent_frame_type = write_resp_received; |
| 555 | /* The code enters here, whenever a I frame is resent and for |
| 556 | this resent I frame, an I frame received from PN544. |
| 557 | So the S frame is sent as the acknowledgment */ |
| 558 | if (NFCSTATUS_BUSY == |
| 559 | PHNFCSTATUS(ps_frame_info->write_status)) |
| 560 | { |
| 561 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 562 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 563 | } |
| 564 | |
| 565 | #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB |
| 566 | phLlcNfc_H_SendInfo (ps_llc_ctxt); |
| 567 | #endif /* #ifdef LLC_UPP_LAYER_NTFY_WRITE_RSP_CB */ |
| 568 | break; |
| 569 | } |
| 570 | |
| 571 | case reject_s_frame: |
| 572 | { |
| 573 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 574 | PH_LLCNFC_READWAIT_OFF, |
| 575 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 576 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 577 | |
| 578 | if (NFCSTATUS_BUSY == |
| 579 | PHNFCSTATUS(ps_frame_info->write_status)) |
| 580 | { |
| 581 | ps_frame_info->write_status = NFCSTATUS_PENDING; |
| 582 | result = phLlcNfc_H_WriteWaitCall (ps_llc_ctxt); |
| 583 | } |
| 584 | break; |
| 585 | } |
| 586 | |
| 587 | case u_a_frame: |
| 588 | { |
| 589 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 590 | PH_LLCNFC_READWAIT_OFF, |
| 591 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 592 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 593 | |
| 594 | PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt); |
| 595 | |
| 596 | if(ps_frame_info->s_send_store.winsize_cnt > 0) |
| 597 | { |
| 598 | result = phLlcNfc_H_SendUserIFrame (ps_llc_ctxt, |
| 599 | &(ps_frame_info->s_send_store)); |
| 600 | } |
| 601 | break; |
| 602 | } |
| 603 | |
| 604 | case resend_rej_s_frame: |
| 605 | { |
| 606 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 607 | PH_LLCNFC_READWAIT_OFF, |
| 608 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 609 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 610 | |
| 611 | PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt); |
| 612 | |
| 613 | if(ps_frame_info->s_send_store.winsize_cnt > 0) |
| 614 | { |
| 615 | result = phLlcNfc_H_SendTimedOutIFrame (ps_llc_ctxt, |
| 616 | &(ps_frame_info->s_send_store), 0); |
| 617 | } |
| 618 | break; |
| 619 | } |
| 620 | |
| 621 | default : |
| 622 | { |
| 623 | break; |
| 624 | } |
| 625 | } |
| 626 | } |
| 627 | else |
| 628 | { |
| 629 | /* Write not successful */ |
| 630 | if(NULL != ps_llc_ctxt->cb_for_if.send_complete) |
| 631 | { |
| 632 | phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER, |
| 633 | ps_llc_ctxt->s_timerinfo.guard_to_count); |
| 634 | PH_LLCNFC_DEBUG("Error status received : 0x%x\n", pCompInfo->status); |
| 635 | ps_llc_ctxt->cb_for_if.send_complete( |
| 636 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 637 | pHwInfo, pCompInfo); |
| 638 | } |
| 639 | } |
| 640 | } |
| 641 | PH_LLCNFC_PRINT("\n\nLLC : WRITE RESP CB END\n\n"); |
| 642 | } |
| 643 | |
| 644 | static |
| 645 | void |
| 646 | phLlcNfc_RdResp_Cb( |
| 647 | void *pContext, |
| 648 | void *pHwInfo, |
| 649 | phNfc_sTransactionInfo_t *pCompInfo |
| 650 | ) |
| 651 | { |
| 652 | /* |
| 653 | 1. LLC Receive has been called by the upper layer, the response |
| 654 | for this function is called by the lower layer |
| 655 | 2. Get the frame information from the receive buffer |
| 656 | 3. Depending on the received frame type, process the received |
| 657 | buffer |
| 658 | */ |
| 659 | NFCSTATUS result = NFCSTATUS_SUCCESS; |
| 660 | phLlcNfc_Context_t *ps_llc_ctxt = (phLlcNfc_Context_t*)pContext; |
| 661 | void *p_upperctxt = NULL; |
| 662 | uint8_t crc1 = 0, |
| 663 | crc2 = 0; |
| 664 | phLlcNfc_Frame_t *ps_frame_info = NULL; |
| 665 | phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; |
| 666 | phLlcNfc_Payload_t *ps_llc_payload = NULL; |
| 667 | pphNfcIF_Notification_CB_t notifyul = NULL; |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 668 | phNfc_sCompletionInfo_t notifyinfo = {0,0,0}; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 669 | |
| 670 | PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB CALLED\n\n"); |
| 671 | |
| 672 | if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) && (NULL != pHwInfo) |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 673 | && (NULL != pCompInfo->buffer)) |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 674 | { |
| 675 | ps_frame_info = &(ps_llc_ctxt->s_frameinfo); |
| 676 | ps_recv_pkt = &(ps_frame_info->s_recvpacket); |
| 677 | ps_llc_payload = &(ps_recv_pkt->s_llcbuf.sllcpayload); |
| 678 | |
| 679 | ps_llc_ctxt->s_frameinfo.read_pending = PH_LLCNFC_READPEND_FLAG_OFF; |
| 680 | |
| 681 | if (NFCSTATUS_SUCCESS == pCompInfo->status) |
| 682 | { |
| 683 | if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) && |
| 684 | (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < *(pCompInfo->buffer)) && |
| 685 | (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > *(pCompInfo->buffer)))) |
| 686 | { |
| 687 | PH_LLCNFC_PRINT("Buffer received : \n"); |
| 688 | PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length); |
| 689 | |
| 690 | #if 0 |
| 691 | /* Received length is 1 and receive buffer |
| 692 | contains the length field which is greater than 2, |
| 693 | so read the remaining bytes*/ |
| 694 | ps_recv_pkt->s_llcbuf.llc_length_byte = pCompInfo->buffer[0]; |
| 695 | #endif |
| 696 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 697 | PH_LLCNFC_READWAIT_OFF, |
| 698 | (uint8_t *)ps_llc_payload, |
| 699 | (uint32_t)(ps_recv_pkt->s_llcbuf.llc_length_byte)); |
| 700 | |
| 701 | if ((init_u_rset_frame == ps_frame_info->sent_frame_type) && |
| 702 | (NFCSTATUS_PENDING != result) && |
| 703 | (NULL != ps_llc_ctxt->cb_for_if.notify)) |
| 704 | { |
| 705 | PH_LLCNFC_PRINT("Initialised error\n"); |
| 706 | notifyinfo.status = result; |
| 707 | /* Copy the upper layer callback pointer and the upper |
| 708 | layer context, after that call release */ |
| 709 | notifyul = ps_llc_ctxt->cb_for_if.notify; |
| 710 | p_upperctxt = ps_llc_ctxt->cb_for_if.pif_ctxt; |
| 711 | result = phLlcNfc_Release(ps_llc_ctxt, pHwInfo); |
| 712 | |
| 713 | /* Wrong result, so Init failed sent */ |
| 714 | notifyul(p_upperctxt, pHwInfo, |
| 715 | NFC_NOTIFY_INIT_FAILED, ¬ifyinfo); |
| 716 | } |
| 717 | } |
| 718 | else if (TRUE == ps_llc_ctxt->s_frameinfo.write_pending) |
| 719 | { |
| 720 | /* Ignore the bytes as write is not complete and |
| 721 | pend a read for reading 1 byte */ |
| 722 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 723 | PH_LLCNFC_READWAIT_OFF, |
| 724 | (uint8_t *)&( |
| 725 | ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 726 | PH_LLCNFC_MIN_BUFLEN_RECVD); |
| 727 | } |
| 728 | else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) && |
| 729 | (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) && |
| 730 | (pCompInfo->length == ps_recv_pkt->s_llcbuf.llc_length_byte)) |
| 731 | { |
| 732 | PH_LLCNFC_PRINT("Buffer received : \n"); |
| 733 | PH_LLCNFC_PRINT_BUFFER(pCompInfo->buffer, pCompInfo->length); |
| 734 | PH_LLCNFC_DEBUG("WIN SIZE : 0x%02X\n", ps_frame_info->s_send_store.winsize_cnt); |
| 735 | |
| 736 | /* Receive is complete, so move the state to INITIALISED */ |
| 737 | if (phLlcNfc_Resend_State != ps_llc_ctxt->state) |
| 738 | { |
| 739 | result = phLlcNfc_H_ChangeState(ps_llc_ctxt, |
| 740 | phLlcNfc_Initialised_State); |
| 741 | } |
| 742 | /* Copy the received buffer and length */ |
| 743 | ps_recv_pkt->llcbuf_len = (uint8_t) |
| 744 | (ps_recv_pkt->s_llcbuf.llc_length_byte + 1); |
| 745 | #if 0 |
| 746 | (void)memcpy(ps_llc_payload, pCompInfo->buffer, |
| 747 | pCompInfo->length); |
| 748 | #endif |
| 749 | |
| 750 | /* |
| 751 | Check the CRC |
| 752 | ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf : |
| 753 | consists llc length byte + llc header + data + CRC |
| 754 | (which needs to be calculated by the below function) |
| 755 | ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len : |
| 756 | Total length of the above buffer |
| 757 | ps_llc_ctxt->s_frameinfo.s_recvpacket.llcbuf_len - 2 : |
| 758 | -2 because the CRC has to be calculated, only for the |
| 759 | bytes which has llc length byte + llc header + data. |
| 760 | But total length (llcbuf_len) consists of above mentioned |
| 761 | things with 2 byte CRC |
| 762 | ps_llc_ctxt->s_frameinfo.s_recvpacket.s_llcbuf.sllcpayload.llcpayload : |
| 763 | consists only data (no length byte and no llc header) |
| 764 | (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 4) : |
| 765 | is the array index of the first CRC byte to be calculated |
| 766 | (psllcctxt->s_frameinfo.s_recvpacket.llcbuf_len - 3) : |
| 767 | is the array index of the second CRC byte to be calculated |
| 768 | */ |
| 769 | phLlcNfc_H_ComputeCrc((uint8_t *)&(ps_recv_pkt->s_llcbuf), |
| 770 | (ps_recv_pkt->llcbuf_len - 2), |
| 771 | &crc1, &crc2); |
| 772 | |
| 773 | if ((crc1 == ps_llc_payload->llcpayload[ |
| 774 | (ps_recv_pkt->llcbuf_len - 4)]) |
| 775 | && (crc2 == ps_llc_payload->llcpayload[ |
| 776 | (ps_recv_pkt->llcbuf_len - 3)])) |
| 777 | { |
| 778 | result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt); |
| 779 | } |
| 780 | #ifdef LLC_DISABLE_CRC |
| 781 | else |
| 782 | { |
| 783 | result = phLlcNfc_H_ProRecvFrame(ps_llc_ctxt); |
| 784 | } |
| 785 | #else |
| 786 | else if (ps_frame_info->recv_error_count < |
| 787 | PH_LLCNFC_MAX_REJ_RETRY_COUNT) |
| 788 | { |
Steve Block | 113bdd7 | 2012-01-05 23:18:54 +0000 | [diff] [blame] | 789 | ALOGW("LLC bad crc"); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 790 | PH_LLCNFC_PRINT("CRC ERROR RECVD \n"); |
| 791 | PH_LLCNFC_DEBUG("RECV ERROR COUNT : 0x%02X\n", ps_frame_info->recv_error_count); |
| 792 | |
| 793 | ps_frame_info->recv_error_count = (uint8_t) |
| 794 | (ps_frame_info->recv_error_count + 1); |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 795 | libnfc_llc_error_count++; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 796 | |
| 797 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 798 | PH_LLCNFC_READWAIT_OFF, |
| 799 | (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 800 | PH_LLCNFC_BYTES_INIT_READ); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 801 | #ifdef CRC_ERROR_REJ |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 802 | /* Send REJ (S frame), as the CRC received has error */ |
| 803 | result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt); |
| 804 | |
| 805 | #endif /* #ifdef CRC_ERROR_REJ */ |
| 806 | |
| 807 | } |
| 808 | else |
| 809 | { |
Steve Block | a12acb1 | 2012-01-06 19:10:18 +0000 | [diff] [blame] | 810 | ALOGE("max LLC retries exceeded, stack restart"); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 811 | result = phLlcNfc_Interface_Read (ps_llc_ctxt, |
| 812 | PH_LLCNFC_READWAIT_OFF, |
| 813 | (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 814 | PH_LLCNFC_BYTES_INIT_READ); |
| 815 | |
| 816 | /* Raise the exception for CRC error received from the */ |
| 817 | notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, |
| 818 | NFCSTATUS_BOARD_COMMUNICATION_ERROR); |
| 819 | #if 0 |
| 820 | phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); |
| 821 | #endif /* #if 0 */ |
| 822 | /* Resend done, no answer from the device */ |
| 823 | ps_llc_ctxt->cb_for_if.notify ( |
| 824 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 825 | ps_llc_ctxt->phwinfo, |
| 826 | NFC_NOTIFY_DEVICE_ERROR, |
| 827 | ¬ifyinfo); |
| 828 | } |
| 829 | |
| 830 | #endif /* #ifdef LLC_DISABLE_CRC */ |
| 831 | } /* read more than 1 byte */ |
| 832 | else if (ps_frame_info->recv_error_count >= |
| 833 | PH_LLCNFC_MAX_REJ_RETRY_COUNT) |
| 834 | { |
Steve Block | a12acb1 | 2012-01-06 19:10:18 +0000 | [diff] [blame] | 835 | ALOGE("max LLC retries exceeded, stack restart"); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 836 | result = phLlcNfc_Interface_Read (ps_llc_ctxt, |
| 837 | PH_LLCNFC_READWAIT_OFF, |
| 838 | (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 839 | PH_LLCNFC_BYTES_INIT_READ); |
| 840 | |
| 841 | /* Raise the exception for CRC error received from the */ |
| 842 | notifyinfo.status = PHNFCSTVAL(CID_NFC_LLC, |
| 843 | NFCSTATUS_BOARD_COMMUNICATION_ERROR); |
| 844 | #if 0 |
| 845 | phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); |
| 846 | #endif /* #if 0 */ |
| 847 | /* Resend done, no answer from the device */ |
| 848 | ps_llc_ctxt->cb_for_if.notify ( |
| 849 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 850 | ps_llc_ctxt->phwinfo, |
| 851 | NFC_NOTIFY_DEVICE_ERROR, |
| 852 | ¬ifyinfo); |
| 853 | } |
| 854 | else if (((PH_LLCNFC_MIN_BUFLEN_RECVD + 1) < pCompInfo->length) && |
| 855 | (PH_LLCNFC_MAX_BUFLEN_RECV_SEND > pCompInfo->length) && |
| 856 | (pCompInfo->length != ps_recv_pkt->s_llcbuf.llc_length_byte)) |
| 857 | { |
Steve Block | a12acb1 | 2012-01-06 19:10:18 +0000 | [diff] [blame] | 858 | ALOGE("bad LLC length1 %d", pCompInfo->length); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 859 | ps_frame_info->recv_error_count = (uint8_t) |
| 860 | (ps_frame_info->recv_error_count + 1); |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 861 | libnfc_llc_error_count++; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 862 | |
| 863 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 864 | PH_LLCNFC_READWAIT_OFF, |
| 865 | (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 866 | PH_LLCNFC_BYTES_INIT_READ); |
| 867 | |
| 868 | #ifdef CRC_ERROR_REJ |
| 869 | |
| 870 | /* Send REJ (S frame), as the CRC received has error */ |
| 871 | result = phLlcNfc_H_SendRejectFrame (ps_llc_ctxt); |
| 872 | |
| 873 | #endif /* #ifdef CRC_ERROR_REJ */ |
| 874 | } |
| 875 | else if ((PH_LLCNFC_MIN_BUFLEN_RECVD == pCompInfo->length) && |
| 876 | ((*(pCompInfo->buffer) > (PH_LLCNFC_MAX_BUFLEN_RECV_SEND - 1)) |
| 877 | ||(*(pCompInfo->buffer) <= (PH_LLCNFC_MIN_BUFLEN_RECVD + 1)))) |
| 878 | { |
| 879 | /* Temporary fix for the 0xFF data received |
| 880 | Solution for the read one byte, giving error in buffer |
| 881 | PH_LLCNFC_MAX_BUFLEN_RECV_SEND (0x21) is the maximum |
| 882 | bytes expected by LLC, if the buffer |
| 883 | value is greater than (0x21 - 1), then pend a read to |
| 884 | get 1 byte again |
| 885 | */ |
Steve Block | 113bdd7 | 2012-01-05 23:18:54 +0000 | [diff] [blame] | 886 | ALOGW("bad LLC length byte %x\n", *(pCompInfo->buffer)); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 887 | ps_frame_info->recv_error_count = (uint8_t) |
| 888 | (ps_frame_info->recv_error_count + 1); |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 889 | libnfc_llc_error_count++; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 890 | |
| 891 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 892 | PH_LLCNFC_READWAIT_OFF, |
| 893 | (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 894 | PH_LLCNFC_BYTES_INIT_READ); |
| 895 | } |
| 896 | else |
| 897 | { |
Steve Block | 113bdd7 | 2012-01-05 23:18:54 +0000 | [diff] [blame] | 898 | ALOGW("unknown LLC error1"); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 899 | ps_frame_info->recv_error_count = (uint8_t) |
| 900 | (ps_frame_info->recv_error_count + 1); |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 901 | libnfc_llc_error_count++; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 902 | |
| 903 | phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER, |
| 904 | ps_llc_ctxt->s_timerinfo.guard_to_count); |
| 905 | pCompInfo->status = PHNFCSTVAL(CID_NFC_LLC, |
| 906 | NFCSTATUS_INVALID_FORMAT); |
| 907 | pCompInfo->buffer = NULL; |
| 908 | pCompInfo->length = 0; |
| 909 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 910 | PH_LLCNFC_READWAIT_OFF, |
| 911 | (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 912 | PH_LLCNFC_BYTES_INIT_READ); |
| 913 | if (NULL != ps_llc_ctxt->cb_for_if.receive_complete) |
| 914 | { |
| 915 | ps_llc_ctxt->cb_for_if.receive_complete( |
| 916 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 917 | pHwInfo, pCompInfo); |
| 918 | } |
| 919 | } |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 920 | } else if (NFCSTATUS_READ_FAILED == pCompInfo->status) { |
| 921 | // partial read - try reading the length byte again |
Vladislav Koldobskiy | 978e1ce | 2014-06-06 20:39:37 +0400 | [diff] [blame] | 922 | ALOGV("LLC length mis-match\n"); |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 923 | ps_frame_info->recv_error_count = (uint8_t) |
| 924 | (ps_frame_info->recv_error_count + 1); |
| 925 | libnfc_llc_error_count++; |
| 926 | |
| 927 | result = phLlcNfc_Interface_Read(ps_llc_ctxt, |
| 928 | PH_LLCNFC_READWAIT_OFF, |
| 929 | (uint8_t *)&(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 930 | PH_LLCNFC_BYTES_INIT_READ); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 931 | } |
| 932 | else |
| 933 | { |
Steve Block | 113bdd7 | 2012-01-05 23:18:54 +0000 | [diff] [blame] | 934 | ALOGW("unknown LLC error2"); |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 935 | ps_frame_info->recv_error_count = (uint8_t) |
| 936 | (ps_frame_info->recv_error_count + 1); |
Nick Pelly | 5ea62ad | 2011-10-19 18:36:47 -0700 | [diff] [blame] | 937 | libnfc_llc_error_count++; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 938 | |
| 939 | phLlcNfc_StopTimers(PH_LLCNFC_GUARDTIMER, |
| 940 | ps_llc_ctxt->s_timerinfo.guard_to_count); |
| 941 | PH_LLCNFC_DEBUG("Status Error : 0x%x\n", pCompInfo->status); |
| 942 | if (NULL != ps_llc_ctxt->cb_for_if.receive_complete) |
| 943 | { |
| 944 | ps_llc_ctxt->cb_for_if.receive_complete( |
| 945 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 946 | pHwInfo, pCompInfo); |
| 947 | } |
| 948 | } |
| 949 | } |
| 950 | else |
| 951 | { |
| 952 | if ((NULL != ps_llc_ctxt) && (NULL != pCompInfo) |
| 953 | && (NULL != ps_llc_ctxt->cb_for_if.receive_complete)) |
| 954 | { |
| 955 | ps_llc_ctxt->cb_for_if.receive_complete( |
| 956 | ps_llc_ctxt->cb_for_if.pif_ctxt, |
| 957 | pHwInfo, pCompInfo); |
| 958 | } |
| 959 | } |
| 960 | |
| 961 | PH_LLCNFC_PRINT("\n\nLLC : READ RESP CB END\n\n"); |
| 962 | } |
| 963 | |
| 964 | void |
| 965 | phLlcNfc_H_SendInfo ( |
| 966 | phLlcNfc_Context_t *psLlcCtxt |
| 967 | ) |
| 968 | { |
| 969 | phLlcNfc_LlcPacket_t *ps_recv_pkt = NULL; |
| 970 | phLlcNfc_Frame_t *ps_frame_info = NULL; |
Daniel Tomas | b313c3d | 2011-05-26 15:52:17 +0200 | [diff] [blame] | 971 | phNfc_sTransactionInfo_t comp_info = {0,0,0,0,0}; |
Nick Pelly | 5d9927b | 2010-09-23 12:47:58 -0700 | [diff] [blame] | 972 | |
| 973 | ps_frame_info = &(psLlcCtxt->s_frameinfo); |
| 974 | ps_recv_pkt = &(ps_frame_info->s_recvpacket); |
| 975 | |
| 976 | if ((ps_recv_pkt->llcbuf_len > 0) && |
| 977 | (ps_recv_pkt->llcbuf_len <= PH_LLCNFC_MAX_LLC_PAYLOAD)) |
| 978 | { |
| 979 | comp_info.status = NFCSTATUS_SUCCESS; |
| 980 | /* Chop the extra Llc bytes received */ |
| 981 | #if 0 |
| 982 | comp_info.length = (ps_recv_pkt->llcbuf_len - |
| 983 | PH_LLCNFC_LEN_APPEND); |
| 984 | #else |
| 985 | comp_info.length = (uint16_t)psLlcCtxt->recvbuf_length; |
| 986 | #endif /* */ |
| 987 | |
| 988 | if (0 != comp_info.length) |
| 989 | { |
| 990 | #if 0 |
| 991 | (void)memcpy ((void *)psLlcCtxt->precv_buf, (void *)( |
| 992 | ps_recv_pkt->s_llcbuf.sllcpayload.llcpayload), |
| 993 | comp_info.length); |
| 994 | #endif /* #if 0 */ |
| 995 | comp_info.buffer = psLlcCtxt->precv_buf; |
| 996 | } |
| 997 | else |
| 998 | { |
| 999 | comp_info.buffer = NULL; |
| 1000 | } |
| 1001 | } |
| 1002 | else |
| 1003 | { |
| 1004 | comp_info.status = PHNFCSTVAL(CID_NFC_LLC, |
| 1005 | NFCSTATUS_INVALID_FORMAT); |
| 1006 | comp_info.length = 0; |
| 1007 | comp_info.buffer = NULL; |
| 1008 | } |
| 1009 | |
| 1010 | (void)phLlcNfc_Interface_Read(psLlcCtxt, |
| 1011 | PH_LLCNFC_READWAIT_OFF, |
| 1012 | &(ps_recv_pkt->s_llcbuf.llc_length_byte), |
| 1013 | (uint8_t)PH_LLCNFC_BYTES_INIT_READ); |
| 1014 | |
| 1015 | if ((NFCSTATUS_SUCCESS == comp_info.status) && |
| 1016 | (0 == comp_info.length)) |
| 1017 | { |
| 1018 | /* May be a NULL I frame received from PN544, so dont do |
| 1019 | any thing */ |
| 1020 | } |
| 1021 | else |
| 1022 | { |
| 1023 | if ((NULL != psLlcCtxt->cb_for_if.receive_complete) && |
| 1024 | (TRUE == ps_frame_info->upper_recv_call)) |
| 1025 | { |
| 1026 | ps_frame_info->upper_recv_call = FALSE; |
| 1027 | psLlcCtxt->cb_for_if.receive_complete( |
| 1028 | psLlcCtxt->cb_for_if.pif_ctxt, |
| 1029 | psLlcCtxt->phwinfo, |
| 1030 | &comp_info); |
| 1031 | } |
| 1032 | else |
| 1033 | { |
| 1034 | if (NULL != psLlcCtxt->cb_for_if.notify) |
| 1035 | { |
| 1036 | psLlcCtxt->cb_for_if.notify( |
| 1037 | psLlcCtxt->cb_for_if.pif_ctxt, |
| 1038 | psLlcCtxt->phwinfo, |
| 1039 | NFC_NOTIFY_RECV_COMPLETED, |
| 1040 | &comp_info); |
| 1041 | } |
| 1042 | } |
| 1043 | } |
| 1044 | return; |
| 1045 | } |
| 1046 | |