Serial port under wine

Paul Sheer psheer at icon.co.za
Thu Jan 8 05:58:34 CST 2004


I am trying to write a simple serial port library
that has the same lowest-common-denominator interface
under both Windows and Linux. I developed it under wine
using mingw32 - i want my apps that use it to work under
both windows and linux (these are command-line apps only).

i noticed that wine does not seem to report errors
from GetOverLapped.. and Wait..Object in a way that
makes sense. By ignoring errors, and just looking at
the dwRead result, i got it to work.

my attempt at a posix-like read function is below
(the linux version follows further down)

best wishes

-paul

---------

int serial_port_read (struct serial_port *p, unsigned char *buf, int
buf_len, int milli_timeout)
{
    static int c = 0;
    DWORD dwStart, dwRead, r;
    int l, total = 0;
    dwStart = GetTickCount ();
    while (buf_len > 0) {
	l = serial_port_chars_avail (p);
	if (l < 0)
	    return total > 0 ? total : SERIAL_PORT_ERROR;
	if (l == 0 && GetTickCount () - dwStart >= milli_timeout)
	    return total > 0 ? total : SERIAL_PORT_TIMEOUT;
/* Like POSIX read(), we return without blocking if we have read at
least one character: */
	if (l == 0 && total >= 1)
	    return total;
/* Read minimum of one character, and a maximum of buf_len
characters: */
	CLIP (l, 1, buf_len);
	dwRead = 0;
	if (!ReadFile (p->hComm, buf, l, &dwRead, &p->osRead)) {
	    if ((r = GetLastError ()) == ERROR_IO_PENDING) {
		dwRead = 0;
		GetOverlappedResult (p->hComm, &p->osRead, &dwRead, TRUE);
	    }
	}
	total += dwRead;
	buf_len -= dwRead;
	buf += dwRead;
    }
    return total;
}

------------


int serial_port_read (struct serial_port *p, unsigned char *buf, int
buf_len, int milli_timeout)
{
    int c;
    struct timeval tv;
    fd_set rd;
    if (!buf_len)
	return 0;
    FD_ZERO (&rd);
    FD_SET (p->fd, &rd);
    switch (select (p->fd + 1, &rd, NULL, NULL, milli_timeout < 0 ? NULL
: (tv.tv_sec = milli_timeout / 1000,
									    tv.tv_usec = milli_timeout % 1000,
									    &tv))) {
    case 1:
	c = read (p->fd, buf, buf_len);
	if (!c) {
	    p->error = 0;
	    return SERIAL_PORT_HANGUP;
	}
	if (c < 0) {
	    p->error = errno;
	    return SERIAL_PORT_ERROR;
	}
	return c;
    case 0:
	return SERIAL_PORT_TIMEOUT;
    default:
	p->error = errno;
	return SERIAL_PORT_ERROR;
    }
}









More information about the wine-devel mailing list