www.pudn.com > yModem.rar > xymodem.c


/****************************************Copyright (c)**************************************************                               
**                               Henan Star Hi-Tech CO.,LTD                                       
**                                  All rights reserved. 
** 
**----------------------------------------File Info----------------------------------------------------- 
** 文件名称: 
** 工程项目: 
** 说    明: 
**  
** 作    者:              日    期: 
** 建立版本:              
** 
**----------------------------------------modification-------------------------------------------------- 
** 作    者: 
** 日    期: 
** 版    本:            标    记: 
** 说    明: 
** 
********************************************************************************************************/ 
 
#include "xymodem.h" 
#include "heads.h" 
 
unsigned int buf_filelen(unsigned char *ptr); 
 
/***************************************************************************************** 
** 函数名称: 
** 函数功能: 
** 入口参数: 
** 返 回 值: 
** 编    写:        日    期:      版 本 号: 
** 修改历史: 
******************************************************************************************/ 
int ymodem_init(modem_struct *mblock) 
{ 
    int stat; 
    int max_tries = MODEM_MAX_RETRIES; 
    int crc_tries =MODEM_CRC_RETRIES; 
    unsigned char *bufptr = mblock->buf; 
    unsigned char *namptr = mblock->filename; 
     
    mblock->nxt_num = 0; 
    mblock->modemtype = 2; 
    mblock->rec_err = 0; 
    mblock->crc_mode = 1; 
     
    while (max_tries-- > 0) 
    {    
        stat = modem_recvdata(mblock); 
        if (0 == stat)              //接收成功 
        { 
            //file name 
            while (*bufptr != '\0') 
            { 
                *namptr++ = *bufptr++; 
            } 
            *namptr = '\0'; 
            bufptr++; 
            while (*bufptr == ' ') 
            { 
                bufptr++; 
            } 
            //file length 
            mblock->filelen = buf_filelen(bufptr); 
            //other data; 
            Uart_SendByte(MODEM_ACK); 
            return  0; 
        } 
        else if (2 == stat)         //取消传输 
        { 
            return 2; 
        } 
        else if (-3 == stat) 
        { 
            if (mblock->cur_num == 1) 
            { 
            	mblock->modemtype = 1; 
                mblock->nxt_num = 2; 
                return 1; 
            } 
        } 
        else                   //超时或校验方式不对 
        { 
            if (crc_tries-- <= 0) 
            { 
                crc_tries = MODEM_CRC_RETRIES; 
                mblock->crc_mode = (mblock->crc_mode+1) & 1; 
            } 
        } 
    } 
    return -1; 
} 
 
