0

I have a simple test program which waits for a set of 3 characters to be sent to the USB port (0x10, 0x04 and 0x02) and then should respond with "Hello World". For some reason, the first character is missed off the response so I only see "ello World".

I am using the USB-OTG port with modprobe g_serial for communication if that makes any difference.

What am I missing?

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <linux/usb/g_printer.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>

#define ODROID_SERIAL_GADGET        "/dev/ttyGS0"
#define BUF_SIZE    1024

int main()
{
    struct pollfd   fd[0];
    struct termios tty;
    int timeover=1000;
    static char buf[BUF_SIZE];
    char obuff[] = ".";

    int ox10Found, ox04SeqeunceFound, i;    
    int bytes_read, retval;
    int max_read_time = 2; /* units of 250ms after which incoming data times out - 1 causes larger files to be split */

    fd[0].fd = open(ODROID_SERIAL_GADGET, O_RDWR);
    if (fd[0].fd < 0) {
        printf("Error %d opening %s\n", fd[0].fd, ODROID_SERIAL_GADGET);
        close(fd[0].fd);
        return(-1);
    }

    tcgetattr(fd[0].fd,&tty); /* save current serial port settings */
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); // Enable canonical input - we need to read contorol characters
    tty.c_oflag = 0; // no output processing
    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
    tty.c_cc[VMIN]  = 0;            // 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 controls,
                                    // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
    tty.c_cflag |= 0;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    tcsetattr(fd[0].fd,TCSANOW,&tty);

    fd[0].events = POLLIN | POLLRDNORM;

    ox10Found=0;
    ox04SeqeunceFound=0;

    while (1) {
        /* Wait for up to 1/4 second for data. */
        retval = poll(fd, 1, 250);
        timeover++;
        if (timeover>1000) {
            timeover=max_read_time+1;
        }

        if (retval) {
            bytes_read = read(fd[0].fd, buf, BUF_SIZE);

            if (bytes_read < 0) {
                /* Open device file for serial gadget. */
                printf("Error %d reading from %s\n",fd[0].fd, ODROID_SERIAL_GADGET);
                close(fd[0].fd);
                return(-1);
            }

            for (i = 0; i < bytes_read; i++) {
                if (buf[i]==0x10 && !ox10Found && !ox04SeqeunceFound) {
                    ox10Found=1;
                    continue;
                } else if (buf[i]==0x04 && ox10Found) {
                    ox04SeqeunceFound=1;
                    continue;
                } else {
                    ox10Found=0;
                }

                if (buf[i]==0x02 && ox04SeqeunceFound) {
                    write(fd[0].fd, "Hello World", 11);
                    tcdrain(fd[0].fd); // Wait for output
                }
            }
        }
    }
}
RWAP
  • 11
  • 2
  • `tty.c_oflag = 0;` could be problematic. See [Setting Terminal Modes Properly](http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_12.html#SEC237). `tty.c_oflag &= ~OPOST;` would be better. There are some misleading comments and a garbage statement: `tty.c_cflag |= 0;`. There is no explicit baudrate specification. Otherwise your code seems to function as expected on an ordinary serial port. What happens when the input is received a 2nd time? – sawdust Nov 27 '20 at 23:27
  • I have tried ```tty.c_oflag &= ~OPOST;``` but it made no difference. The second time the input is sent, I get the same output from the serial port - ie the leading "H" is missing. It is peculiar - if I send a longer string of characters to trigger the response, I then lose more characters from the output; which suggests it is something to do with the handling of the serial pointer. It could of course be linked to the program I am using to test the response - what would be the best method of testing this? I cant get PuTTY on Windows to display anything! – RWAP Nov 29 '20 at 15:47
  • *"It could of course be linked to the program I am using to test the response - what would be the best method of testing this?"* (1) Avoid using a word like *"link"* that is jargon. (2) Clarify what program you are using on the host end. You have already mentioned *"a simple test program"* on the target. Are you so foolish as to test with unproven code on both ends of a link? *"I cant get PuTTY ... "* -- Negative summation is not helpful. I already warned you about setting baudrates. – sawdust Nov 30 '20 at 00:57
  • The baudrate is correct at both ends. "link" = jargon? Sorry it is perfect english to say something might be linked to something else. I am using a BASIC program within an emulator which opens a channel direct to the serial port. It prints the 3 characters the C program is expecting to receive and then reads back the input from the same channel. I have been writing BASIC programs to deal with pipes, channels and serial ports for 30+ years. PuTTY on Windows - I start it up - see a blank screen with a green cursor block - Enter the expected keycodes but nothing appears on screen – RWAP Nov 30 '20 at 18:24

0 Answers0