I have two programs I run under Wine that make use of the serial ports. I get this error and fixme when I run then:
err:comm:GetCommState tcgetattr or ioctl error 'Invalid argument' fixme:comm:SetupComm insize 1050 outsize 1050 unimplemented stub I fixed these two in my copy of Wine with the attached patch. First, the GetCommState errors were because I was using a pseudo-tty as the serial port, so setserial didn't work on it. I modified it to ignore errors from setserial that set errno==EINVAL. SetupComm is a function that sets the communications buffer sizes. Wine doesn't have its own communication buffers, so I filled out this function to set the kernel's xmit buffer to the requested amount if possible, and ignore the receive buffer. With these changes, my programs work properly (they worked properly before), and I don't get these complaints from Wine. -----ScottG.
--- wine-20040505/dlls/kernel/comm.c 2004-04-19 16:12:14.000000000 -0400 +++ wine-20040505-sg/dlls/kernel/comm.c 2004-05-15 18:30:26.000000000 -0400 @@ -163,7 +163,10 @@ #ifdef TIOCMGET unsigned int mstat, okay; okay = ioctl(fd, TIOCMGET, &mstat); - if (okay) return okay; + /* If this device isn't a serial port but a pseudo-tty, + * don't return an error */ + if (okay) + return (errno == EINVAL) ? 0 : -1; if (andy) mstat &= andy; mstat |= orrie; return ioctl(fd, TIOCMSET, &mstat); @@ -991,7 +994,10 @@ * * BUGS * - * Stub. + * We don't have our own buffers, so this function isn't really that + * meaningful. Still, Linux will let us set the transmit buffer + * size, so we might as well. + * */ BOOL WINAPI SetupComm( HANDLE handle, /* [in] The just created communication resource handle. */ @@ -999,12 +1005,30 @@ DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */ { int fd; + struct serial_struct ss; + int ret = TRUE; + + if (0>(fd=get_comm_fd( handle, GENERIC_READ ))) + return FALSE; + +#if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL) + do { + /* Assume failure */ + ret = FALSE; + if (ioctl(fd,TIOCGSERIAL,&ss) == -1) + break; + + ss.xmit_fifo_size = outsize; + if (ioctl(fd,TIOCSSERIAL,&ss) == -1) + break; + + /* Yay, it worked */ + ret = TRUE; + } while(0); +#endif - FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize); - fd=get_comm_fd( handle, GENERIC_READ ); - if(0>fd) return FALSE; release_comm_fd( handle, fd ); - return TRUE; + return ret; } /***************************************************************************** @@ -1498,23 +1522,41 @@ { struct termios port; int fd,speed; - int stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE; + int stat; - TRACE("handle %p, ptr %p\n", handle, lpdcb); + // TRACE("handle %p, ptr %p\n", handle, lpdcb); fd = get_comm_fd( handle, GENERIC_READ ); if (fd < 0) return FALSE; - if (tcgetattr(fd, &port) == -1 + TRACE("tcgetattr: fd=%d, port=%p, stat=%p, TIOCMGET is %s\n",fd,&port,&stat, #ifdef TIOCMGET - || ioctl(fd, TIOCMGET, &stat) == -1 +"defined" +#else +"undefined" #endif - ) { + ); + if (tcgetattr(fd, &port) == -1) { int save_error=errno; - ERR("tcgetattr or ioctl error '%s'\n", strerror(save_error)); + ERR("tcgetattr error '%s'\n", strerror(save_error)); COMM_SetCommError(handle,CE_IOE); release_comm_fd( handle, fd ); return FALSE; } + +#ifdef TIOCMGET + if (ioctl(fd, TIOCMGET, &stat) != -1) + ; /* It worked! */ + else if (errno != EINVAL) { + int save_error=errno; + ERR("ioctl(TIOCMGET,...) error '%s'\n", strerror(save_error)); + COMM_SetCommError(handle,CE_IOE); + release_comm_fd( handle, fd ); + return FALSE; + } + else /* EINVAL probably means this was a pseudo-tty */ +#endif + stat = DTR_CONTROL_ENABLE | RTS_CONTROL_ENABLE; + release_comm_fd( handle, fd ); #ifndef __EMX__ #ifdef CBAUD @@ -1889,7 +1931,7 @@ return FALSE; result = ioctl(fd, TIOCMGET, &mstat); release_comm_fd( hFile, fd ); - if (result == -1) + if ((result == -1) && (errno != EINVAL)) { WARN("ioctl failed\n"); return FALSE;