Fail to get data struct from serial port

124 views Asked by At

I would like to send and receive file in below code. but there is wrong in function,"xmodem_receive".

"xmodem_send" function is sending "xmodem_chunk" through "tty/AMA0" and receive data are " ret = saferead(fd, &chunk, sizeof(chunk)) " in "xmodem_receive" but There are no reading data in this line! Rather, This line stop my code. Anyone teach me required at least to run this code?

This is the code (omitted).

#define X_STX 0x02
#define X_EOT 0x04
#define X_ACK 0x06
#define X_NAK 0x15

#define min(a, b)   ((a) < (b) ? (a) : (b))

#define DEBUG 0

struct xmodem_chunk {
    uint8_t start;
    uint8_t blk;
    uint8_t blk_neg;
    uint8_t payload[1024];
    uint16_t crc;
} __attribute__((packed));

#define CRC_POLY 0x1021

int saferead(int fd, const void *p, size_t want){
      int ret;
      int ret_sum = 0;

      errno = 0;
      while (want){
          ret = read(fd, (uint8_t*)p, want);
          if(ret == 0)
                return -1; /* EOF */
          if(ret <= 0){
               if(errno != EINTR && errno != EAGAIN ) {
               return -1;
          }
          errno = 0;
          continue;
         }
         want -= ret;
         p = (uint8_t*) p + ret;
         ret_sum += ret;
     }
     return ret_sum;
   }
static int xmodem_send(int serial_fd, const char *filename)
   {
      int ret, fd;
      uint8_t eof = X_EOT; 
      struct xmodem_chunk chunk; 

      fd = open(filename, O_RDONLY); 
      if(fd < 0){ 
          perror("open");
          return -errno;
      } 


      fstat(fd, &stat); 
      len = stat.st_size; 
      buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 

      if(!buf){ 
          perror("mmap");
          return -errno;
      }
      printf("Sending %s \n", filename);
      chunk.start = X_STX; 

      while (len){
          size_t z = 0;
          int next = 0;
          char status;

          z = min(len, sizeof(chunk.payload)); 
          memcpy(chunk.payload, buf, z);
          memset(chunk.payload + z, 0xff, sizeof(chunk.payload) - z); 
          chunk.crc = swap16(crc16(chunk.payload, sizeof(chunk.payload)));
          chunk.blk_neg = 0xff - chunk.blk; 
          int i;
          for(i = 0; i < 3; i++){
               ret = safewrite(serial_fd, &chunk, sizeof(chunk)); 
               if(ret != sizeof(chunk)){
                   return -errno;
               }
          }
         if(next){
             chunk.blk++;
             len -= z;
             buf += z;
         }
     }

     ret = safewrite(serial_fd, &eof, sizeof(eof));
     if(ret != sizeof(eof))
         return -errno;

     return 0;
 }

 static xmodem_receive(int serial_fd, char* filename){
     size_t len;
     int ret, fd;
     size_t retry;
     struct xmodem_chunk chunk;
     struct stat stat;
     FILE *fp;
     uint8_t eof = X_EOT;
     int eof_count=0;


     retry = 3;
     fp = fopen(filename, "ab+");


    while(1){
        int garbage_count=0;
        int correct_count=0;
        uint8_t chunk_payload[1024];
        uint8_t garbage_payload[3][1024];
        uint16_t garbage_crc[3];
        size_t z = 0;   
        while(retry){

                int next = 0;

                ret = saferead(fd, &chunk, sizeof(chunk)); <--This line is the problem.
                z = sizeof(chunk.payload);
                if(chunk.start != X_STX){
                     printf("error STX\n");
                     return 0; // error
                }
                printf("retry part\n");
                if(chunk.crc != swap16(crc16(chunk.payload, sizeof(chunk.payload)))){ 
                     if(garbage_count > 1){
                         int i;
                         for(i=0; i < garbage_count; i++){
                            if(chunk.crc == swap16(crc16(garbage_payload[i], sizeof(chunk.payload)))){
                                correct_count++;
                                memcpy(chunk_payload, garbage_payload[i], len);
                            }
                        }
                        if(correct_count < 1){
                            memcpy(garbage_payload[garbage_count], &chunk.payload, len);
                            garbage_count++;
                        }
                        printf("garbage#1\n");  
                     }else{
                         memcpy(garbage_payload[0], &chunk.payload, len);
                         garbage_crc[0] = chunk.crc;
                         garbage_count++;
                         printf("garbage#2\n");
                     }


                 }else{
                     printf("correct\n");
                     correct_count++;
                     memcpy(chunk_payload , &chunk.payload, len);
                 }
         }
         safewrite(fd, &chunk_payload, z);           
     }
     close(fd);
     return 0;
 }


  int main(int argc, char **argv){
        int a, ret, serial_fd;

        serial_fd = open_serial("/dev/ttyUSB0", 115200);
        // serial_fd = open_serial("/dev/ttyAMA0", 115200);

        ret = xmodem_receive(serial_fd, "sample.jpg");
        // ret = xmodem_send(serial_fd, "sample.jpg");

  } 

