参照上述伪代码 , 依据目标系统具体情况编写相应功能代码即可 。注意,上述代码能够正常工作的关键是目标系统的串口驱动必须能够正常工作且健壮、可靠 。因为tty层封装的其实就是操作ppp拨号终端的串口驱动代码,tty只是做了一层简单封装罢了 。os_adapter.c文件中关于ppp部分还有如下几项定义需要根据你的实际目标环境进行配置:
#if SUPPORT_PPP//* 连接ppp拨号终端的串口名称,有几个模块 , 就指定几个,其存储的单元索引应等于os_open_tty()返回的对应串口的tty句柄值const CHAR *or_pszaTTY[PPP_NETLINK_NUM] = { …… /* 如"串口1", "串口2"等 */ }; //* 指定ppp拨号的apn、用户和密码 , 系统支持几路ppp , 就需要指定几组拨号信息//* ST_DIAL_AUTH_INFO结构体保存这几个信息,该结构体的详细内容参见协议栈源码ppp/ppp.h文件//* 这里设置的apn等拨号认证信息会替代前面说过的APN_DEFAULT、AUTH_USER_DEFAULT、AUTH_PASSWORD_DEFAULT等缺省设置const ST_DIAL_AUTH_INFO or_staDialAuth[PPP_NETLINK_NUM] = {{ "4gnet", "card", "any_char" },//* 注意ppp账户和密码尽量控制在20个字节以内,太长需要需要修改chap.c//* 中send_response()函数的szData数组容量及pap.c中pap_send_auth_request()函数的//* ubaPacket数组的容量,确保其能够封装一个完整的响应报文/* 系统存在几路ppp链路 , 就在这里添加几路拨号认证信息 */}; //* ppp链路协商的初始协商配置信息,协商成功后这里保存最终的协商结果,ST_PPPNEGORESULT结构体的详细说明参见下文ST_PPPNEGORESULT o_staNegoResult[PPP_NETLINK_NUM] = {{{ 0, PPP_MRU, ACCM_INIT,{ PPP_CHAP, 0x05 /* CHAP协议,0-4未使用,0x05代表采用MD5算法 */ }, TRUE, TRUE, FALSE, FALSE },{ IP_ADDR_INIT, DNS_ADDR_INIT, DNS_ADDR_INIT, IP_ADDR_INIT, MASK_INIT }, 0},/* 系统存在几路ppp链路,就在这里添加几路的协商初始值,如果不确定,可以将上面预定义的初始值直接复制过来即可 */};#endif
上面给出的代码做了几件事情:1)指定tty设备连接的串口名称;2)指定拨号认证信息:apn、用户和密码;3)指定ppp链路协商初始值;
总之 , 你的目标系统连接了几个拨号终端,这几件事情就要针对特定的终端分别做一遍,单独指定 。这里需要重点说明的是ppp链路协商配置信息 。这些信息由ST_PPPNEGORESULT结构体保存(参见negotiation_storage.h文件):
typedef struct _ST_PPPNEGORESULT_ {struct {UINT unMagicNum; //* 幻数(魔术字)USHORT usMRU;//* 最大接收单元,缺省值由PPP_MRU宏指定,一般为1500字节UINT unACCM;//* ACCM,异步控制字符映射,指定哪些字符需要转义,如果不确定 , 建议采用ACCM_INIT宏指定的缺省值struct { //* 保存认证信息的结构体USHORT usType;//* 指定认证类型:chap或pap,缺省chap认证UCHAR ubaData[16]; //* 认证报文携带的数据 , 不同的协议携带的数据类型不同,一般情况下采用协议栈的缺省值即可} stAuth;BOOL blIsProtoComp;//* 是否采用协议域压缩(本地设置项,代表协议栈一侧,协商结果不影响该字段)BOOL blIsAddrCtlComp;//* 是否采用地址及控制域压缩(本地设置项,代表协议栈一侧,协商结果不影响该字段)BOOL blIsNegoValOfProtoComp;//* 协议域是否压缩的协商结果值(远端设置项 , 代表对端是否支持该配置,协商结果影响该字段)BOOL blIsNegoValOfAddrCtlComp; //* 地址及控制域是否压缩的协商结果值(远端设置项,同上)} stLCP;//* 存储ppp链路的初始及协商成功后的地址信息struct {UINT unAddr;//* ip地址,初始值由协议栈提供的IP_ADDR_INIT宏指定,不要擅自修改UINT unPrimaryDNS;//* 主dns服务器地址,初始值由协议栈提供的DNS_ADDR_INIT宏指定,不要擅自修改UINT unSecondaryDNS;//* 次dns服务器地址,初始值由协议栈提供的DNS_ADDR_INIT宏指定,不要擅自修改UINT unPointToPointAddr; //* 点对点地址 , 初始值由协议栈提供的IP_ADDR_INIT宏指定,不要擅自修改UINT unSubnetMask;//* 子网掩码} stIPCP;UCHAR ubIdentifier;//* 标识域 , 从0开始自增,唯一的标识一个ppp报文 , 用于确定应答报文UINT unLastRcvedSecs; //* 最近一次收到对端报文时的秒数,其用于ppp链路故障探测,无需关心,协议栈底层使用} ST_PPPNEGORESULT, *PST_PPPNEGORESULT;
基本上,要调整的地方几乎没有,我们直接采用缺省值即可 。
移植工作的最后一步就是把ppp网卡的主处理线程thread_ppp_handler()添加到os适配层的工作线程列表中 。也就是前面讲解os适配层移植工作时提到的lr_stcbaPStackThread数组 。这个数组保存了协议栈内部工作线程列表,我们先前已经添加了one-shot定时器工作线程thread_one_shot_timer_count() 。我们再把ppp主处理线程添加到这个数组中即可 。伪代码实现如下:
推荐阅读
- 2 onps栈移植说明——编译器及os适配层移植
- 1 onps栈移植说明——onps栈的配置及裁剪
- 开源网络协议栈onps诞生记
- <一>从指令角度了解函数堆栈调用过程
- stm32h750移植lvgl
- 3 Python全栈工程师之从网页搭建入门到Flask全栈项目实战 - 入门Flask微框架
- 都卷Java,你看看你得学多少技术栈才能工作!
- flutter系列之:flutter中可以建索引的栈布局IndexedStack
- SpringBoot+Vue3 AgileBoot - 手把手一步一步带你Run起全栈项目
- C++ 使用栈求解中缀、后缀表达式的值