/***************************************************************************************** 
** 函数名称: 
** 函数功能: 
** 入口参数: 
** 返 回 值:0:成功接收数据                 -1:接收超时             -2:帧错误 
             -3:帧序号序号错误(严重错误)    1:消息结束              2:取消发送           
** 编    写:        日    期:      版 本 号: 
** 修改历史: 
******************************************************************************************/ 
int modem_recvdata(modem_struct *mblock) 
{ 
    int stat, hd_found=0, i; 
    int can_counter=0, eot_counter=0; 
    unsigned char *in_ptr = mblock->buf; 
    int cksum; 
    unsigned char ch, blk, cblk, crch, crcl; 
     
    Uart_RxEmpty();                         //接收缓冲区清空 
     
    if (mblock->nxt_num == 0) 
    { 
        if (mblock->crc_mode) 
        { 
            Uart_SendByte(MODEM_C); 
        } 
        else 
        { 
            Uart_SendByte(MODEM_NAK); 
        } 
    } 
    else 
    { 
        if (mblock->rec_err) 
        { 
            Uart_SendByte(MODEM_NAK); 
        } 
        else 
        { 
            if (mblock->nxt_num == 1) 
            { 
                if (mblock->crc_mode) 
                { 
                    Uart_SendByte(MODEM_C); 
                } 
                else 
                { 
                    Uart_SendByte(MODEM_NAK); 
                } 
            } 
            else 
            { 
                Uart_SendByte(MODEM_ACK); 
            } 
        } 
    } 
    while (!hd_found)                               //头字节 
    { 
        stat = Uart_RecvByteTimeout(&ch); 
        if (stat == 0) 
        { 
            switch (ch) 
            { 
                case MODEM_SOH : 
                    hd_found = 1; 
                    mblock->len = 128; 
                    break; 
                case MODEM_STX : 
                    hd_found = 1; 
                    mblock->len = 1024; 
                    break; 
                case MODEM_CAN : 
                    if ((++can_counter) >= MODEM_CAN_COUNT) 
                    { 
                        return 2; 
                    } 
                    break; 
                case MODEM_EOT :                                //文件传输结束 
                    if ((++eot_counter) >= MODEM_EOT_COUNT) 
                    { 
                        Uart_SendByte(MODEM_ACK); 
                        if (mblock->modemtype == 2)         //Ymodem协议为批文件传输协议 
                        { 
                            Uart_SendByte(MODEM_C);          //单个文件需 C ACK C后会自动停止传输 
                            Uart_SendByte(MODEM_ACK); 
                            Uart_SendByte(MODEM_C); 
                            modem_cancle();               //多个文件强制停止传输 
                        } 
                        return 1; 
                    } 
                    break; 
                default: 
                    break; 
            } 
        } 
        else 
        { 
            return -1; 
        } 
    } 
     
    stat = Uart_RecvByteTimeout(&blk);           //数据块错误或超时 
    if (stat != 0) 
    { 
        return -1; 
    } 
 
    stat = Uart_RecvByteTimeout(&cblk);           //数块补码 
    if (stat != 0) 
    { 
       return -1; 
    } 
 
    for (i=0; i < mblock->len ; i++) 
    { 
        stat = Uart_RecvByteTimeout(in_ptr++); 
        if (stat != 0) 
        { 
            return -1; 
        } 
    } 
     
    stat = Uart_RecvByteTimeout(&crch);         //CRC 
    if (stat != 0) 
    { 
        return -1; 
    } 
     
    if (mblock->crc_mode) 
    { 
        stat = Uart_RecvByteTimeout(&crcl);              
        if (stat != 0) 
        { 
            return -1; 
        } 
    } 
 
    if (blk^cblk != 0xff)                        
    { 
        return (-2); 
    } 
 
    if (mblock->crc_mode) 
    { 
        in_ptr = mblock->buf; 
        cksum = 0; 
         
        for (stat=mblock->len ; stat>0; stat--) 
        { 
            cksum = cksum^(int)(*in_ptr++) << 8; 
            for (i=8; i!=0; i--) 
            { 
                if (cksum & 0x8000) 
                    cksum = cksum << 1 ^ 0x1021; 
                else 
                    cksum = cksum << 1; 
            } 
        } 
        cksum &= 0xffff; 
         
        if (cksum != (crch<<8 | crcl)) 
        { 
            mblock->rec_err = 1; 
            return (-2); 
        } 
    } 
    else 
    { 
        for (i=0; ilen; i++)                //和校验方式 
        { 
            cksum += mblock->buf[i]; 
        } 
        if ((cksum&0xff)!=crch) 
        { 
            mblock->rec_err = 1; 
            return (-2); 
        } 
    } 
     
    mblock->cur_num = blk; 
    if (blk != mblock->nxt_num)                      //blk检查 
    {  
        return (-3); 
    } 
 
    mblock->nxt_num++; 
    mblock->rec_err = 0; 
    return 0; 
} 
 
unsigned int buf_filelen(unsigned char *ptr) 
{ 
    int datatype=10, result=0; 
 
    if (ptr[0]=='0' && (ptr[1]=='x' && ptr[1]=='X')) 
    { 
        datatype = 16; 
        ptr += 2; 
    } 
 
    for ( ; *ptr!='\0'; ptr++) 
    { 
        if (*ptr>= '0' && *ptr<='9') 
        { 
            result =result*datatype+*ptr-'0'; 
        } 
        else 
        { 
            if (datatype == 10) 
            { 
                return result; 
            } 
            else 
            { 
                if (*ptr>='A' && *ptr<='F') 
                { 
                    result = result*16 + *ptr-55;             //55 = 'A'-10 
                } 
                else if (*ptr>='a' && *ptr<='f') 
                { 
                    result = result*16 + *ptr-87;             //87 = 'a'-10 
                } 
                else 
                { 
                    return result; 
                } 
            } 
        } 
    } 
    return result; 
} 
 
 
void modem_cancle(void) 
{ 
    Uart_SendByte(0x18); 
    Uart_SendByte(0x18); 
    Uart_SendByte(0x18); 
    Uart_SendByte(0x18); 
    Uart_SendByte(0x18); 
}