/*!
 * \brief Receives the HCI Admin Commands from the corresponding peripheral device.
 *
 * This function receives  the HCI Admin Commands from the connected NFC Pheripheral
 * device
 */
static
 NFCSTATUS
 phHciNfc_Recv_Admin_Cmd (
                        void                *psContext,
                        void                *pHwRef,
                        uint8_t             *pCmd,
#ifdef ONE_BYTE_LEN
                        uint8_t             length
#else
                        uint16_t            length
#endif
                     )
{
    phHciNfc_sContext_t         *psHciContext = 
                                    (phHciNfc_sContext_t *)psContext ;
    phHciNfc_HCP_Packet_t       *hcp_packet = NULL;
    phHciNfc_HCP_Message_t      *hcp_message = NULL;
    phHciNfc_AdminGate_Info_t   *p_admin_info=NULL;
    phHciNfc_Pipe_Info_t        *p_pipe_info = NULL;
    uint8_t                     index=0;
    uint8_t                     pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID;
    uint8_t                     cmd = (uint8_t) HCP_MSG_INSTRUCTION_INVALID;
    uint8_t                     response = (uint8_t) ANY_OK;
    NFCSTATUS                   status = NFCSTATUS_SUCCESS;

    if( (NULL == psHciContext) 
        || (NULL == pHwRef) 
        || (HCP_HEADER_LEN > length ) 
      )
    {
      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
    }
    else
    {
        hcp_packet = (phHciNfc_HCP_Packet_t *)pCmd;
        hcp_message = &hcp_packet->msg.message;
        p_admin_info = psHciContext->p_admin_info;
        /* Get the Command instruction bits from the Message Header */
        cmd = (uint8_t) GET_BITS8( hcp_message->msg_header,
            HCP_MSG_INSTRUCTION_OFFSET, HCP_MSG_INSTRUCTION_LEN);

        switch( cmd )
        {
            /* These are notifications sent by the Host Controller */
            case ADM_NOTIFY_PIPE_CREATED:
            {
                pipe_id = hcp_message->payload[RESPONSE_PIPEID_OFFSET];
                p_pipe_info = (phHciNfc_Pipe_Info_t *)
                        phOsalNfc_GetMemory(sizeof(phHciNfc_Pipe_Info_t));
                if(NULL != p_pipe_info)
                {
                    /* The Source Host is the UICC Host */
                    p_pipe_info->pipe.source.host_id = 
                                    hcp_message->payload[index++];
                    /* The Source Gate is same as the Destination Gate */
                    p_pipe_info->pipe.source.gate_id    = 
                                    hcp_message->payload[index++];
                    /* The Source Host is the Terminal Host */
                    p_pipe_info->pipe.dest.host_id = 
                                    hcp_message->payload[index++];
                    p_pipe_info->pipe.dest.gate_id  = 
                                    hcp_message->payload[index++];
                    p_pipe_info->pipe.pipe_id   = 
                                    hcp_message->payload[index++];
                }
                status = phHciNfc_Update_PipeInfo(psHciContext,
                    &(p_admin_info->pipe_seq), pipe_id, p_pipe_info);

                if( NFCSTATUS_SUCCESS == status )
                {
                    psHciContext->p_pipe_list[pipe_id] = p_pipe_info;
                    if (NULL != p_pipe_info)
                    {
                        p_pipe_info->pipe.pipe_id = pipe_id;
                    }
                }
                break;
            }
            case ADM_NOTIFY_PIPE_DELETED:
            {
                pipe_id = hcp_message->payload[index++];
                p_pipe_info = psHciContext->p_pipe_list[pipe_id];
                if ( NULL != p_pipe_info )
                {
                        status = phHciNfc_Update_PipeInfo(
                            psHciContext, &(p_admin_info->pipe_seq),
                             (uint8_t) HCI_UNKNOWN_PIPE_ID, p_pipe_info);
                    if(NFCSTATUS_SUCCESS == status )
                    {
                        phOsalNfc_FreeMemory(p_pipe_info);
                        psHciContext->p_pipe_list[pipe_id] = NULL;
                    }
                }
                break;
            }
            /* TODO: Since we receive the Host ID, we need to clear
             * all the pipes created with the host
             */
            case ADM_NOTIFY_ALL_PIPE_CLEARED:
            {
                break;
            }
            /* case ADM_CREATE_PIPE: */
            /* case ADM_DELETE_PIPE: */
            /* case ADM_CLEAR_ALL_PIPE: */
            default:
            {
                response = ANY_E_CMD_NOT_SUPPORTED;
                status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_COMMAND_NOT_SUPPORTED);
                break;
            }
        }
        hcp_packet = (phHciNfc_HCP_Packet_t *) psHciContext->send_buffer;
        phHciNfc_Build_HCPFrame(hcp_packet,HCP_CHAINBIT_DEFAULT,
                                (uint8_t) HCI_ADMIN_PIPE_ID,
                                HCP_MSG_TYPE_RESPONSE, response );
        psHciContext->tx_total = HCP_HEADER_LEN;
        status = phHciNfc_Send_HCP( (void *)psHciContext, (void *)pHwRef );

        p_admin_info->admin_pipe_info->recv_msg_type = HCP_MSG_TYPE_COMMAND;
        p_admin_info->admin_pipe_info->sent_msg_type = HCP_MSG_TYPE_RESPONSE;
        p_admin_info->admin_pipe_info->prev_msg = response;
        p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_PENDING;
    }
    return status;
}
NFCSTATUS
phHciNfc_Update_Pipe(
                        phHciNfc_sContext_t     *psHciContext,
                        void                    *pHwRef,
                        phHciNfc_PipeMgmt_Seq_t *p_pipe_seq
                    )
{
    static uint8_t pipe_index = HCI_DYNAMIC_PIPE_ID;
    phHciNfc_Pipe_Info_t  *p_pipe_info = NULL;
    NFCSTATUS       status = NFCSTATUS_SUCCESS;


    for (pipe_index = 0;
            (pipe_index +  HCI_DYNAMIC_PIPE_ID) <=
                (uint8_t)(sizeof(host_gate_list)/sizeof(phHciNfc_GateID_t) );
                    pipe_index++)
    {
        status = phHciNfc_Allocate_Resource((void **)&p_pipe_info,
                                            sizeof(phHciNfc_Pipe_Info_t));

        if( (NFCSTATUS_SUCCESS == status)
            && (NULL != p_pipe_info))
        {
            /* The Source Host is the Terminal Host */
            p_pipe_info->pipe.source.host_id  = (uint8_t) phHciNfc_TerminalHostID;

            /* The Source Gate is same as the Destination Gate */
            p_pipe_info->pipe.source.gate_id    =
                                    host_gate_list[pipe_index];
            p_pipe_info->pipe.dest.host_id =
                                    phHciNfc_HostControllerID;
            p_pipe_info->pipe.dest.gate_id  =
                                    host_gate_list[pipe_index];
            /* The Pipe ID is unknown until it is assigned */
            p_pipe_info->pipe.pipe_id   = (uint8_t) HCI_UNKNOWN_PIPE_ID;

            /* Initialise the Resources for the particular Gate */

            status = phHciNfc_Create_All_Pipes(psHciContext,
                                            pHwRef, p_pipe_seq );

            if( NFCSTATUS_SUCCESS == status )
            {
                uint8_t pipe_id = (uint8_t)(pipe_index + HCI_DYNAMIC_PIPE_ID);
                status = phHciNfc_Update_PipeInfo( psHciContext, p_pipe_seq ,
                                        pipe_id, p_pipe_info );
                if( NFCSTATUS_SUCCESS == status )
                {
                    p_pipe_info->pipe.pipe_id = pipe_id;
                    psHciContext->p_pipe_list[pipe_id] = p_pipe_info;
                }
                else
                {
                    phOsalNfc_FreeMemory(p_pipe_info);
                }
                p_pipe_info = NULL;
            }
            else
            {
                phOsalNfc_FreeMemory(p_pipe_info);
                p_pipe_info = NULL;
            }
        }
        else
        {
            status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INSUFFICIENT_RESOURCES);
        }
    }

    if( NFCSTATUS_SUCCESS == status )
    {
        status = phHciNfc_LinkMgmt_Initialise( psHciContext,pHwRef );
        if(NFCSTATUS_SUCCESS == status)
        {
            status = phHciNfc_ReaderMgmt_Initialise( psHciContext,pHwRef );
        }
        if(NFCSTATUS_SUCCESS == status)
        {
            status = phHciNfc_EmuMgmt_Initialise( psHciContext,pHwRef );
        }
    }

    return status;
}
static
NFCSTATUS
phHciNfc_Recv_Admin_Response(
                        void                *psContext,
                        void                *pHwRef,
                        uint8_t             *pResponse,
#ifdef ONE_BYTE_LEN
                        uint8_t             length
#else
                        uint16_t            length
#endif
                    )
{
    phHciNfc_sContext_t         *psHciContext = 
                                    (phHciNfc_sContext_t *)psContext ;
    phHciNfc_HCP_Packet_t       *hcp_packet = NULL;
    phHciNfc_HCP_Message_t      *hcp_message = NULL;
    phHciNfc_Pipe_Info_t        *p_pipe_info = NULL;
    phHciNfc_AdminGate_Info_t   *p_admin_info = NULL;
    NFCSTATUS                   status = NFCSTATUS_SUCCESS;
    uint8_t                     pipe_id = (uint8_t) HCI_UNKNOWN_PIPE_ID;
    uint8_t                     prev_cmd = 0;
    NFCSTATUS                   prev_status = NFCSTATUS_SUCCESS;

    if( (NULL == psHciContext) || (NULL == pHwRef) )
    {
      status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_PARAMETER);
    }
    else if ( NULL == psHciContext->p_admin_info )
    {
        status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_INFORMATION);
    }
    else
    {
        hcp_packet = (phHciNfc_HCP_Packet_t *)pResponse;
        hcp_message = &hcp_packet->msg.message;
        p_admin_info = psHciContext->p_admin_info;
        prev_cmd = p_admin_info->admin_pipe_info->prev_msg ;
        prev_status = p_admin_info->admin_pipe_info->prev_status ;
        if(prev_status == NFCSTATUS_PENDING)
        {
            switch(prev_cmd)
            {
                case ANY_SET_PARAMETER:
                {
                    break;
                }
                case ANY_GET_PARAMETER:
                {
                    status = phHciNfc_Admin_InfoUpdate(psHciContext,
                                (phHal_sHwReference_t *)pHwRef,
                                p_admin_info->admin_pipe_info->reg_index, 
                                    &pResponse[HCP_HEADER_LEN],
                                        (uint8_t)(length - HCP_HEADER_LEN));
                    break;
                }
                case ANY_OPEN_PIPE:
                {
                    break;
                }
                case ANY_CLOSE_PIPE:
                {
                    phOsalNfc_FreeMemory(p_admin_info->admin_pipe_info);
                    p_admin_info->admin_pipe_info = NULL;
                    psHciContext->p_pipe_list[PIPETYPE_STATIC_ADMIN] = NULL;
                    break;
                }
                case ADM_CREATE_PIPE:
                {
                    p_pipe_info = (phHciNfc_Pipe_Info_t *)
                                        p_admin_info->admin_pipe_info->param_info;
                    pipe_id = hcp_message->payload[RESPONSE_PIPEID_OFFSET];
                    status = phHciNfc_Update_PipeInfo(psHciContext,
                        &(p_admin_info->pipe_seq), pipe_id, p_pipe_info);
                    if(NFCSTATUS_SUCCESS == status )
                    {
                        psHciContext->p_pipe_list[pipe_id] = p_pipe_info;
                        p_pipe_info->pipe.pipe_id = pipe_id;
                    }
                    break;
                }
                case ADM_DELETE_PIPE:
                {
                    p_pipe_info = (phHciNfc_Pipe_Info_t *)
                                    p_admin_info->admin_pipe_info->param_info;
                    if ( NULL != p_pipe_info )
                    {
                        pipe_id = p_pipe_info->pipe.pipe_id;
                        status = phHciNfc_Update_PipeInfo(
                            psHciContext, &(p_admin_info->pipe_seq),
                             (uint8_t) HCI_UNKNOWN_PIPE_ID, p_pipe_info);
                        if(NFCSTATUS_SUCCESS == status )
                        {
                            phOsalNfc_FreeMemory(p_pipe_info);
                            psHciContext->p_pipe_list[pipe_id] = NULL;
                        }
                    }
                    break;
                }
                case ADM_CLEAR_ALL_PIPE:
                {
                    break;
                }
                default:
                {
                    status = PHNFCSTVAL(CID_NFC_HCI, NFCSTATUS_INVALID_HCI_RESPONSE);
                    HCI_DEBUG("%s: Default Statement Should Not Occur \n",
                                                    "phHciNfc_Recv_Admin_Response");
                    break;
                }
            }
        }
        if( NFCSTATUS_SUCCESS == status )
        {
            if( NULL != p_admin_info->admin_pipe_info)
            {
                p_admin_info->admin_pipe_info->prev_status = NFCSTATUS_SUCCESS;
            }
            p_admin_info->current_seq = p_admin_info->next_seq;
        }
    }
    return status;
}