This is full code(Sorry to have kept you waiting)

`
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/mman.h>


#define X_STX 0x02
#define X_EOT 0x04
#define X_ACK 0x06
#define X_NAK 0x15

#define min(a, b)   ((a) < (b) ? (a) : (b))

#define DEBUG 0

struct xmodem_chunk {
    uint8_t start;
    uint8_t blk;
    uint8_t blk_neg;
    uint8_t payload[1024];
    uint16_t crc;
} __attribute__((packed));

#define CRC_POLY 0x1021

/* 'Safe' write */
int safewrite(int fd, const void *p, size_t want){
    int ret;
    int ret_sum = 0;

    errno = 0;
    while(want){
        ret = write(fd, (uint8_t *)p,want);
        if(ret <= 0) {
            if (errno != EINTR && errno != EAGAIN){
                return -1;
            }
            errno = 0;
            continue;
        }
        want -= ret;
        p = (uint8_t*) p + ret;
        ret_sum += ret;
    }
    return ret_sum;
}

int saferead(int fd, const void *p, size_t want){
    int ret;
    int ret_sum = 0;

    errno = 0;
    while (want){
        ret = read(fd, (uint8_t*)p, want);
        if(ret == 0)
            return -1; /* EOF */
        if(ret <= 0){
            if(errno != EINTR && errno != EAGAIN ) {
                return -1;
            }
            errno = 0;
            continue;
        }
        want -= ret;
        p = (uint8_t*) p + ret;
        ret_sum += ret;
    }
    return ret_sum;
}

static uint16_t crc_update(uint16_t crc_in, int incr)
{
    uint16_t xor = crc_in >> 15;
    uint16_t out = crc_in << 1;

    if(incr)
        out++;

    if(xor)
        out ^= CRC_POLY; // xor 0b1000000100001

    return out;
}

static uint16_t crc16(const uint8_t *data, uint16_t size) 
{
    uint16_t crc, i;

    for(crc = 0; size > 0; size--, data++) 
        for(i = 0x80; i; i >> 1) 
            crc = crc_update(crc, *data & i); 

    for ( i = 0; i < 16; i++)
        crc = crc_update(crc, 0);

    return crc;
}
static uint16_t swap16(uint16_t in) 
{
    return (in >> 8) | ((in & 0xff) << 8);
}

enum {
    PROTOCOL_XMODEM,
    PROTOCOL_YMODEM,
};

static int xymodem_send(int serial_fd, const char *filename)
{
    size_t len; 
    int ret, fd;
    uint8_t answer;
    struct stat stat;
    const uint8_t *buf;
    uint8_t eof = X_EOT; 
    struct xmodem_chunk chunk; 
    int skip_payload = 0;

    fd = open(filename, O_RDONLY); 
    if(fd < 0){ 
        perror("open");
        return -errno;
    }   


    fstat(fd, &stat); 
    len = stat.st_size;
    buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);

    if(!buf){ 
        perror("mmap");
        return -errno;
    }

    if(DEBUG) {
        printf("Wainting for receiver ping ...");
        fflush(stdout); 

        do {
            ret = read(serial_fd, &answer, sizeof(answer)); 
            if(ret != sizeof(answer)){
                perror("read");
                return -errno;
            }
        }while (answer != 'C'); 

        printf("dome.\n");

    }

    printf("Sending %s ", filename);
/*
    if(protocol == PROTOCOL_YMODEM) {
        strncpy ((char*) chunk.payload, filename, sizeof(chunk.payload));
        chunk.blk = 0;
        skip_payload = 1;
    }else {
        chunk.blk = 1;
    }
*/
    chunk.start = X_STX; 
    while (len){
        size_t z = 0;
        int next = 0;
        char status;

        z = min(len, sizeof(chunk.payload)); 
        memcpy(chunk.payload, buf, z);
        memset(chunk.payload + z, 0xff, sizeof(chunk.payload) - z); // 

        chunk.crc = swap16(crc16(chunk.payload, sizeof(chunk.payload)));
        chunk.blk_neg = 0xff - chunk.blk; 
        int i;
        for(i = 0; i < 3; i++){
            ret = safewrite(serial_fd, &chunk, sizeof(chunk)); 
            if(ret != sizeof(chunk)){
                return -errno;
            }
        }

        if(next){
            chunk.blk++;
            len -= z;
            buf += z;
        }
    }

    ret = safewrite(serial_fd, &eof, sizeof(eof));
    if(ret != sizeof(eof))
        return -errno;
    ret = safewrite(serial_fd, &eof, sizeof(eof));
    if (ret != sizeof(eof))
        return -errno;

    ret = safewrite(serial_fd, &eof, sizeof(eof));
    if (ret != sizeof(eof))
        return -errno;
    printf("done.\n");

    return 0;
}

static xmodem_receive(int serial_fd, char* filename){
    size_t len;
    int ret, fd;
    size_t retry;
    uint8_t expected_blkno;
    size_t nrecv;
    uint16_t crch, crcl;
    size_t datalen;
    struct xmodem_chunk chunk;
    struct stat stat;
    int file_size=0;
    int c;
    FILE *fp;
    char* exet;
    uint8_t send_start;
    uint8_t eof = X_EOT;
    int eof_count=0;


    retry = 3;

    fp = fopen(filename, "ab+");


    while(1){

        int v_stx_count=0;
        int inv_stx_count=0;
        int garbage_blk_count=0;
        int correct_blk_count=0;
        int garbage_count=0;
        int correct_count=0;
        uint8_t chunk_payload[1024];
        uint8_t garbage_payload[3][1024];
        uint16_t garbage_crc[3];
        int val_payload_crc_pr = 0;
        int val_payload_crc_cr = 0;
        int val_payload_crc_nx = 0;
        int pr_val_crc=0;
        int nx_val_crc=0;

        int val_crc=0;
        size_t z = 0;   
        while(retry){

                int next = 0;

                ret = saferead(fd, &chunk, 1);
                printf("read chunk");
                z = sizeof(chunk.payload);
                if(chunk.start != X_STX){
                    printf("error STX\n");
                    return 0; // error
                }
                printf("retry part\n");
                if(chunk.crc != swap16(crc16(chunk.payload, sizeof(chunk.payload)))){ 
                    if(garbage_count > 1){
                        int i;
                        for(i=0; i < garbage_count; i++){

                            if(chunk.crc == swap16(crc16(garbage_payload[i], sizeof(chunk.payload)))){
                                correct_count++;
                                memcpy(chunk_payload, garbage_payload[i], len);
                            }
                        }
                        if(correct_count < 1){
                            memcpy(garbage_payload[garbage_count], &chunk.payload, len);
                            garbage_count++;
                        }
                        printf("garbage#1\n");  
                    }else{
                        // ごみの登録
                        memcpy(garbage_payload[0], &chunk.payload, len);
                        garbage_crc[0] = chunk.crc;
                        garbage_count++;
                        printf("garbage#2\n");
                    }


                }else{
                    printf("correct\n");
                    correct_count++;
                    memcpy(chunk_payload , &chunk.payload, len);
                }



        }
        safewrite(fd, &chunk_payload, z);            


    }
    close(fd);
    return 0;
}

static int open_serial(const char *path, int baud)
{
    int fd;
    struct termios tty;

    fd = open(path, O_RDWR | O_SYNC);
    if(fd < 0) {
        perror("open");
        return -errno;
    }

    memset(&tty, 0, sizeof(tty));
    if(tcgetattr(fd, &tty) != 0) {
        perror("tcgetattr");
        return -errno;
    }

    cfsetospeed(&tty, baud);
    cfsetispeed(&tty, baud);

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit
    tty.c_iflag &= ~IGNBRK;             // disable break processing
    tty.c_lflag = 0;                // nosignaling chars, no echo,
    // no canonical processing
    tty.c_oflag = 0;                // no remapping, no delays
    tty.c_cc[VMIN] = 1;             // read doesn't block
    tty.c_cc[VTIME] = 5;                // 0.5 seconds read timeout

    tty.c_iflag &= ~(IXON | IXOFF | IXANY);     // shut off xon/xoff ctrl

    tty.c_cflag |= (CLOCAL | CREAD);        // ignore modem controlsm

    tty.c_cflag &= ~(PARENB | PARODD);      // ignore modem controls,
    // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off party
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        perror("tcsetattr");
        return -errno;
    }

    return fd;
}

static void dump_serial(int serial_fd)
{
    char in;

    for (;;) {
        read(serial_fd, &in, sizeof(in));
        printf("%c", in);
        fflush(stdout);
    }
}

int main(int argc, char **argv){
    int a, ret, serial_fd;

    serial_fd = open_serial("/dev/ttyUSB0", 115200);


    ret = xmodem_receive(serial_fd, "sample.jpg");
//  dump_serial(serial_fd);

}   
`
1

There are 1 answers

0
sawdust On BEST ANSWER

Your program never receives any data because it never tries to perform I/O with the serial port. xmodem_receive() never uses its parameter serial_fd.

static xmodem_receive(int serial_fd, char* filename){

Instead this routine uses the uninitialized variable fd as arguments in calls to saferead() and safewrite().

    int ret, fd;
...
                ret = saferead(fd, &chunk, 1);
...
        safewrite(fd, &chunk_payload, z);            

To compound this error, you don't bother to check the return values from these calls, so any errors due to use of the uninitialized variable (i.e. an invalid file descriptor) get silently discarded.