⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xymodem.c

📁 XModem / YModem Source Code
💻 C
字号:

#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)              // receive successful
      {
         //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)         // cancel transfer
      {
         return 2;
      }
      else if (-3 == stat)
      {
         if (mblock->cur_num == 1)
         {
            mblock->modemtype = 1;
            mblock->nxt_num = 2;
            return 1;
         }
      }
      else   // cancel transfer
      {
         if (crc_tries-- <= 0)
         {
            crc_tries = MODEM_CRC_RETRIES;
            mblock->crc_mode = (mblock->crc_mode+1) & 1;
         }
      }
   }
   return -1;
}

/*****************************************************************************************
*  0: Transfer successful
* -1: Receive overtime
* -2: error
* -4: serious error
*  1: end of message
*  2: cancel transfer
******************************************************************************************/
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(); // Clear receive buffer
    
   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) // header block
   {
      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 :                                // End of Transfer
                              if ((++eot_counter) >= MODEM_EOT_COUNT)
                              {
                                 Uart_SendByte(MODEM_ACK);
                                 if (mblock->modemtype == 2)         //Ymodem batch file transfer
                                 {
                                    Uart_SendByte(MODEM_C);          // automatic transfer stop after single file
                                    Uart_SendByte(MODEM_ACK);
                                    Uart_SendByte(MODEM_C);
                                    modem_cancle();               // cancel transfer after multiple file
                                 }
                                 return 1;
                              }
                              break;
            default:
                              break;
         }
      }
      else
      {
         return -1;
      }
   }
    
   stat = Uart_RecvByteTimeout(&blk);           // data block error or overtime
   if (stat != 0)
   {
      return -1;
   }

   stat = Uart_RecvByteTimeout(&cblk);           // data block 
   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; i<mblock->len; i++)                // crc check method
      {
         cksum += mblock->buf[i];
      }
      if ((cksum&0xff)!=crch)
      {
         mblock->rec_err = 1;
         return (-2);
      }
   }
    
   mblock->cur_num = blk;
   if (blk != mblock->nxt_num)                      // block check
   { 
      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);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -