给gkermit添加串口通信功能 1

首先给出原始代码的分析,我使用的是Ubuntu的代码,打算在Linux和Cygwin下都能用。

 

   Gkermit代码分析

前言
    Cygwin串口设备映射
        linux下的/dev/ttyS[n]在cygwin会映射到Windows串口设备 //./COM[n + 1]
        例如 /dev/ttyS0  等价于 COM1

 

一、代码组织结构
   ++- .
    +- gkermit.h    程序公共头文件

    +- gkermit.c    程序入口、字符编解码、打包解包、有效性验证 (main入口)
    +- gcmdline.c   命令行分析相关的代码
    +- gunixio.c    Unix IO 相关的操作

    +- gproto.w     状态机源代码
       gproto.c     自动生成的代码

    +- gwart.c      简易的lex分析器,用于处理.w代码,生成.c的文件

 

二、基本函数列表
    ------ 字符接口 ------
    gkermit.h ---------------------------------------------------------------------------------
        #define tochar(ch)  ((ch) + SP )     转换整型到可打印字符,参见标准P13页
        #define xunchar(ch) ((ch) - SP )     tochar的反向操作
        #define ctl(ch)     ((ch) ^ 64 )     控制字符和可打印字符的转换
        #define zgetc(a) (((--zincnt)>=0) ?     如果缓冲为空则实际读取文件
                ((int)(*zinptr++) & 0xff) :
                zfillbuf(a))

    ------ 函数原型 ------
    gunixio.c ---------------------------------------------------------------------------------
        SIGTYP doexit (int)    结束程序:正常或异常退出
        VOID sysinit (void)    系统初始化:
        char dopar (char)      Parity奇偶校验
        VOID tmsg (char *)     将参数指向的字符串输出到终端
        VOID tmsgl (char *)    将参数指向的字符串输出到终端(带换行)
        int ttopen (char *)    打开设备
        int ttpkt (int)        设置通信设备工作在RAW模式
        int ttres (void)       复位通信设备
        int ttinl (char *,     读取一个包:以EOL结尾,包含超时机制
                    int,
                    int,
                    char,
                    char,
                    int)
        int ttol (char *,      发送一个包:原样发送上层提供的包
                    int)
        int ttchk (void)       查看输入是否正常
        int ttflui (void)      同步缓冲到设备
        long zchki (char *)    查看文件是否可被读取
        int zchko (char *)     查看文件是否可被写入
        int zopeni (char *)    打开现存的文件:就是用于发送的文件
        int zopeno (char *)    新建一个输出文件:就是用于存放接收到的文件
        int zclosi (void)      关闭输入文件句柄
        int zcloso (int)       关闭输出文件句柄
        int zfillbuf (int)     从文件读取到缓冲
        VOID zltor (char *,    本地到远程的文件名转换,同时处理文件名中的特殊字符:local to remote
                    char *,
                    int)
        int zrtol (char *,     远程到本地的文件名转换,同时处理文件名中的特殊字符:remote to local
                    char *,
                    int,
                    int)
        int zbackup (char *)   备份已有的文件:在文件名后加上“.~数字~”

    gkermit.c ---------------------------------------------------------------------------------
        int input (void)        被状态机调用:获取输入文件的包
        VOID nxtpkt (void)      初始化下一个包的序列号
        int ack (void)          发送DATA是空的ACK回复包:调用 spacket 函数
        int ack1 (char *)       发送含有特定串的ACK回复包
        int nak (void)          发送拒绝包
        VOID tinit (void)      “发送”传输回话初始化
        VOID errpkt (char *)  发送ERROR包
        int sinit (char)      发送 S(Init packet)
        int sfile (void)      发送 F(File header packet)
        int sdata (void)      发送 Send Data packet
        int seof (char *)      发送 Send EOF packet
        int seot (void)      发送 Send EOT packet
        int resend (void)      包的重发
        int decode (int)      解析包的 data field
        int encstr (char *)  从字符串编码生成数据包:调用 getpkt 函数
        int gattr (char *)      接收文件属性包
        int sattr (void)      发送文件属性包
        VOID ginit (void)      “接收”传输会话初始化
        int scmd (char, char *) 发送kermit命令到server
        VOID rinit (void)      接收 Init 包
        int gnfile (void)      获取下一个发送的文件名
        int rcvfil (void)      接收文件
        VOID spar (char *)      设置kermit运行参数:从收到的数据中获得参数
        char *rpar (void)      回复kermit运行参数:本地使用的参数
        VOID usage (void)      输出帮助信息

        ------ 只在 gkermic.c 中使用的函数:非全局使用的函数 ------
        int spacket (char,int,int,char *)   构建一个包并发送:调用 ttol  函数发送
        int rpacket (void)                  读取一个包并解析:调用 ttinl 函数读取
        unsigned int chk1 (char *,int)      12bit 块 校验:调用了chksum函数
        unsigned int chk3 (char *,int)      16bit CRC校验
        unsigned int chksum (char *,int)    算数校验
        int getpkt (int)                  从文件读取数据并构建包
        VOID encode (int,int)               将一个字符编码进包
        VOID decstr (char *)              解包并存到字符串缓冲之中:调用 decode 函数


    gcmdline.c --------------------------------------------------------------------------------
        int cmdlin (void)      命令行Parser,只是处理命令行参数,并
                                用提取的参数更新全局参数变量。

    gproto.c ----------------------------------------------------------------------------------
        int gwart (void)      状态机调度表

