ucom serial bug?

Gabor gabor at sentex.net
Wed Dec 3 12:09:57 PST 2008


Hi USB developers,

We have a program that communicates through serial ports with a legacy Windows application that we do not control. Using onboard 
serial ports, everything works fine.  When we try to use a USB to serial converter(type doesn't matter, UFTDI or Prolific) we run 
into problems. The first time we start up our side, everything works.  The second time we don't get carrier(DCD).  The other side is 
always running. Since we have no control over the legacy Windows program as it was written by another company we need carrier to be 
asserted to work.  I am including two little programs that illustrate the issue. Also, we do not encounter this issue when using 
NetBSD and its USB drivers.

To illustrate connect one machine to another using a null modem cable and on the end where you use check-carrier.c use the USB 
dongle.  Run the server.c on the other end.  Both take as argument the name of the device.  Start server.c first.

We have reproduced this problem on both CURRENT and RELENG_7.  Thanks for any insight.
-- 
Success is the result when preparation meets opportunity.
-------------- next part --------------
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ttycom.h>
#include <sys/ioctl.h>

int
main(int argc, char **argv)
{
    int fd, ctl, state = 0, val;
    struct termios t;


    if (argc < 2) {
        fprintf(stderr, "Usage: %s <device>\n", argv[0]);
        return 1;
    }
    if ((fd = open(argv[1], O_RDWR)) < 0) {
        fprintf(stderr, "errno: %d, error: %s\n", errno, strerror(errno));
        return 1;
    }
    if (tcgetattr(fd, &t) >= 0) {
        t.c_ispeed = 1200;
        t.c_ospeed = 1200;
        t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOCTL | ECHOPRT | ALTWERASE | NOFLSH | TOSTOP | FLUSHO | PENDIN | NOKERNINFO | EXTPROC);
        t.c_iflag &= ~(ISTRIP | ICRNL | INLCR | IGNCR | IXON | IXOFF | IXANY | IMAXBEL | IGNBRK | BRKINT | INPCK | IGNPAR | PARMRK);
        t.c_iflag |= IGNBRK;
        t.c_oflag &= ~(OPOST | ONLCR | OCRNL | OXTABS | ONOEOT | ONOCR | ONLRET);
        t.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CCTS_OFLOW | CRTS_IFLOW | CDTR_IFLOW | CDSR_OFLOW | CCAR_OFLOW);
        t.c_cflag |= (CS8|CREAD);
        t.c_cc[VMIN] = 1;
        t.c_cc[VTIME] = 0;
        tcsetattr(fd, TCSANOW, &t);
        val = fcntl(fd, F_GETFL, 0);
        if (val >= 0) {
            fcntl(fd, F_SETFL, val | O_NONBLOCK);
        }
    }
    else {
        fprintf(stderr, "errno: %d, error: %s\n", errno, strerror(errno));
        return 1;
    }

    if ((ctl = ioctl(fd, TIOCMGET, &state)) < 0) {
        fprintf(stderr, "errno: %d, error: %s\n", errno, strerror(errno));
        return 1;
    }

    if ((ctl = ioctl(fd, TIOCMGET, &state)) < 0) {
        fprintf(stderr, "errno: %d, error: %s\n", errno, strerror(errno));
        return 1;
    }
    state |= TIOCM_DCD;
    ioctl(fd, TIOCMSET, &state);
    if ((ctl = ioctl(fd, TIOCMGET, &state)) < 0) {
        fprintf(stderr, "errno: %d, error: %s\n", errno, strerror(errno));
        return 1;
    }
    if ((state & TIOCM_DCD)) {
        printf("got carrier\n");
    }
    else {
        printf("%d\n", state);
    }
    if ((state & TIOCM_LE)) {
        printf("TIOCM_LE\n");
    }
    if ((state & TIOCM_DTR)) {
        printf("TIOCM_DTR\n");
    }
    if ((state & TIOCM_RTS)) {
        printf("TIOCM_RTS\n");
    }
    if ((state & TIOCM_ST)) {
        printf("TIOCM_ST\n");
    }
    if ((state & TIOCM_SR)) {
        printf("TIOCM_SR\n");
    }
    if ((state & TIOCM_CTS)) {
        printf("TIOCM_CTS\n");
    }
    if ((state & TIOCM_DCD)) {
        printf("TIOCM_DCD\n");
    }
    if ((state & TIOCM_RI)) {
        printf("TIOCM_RI\n");
    }
    if ((state & TIOCM_DSR)) {
        printf("TIOCM_DSR\n");
    }
    return 0;
}

-------------- next part --------------
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>

int
main(int argc, char **argv)
{
    int fd = -1, val, n, len;
    unsigned char buf[80];
    struct termios t;
    fd_set rin;
    struct timeval tv;


    if (argc < 2) {
        fprintf(stderr, "Usage: %s </dev/cuaa?>\n", argv[0]);
        return 1;
    }
REDO:
    if (fd > -1) {
        close(fd);
    }
    fd = open(argv[1], O_RDWR);
    if (fd > 0) {
        if (tcgetattr(fd, &t) >= 0) {
            t.c_ispeed = 1200;
            t.c_ospeed = 1200;
            t.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOCTL | ECHOPRT | ALTWERASE | NOFLSH | TOSTOP | FLUSHO | PENDIN | NOKERNINFO | EXTPROC);
            t.c_iflag &= ~(ISTRIP | ICRNL | INLCR | IGNCR | IXON | IXOFF | IXANY | IMAXBEL | IGNBRK | BRKINT | INPCK | IGNPAR | PARMRK);
            t.c_oflag &= ~(OPOST | ONLCR | OCRNL | OXTABS | ONOEOT | ONOCR | ONLRET);
            t.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CCTS_OFLOW | CRTS_IFLOW | CDTR_IFLOW | CDSR_OFLOW | CCAR_OFLOW);
            t.c_cflag |= (CS8);
            t.c_cc[VMIN] = 1;
            t.c_cc[VTIME] = 0;
            tcsetattr(fd, TCSANOW, &t);
            val = fcntl(fd, F_GETFL, 0);
            if (val >= 0) {
                fcntl(fd, F_SETFL, val | O_NONBLOCK);
            }
        }
        while (1) {
            FD_ZERO(&rin);
            FD_SET(fd, &rin);
            n = select(fd + 1, &rin, 0, 0, 0);
            len = 0;
            if (n > 0 && FD_ISSET(fd, &rin)) {
                n = read(fd, buf, 1);
                if (n <= 0) {
                    goto REDO;
                }
                len = n;
                while (1) {
                    FD_ZERO(&rin);
                    FD_SET(fd, &rin);
                    tv.tv_sec = 0;
                    tv.tv_usec = 80000L;
                    n = select(fd + 1, &rin, 0, 0, &tv);
                    if (n > 0 && FD_ISSET(fd, &rin)) {
                        n = read(fd, buf + len, 80);
                        if (n <= 0) {
                            goto REDO;
                        }
                        len += n;
                        if (len == 3) {
                            if (isatty(fileno(stdout)))
                                fprintf(stderr, ".");
                            buf[0] = 0x04 | 0x80;
                            write(fd, buf, 1);
                            break;
                        }
                    }
                    else {
                        goto REDO;
                    }
                }
            }
            else {
                goto REDO;
            }
        }
    }
    else {
        fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno));
        return 1;
    }

    return 0;
}



More information about the freebsd-usb mailing list