/*****************************************************************************
 函 数 名  : SavePppChallengeFrame
 功能描述  : 在DART工程中将消息码流中CHAP数据写回到CHAP全局变量中
 输入参数  : ucPppId - PPP链接ID
             pucData - 消息码流, 首字节指向PPP帧数据的首字节
 输出参数  : 无
 返 回 值  : 无
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2009年12月10日
    作    者   : liukai
    修改内容   : Created

*****************************************************************************/
VOS_VOID SavePppChallengeFrame(VOS_UINT8 ucPppId, VOS_UINT8 *pucData)
{
    VOS_UINT16 usLen;
    const VOS_UINT8 ucLenghFieldPos = 5;
    const VOS_UINT8 ucLenghCodePos = 3;
    VOS_UINT8 *pucCurrData;
    VOS_UINT8  ucHigh;
    VOS_UINT8  ucLow;
    struct chap *pstChap;
    VOS_UINT8 *pucChallengeBuf;

    pucCurrData = pucData + ucLenghFieldPos;    /* point to Length Field */

    /* get the length of CHAP Challenge Frame */
    ucHigh = *pucCurrData;
    pucCurrData++;
    ucLow = *pucCurrData;
    usLen = (VOS_UINT16)((ucLow) | (((VOS_UINT16)(ucHigh))<<8));

    pucCurrData = pucData + ucLenghCodePos;    /* point to Code Field */
    pstChap = (&(PPP_LINK(ucPppId)->chap));
    pucChallengeBuf = pstChap->RecordData.BufChallenge;
    PS_MEM_CPY(pucChallengeBuf, pucCurrData, usLen);    /* save data */
    pstChap->RecordData.LenOfChallenge = usLen;
}
/*****************************************************************************
 Prototype      : Ppp_CreateRawDataPppReq
 Description    : 创建PDP类型为PPP的PPP实体,但不做链路管理,只作数据的封装和解封装

 Input          : ---
 Output         : ---创建成功后返回的PPP ID
 Return Value   : ---VOS_UINT32
 Calls          : ---
 Called By      : ---

 History        : ---
  1.Date        : 2005-11-18
    Author      : ---
    Modification: Created function
*****************************************************************************/
VOS_UINT32 Ppp_CreateRawDataPppReq ( PPP_ID *pusPppId)
{
    PPP_ID  pppid_get;


    if (VOS_NULL_PTR == pusPppId)
    {
        return VOS_ERR;
    }

    /*从PPP ID数组中得到一个空闲的PPP ID*/
    pppid_get = PppGetId();

    /*如果没有空闲的PPP ID*/
    if (0 == pppid_get)
    {
        return VOS_ERR;
    }

    /* PPP类型PDP激活时,无法得知TE和网络端的协商结果,强制赋值 */
    PPP_LINK(pppid_get)->lcp.his_accmap = 0xffffffff;

    /*如果有空闲的PPP ID,首先将申请得到的PPP ID赋值给AT_CMD*/
    *pusPppId = pppid_get;

    /* 初始化HDLC相关配置 */
    PPP_InitHdlcConfig(pppid_get);

    /* 可维可测信息上报*/
    Ppp_EventMntnInfo(pppid_get, AT_PPP_CREATE_RAW_PPP_REQ);

    /*返回正确*/
    return VOS_OK;
} /* Ppp_CreateRawDataPppReq */
/*****************************************************************************
 Prototype      : Ppp_CreatePppReq
 Description    : 为AT模块"创建PPP链路"提供对应的API函数。

 Input          : ---
 Output         : ---创建成功后返回的PPP ID
 Return Value   : ---VOS_UINT32
 Calls          : ---
 Called By      : ---

 History        : ---
  1.Date        : 2005-11-18
    Author      : ---
    Modification: Created function
*****************************************************************************/
VOS_UINT32 Ppp_CreatePppReq ( PPP_ID *pusPppId)
{
    PPP_ID pppid_get;


    if(pusPppId == VOS_NULL)
    {
        return VOS_ERR;
    }

    /*从PPP ID数组中得到一个空闲的PPP ID*/
    pppid_get = PppGetId();

    /*如果没有空闲的PPP ID*/
    if(pppid_get == 0)
    {
        return VOS_ERR;
    }

    /*如果有空闲的PPP ID,首先将申请得到的PPP ID赋值给AT_CMD*/
    *pusPppId = pppid_get;

    /*然后调用PPP模块对应的函数*/
    link_Init(PPP_LINK(pppid_get));
    PPP_LINK(pppid_get)->phase = PHASE_ESTABLISH;
    PPP_LINK(pppid_get)->lcp.fsm.state = ST_CLOSED;

    fsm_Open(&(PPP_LINK(pppid_get)->lcp.fsm));

    /*释放PPP数据队列*/
    PPP_ClearDataQ();

    /* 初始化HDLC相关配置 */
    PPP_InitHdlcConfig(pppid_get);

    /* 可维可测信息上报*/
    Ppp_EventMntnInfo(pppid_get, AT_PPP_CREATE_PPP_REQ);

    /*返回正确*/
    return VOS_OK;
}
VOS_UINT32 PPP_SavePcoInfo
(
    PPP_ID usPppId,
    AT_PPP_IND_CONFIG_INFO_STRU *pstAtPppIndConfigInfo
)
{
    struct ipcp                         *pstIpcp;
    AT_PPP_PCO_IPV4_ITEM_STRU           *pstPcoIpv4Item;


    pstIpcp        = &(PPP_LINK(usPppId)->ipcp);
    pstPcoIpv4Item = &(pstAtPppIndConfigInfo->stPcoIpv4Item);


    PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, PS_PRINT_INFO,
                  "PPP_SavePcoInfo, aucIpAddr %d\r\n",
                  (VOS_INT)pstAtPppIndConfigInfo->aucIpAddr);
    PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, PS_PRINT_INFO,
                  "PPP_SavePcoInfo, bitOpPriDns %d, aucPriDns %d\r\n",
                  (VOS_INT)pstPcoIpv4Item->bitOpPriDns, (VOS_INT)pstPcoIpv4Item->aucPriDns);
    PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, PS_PRINT_INFO,
                  "PPP_SavePcoInfo, bitOpSecDns %d, aucSecDns %d\r\n",
                  (VOS_INT)pstPcoIpv4Item->bitOpSecDns, (VOS_INT)pstPcoIpv4Item->aucSecDns);
    PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, PS_PRINT_INFO,
                  "PPP_SavePcoInfo, bitOpPriNbns %d, aucPriNbns %d\r\n",
                  (VOS_INT)pstPcoIpv4Item->bitOpPriNbns, (VOS_INT)pstPcoIpv4Item->aucPriNbns);
    PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, PS_PRINT_INFO,
                  "PPP_SavePcoInfo, bitOpSecNbns %d, aucSecNbns %d\r\n",
                  (VOS_INT)pstPcoIpv4Item->bitOpSecNbns, (VOS_INT)pstPcoIpv4Item->aucSecNbns);

    /* 保存主DNS服务器地址 */
    if ( pstPcoIpv4Item->bitOpPriDns )
    {
        PS_MEM_CPY(&(pstIpcp->PriDnsAddr.s_addr), pstPcoIpv4Item->aucPriDns, IPV4_ADDR_LEN);
        pstIpcp->PriDns_neg |= NEG_ACCEPTED;
    }

    /* 保存辅DNS服务器地址 */
    if ( pstPcoIpv4Item->bitOpSecDns )
    {
        PS_MEM_CPY(&(pstIpcp->SecDnsAddr.s_addr), pstPcoIpv4Item->aucSecDns, IPV4_ADDR_LEN);
        pstIpcp->SecDns_neg |= NEG_ACCEPTED;
    }

    /* 保存主NBNS服务器地址 */
    if ( (pstPcoIpv4Item->bitOpPriNbns)
         && (WINS_CONFIG_ENABLE == g_ucPppConfigWins))
    {
        PS_MEM_CPY(&(pstIpcp->PriNbnsAddr.s_addr), pstPcoIpv4Item->aucPriNbns, IPV4_ADDR_LEN);
        pstIpcp->PriNbns_neg |= NEG_ACCEPTED;
    }

    /* 保存辅NBNS服务器地址 */
    if ( (pstPcoIpv4Item->bitOpSecNbns)
         && (WINS_CONFIG_ENABLE == g_ucPppConfigWins))
    {
        PS_MEM_CPY(&(pstIpcp->SecNbnsAddr.s_addr), pstPcoIpv4Item->aucSecNbns, IPV4_ADDR_LEN);
        pstIpcp->SecNbns_neg |= NEG_ACCEPTED;
    }

    /* 参考Ppp_RcvConfigInfoInd实现,peer_ip填主机地址aucIpAddr */
    PS_MEM_CPY(&(pstIpcp->peer_ip.s_addr), pstAtPppIndConfigInfo->aucIpAddr, IPV4_ADDR_LEN);
    pstIpcp->IpAddr_neg |= NEG_ACCEPTED;

    /* 切换IPCP协商状态 */
    if(pstIpcp->stage == IPCP_REQ_RECEIVED)
    {
        pstIpcp->stage = IPCP_SUCCESS_FROM_GGSN;
    }

    return VOS_OK;
}
/*****************************************************************************
 Prototype      : Ppp_ReleasePppReq
 Description    : 为AT模块"释放PPP链路"提供对应的API函数。

 Input          : ---要释放的PPP链路对应的PPP ID
 Output         : ---
 Return Value   : ---VOS_UINT32
 Calls          : ---
 Called By      : ---

 History        : ---
  1.Date        : 2005-11-18
    Author      : ---
    Modification: Created function
*****************************************************************************/
VOS_UINT32 Ppp_ReleasePppReq ( PPP_ID usPppId)
{
    VOS_UINT32                          ulRet;


    /* 可维可测信息上报*/
    Ppp_EventMntnInfo(usPppId, AT_PPP_RELEASE_PPP_REQ);

    if(VOS_OK != PppIsIdValid(usPppId))
    {
        return VOS_ERR;
    }

    /* 如果当前PPP在PHASE_NETWORK阶段,属于网侧主动去激活
       此时PPP等待和PC间PPP协议结束后通知AT拉管脚信号,并起定时器保护*/
    if (PHASE_NETWORK == (PPP_LINK(usPppId)->phase))
    {
        if (VOS_NULL_PTR != (PPP_LINK(usPppId)->lcp.hLcpCloseTimer))
        {
            PS_STOP_REL_TIMER(&(PPP_LINK(usPppId)->lcp.hLcpCloseTimer));
            PPP_LINK(usPppId)->lcp.hLcpCloseTimer= VOS_NULL_PTR;
        }

        /*起定时器,确保通知拉AT管脚信号*/
        ulRet = VOS_StartRelTimer(&(PPP_LINK(usPppId)->lcp.hLcpCloseTimer),  PS_PID_APP_PPP,
            1000,  usPppId,  PHASE_TERMINATE_PENDING,  VOS_RELTIMER_NOLOOP,  VOS_TIMER_PRECISION_5 );

        if (VOS_OK != ulRet)
        {
            PPP_LINK(usPppId)->lcp.hLcpCloseTimer = VOS_NULL_PTR;
            PPP_ProcPppDisconnEvent(usPppId);
        }
    }

    /*首先调用PPP模块对应的函数*/
    fsm_Close(&(PPP_LINK(usPppId)->ipcp.fsm));
    fsm_Close(&(PPP_LINK(usPppId)->lcp.fsm));

    /*停止IPCP状态机定时器:*/
    if( VOS_NULL_PTR !=((PPP_LINK(usPppId))->ipcp.fsm.timer) )
    {
        VOS_StopRelTimer(&((PPP_LINK(usPppId))->ipcp.fsm.timer));
        (PPP_LINK(usPppId))->ipcp.fsm.timer = VOS_NULL_PTR;
    }

    /*停止CHAP状态机定时器:*/
    if( VOS_NULL_PTR !=((PPP_LINK(usPppId))->chap.auth.hAuthTimer) )
    {
        VOS_StopRelTimer(&((PPP_LINK(usPppId))->chap.auth.hAuthTimer));
        (PPP_LINK(usPppId))->chap.auth.hAuthTimer = VOS_NULL_PTR;
    }

    /*停止LCP状态机定时器:*/
    if( VOS_NULL_PTR !=((PPP_LINK(usPppId))->lcp.fsm.timer) )
    {
        VOS_StopRelTimer(&((PPP_LINK(usPppId))->lcp.fsm.timer));
        (PPP_LINK(usPppId))->lcp.fsm.timer = VOS_NULL_PTR;
    }

    /*释放待PDP激活定时器*/
    if (VOS_NULL_PTR != (PPP_LINK(usPppId)->ipcp.hIpcpPendTimer))
    {
        PS_STOP_REL_TIMER(&(PPP_LINK(usPppId)->ipcp.hIpcpPendTimer));
        PPP_LINK(usPppId)->ipcp.hIpcpPendTimer = VOS_NULL_PTR;
    }

    /*释放待处理IPCP帧*/
    if (VOS_NULL_PTR != (PPP_LINK(usPppId)->ipcp.pstIpcpPendFrame))
    {
        ppp_m_freem(PPP_LINK(usPppId)->ipcp.pstIpcpPendFrame);
        PPP_LINK(usPppId)->ipcp.pstIpcpPendFrame = VOS_NULL_PTR;
    }

    PppFreeId(usPppId);

    /* 不用释放PPP数据队列,因为只要队列里面有数据,PPP任务就会被调度起来处理,
       如果HDLC处理完成而PPP实体已经释放,那么封装或解封装出来的数据自然会被丢弃。
       这个API会在AT任务里被调用,如果这里把数据放掉,PPP任务有可能正在使用 */
    /* PPP_ClearDataQ(); */

    /*返回正确*/
    return VOS_OK;
}