Commit a1c45a52 authored by Ove Kaaven's avatar Ove Kaaven Committed by Alexandre Julliard

Made commerror and eventmask local to each port (for win16), made the

win16 routines use port indices instead of UNIX fds (this should make some Visual Basic stuff and similar garbage start working), moved some stuff around (win16 routines at top of file, win32 routines at bottom), made a couple of win32 routines use win32 handles, and added a few hints as to how to implement asynchronous buffers, based on which EnableCommNotification can eventually be implemented.
parent fab975e6
......@@ -10,6 +10,12 @@ struct DosDeviceStruct {
int unget;
int unget_byte;
int baudrate;
/* events */
int commerror, eventmask;
/* buffers */
char *inbuf,*outbuf;
/* notifications */
int wnd, n_read, n_write;
};
extern void COMM_Init(void);
......
......@@ -2,8 +2,11 @@
* DEC 93 Erik Bos <erik@xs4all.nl>
*
* Copyright 1996 Marcus Meissner
* FIXME: use HFILEs instead of unixfds
* the win32 functions here get HFILEs already.
*
* Mar 3, 1999. Ove Kven <ovek@arcticnet.no>
* - Use port indices instead of unixfds for win16
* - Moved things around (separated win16 and win32 routines)
* - Added some hints on how to implement buffers and EnableCommNotification.
*
* May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
* - ptr->fd wasn't getting cleared on close.
......@@ -72,6 +75,7 @@
#include "server.h"
#include "process.h"
#include "winerror.h"
#include "async.h"
#include "debug.h"
......@@ -79,11 +83,6 @@
#define TIOCINQ FIONREAD
#endif
#define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
/*
* [RER] These are globals are wrong. They should be in DosDeviceStruct
* on a per port basis.
*/
int commerror = 0, eventmask = 0;
/*
* [V] If above globals are wrong, the one below will be wrong as well. It
......@@ -162,10 +161,10 @@ void COMM_Init(void)
}
struct DosDeviceStruct *GetDeviceStruct(int fd)
struct DosDeviceStruct *GetDeviceStruct_fd(int fd)
{
int x;
for (x=0; x!=MAX_PORTS; x++) {
if (COM[x].fd == fd)
return &COM[x];
......@@ -176,7 +175,22 @@ struct DosDeviceStruct *GetDeviceStruct(int fd)
return NULL;
}
int GetCommPort(int fd)
struct DosDeviceStruct *GetDeviceStruct(int fd)
{
if ((fd&0x7F)<=MAX_PORTS) {
if (!(fd&0x80)) {
if (COM[fd].fd)
return &COM[fd];
} else {
if (LPT[fd].fd)
return &LPT[fd];
}
}
return NULL;
}
int GetCommPort_fd(int fd)
{
int x;
......@@ -207,6 +221,18 @@ int WinError(void)
}
}
static void WINE_UNUSED comm_notification(int fd,void*private)
{
/* in here, we need to:
1. read any data from the comm port
2. save it into our own internal buffers
(we need our own buffers to implement notifications properly!)
3. write data from our own internal buffers to the comm port
4. if wnd is set, send WM_COMMNOTIFY (using PostMessage) when
thresholds set by EnableCommNotification are passed */
}
/**************************************************************************
* BuildCommDCB (USER.213)
*/
......@@ -218,28 +244,23 @@ BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
char *ptr, temp[256];
TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
commerror = 0;
if (!lstrncmpiA(device,"COM",3)) {
port = device[3] - '0';
if (port-- == 0) {
ERR(comm, "BUG ! COM0 can't exists!.\n");
commerror = IE_BADID;
ERR(comm, "BUG ! COM0 can't exist!.\n");
return -1;
}
if (!ValidCOMPort(port)) {
commerror = IE_BADID;
return -1;
}
memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
if (!COM[port].fd) {
OpenComm16(device, 0, 0);
}
lpdcb->Id = COM[port].fd;
lpdcb->Id = port;
if (!*(device+4))
return 0;
......@@ -303,165 +324,6 @@ BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
return 0;
}
/**************************************************************************
* BuildCommDCBA (KERNEL32.14)
*/
BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
{
return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
}
/**************************************************************************
* BuildCommDCBAndTimeoutsA (KERNEL32.15)
*/
BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
LPCOMMTIMEOUTS lptimeouts)
{
int port;
char *ptr,*temp;
TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
commerror = 0;
if (!lstrncmpiA(device,"COM",3)) {
port=device[3]-'0';
if (port--==0) {
ERR(comm,"BUG! COM0 can't exists!.\n");
return FALSE;
}
if (!ValidCOMPort(port))
return FALSE;
if (*(device+4)!=':')
return FALSE;
temp=(LPSTR)(device+5);
} else
temp=(LPSTR)device;
memset(lpdcb, 0, sizeof(DCB)); /* initialize */
lpdcb->DCBlength = sizeof(DCB);
if (strchr(temp,',')) { /* old style */
DCB16 dcb16;
BOOL16 ret;
char last=temp[strlen(temp)-1];
ret=BuildCommDCB16(device,&dcb16);
if (!ret)
return FALSE;
lpdcb->BaudRate = dcb16.BaudRate;
lpdcb->ByteSize = dcb16.ByteSize;
lpdcb->fBinary = dcb16.fBinary;
lpdcb->Parity = dcb16.Parity;
lpdcb->fParity = dcb16.fParity;
lpdcb->fNull = dcb16.fNull;
lpdcb->StopBits = dcb16.StopBits;
if (last == 'x') {
lpdcb->fInX = TRUE;
lpdcb->fOutX = TRUE;
lpdcb->fOutxCtsFlow = FALSE;
lpdcb->fOutxDsrFlow = FALSE;
lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
} else if (last=='p') {
lpdcb->fInX = FALSE;
lpdcb->fOutX = FALSE;
lpdcb->fOutxCtsFlow = TRUE;
lpdcb->fOutxDsrFlow = TRUE;
lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
} else {
lpdcb->fInX = FALSE;
lpdcb->fOutX = FALSE;
lpdcb->fOutxCtsFlow = FALSE;
lpdcb->fOutxDsrFlow = FALSE;
lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
}
lpdcb->XonChar = dcb16.XonChar;
lpdcb->XoffChar = dcb16.XoffChar;
lpdcb->ErrorChar= dcb16.PeChar;
lpdcb->fErrorChar= dcb16.fPeChar;
lpdcb->EofChar = dcb16.EofChar;
lpdcb->EvtChar = dcb16.EvtChar;
lpdcb->XonLim = dcb16.XonLim;
lpdcb->XoffLim = dcb16.XoffLim;
return TRUE;
}
ptr=strtok(temp," ");
while (ptr) {
DWORD flag,x;
flag=0;
if (!strncmp("baud=",ptr,5)) {
if (!sscanf(ptr+5,"%ld",&x))
WARN(comm,"Couldn't parse %s\n",ptr);
lpdcb->BaudRate = x;
flag=1;
}
if (!strncmp("stop=",ptr,5)) {
if (!sscanf(ptr+5,"%ld",&x))
WARN(comm,"Couldn't parse %s\n",ptr);
lpdcb->StopBits = x;
flag=1;
}
if (!strncmp("data=",ptr,5)) {
if (!sscanf(ptr+5,"%ld",&x))
WARN(comm,"Couldn't parse %s\n",ptr);
lpdcb->ByteSize = x;
flag=1;
}
if (!strncmp("parity=",ptr,7)) {
lpdcb->fParity = TRUE;
switch (ptr[8]) {
case 'N':case 'n':
lpdcb->fParity = FALSE;
lpdcb->Parity = NOPARITY;
break;
case 'E':case 'e':
lpdcb->Parity = EVENPARITY;
break;
case 'O':case 'o':
lpdcb->Parity = ODDPARITY;
break;
case 'M':case 'm':
lpdcb->Parity = MARKPARITY;
break;
}
flag=1;
}
if (!flag)
ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
ptr=strtok(NULL," ");
}
if (lpdcb->BaudRate==110)
lpdcb->StopBits = 2;
return TRUE;
}
/**************************************************************************
* BuildCommDCBAndTimeoutsW (KERNEL32.16)
*/
BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
LPCOMMTIMEOUTS lptimeouts )
{
LPSTR devidA;
BOOL ret;
TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
HeapFree( GetProcessHeap(), 0, devidA );
return ret;
}
/**************************************************************************
* BuildCommDCBW (KERNEL32.17)
*/
BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
{
return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
}
/*****************************************************************************
* OpenComm (USER.200)
*/
......@@ -470,14 +332,12 @@ INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
int port,fd;
TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
commerror = 0;
if (!lstrncmpiA(device,"COM",3)) {
port = device[3] - '0';
if (port-- == 0) {
ERR(comm, "BUG ! COM0 doesn't exist !\n");
commerror = IE_BADID;
}
/* to help GetCommError return left buffsize [V] */
......@@ -487,46 +347,55 @@ INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
TRACE(comm, "%s = %s\n", device, COM[port].devicename);
if (!ValidCOMPort(port)) {
commerror = IE_BADID;
return -1;
return IE_BADID;
}
if (COM[port].fd) {
return COM[port].fd;
return IE_OPEN;
}
fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
if (fd == -1) {
commerror = WinError();
return -1;
return WinError();
} else {
unknown[port] = SEGPTR_ALLOC(40);
bzero(unknown[port],40);
COM[port].fd = fd;
COM[port].fd = fd;
COM[port].commerror = 0;
COM[port].eventmask = 0;
/* save terminal state */
tcgetattr(fd,&m_stat[port]);
return fd;
#if 0
/* allocate buffers */
/* ... */
/* enable async notifications */
ASYNC_RegisterFD(COM[port].fd,comm_notification,&COM[port]);
#endif
return port;
}
}
else
if (!lstrncmpiA(device,"LPT",3)) {
port = device[3] - '0';
if (port-- == 0) {
ERR(comm, "BUG ! LPT0 doesn't exist !\n");
}
if (!ValidLPTPort(port)) {
commerror = IE_BADID;
return -1;
return IE_BADID;
}
if (LPT[port].fd) {
commerror = IE_OPEN;
return -1;
return IE_OPEN;
}
fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
if (fd == -1) {
commerror = WinError();
return -1;
return WinError();
} else {
LPT[port].fd = fd;
return fd;
LPT[port].commerror = 0;
LPT[port].eventmask = 0;
return port|0x80;
}
}
return 0;
......@@ -535,27 +404,34 @@ INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
/*****************************************************************************
* CloseComm (USER.207)
*/
INT16 WINAPI CloseComm16(INT16 fd)
INT16 WINAPI CloseComm16(INT16 cid)
{
int port;
struct DosDeviceStruct *ptr;
TRACE(comm,"fd %d\n", fd);
if ((port = GetCommPort(fd)) !=-1) { /* [LW] */
SEGPTR_FREE(unknown[port]);
COM[port].fd = 0; /* my adaptation of RER's fix */
} else {
commerror = IE_BADID;
TRACE(comm,"cid=%d\n", cid);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if (!(cid&0x80)) {
/* COM port */
SEGPTR_FREE(unknown[cid]); /* [LW] */
#if 0
/* disable async notifications */
ASYNC_UnregisterFD(COM[cid].fd,comm_notification);
/* free buffers */
/* ... */
#endif
/* reset modem lines */
tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
}
/* reset modem lines */
tcsetattr(fd,TCSANOW,&m_stat[port]);
if (close(fd) == -1) {
commerror = WinError();
if (close(ptr->fd) == -1) {
ptr->commerror = WinError();
/* FIXME: should we clear ptr->fd here? */
return -1;
} else {
commerror = 0;
ptr->commerror = 0;
ptr->fd = 0;
return 0;
}
}
......@@ -563,87 +439,52 @@ INT16 WINAPI CloseComm16(INT16 fd)
/*****************************************************************************
* SetCommBreak (USER.210)
*/
INT16 WINAPI SetCommBreak16(INT16 fd)
INT16 WINAPI SetCommBreak16(INT16 cid)
{
struct DosDeviceStruct *ptr;
TRACE(comm,"fd=%d\n", fd);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
TRACE(comm,"cid=%d\n", cid);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
ptr->suspended = 1;
commerror = 0;
ptr->commerror = 0;
return 0;
}
/*****************************************************************************
* SetCommBreak (KERNEL32.449)
*/
BOOL WINAPI SetCommBreak(INT fd)
{
struct DosDeviceStruct *ptr;
TRACE(comm,"fd=%d\n", fd);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
return FALSE;
}
ptr->suspended = 1;
commerror = 0;
return TRUE;
}
/*****************************************************************************
* ClearCommBreak (USER.211)
*/
INT16 WINAPI ClearCommBreak16(INT16 fd)
INT16 WINAPI ClearCommBreak16(INT16 cid)
{
struct DosDeviceStruct *ptr;
TRACE(comm,"fd=%d\n", fd);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
TRACE(comm,"cid=%d\n", cid);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
ptr->suspended = 0;
commerror = 0;
ptr->commerror = 0;
return 0;
}
/*****************************************************************************
* ClearCommBreak (KERNEL32.20)
*/
BOOL WINAPI ClearCommBreak(INT fd)
{
struct DosDeviceStruct *ptr;
TRACE(comm,"fd=%d\n", fd);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
return FALSE;
}
ptr->suspended = 0;
commerror = 0;
return TRUE;
}
/*****************************************************************************
* EscapeCommFunction (USER.214)
*/
LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
{
int max;
struct DosDeviceStruct *ptr;
struct termios port;
TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
if (tcgetattr(fd,&port) == -1) {
commerror=WinError();
TRACE(comm,"cid=%d, function=%d\n", cid, nFunction);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if (tcgetattr(ptr->fd,&port) == -1) {
ptr->commerror=WinError();
return -1;
}
......@@ -694,178 +535,71 @@ LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
break;
default:
WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
fd, nFunction);
WARN(comm,"(cid=%d,nFunction=%d): Unknown function\n",
cid, nFunction);
break;
}
if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
commerror = WinError();
if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
ptr->commerror = WinError();
return -1;
} else {
commerror = 0;
ptr->commerror = 0;
return 0;
}
}
/*****************************************************************************
* EscapeCommFunction (KERNEL32.214)
* FlushComm (USER.215)
*/
BOOL WINAPI EscapeCommFunction(INT fd,UINT nFunction)
INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
{
struct termios port;
int queue;
struct DosDeviceStruct *ptr;
TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
if (tcgetattr(fd,&port) == -1) {
commerror=WinError();
return FALSE;
TRACE(comm,"cid=%d, queue=%d\n", cid, fnQueue);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
return FALSE;
switch (fnQueue) {
case 0: queue = TCOFLUSH;
break;
case 1: queue = TCIFLUSH;
break;
default:WARN(comm,"(cid=%d,fnQueue=%d):Unknown queue\n",
cid, fnQueue);
return -1;
}
if (tcflush(ptr->fd, queue)) {
ptr->commerror = WinError();
return -1;
} else {
ptr->commerror = 0;
return 0;
}
switch (nFunction) {
case RESETDEV:
break;
#ifdef TIOCM_DTR
case CLRDTR:
port.c_cflag &= TIOCM_DTR;
break;
#endif
#ifdef TIOCM_RTS
case CLRRTS:
port.c_cflag &= TIOCM_RTS;
break;
#endif
#ifdef CRTSCTS
case SETDTR:
port.c_cflag |= CRTSCTS;
break;
case SETRTS:
port.c_cflag |= CRTSCTS;
break;
#endif
case SETXOFF:
port.c_iflag |= IXOFF;
break;
case SETXON:
port.c_iflag |= IXON;
break;
case SETBREAK:
ptr->suspended = 1;
break;
case CLRBREAK:
ptr->suspended = 0;
break;
default:
WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
fd, nFunction);
break;
}
if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
commerror = WinError();
return FALSE;
} else {
commerror = 0;
return TRUE;
}
}
/*****************************************************************************
* FlushComm (USER.215)
*/
INT16 WINAPI FlushComm16(INT16 fd,INT16 fnQueue)
{
int queue;
TRACE(comm,"fd=%d, queue=%d\n", fd, fnQueue);
switch (fnQueue) {
case 0: queue = TCOFLUSH;
break;
case 1: queue = TCIFLUSH;
break;
default:WARN(comm,"(fd=%d,fnQueue=%d):Unknown queue\n",
fd, fnQueue);
return -1;
}
if (tcflush(fd, queue)) {
commerror = WinError();
return -1;
} else {
commerror = 0;
return 0;
}
}
/********************************************************************
* PurgeComm (KERNEL32.557)
*/
BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
{
int fd;
struct get_write_fd_request req;
TRACE(comm,"handle %d, flags %lx\n", handle, flags);
req.handle = handle;
CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
CLIENT_WaitReply( NULL, &fd, 0 );
if(fd<0)
return FALSE;
/*
** not exactly sure how these are different
** Perhaps if we had our own internal queues, one flushes them
** and the other flushes the kernel's buffers.
*/
if(flags&PURGE_TXABORT)
{
tcflush(fd,TCOFLUSH);
}
if(flags&PURGE_RXABORT)
{
tcflush(fd,TCIFLUSH);
}
if(flags&PURGE_TXCLEAR)
{
tcflush(fd,TCOFLUSH);
}
if(flags&PURGE_RXCLEAR)
{
tcflush(fd,TCIFLUSH);
}
return 1;
}
}
/********************************************************************
* GetCommError (USER.203)
*/
INT16 WINAPI GetCommError16(INT16 fd,LPCOMSTAT16 lpStat)
INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
{
int temperror;
unsigned long cnt;
int rc;
struct DosDeviceStruct *ptr;
unsigned char *stol;
int act;
unsigned int mstat;
if ((act = GetCommPort(fd)) == -1) {
WARN(comm," fd %d not comm port\n",fd);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if (cid&0x80) {
WARN(comm," cid %d not comm port\n",cid);
return CE_MODE;
}
stol = (unsigned char *)unknown[act] + COMM_MSR_OFFSET;
ioctl(fd,TIOCMGET,&mstat);
stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
ioctl(ptr->fd,TIOCMGET,&mstat);
if( mstat&TIOCM_CAR )
*stol |= 0x80;
else
......@@ -874,137 +608,68 @@ INT16 WINAPI GetCommError16(INT16 fd,LPCOMSTAT16 lpStat)
if (lpStat) {
lpStat->status = 0;
rc = ioctl(fd, TIOCOUTQ, &cnt);
rc = ioctl(ptr->fd, TIOCOUTQ, &cnt);
if (rc) WARN(comm, "Error !\n");
lpStat->cbOutQue = cnt + iGlobalOutQueueFiller;
rc = ioctl(fd, TIOCINQ, &cnt);
rc = ioctl(ptr->fd, TIOCINQ, &cnt);
if (rc) WARN(comm, "Error !\n");
lpStat->cbInQue = cnt;
TRACE(comm, "fd %d, error %d, lpStat %d %d %d stol %x\n",
fd, commerror, lpStat->status, lpStat->cbInQue,
TRACE(comm, "cid %d, error %d, lpStat %d %d %d stol %x\n",
cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
lpStat->cbOutQue, *stol);
}
else
TRACE(comm, "fd %d, error %d, lpStat NULL stol %x\n",
fd, commerror, *stol);
TRACE(comm, "cid %d, error %d, lpStat NULL stol %x\n",
cid, ptr->commerror, *stol);
/*
* [RER] I have no idea what the following is trying to accomplish.
* [RER] It is certainly not what the reference manual suggests.
*/
temperror = commerror;
commerror = 0;
/* Return any errors and clear it */
temperror = ptr->commerror;
ptr->commerror = 0;
return(temperror);
}
/*****************************************************************************
* COMM_Handle2fd
* returns a file descriptor for reading from or writing to
* mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
* the handle afterwards!
*/
int COMM_Handle2fd(HANDLE handle, int mode) {
struct get_read_fd_request r_req;
struct get_write_fd_request w_req;
int fd;
w_req.handle = r_req.handle = handle;
switch(mode) {
case GENERIC_WRITE:
CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &w_req, sizeof(w_req) );
break;
case GENERIC_READ:
CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &r_req, sizeof(r_req) );
break;
default:
ERR(comm,"COMM_Handle2fd: Don't know what type of fd is required.\n");
return -1;
}
CLIENT_WaitReply( NULL, &fd, 0 );
return fd;
}
/*****************************************************************************
* ClearCommError (KERNEL32.21)
*/
BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
{
int fd;
fd=COMM_Handle2fd(handle,GENERIC_READ);
if(0>fd)
{
return FALSE;
}
if (lpStat)
{
lpStat->status = 0;
if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
WARN(comm, "ioctl returned error\n");
if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
WARN(comm, "ioctl returned error\n");
}
close(fd);
TRACE(comm,"handle %d cbInQue = %ld cbOutQue = %ld\n",
handle,
lpStat->cbInQue,
lpStat->cbOutQue);
if(errors)
*errors = 0;
/*
** After an asynchronous write opperation, the
** app will call ClearCommError to see if the
** results are ready yet. It waits for ERROR_IO_PENDING
*/
commerror = ERROR_IO_PENDING;
return TRUE;
}
/*****************************************************************************
* SetCommEventMask (USER.208)
*/
SEGPTR WINAPI SetCommEventMask16(INT16 fd,UINT16 fuEvtMask)
SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
{
struct DosDeviceStruct *ptr;
unsigned char *stol;
int act;
int repid;
unsigned int mstat;
TRACE(comm,"fd %d,mask %d\n",fd,fuEvtMask);
eventmask |= fuEvtMask;
if ((act = GetCommPort(fd)) == -1) {
WARN(comm," fd %d not comm port\n",act);
TRACE(comm,"cid %d,mask %d\n",cid,fuEvtMask);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
ptr->eventmask |= fuEvtMask;
if (cid&0x80) {
WARN(comm," cid %d not comm port\n",cid);
return SEGPTR_GET(NULL);
}
stol = (unsigned char *)unknown[act];
stol += COMM_MSR_OFFSET;
repid = ioctl(fd,TIOCMGET,&mstat);
TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[act]);
stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
repid = ioctl(ptr->fd,TIOCMGET,&mstat);
TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
else {*stol &=0x7f;}
TRACE(comm," modem dcd construct %x\n",*stol);
return SEGPTR_GET(unknown[act]);
return SEGPTR_GET(unknown[cid]);
}
/*****************************************************************************
* GetCommEventMask (USER.209)
*/
UINT16 WINAPI GetCommEventMask16(INT16 fd,UINT16 fnEvtClear)
UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
{
int events = 0;
struct DosDeviceStruct *ptr;
TRACE(comm, "fd %d, mask %d\n", fd, fnEvtClear);
TRACE(comm, "cid %d, mask %d\n", cid, fnEvtClear);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
/*
* Determine if any characters are available
......@@ -1014,7 +679,7 @@ UINT16 WINAPI GetCommEventMask16(INT16 fd,UINT16 fnEvtClear)
int rc;
unsigned long cnt;
rc = ioctl(fd, TIOCINQ, &cnt);
rc = ioctl(ptr->fd, TIOCINQ, &cnt);
if (cnt) events |= EV_RXCHAR;
TRACE(comm, "rxchar %ld\n", cnt);
......@@ -1032,63 +697,13 @@ UINT16 WINAPI GetCommEventMask16(INT16 fd,UINT16 fnEvtClear)
* [RER] The following was gibberish
*/
#if 0
tempmask = eventmask;
eventmask &= ~fnEvtClear;
return eventmask;
tempmask = ptr->eventmask;
ptr->eventmask &= ~fnEvtClear;
return ptr->eventmask;
#endif
}
/*****************************************************************************
* SetupComm (KERNEL32.676)
*/
BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
{
int fd;
FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
fd=COMM_Handle2fd(handle,GENERIC_WRITE);
if(0>fd)
{
return FALSE;
}
close(fd);
return TRUE;
}
/*****************************************************************************
* GetCommMask (KERNEL32.156)
*/
BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
{
int fd;
TRACE(comm, "handle %d, mask %p\n", handle, evtmask);
if(0>(fd=COMM_Handle2fd(handle,GENERIC_READ)))
{
return FALSE;
}
close(fd);
*evtmask = eventmask;
return TRUE;
}
/*****************************************************************************
* SetCommMask (KERNEL32.451)
*/
BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
{
int fd;
TRACE(comm, "handle %d, mask %lx\n", handle, evtmask);
if(0>(fd=COMM_Handle2fd(handle,GENERIC_WRITE))) {
return FALSE;
}
close(fd);
eventmask = evtmask;
return TRUE;
}
/*****************************************************************************
* SetCommState16 (USER.201)
*/
INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
......@@ -1096,9 +711,12 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
struct termios port;
struct DosDeviceStruct *ptr;
TRACE(comm, "fd %d, ptr %p\n", lpdcb->Id, lpdcb);
if (tcgetattr(lpdcb->Id, &port) == -1) {
commerror = WinError();
TRACE(comm, "cid %d, ptr %p\n", lpdcb->Id, lpdcb);
if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
return -1;
}
if (tcgetattr(ptr->fd, &port) == -1) {
ptr->commerror = WinError();
return -1;
}
......@@ -1120,10 +738,6 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
port.c_lflag &= ~(ICANON|ECHO|ISIG);
port.c_lflag |= NOFLSH;
if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
commerror = IE_BADID;
return -1;
}
if (ptr->baudrate > 0)
lpdcb->BaudRate = ptr->baudrate;
TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
......@@ -1177,7 +791,7 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
break;
#endif
default:
commerror = IE_BAUDRATE;
ptr->commerror = IE_BAUDRATE;
return -1;
}
#elif !defined(__EMX__)
......@@ -1219,7 +833,7 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
port.c_ospeed = B38400;
break;
default:
commerror = IE_BAUDRATE;
ptr->commerror = IE_BAUDRATE;
return -1;
}
port.c_ispeed = port.c_ospeed;
......@@ -1240,7 +854,7 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
port.c_cflag |= CS8;
break;
default:
commerror = IE_BYTESIZE;
ptr->commerror = IE_BYTESIZE;
return -1;
}
......@@ -1260,7 +874,7 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
port.c_iflag |= INPCK;
break;
default:
commerror = IE_BYTESIZE;
ptr->commerror = IE_BYTESIZE;
return -1;
}
......@@ -1275,7 +889,7 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
port.c_cflag |= CSTOPB;
break;
default:
commerror = IE_BYTESIZE;
ptr->commerror = IE_BYTESIZE;
return -1;
}
#ifdef CRTSCTS
......@@ -1295,13 +909,711 @@ INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
else
port.c_iflag &= ~IXOFF;
if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
commerror = WinError();
return FALSE;
} else {
commerror = 0;
return 0;
}
if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
ptr->commerror = WinError();
return FALSE;
} else {
ptr->commerror = 0;
return 0;
}
}
/*****************************************************************************
* GetCommState (USER.202)
*/
INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
{
struct DosDeviceStruct *ptr;
struct termios port;
TRACE(comm,"cid %d, ptr %p\n", cid, lpdcb);
if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
return -1;
}
if (tcgetattr(ptr->fd, &port) == -1) {
ptr->commerror = WinError();
return -1;
}
lpdcb->Id = cid;
#ifndef __EMX__
#ifdef CBAUD
switch (port.c_cflag & CBAUD) {
#else
switch (port.c_ospeed) {
#endif
case B110:
lpdcb->BaudRate = 110;
break;
case B300:
lpdcb->BaudRate = 300;
break;
case B600:
lpdcb->BaudRate = 600;
break;
case B1200:
lpdcb->BaudRate = 1200;
break;
case B2400:
lpdcb->BaudRate = 2400;
break;
case B4800:
lpdcb->BaudRate = 4800;
break;
case B9600:
lpdcb->BaudRate = 9600;
break;
case B19200:
lpdcb->BaudRate = 19200;
break;
case B38400:
lpdcb->BaudRate = 38400;
break;
#ifdef B57600
case B57600:
lpdcb->BaudRate = 57600;
break;
#endif
#ifdef B115200
case B115200:
lpdcb->BaudRate = 57601;
break;
#endif
}
#endif
switch (port.c_cflag & CSIZE) {
case CS5:
lpdcb->ByteSize = 5;
break;
case CS6:
lpdcb->ByteSize = 6;
break;
case CS7:
lpdcb->ByteSize = 7;
break;
case CS8:
lpdcb->ByteSize = 8;
break;
}
switch (port.c_cflag & (PARENB | PARODD)) {
case 0:
lpdcb->fParity = FALSE;
lpdcb->Parity = NOPARITY;
break;
case PARENB:
lpdcb->fParity = TRUE;
lpdcb->Parity = EVENPARITY;
break;
case (PARENB | PARODD):
lpdcb->fParity = TRUE;
lpdcb->Parity = ODDPARITY;
break;
}
if (port.c_cflag & CSTOPB)
lpdcb->StopBits = TWOSTOPBITS;
else
lpdcb->StopBits = ONESTOPBIT;
lpdcb->RlsTimeout = 50;
lpdcb->CtsTimeout = 50;
lpdcb->DsrTimeout = 50;
lpdcb->fNull = 0;
lpdcb->fChEvt = 0;
lpdcb->fBinary = 1;
lpdcb->fDtrDisable = 0;
#ifdef CRTSCTS
if (port.c_cflag & CRTSCTS) {
lpdcb->fDtrflow = 1;
lpdcb->fRtsflow = 1;
lpdcb->fOutxCtsFlow = 1;
lpdcb->fOutxDsrFlow = 1;
} else
#endif
lpdcb->fDtrDisable = 1;
if (port.c_iflag & IXON)
lpdcb->fInX = 1;
else
lpdcb->fInX = 0;
if (port.c_iflag & IXOFF)
lpdcb->fOutX = 1;
else
lpdcb->fOutX = 0;
/*
lpdcb->XonChar =
lpdcb->XoffChar =
*/
lpdcb->XonLim = 10;
lpdcb->XoffLim = 10;
ptr->commerror = 0;
return 0;
}
/*****************************************************************************
* TransmitCommChar (USER.206)
*/
INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
{
struct DosDeviceStruct *ptr;
TRACE(comm, "cid %d, data %d \n", cid, chTransmit);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if (ptr->suspended) {
ptr->commerror = IE_HARDWARE;
return -1;
}
if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
ptr->commerror = WinError();
return -1;
} else {
ptr->commerror = 0;
return 0;
}
}
/*****************************************************************************
* UngetCommChar (USER.212)
*/
INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
{
struct DosDeviceStruct *ptr;
TRACE(comm,"cid %d (char %d)\n", cid, chUnget);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if (ptr->suspended) {
ptr->commerror = IE_HARDWARE;
return -1;
}
ptr->unget = 1;
ptr->unget_byte = chUnget;
ptr->commerror = 0;
return 0;
}
/*****************************************************************************
* ReadComm (USER.204)
*/
INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
{
int status, length;
struct DosDeviceStruct *ptr;
TRACE(comm, "cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if (ptr->suspended) {
ptr->commerror = IE_HARDWARE;
return -1;
}
if (ptr->unget) {
*lpvBuf = ptr->unget_byte;
lpvBuf++;
ptr->unget = 0;
length = 1;
} else
length = 0;
status = read(ptr->fd, (void *) lpvBuf, cbRead);
if (status == -1) {
if (errno != EAGAIN) {
ptr->commerror = WinError();
return -1 - length;
} else {
ptr->commerror = 0;
return length;
}
} else {
TRACE(comm,"%.*s\n", length+status, lpvBuf);
ptr->commerror = 0;
return length + status;
}
}
/*****************************************************************************
* WriteComm (USER.205)
*/
INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
{
int length;
struct DosDeviceStruct *ptr;
TRACE(comm,"cid %d, ptr %p, length %d\n",
cid, lpvBuf, cbWrite);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return -1;
}
if (ptr->suspended) {
ptr->commerror = IE_HARDWARE;
return -1;
}
TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
length = write(ptr->fd, (void *) lpvBuf, cbWrite);
if (length == -1) {
ptr->commerror = WinError();
return -1;
} else {
ptr->commerror = 0;
return length;
}
}
/***********************************************************************
* EnableCommNotification (USER.246)
*/
BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
INT16 cbWriteNotify, INT16 cbOutQueue )
{
struct DosDeviceStruct *ptr;
FIXME(comm, "(%d, %x, %d, %d):stub.\n", cid, hwnd, cbWriteNotify, cbOutQueue);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
ptr->commerror = IE_BADID;
return -1;
}
ptr->wnd = hwnd;
ptr->n_read = cbWriteNotify;
ptr->n_write = cbOutQueue;
return TRUE;
}
/**************************************************************************
* BuildCommDCBA (KERNEL32.14)
*/
BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
{
return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
}
/**************************************************************************
* BuildCommDCBAndTimeoutsA (KERNEL32.15)
*/
BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
LPCOMMTIMEOUTS lptimeouts)
{
int port;
char *ptr,*temp;
TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
if (!lstrncmpiA(device,"COM",3)) {
port=device[3]-'0';
if (port--==0) {
ERR(comm,"BUG! COM0 can't exists!.\n");
return FALSE;
}
if (!ValidCOMPort(port))
return FALSE;
if (*(device+4)!=':')
return FALSE;
temp=(LPSTR)(device+5);
} else
temp=(LPSTR)device;
memset(lpdcb, 0, sizeof(DCB)); /* initialize */
lpdcb->DCBlength = sizeof(DCB);
if (strchr(temp,',')) { /* old style */
DCB16 dcb16;
BOOL16 ret;
char last=temp[strlen(temp)-1];
ret=BuildCommDCB16(device,&dcb16);
if (!ret)
return FALSE;
lpdcb->BaudRate = dcb16.BaudRate;
lpdcb->ByteSize = dcb16.ByteSize;
lpdcb->fBinary = dcb16.fBinary;
lpdcb->Parity = dcb16.Parity;
lpdcb->fParity = dcb16.fParity;
lpdcb->fNull = dcb16.fNull;
lpdcb->StopBits = dcb16.StopBits;
if (last == 'x') {
lpdcb->fInX = TRUE;
lpdcb->fOutX = TRUE;
lpdcb->fOutxCtsFlow = FALSE;
lpdcb->fOutxDsrFlow = FALSE;
lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
} else if (last=='p') {
lpdcb->fInX = FALSE;
lpdcb->fOutX = FALSE;
lpdcb->fOutxCtsFlow = TRUE;
lpdcb->fOutxDsrFlow = TRUE;
lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
} else {
lpdcb->fInX = FALSE;
lpdcb->fOutX = FALSE;
lpdcb->fOutxCtsFlow = FALSE;
lpdcb->fOutxDsrFlow = FALSE;
lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
}
lpdcb->XonChar = dcb16.XonChar;
lpdcb->XoffChar = dcb16.XoffChar;
lpdcb->ErrorChar= dcb16.PeChar;
lpdcb->fErrorChar= dcb16.fPeChar;
lpdcb->EofChar = dcb16.EofChar;
lpdcb->EvtChar = dcb16.EvtChar;
lpdcb->XonLim = dcb16.XonLim;
lpdcb->XoffLim = dcb16.XoffLim;
return TRUE;
}
ptr=strtok(temp," ");
while (ptr) {
DWORD flag,x;
flag=0;
if (!strncmp("baud=",ptr,5)) {
if (!sscanf(ptr+5,"%ld",&x))
WARN(comm,"Couldn't parse %s\n",ptr);
lpdcb->BaudRate = x;
flag=1;
}
if (!strncmp("stop=",ptr,5)) {
if (!sscanf(ptr+5,"%ld",&x))
WARN(comm,"Couldn't parse %s\n",ptr);
lpdcb->StopBits = x;
flag=1;
}
if (!strncmp("data=",ptr,5)) {
if (!sscanf(ptr+5,"%ld",&x))
WARN(comm,"Couldn't parse %s\n",ptr);
lpdcb->ByteSize = x;
flag=1;
}
if (!strncmp("parity=",ptr,7)) {
lpdcb->fParity = TRUE;
switch (ptr[8]) {
case 'N':case 'n':
lpdcb->fParity = FALSE;
lpdcb->Parity = NOPARITY;
break;
case 'E':case 'e':
lpdcb->Parity = EVENPARITY;
break;
case 'O':case 'o':
lpdcb->Parity = ODDPARITY;
break;
case 'M':case 'm':
lpdcb->Parity = MARKPARITY;
break;
}
flag=1;
}
if (!flag)
ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
ptr=strtok(NULL," ");
}
if (lpdcb->BaudRate==110)
lpdcb->StopBits = 2;
return TRUE;
}
/**************************************************************************
* BuildCommDCBAndTimeoutsW (KERNEL32.16)
*/
BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
LPCOMMTIMEOUTS lptimeouts )
{
LPSTR devidA;
BOOL ret;
TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
HeapFree( GetProcessHeap(), 0, devidA );
return ret;
}
/**************************************************************************
* BuildCommDCBW (KERNEL32.17)
*/
BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
{
return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
}
/*****************************************************************************
* COMM_Handle2fd
* returns a file descriptor for reading from or writing to
* mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
* the handle afterwards!
*/
int COMM_Handle2fd(HANDLE handle, int mode) {
struct get_read_fd_request r_req;
struct get_write_fd_request w_req;
int fd;
w_req.handle = r_req.handle = handle;
switch(mode) {
case GENERIC_WRITE:
CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &w_req, sizeof(w_req) );
break;
case GENERIC_READ:
CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &r_req, sizeof(r_req) );
break;
default:
ERR(comm,"COMM_Handle2fd: Don't know what type of fd is required.\n");
return -1;
}
CLIENT_WaitReply( NULL, &fd, 0 );
return fd;
}
/* FIXME: having these global for win32 for now */
int commerror=0,eventmask=0;
/*****************************************************************************
* SetCommBreak (KERNEL32.449)
*/
BOOL WINAPI SetCommBreak(HANDLE handle)
{
FIXME(comm,"handle %d, stub!\n", handle);
return TRUE;
}
/*****************************************************************************
* ClearCommBreak (KERNEL32.20)
*/
BOOL WINAPI ClearCommBreak(HANDLE handle)
{
FIXME(comm,"handle %d, stub!\n", handle);
return TRUE;
}
/*****************************************************************************
* EscapeCommFunction (KERNEL32.214)
*/
BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
{
int fd;
struct termios port;
TRACE(comm,"handle %d, function=%d\n", handle, nFunction);
fd = COMM_Handle2fd(handle, GENERIC_WRITE);
if(fd<0)
return FALSE;
if (tcgetattr(fd,&port) == -1) {
commerror=WinError();
close(fd);
return FALSE;
}
switch (nFunction) {
case RESETDEV:
break;
#ifdef TIOCM_DTR
case CLRDTR:
port.c_cflag &= TIOCM_DTR;
break;
#endif
#ifdef TIOCM_RTS
case CLRRTS:
port.c_cflag &= TIOCM_RTS;
break;
#endif
#ifdef CRTSCTS
case SETDTR:
port.c_cflag |= CRTSCTS;
break;
case SETRTS:
port.c_cflag |= CRTSCTS;
break;
#endif
case SETXOFF:
port.c_iflag |= IXOFF;
break;
case SETXON:
port.c_iflag |= IXON;
break;
case SETBREAK:
FIXME(comm,"setbreak, stub\n");
/* ptr->suspended = 1; */
break;
case CLRBREAK:
FIXME(comm,"clrbreak, stub\n");
/* ptr->suspended = 0; */
break;
default:
WARN(comm,"(handle=%d,nFunction=%d): Unknown function\n",
handle, nFunction);
break;
}
if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
commerror = WinError();
close(fd);
return FALSE;
} else {
commerror = 0;
close(fd);
return TRUE;
}
}
/********************************************************************
* PurgeComm (KERNEL32.557)
*/
BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
{
int fd;
TRACE(comm,"handle %d, flags %lx\n", handle, flags);
fd = COMM_Handle2fd(handle, GENERIC_WRITE);
if(fd<0)
return FALSE;
/*
** not exactly sure how these are different
** Perhaps if we had our own internal queues, one flushes them
** and the other flushes the kernel's buffers.
*/
if(flags&PURGE_TXABORT)
{
tcflush(fd,TCOFLUSH);
}
if(flags&PURGE_RXABORT)
{
tcflush(fd,TCIFLUSH);
}
if(flags&PURGE_TXCLEAR)
{
tcflush(fd,TCOFLUSH);
}
if(flags&PURGE_RXCLEAR)
{
tcflush(fd,TCIFLUSH);
}
close(fd);
return 1;
}
/*****************************************************************************
* ClearCommError (KERNEL32.21)
*/
BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
{
int fd;
fd=COMM_Handle2fd(handle,GENERIC_READ);
if(0>fd)
{
return FALSE;
}
if (lpStat)
{
lpStat->status = 0;
if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
WARN(comm, "ioctl returned error\n");
if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
WARN(comm, "ioctl returned error\n");
}
close(fd);
TRACE(comm,"handle %d cbInQue = %ld cbOutQue = %ld\n",
handle,
lpStat->cbInQue,
lpStat->cbOutQue);
if(errors)
*errors = 0;
/*
** After an asynchronous write opperation, the
** app will call ClearCommError to see if the
** results are ready yet. It waits for ERROR_IO_PENDING
*/
commerror = ERROR_IO_PENDING;
return TRUE;
}
/*****************************************************************************
* SetupComm (KERNEL32.676)
*/
BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
{
int fd;
FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
fd=COMM_Handle2fd(handle,GENERIC_WRITE);
if(0>fd)
{
return FALSE;
}
close(fd);
return TRUE;
}
/*****************************************************************************
* GetCommMask (KERNEL32.156)
*/
BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
{
int fd;
TRACE(comm, "handle %d, mask %p\n", handle, evtmask);
if(0>(fd=COMM_Handle2fd(handle,GENERIC_READ)))
{
return FALSE;
}
close(fd);
*evtmask = eventmask;
return TRUE;
}
/*****************************************************************************
* SetCommMask (KERNEL32.451)
*/
BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
{
int fd;
TRACE(comm, "handle %d, mask %lx\n", handle, evtmask);
if(0>(fd=COMM_Handle2fd(handle,GENERIC_WRITE))) {
return FALSE;
}
close(fd);
eventmask = evtmask;
return TRUE;
}
/*****************************************************************************
......@@ -1519,138 +1831,6 @@ BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
/*****************************************************************************
* GetCommState (USER.202)
*/
INT16 WINAPI GetCommState16(INT16 fd, LPDCB16 lpdcb)
{
struct termios port;
TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
if (tcgetattr(fd, &port) == -1) {
commerror = WinError();
return -1;
}
lpdcb->Id = fd;
#ifndef __EMX__
#ifdef CBAUD
switch (port.c_cflag & CBAUD) {
#else
switch (port.c_ospeed) {
#endif
case B110:
lpdcb->BaudRate = 110;
break;
case B300:
lpdcb->BaudRate = 300;
break;
case B600:
lpdcb->BaudRate = 600;
break;
case B1200:
lpdcb->BaudRate = 1200;
break;
case B2400:
lpdcb->BaudRate = 2400;
break;
case B4800:
lpdcb->BaudRate = 4800;
break;
case B9600:
lpdcb->BaudRate = 9600;
break;
case B19200:
lpdcb->BaudRate = 19200;
break;
case B38400:
lpdcb->BaudRate = 38400;
break;
#ifdef B57600
case B57600:
lpdcb->BaudRate = 57600;
break;
#endif
#ifdef B115200
case B115200:
lpdcb->BaudRate = 57601;
break;
#endif
}
#endif
switch (port.c_cflag & CSIZE) {
case CS5:
lpdcb->ByteSize = 5;
break;
case CS6:
lpdcb->ByteSize = 6;
break;
case CS7:
lpdcb->ByteSize = 7;
break;
case CS8:
lpdcb->ByteSize = 8;
break;
}
switch (port.c_cflag & (PARENB | PARODD)) {
case 0:
lpdcb->fParity = FALSE;
lpdcb->Parity = NOPARITY;
break;
case PARENB:
lpdcb->fParity = TRUE;
lpdcb->Parity = EVENPARITY;
break;
case (PARENB | PARODD):
lpdcb->fParity = TRUE;
lpdcb->Parity = ODDPARITY;
break;
}
if (port.c_cflag & CSTOPB)
lpdcb->StopBits = TWOSTOPBITS;
else
lpdcb->StopBits = ONESTOPBIT;
lpdcb->RlsTimeout = 50;
lpdcb->CtsTimeout = 50;
lpdcb->DsrTimeout = 50;
lpdcb->fNull = 0;
lpdcb->fChEvt = 0;
lpdcb->fBinary = 1;
lpdcb->fDtrDisable = 0;
#ifdef CRTSCTS
if (port.c_cflag & CRTSCTS) {
lpdcb->fDtrflow = 1;
lpdcb->fRtsflow = 1;
lpdcb->fOutxCtsFlow = 1;
lpdcb->fOutxDsrFlow = 1;
} else
#endif
lpdcb->fDtrDisable = 1;
if (port.c_iflag & IXON)
lpdcb->fInX = 1;
else
lpdcb->fInX = 0;
if (port.c_iflag & IXOFF)
lpdcb->fOutX = 1;
else
lpdcb->fOutX = 0;
/*
lpdcb->XonChar =
lpdcb->XoffChar =
*/
lpdcb->XonLim = 10;
lpdcb->XoffLim = 10;
commerror = 0;
return 0;
}
/*****************************************************************************
* GetCommState (KERNEL32.159)
*/
BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
......@@ -1782,184 +1962,44 @@ BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
}
/*****************************************************************************
* TransmitCommChar (USER.206)
*/
INT16 WINAPI TransmitCommChar16(INT16 fd,CHAR chTransmit)
{
struct DosDeviceStruct *ptr;
TRACE(comm, "fd %d, data %d \n", fd, chTransmit);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
return -1;
}
if (ptr->suspended) {
commerror = IE_HARDWARE;
return -1;
}
if (write(fd, (void *) &chTransmit, 1) == -1) {
commerror = WinError();
return -1;
} else {
commerror = 0;
return 0;
}
}
/*****************************************************************************
* TransmitCommChar (KERNEL32.535)
*/
BOOL WINAPI TransmitCommChar(INT fd,CHAR chTransmit)
BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
{
struct DosDeviceStruct *ptr;
TRACE(comm,"(%d,'%c')\n",fd,chTransmit);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
FIXME(comm,"(%d,'%c'), use win32 handle!\n",cid,chTransmit);
if ((ptr = GetDeviceStruct(cid)) == NULL) {
return FALSE;
}
if (ptr->suspended) {
commerror = IE_HARDWARE;
ptr->commerror = IE_HARDWARE;
return FALSE;
}
if (write(fd, (void *) &chTransmit, 1) == -1) {
commerror = WinError();
if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
ptr->commerror = WinError();
return FALSE;
} else {
commerror = 0;
ptr->commerror = 0;
return TRUE;
}
}
/*****************************************************************************
* UngetCommChar (USER.212)
*/
INT16 WINAPI UngetCommChar16(INT16 fd,CHAR chUnget)
{
struct DosDeviceStruct *ptr;
TRACE(comm,"fd %d (char %d)\n", fd, chUnget);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
return -1;
}
if (ptr->suspended) {
commerror = IE_HARDWARE;
return -1;
}
ptr->unget = 1;
ptr->unget_byte = chUnget;
commerror = 0;
return 0;
}
/*****************************************************************************
* ReadComm (USER.204)
*/
INT16 WINAPI ReadComm16(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
{
int status, length;
struct DosDeviceStruct *ptr;
TRACE(comm, "fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
return -1;
}
if (ptr->suspended) {
commerror = IE_HARDWARE;
return -1;
}
if (ptr->unget) {
*lpvBuf = ptr->unget_byte;
lpvBuf++;
ptr->unget = 0;
length = 1;
} else
length = 0;
status = read(fd, (void *) lpvBuf, cbRead);
if (status == -1) {
if (errno != EAGAIN) {
commerror = WinError();
return -1 - length;
} else {
commerror = 0;
return length;
}
} else {
TRACE(comm,"%.*s\n", length+status, lpvBuf);
commerror = 0;
return length + status;
}
}
/*****************************************************************************
* WriteComm (USER.205)
*/
INT16 WINAPI WriteComm16(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
{
int length;
struct DosDeviceStruct *ptr;
TRACE(comm,"fd %d, ptr %p, length %d\n",
fd, lpvBuf, cbWrite);
if ((ptr = GetDeviceStruct(fd)) == NULL) {
commerror = IE_BADID;
return -1;
}
if (ptr->suspended) {
commerror = IE_HARDWARE;
return -1;
}
TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
length = write(fd, (void *) lpvBuf, cbWrite);
if (length == -1) {
commerror = WinError();
return -1;
} else {
commerror = 0;
return length;
}
}
/*****************************************************************************
* GetCommTimeouts (KERNEL32.160)
*/
BOOL WINAPI GetCommTimeouts(INT fd,LPCOMMTIMEOUTS lptimeouts)
BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
{
FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
return TRUE;
}
/*****************************************************************************
* SetCommTimeouts (KERNEL32.453)
*/
BOOL WINAPI SetCommTimeouts(INT fd,LPCOMMTIMEOUTS lptimeouts) {
FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
return TRUE;
}
/***********************************************************************
* EnableCommNotification (USER.246)
*/
BOOL16 WINAPI EnableCommNotification16( INT16 fd, HWND16 hwnd,
INT16 cbWriteNotify, INT16 cbOutQueue )
{
FIXME(comm, "(%d, %x, %d, %d):stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);
BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
return TRUE;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment