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.
#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;
}

#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;
}

_______________________________________________
freebsd-usb@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to