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 /*! 19 * =========================================================================== * 20 * * 21 * * 22 * \file phHciNfc_LinkMgmt.c * 23 * \brief HCI Link Management Gate Routines. * 24 * * 25 * * 26 * Project: NFC-FRI-1.1 * 27 * * 28 * $Date: Thu Feb 11 18:52:19 2010 $ * 29 * $Author: ing04880 $ * 30 * $Revision: 1.11 $ * 31 * $Aliases: NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ * 32 * * 33 * =========================================================================== * 34 */ 35 36 /* 37 ***************************** Header File Inclusion **************************** 38 */ 39 #include <phNfcCompId.h> 40 #include <phHciNfc_Pipe.h> 41 #include <phHciNfc_LinkMgmt.h> 42 #include <phOsalNfc.h> 43 44 /* 45 ****************************** Macro Definitions ******************************* 46 */ 47 48 #define REC_ERROR_INDEX 0x01U 49 50 #define REC_RETRY_LEN 0x02U 51 52 /* 53 *************************** Structure and Enumeration *************************** 54 */ 55 56 57 /** \defgroup grp_hci_nfc HCI Link Management Component 58 * 59 * 60 */ 61 62 typedef enum phHciNfc_LinkMgmt_Seq{ 63 LINK_MGMT_PIPE_OPEN = 0x00U, 64 LINK_MGMT_GET_REC_ERROR, 65 LINK_MGMT_SET_REC_ERROR, 66 LINK_MGMT_PIPE_CLOSE 67 } phHciNfc_LinkMgmt_Seq_t; 68 69 typedef struct phHciNfc_LinkMgmt_Info{ 70 phHciNfc_LinkMgmt_Seq_t link_cur_seq; 71 phHciNfc_LinkMgmt_Seq_t link_next_seq; 72 phHciNfc_Pipe_Info_t *p_pipe_info; 73 /* Rec Error Count Number from the Host Controller */ 74 uint16_t hc_rec_error; 75 /* Rec Error Count Number of the Terminal Host */ 76 uint16_t rec_error; 77 } phHciNfc_LinkMgmt_Info_t; 78 79 80 /* 81 *************************** Static Function Declaration ************************** 82 */ 83 84 static 85 NFCSTATUS 86 phHciNfc_LinkMgmt_InfoUpdate( 87 phHciNfc_sContext_t *psHciContext, 88 phHal_sHwReference_t *pHwRef, 89 uint8_t index, 90 uint8_t *reg_value, 91 uint8_t reg_length 92 ); 93 static 94 NFCSTATUS 95 phHciNfc_Recv_LinkMgmt_Response( 96 void *psHciContext, 97 void *pHwRef, 98 uint8_t *pResponse, 99 #ifdef ONE_BYTE_LEN 100 uint8_t length 101 #else 102 uint16_t length 103 #endif 104 ); 105 106 107 /* 108 *************************** Function Definitions *************************** 109 */ 110 111 112 113 114 /*! 115 * \brief Initialisation of Link Managment Gate. 116 * 117 * This function initialses the Link Management gate and 118 * populates the Link Management Information Structure 119 * 120 */ 121 122 NFCSTATUS 123 phHciNfc_LinkMgmt_Initialise( 124 phHciNfc_sContext_t *psHciContext, 125 void *pHwRef 126 ) 127 { 128 NFCSTATUS status = NFCSTATUS_SUCCESS; 129 phHciNfc_Pipe_Info_t *p_pipe_info = NULL; 130 phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; 131 uint8_t link_pipe_id = (uint8_t)HCI_UNKNOWN_PIPE_ID; 132 133 if( ( NULL == psHciContext ) 134 || (NULL == pHwRef ) 135 ) 136 { 137 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); 138 } 139 else 140 { 141 if( ( NULL == psHciContext->p_link_mgmt_info ) 142 && (phHciNfc_Allocate_Resource((void **)(&p_link_mgmt_info), 143 sizeof(phHciNfc_LinkMgmt_Info_t))== NFCSTATUS_SUCCESS) 144 ) 145 { 146 psHciContext->p_link_mgmt_info = p_link_mgmt_info; 147 p_link_mgmt_info->link_cur_seq = LINK_MGMT_PIPE_OPEN; 148 p_link_mgmt_info->link_next_seq = LINK_MGMT_PIPE_OPEN; 149 p_link_mgmt_info->p_pipe_info = NULL; 150 } 151 else 152 { 153 p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) 154 psHciContext->p_link_mgmt_info ; 155 } 156 157 if( NULL == p_link_mgmt_info ) 158 { 159 status = PHNFCSTVAL(CID_NFC_HCI, 160 NFCSTATUS_INVALID_HCI_INFORMATION); 161 } 162 #ifdef ESTABLISH_SESSION 163 else if( hciMode_Session == psHciContext->hci_mode ) 164 { 165 status = NFCSTATUS_SUCCESS; 166 } 167 #endif 168 else 169 { 170 switch(p_link_mgmt_info->link_cur_seq ) 171 { 172 /* Link Mgmt pipe open sequence */ 173 case LINK_MGMT_PIPE_OPEN: 174 { 175 if(phHciNfc_Allocate_Resource((void **)(&p_pipe_info), 176 sizeof(phHciNfc_Pipe_Info_t))!= NFCSTATUS_SUCCESS) 177 { 178 status = PHNFCSTVAL(CID_NFC_HCI, 179 NFCSTATUS_INSUFFICIENT_RESOURCES); 180 } 181 else 182 { 183 /* Populate the pipe information in the pipe handle */ 184 ((phHciNfc_Pipe_Info_t *)p_pipe_info)->pipe.pipe_id = 185 PIPETYPE_STATIC_LINK; 186 ((phHciNfc_Pipe_Info_t *)p_pipe_info)->recv_resp = 187 &phHciNfc_Recv_LinkMgmt_Response; 188 psHciContext->p_pipe_list[PIPETYPE_STATIC_LINK] = 189 p_pipe_info ; 190 status = phHciNfc_Open_Pipe( psHciContext, 191 pHwRef,p_pipe_info ); 192 if(status == NFCSTATUS_SUCCESS) 193 { 194 p_link_mgmt_info->p_pipe_info = p_pipe_info ; 195 p_link_mgmt_info->link_next_seq = 196 LINK_MGMT_GET_REC_ERROR; 197 status = NFCSTATUS_PENDING; 198 } 199 } 200 break; 201 } 202 case LINK_MGMT_GET_REC_ERROR: 203 { 204 p_pipe_info = p_link_mgmt_info->p_pipe_info; 205 if(NULL == p_pipe_info ) 206 { 207 status = PHNFCSTVAL(CID_NFC_HCI, 208 NFCSTATUS_INVALID_HCI_SEQUENCE); 209 } 210 else 211 { 212 p_pipe_info->reg_index = REC_ERROR_INDEX; 213 link_pipe_id = PIPETYPE_STATIC_LINK ; 214 status = 215 phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, 216 link_pipe_id, (uint8_t)ANY_GET_PARAMETER ); 217 if(NFCSTATUS_PENDING == status ) 218 { 219 p_link_mgmt_info->link_next_seq = 220 LINK_MGMT_PIPE_CLOSE; 221 status = NFCSTATUS_SUCCESS; 222 } 223 } 224 break; 225 } 226 case LINK_MGMT_SET_REC_ERROR: 227 { 228 p_pipe_info = p_link_mgmt_info->p_pipe_info; 229 if(NULL == p_pipe_info ) 230 { 231 status = PHNFCSTVAL(CID_NFC_HCI, 232 NFCSTATUS_INVALID_HCI_SEQUENCE); 233 } 234 else 235 { 236 p_pipe_info->reg_index = REC_ERROR_INDEX; 237 link_pipe_id = PIPETYPE_STATIC_LINK ; 238 status = 239 phHciNfc_Send_Generic_Cmd( psHciContext, pHwRef, 240 link_pipe_id, (uint8_t)ANY_GET_PARAMETER ); 241 if(NFCSTATUS_PENDING == status ) 242 { 243 p_link_mgmt_info->link_next_seq = 244 LINK_MGMT_PIPE_CLOSE; 245 status = NFCSTATUS_SUCCESS; 246 } 247 } 248 break; 249 } 250 default: 251 { 252 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_SEQUENCE); 253 break; 254 } 255 256 }/* End of the Sequence Switch */ 257 258 }/* End of the Link Info Memory Check */ 259 } /* End of Null Context Check */ 260 261 return status; 262 } 263 264 /*! 265 * \brief Opens the Link Management Pipe of the Link Management Gate. 266 * 267 * This function Opens the Link Management Pipe of the Link Management 268 * Gate and Confirms that the HCI Link is behaving as expected. 269 */ 270 271 NFCSTATUS 272 phHciNfc_LinkMgmt_Open( 273 phHciNfc_sContext_t *psHciContext, 274 void *pHwRef 275 ) 276 { 277 NFCSTATUS status = NFCSTATUS_SUCCESS; 278 279 if( (NULL == psHciContext) || (NULL == pHwRef) ) 280 { 281 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); 282 } 283 else 284 { 285 phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info= 286 (phHciNfc_LinkMgmt_Info_t *)psHciContext->p_link_mgmt_info ; 287 if(( NULL != p_link_mgmt_info ) && 288 ( NULL != p_link_mgmt_info->p_pipe_info )) 289 { 290 status = phHciNfc_Open_Pipe( psHciContext, 291 pHwRef, p_link_mgmt_info->p_pipe_info ); 292 if(status == NFCSTATUS_SUCCESS) 293 { 294 status = NFCSTATUS_PENDING; 295 } 296 } 297 else 298 { 299 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED); 300 301 }/* End of the Identity Info Memory Check */ 302 303 } /* End of Null Context Check */ 304 305 return status; 306 } 307 308 309 NFCSTATUS 310 phHciNfc_LinkMgmt_Release( 311 phHciNfc_sContext_t *psHciContext, 312 void *pHwRef 313 ) 314 { 315 NFCSTATUS status = NFCSTATUS_SUCCESS; 316 phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; 317 318 if( (NULL == psHciContext) || (NULL == pHwRef) ) 319 { 320 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); 321 } 322 else 323 { 324 if( NULL != psHciContext->p_link_mgmt_info ) 325 { 326 p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) 327 psHciContext->p_link_mgmt_info ; 328 status = phHciNfc_Close_Pipe( psHciContext, 329 pHwRef, p_link_mgmt_info->p_pipe_info ); 330 } 331 else 332 { 333 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_NOT_ALLOWED); 334 335 }/* End of the Identity Info Memory Check */ 336 337 338 } /* End of Null Context Check */ 339 340 return status; 341 } 342 343 344 /*! 345 * \brief Receives the HCI Response from the corresponding peripheral device. 346 * 347 * This function receives the HCI Command Response from the connected NFC 348 * Pheripheral device. 349 */ 350 static 351 NFCSTATUS 352 phHciNfc_Recv_LinkMgmt_Response( 353 void *psContext, 354 void *pHwRef, 355 uint8_t *pResponse, 356 #ifdef ONE_BYTE_LEN 357 uint8_t length 358 #else 359 uint16_t length 360 #endif 361 ) 362 { 363 phHciNfc_sContext_t *psHciContext = 364 (phHciNfc_sContext_t *)psContext ; 365 phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; 366 NFCSTATUS status = NFCSTATUS_SUCCESS; 367 uint8_t prev_cmd = ANY_GET_PARAMETER; 368 369 if( (NULL == psHciContext) || (NULL == pHwRef) ) 370 { 371 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); 372 } 373 else if( NULL == psHciContext->p_link_mgmt_info ) 374 { 375 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_FEATURE_NOT_SUPPORTED); 376 } 377 else 378 { 379 p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) 380 psHciContext->p_link_mgmt_info ; 381 prev_cmd = p_link_mgmt_info->p_pipe_info->prev_msg ; 382 switch(prev_cmd) 383 { 384 case ANY_GET_PARAMETER: 385 { 386 status = phHciNfc_LinkMgmt_InfoUpdate(psHciContext, 387 (phHal_sHwReference_t *)pHwRef, 388 p_link_mgmt_info->p_pipe_info->reg_index, 389 &pResponse[HCP_HEADER_LEN], 390 (uint8_t)(length - HCP_HEADER_LEN)); 391 break; 392 } 393 case ANY_SET_PARAMETER: 394 { 395 status = PHNFCSTVAL(CID_NFC_HCI, 396 NFCSTATUS_FEATURE_NOT_SUPPORTED); 397 break; 398 } 399 case ANY_OPEN_PIPE: 400 { 401 break; 402 } 403 case ANY_CLOSE_PIPE: 404 { 405 phOsalNfc_FreeMemory(p_link_mgmt_info->p_pipe_info); 406 p_link_mgmt_info->p_pipe_info = NULL; 407 psHciContext->p_pipe_list[PIPETYPE_STATIC_LINK] = NULL; 408 break; 409 } 410 default: 411 { 412 status = PHNFCSTVAL(CID_NFC_HCI, 413 NFCSTATUS_INVALID_HCI_RESPONSE); 414 break; 415 } 416 } 417 if( NFCSTATUS_SUCCESS == status ) 418 { 419 if( NULL != p_link_mgmt_info->p_pipe_info) 420 { 421 p_link_mgmt_info->p_pipe_info->prev_status = NFCSTATUS_SUCCESS; 422 } 423 p_link_mgmt_info->link_cur_seq = p_link_mgmt_info->link_next_seq; 424 } 425 426 } 427 return status; 428 } 429 430 431 static 432 NFCSTATUS 433 phHciNfc_LinkMgmt_InfoUpdate( 434 phHciNfc_sContext_t *psHciContext, 435 phHal_sHwReference_t *pHwRef, 436 uint8_t index, 437 uint8_t *reg_value, 438 uint8_t reg_length 439 ) 440 { 441 phHciNfc_LinkMgmt_Info_t *p_link_mgmt_info=NULL; 442 NFCSTATUS status = NFCSTATUS_SUCCESS; 443 uint8_t i=0; 444 if( (NULL == psHciContext) 445 || (NULL == pHwRef) 446 || (NULL == reg_value) 447 || (reg_length == 0) 448 ) 449 { 450 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER); 451 } 452 else if ( NULL == psHciContext->p_link_mgmt_info ) 453 { 454 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); 455 } 456 else 457 { 458 p_link_mgmt_info = (phHciNfc_LinkMgmt_Info_t *) 459 psHciContext->p_link_mgmt_info ; 460 if (REC_ERROR_INDEX == index) 461 { 462 HCI_PRINT_BUFFER("\tHost Controller REC Error Count :",reg_value,reg_length); 463 /* p_link_mgmt_info->hc_rec_error = reg_value[i] ; */ 464 for(i=0 ;(reg_length == REC_RETRY_LEN)&&(i < reg_length); i++) 465 { 466 p_link_mgmt_info->hc_rec_error |= 467 (uint16_t)(reg_value[i] << (BYTE_SIZE * i)); 468 } 469 } 470 else 471 { 472 status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION); 473 } /* End of the Index Check */ 474 475 } /* End of Context and the Link information validity check */ 476 477 return status; 478 } 479