三、函数调用关系
    由于大部分系统相关的操作都在gunixio.c,于是下面的分析都是对gunixio的调用的分析。
    为了使用windows的本地的函数进行替换。只要移植gunixio.c里的函数就可以了,其他的代码在mingw和vc中都可编译通过
    以下是在gunixio的所有函数执行的时候加入输出语句。
        ttopen      --打开串口
        ttpkt       --设置串口工作在raw模式

        G-Kermit CU-1.00, Columbia University, 1999-12-25
         * Open device /dev/ttyS0
         * Escape back to your local Kermit and give a SEND command.

         * KERMIT READY TO RECEIVE...

        ttinl       --读取包:所有串口的读取read都是通过这个函数,gwart调用input->rpacket->ttinl->read
        ttflui      --清空串口缓冲:丢弃输入,发送输出,结束之后进行状态处理(状态调度表)
         * recv INIT
        ttol        --写入包:所有串口的写入write都是通过这个函数
        ttinl       --读取包
        ttflui      --......
         * recv HEADER
        zrtol       --将远程的文件名转换为本地的
        zbackup     --判断本地是否有同名的文件,并处理备份
        zchko       --检查输出的文件是否可写
        zchki       --检查输出的文件是否可读
        zopeno      --打开输出文件的句柄
        ttol        --送出包
        ttinl       --读取包
        ttflui      --......
         * recv ATTRIBUTES
         * will RECEIVE 1 byte
        ttol        --送出包
        ttinl       --读取包
        ttflui      --......
         * recv DATA [complete]
        ttol        --送出包
        ttinl       --读取包
        ttflui      --......
         * recv EOF
        zcloso
        ttol        --送出包
        ttinl       --读取包
        ttflui      --......
         * recv EOT
        ttol       --读取包
         * exchange filesize 0x1 [1] bytes
        END
        ttres
           
详细输出模式
        G-Kermit CU-1.00, Columbia University, 1999-12-25: POSIX
        MAXPATHLEN = 1024
        cmdlin action = v
        ttopen
        ttopen __STDC__
        ttopen SIG_V
        ttopen nonblocking read/write
        ttopen TINBUFSIZ = 4080
        ttopen xonxoff = 0
        ttopen noxonxoff = 0
        ttopen ttflags -1
        ttopen nomodes 0
        ttopen nonblock = 0
        ttpkt
        input[v]
        G-Kermit CU-1.00, Columbia University, 1999-12-25
         * Open device /dev/ttyS0
         * Escape back to your local Kermit and give a SEND command.

         * KERMIT READY TO RECEIVE...

        ttinl
        ttinl read timo = 9
        ttinl length = 25
        PKT<-[^A9 S~' @-#Y3~*!J*0+++B"U1@G](27) rc=0
        rpacket type=S, seq=00, len=22
        chksum=1445
        ttflui
        ttflui = 0, errno = 0
        input[S]
         * recv INIT
        spar attributes=1 longpackets=1
        spar whatami = 0x22
        spar streamok = -1
        spar sysid [U1]
        spar recognizes peer
        rpar streamok=-1 whatami=38
        chksum=1455
        ttol
        PKT->[^A9 Y~' @-#Y3~*!J*0+++F"U1@Q](28)
        ttinl
        ttinl read timo = 7
        ttinl length = 13
        PKT<-[^A-!Ftest.txt&4;](15) rc=0
        rpacket type=F, seq=01, len=8
        crc=25883
        ttflui
        ttflui = 0, errno = 0
        input[F]
         * recv HEADER
        zrtol
        zbackup
        zbackup A test.txt: 8
        zbackup B test.txt
        zbackup test.txt.~2~: OK
        rcvfil filename [test.txt]
        zchko
        zchki
        zchko(.) x = 0 errno = 0
        zopeno
        zopeno test.txt: 0
        crc=3239
        ttol
        PKT->[^A-!Ytest.txt RG](16)
        ttinl
        ttinl read timo = 7
        ttinl length = 12
        PKT<-[^A,"A""B81!1)R0](14) rc=0
        rpacket type=A, seq=02, len=7
        crc=40080
        ttflui
        ttflui = 0, errno = 0
        input[A]
         * recv ATTRIBUTES
         * will RECEIVE 1 byte
        crc=58689
        ttol
        PKT->[^A%"Y.5!](8)
        ttinl
        ttinl read timo = 7
        ttinl length = 7
        PKT<-[^A'#D#J'O!](9) rc=0
        rpacket type=D, seq=03, len=2
        crc=31681
        ttflui
        ttflui = 0, errno = 0
        input[D]
         * recv DATA [complete]
        crc=64665
        ttol
        PKT->[^A%#Y/R9](8)
        ttinl
        ttinl read timo = 7
        ttinl length = 5
        PKT<-[^A%$Z(,*](7) rc=0
        rpacket type=Z, seq=04, len=0
        crc=33546
        ttflui
        ttflui = 0, errno = 0
        input[Z]
         * recv EOF
        zcloso
        zcloso(test.txt) cx = 0 keep = 0
        crc=45457
        ttol
        PKT->[^A%$Y+&1](8)
        ttinl
        ttinl read timo = 7
        ttinl length = 5
        PKT<-[^A%%B 8;](7) rc=0
        rpacket type=B, seq=05, len=0
        crc=1563
        ttflui
        ttflui = 0, errno = 0
        input[B]
         * recv EOT
        crc=43081
        ttol
        PKT->[^A%%Y*A)](8)
         * exchange filesize 0x1 [1] bytes
        END
        ttres
        exit 0
               

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值