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