Home | History | Annotate | Download | only in src
      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