2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
9 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
12 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
13 * - Use port indices instead of unixfds for win16
14 * - Moved things around (separated win16 and win32 routines)
15 * - Added some hints on how to implement buffers and EnableCommNotification.
17 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
18 * - ptr->fd wasn't getting cleared on close.
19 * - GetCommEventMask() and GetCommError() didn't do much of anything.
20 * IMHO, they are still wrong, but they at least implement the RXCHAR
21 * event and return I/O queue sizes, which makes the app I'm interested
22 * in (analog devices EZKIT DSP development system) work.
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
26 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
28 * Oktober 98, Rein Klazes [RHK]
29 * A program that wants to monitor the modem status line (RLSD/DCD) may
30 * poll the modem status register in the commMask structure. I update the bit
31 * in GetCommError, waiting for an implementation of communication events.
47 #ifdef HAVE_SYS_FILIO_H
48 # include <sys/filio.h>
50 #include <sys/ioctl.h>
53 #include "wine/winuser16.h"
55 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
70 #include "debugtools.h"
72 DEFAULT_DEBUG_CHANNEL(comm
)
75 #define TIOCINQ FIONREAD
77 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
80 struct DosDeviceStruct COM
[MAX_PORTS
];
81 struct DosDeviceStruct LPT
[MAX_PORTS
];
82 /* pointers to unknown(==undocumented) comm structure */
83 LPCVOID
*unknown
[MAX_PORTS
];
84 /* save terminal states */
85 static struct termios m_stat
[MAX_PORTS
];
90 char option
[10], temp
[256], *btemp
;
93 for (x
=0; x
!=MAX_PORTS
; x
++) {
94 strcpy(option
,"COMx");
98 PROFILE_GetWineIniString( "serialports", option
, "*",
100 if (!strcmp(temp
, "*") || *temp
== '\0')
101 COM
[x
].devicename
= NULL
;
103 btemp
= strchr(temp
,',');
106 COM
[x
].baudrate
= atoi(btemp
);
108 COM
[x
].baudrate
= -1;
111 if (!S_ISCHR(st
.st_mode
))
112 WARN("Can't use `%s' as %s !\n", temp
, option
);
114 if ((COM
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
115 WARN("Can't malloc for device info!\n");
118 strcpy(COM
[x
].devicename
, temp
);
120 TRACE("%s = %s\n", option
, COM
[x
].devicename
);
123 strcpy(option
, "LPTx");
127 PROFILE_GetWineIniString( "parallelports", option
, "*",
128 temp
, sizeof(temp
) );
129 if (!strcmp(temp
, "*") || *temp
== '\0')
130 LPT
[x
].devicename
= NULL
;
133 if (!S_ISCHR(st
.st_mode
))
134 WARN("Can't use `%s' as %s !\n", temp
, option
);
136 if ((LPT
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
137 WARN("Can't malloc for device info!\n");
140 strcpy(LPT
[x
].devicename
, temp
);
142 TRACE("%s = %s\n", option
, LPT
[x
].devicename
);
149 static struct DosDeviceStruct
*GetDeviceStruct(int fd
)
151 if ((fd
&0x7F)<=MAX_PORTS
) {
152 if (!(fd
&FLAG_LPT
)) {
164 static int GetCommPort_fd(int fd
)
168 for (x
=0; x
<MAX_PORTS
; x
++) {
176 static int ValidCOMPort(int x
)
178 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
181 static int ValidLPTPort(int x
)
183 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
186 static int WinError(void)
188 TRACE("errno = %d\n", errno
);
195 static unsigned comm_inbuf(struct DosDeviceStruct
*ptr
)
197 return ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? ptr
->ibuf_size
: 0)
198 + ptr
->ibuf_head
- ptr
->ibuf_tail
;
201 static unsigned comm_outbuf(struct DosDeviceStruct
*ptr
)
203 return ((ptr
->obuf_tail
> ptr
->obuf_head
) ? ptr
->obuf_size
: 0)
204 + ptr
->obuf_head
- ptr
->obuf_tail
;
207 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
209 unsigned int mstat
, okay
;
210 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
211 if (okay
) return okay
;
212 if (andy
) mstat
&= andy
;
214 return ioctl(fd
, TIOCMSET
, &mstat
);
217 static void CALLBACK
comm_notification( ULONG_PTR
private )
219 struct DosDeviceStruct
*ptr
= (struct DosDeviceStruct
*)private;
220 int prev
, bleft
, len
;
222 int cid
= GetCommPort_fd(ptr
->fd
);
224 TRACE("async notification\n");
225 /* read data from comm port */
226 prev
= comm_inbuf(ptr
);
228 bleft
= ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? (ptr
->ibuf_tail
-1) : ptr
->ibuf_size
)
230 len
= read(ptr
->fd
, ptr
->inbuf
+ ptr
->ibuf_head
, bleft
?bleft
:1);
233 ptr
->commerror
= CE_RXOVER
;
235 /* check for events */
236 if ((ptr
->eventmask
& EV_RXFLAG
) &&
237 memchr(ptr
->inbuf
+ ptr
->ibuf_head
, ptr
->evtchar
, len
)) {
238 *(WORD
*)(unknown
[cid
]) |= EV_RXFLAG
;
241 if (ptr
->eventmask
& EV_RXCHAR
) {
242 *(WORD
*)(unknown
[cid
]) |= EV_RXCHAR
;
245 /* advance buffer position */
246 ptr
->ibuf_head
+= len
;
247 if (ptr
->ibuf_head
>= ptr
->ibuf_size
)
252 /* check for notification */
253 if (ptr
->wnd
&& (ptr
->n_read
>0) && (prev
<ptr
->n_read
) &&
254 (comm_inbuf(ptr
)>=ptr
->n_read
)) {
255 /* passed the receive notification threshold */
259 /* write any TransmitCommChar character */
261 len
= write(ptr
->fd
, &(ptr
->xmit
), 1);
262 if (len
> 0) ptr
->xmit
= -1;
264 /* write from output queue */
265 prev
= comm_outbuf(ptr
);
267 bleft
= ((ptr
->obuf_tail
<= ptr
->obuf_head
) ? ptr
->obuf_head
: ptr
->obuf_size
)
269 len
= bleft
? write(ptr
->fd
, ptr
->outbuf
+ ptr
->obuf_tail
, bleft
) : 0;
271 ptr
->obuf_tail
+= len
;
272 if (ptr
->obuf_tail
>= ptr
->obuf_size
)
275 if ((ptr
->obuf_tail
== ptr
->obuf_head
) && (ptr
->eventmask
& EV_TXEMPTY
)) {
276 *(WORD
*)(unknown
[cid
]) |= EV_TXEMPTY
;
281 /* check for notification */
282 if (ptr
->wnd
&& (ptr
->n_write
>0) && (prev
>=ptr
->n_write
) &&
283 (comm_outbuf(ptr
)<ptr
->n_write
)) {
284 /* passed the transmit notification threshold */
288 /* send notifications, if any */
289 if (ptr
->wnd
&& mask
) {
290 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr
->wnd
, cid
, mask
);
291 PostMessage16(ptr
->wnd
, WM_COMMNOTIFY
, cid
, mask
);
295 /**************************************************************************
296 * BuildCommDCB (USER.213)
298 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
300 /* "COM1:9600,n,8,1" */
303 char *ptr
, temp
[256];
305 TRACE("(%s), ptr %p\n", device
, lpdcb
);
307 if (!lstrncmpiA(device
,"COM",3)) {
308 port
= device
[3] - '0';
312 ERR("BUG ! COM0 can't exist!.\n");
316 if (!ValidCOMPort(port
)) {
320 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
327 if (*(device
+4) != ':')
330 strcpy(temp
,device
+5);
331 ptr
= strtok(temp
, ", ");
333 if (COM
[port
].baudrate
> 0)
334 lpdcb
->BaudRate
= COM
[port
].baudrate
;
336 lpdcb
->BaudRate
= atoi(ptr
);
337 TRACE("baudrate (%d)\n", lpdcb
->BaudRate
);
339 ptr
= strtok(NULL
, ", ");
341 *ptr
= toupper(*ptr
);
343 TRACE("parity (%c)\n", *ptr
);
344 lpdcb
->fParity
= TRUE
;
347 lpdcb
->Parity
= NOPARITY
;
348 lpdcb
->fParity
= FALSE
;
351 lpdcb
->Parity
= EVENPARITY
;
354 lpdcb
->Parity
= MARKPARITY
;
357 lpdcb
->Parity
= ODDPARITY
;
360 WARN("Unknown parity `%c'!\n", *ptr
);
364 ptr
= strtok(NULL
, ", ");
365 TRACE("charsize (%c)\n", *ptr
);
366 lpdcb
->ByteSize
= *ptr
- '0';
368 ptr
= strtok(NULL
, ", ");
369 TRACE("stopbits (%c)\n", *ptr
);
372 lpdcb
->StopBits
= ONESTOPBIT
;
375 lpdcb
->StopBits
= TWOSTOPBITS
;
378 WARN("Unknown # of stopbits `%c'!\n", *ptr
);
386 /*****************************************************************************
387 * OpenComm (USER.200)
389 INT16 WINAPI
OpenComm16(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
393 TRACE("%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
395 if (strlen(device
) < 4)
398 port
= device
[3] - '0';
401 ERR("BUG ! COM0 or LPT0 don't exist !\n");
403 if (!lstrncmpiA(device
,"COM",3)) {
405 TRACE("%s = %s\n", device
, COM
[port
].devicename
);
407 if (!ValidCOMPort(port
))
413 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
415 ERR("error=%d\n", errno
);
418 unknown
[port
] = SEGPTR_ALLOC(40);
419 bzero(unknown
[port
],40);
421 COM
[port
].commerror
= 0;
422 COM
[port
].eventmask
= 0;
423 COM
[port
].evtchar
= 0; /* FIXME: default? */
424 /* save terminal state */
425 tcgetattr(fd
,&m_stat
[port
]);
426 /* set default parameters */
427 if(COM
[port
].baudrate
>-1){
429 GetCommState16(port
, &dcb
);
430 dcb
.BaudRate
=COM
[port
].baudrate
;
432 * databits, parity, stopbits
434 SetCommState16( &dcb
);
436 /* init priority characters */
437 COM
[port
].unget
= -1;
439 /* allocate buffers */
440 COM
[port
].ibuf_size
= cbInQueue
;
441 COM
[port
].ibuf_head
= COM
[port
].ibuf_tail
= 0;
442 COM
[port
].obuf_size
= cbOutQueue
;
443 COM
[port
].obuf_head
= COM
[port
].obuf_tail
= 0;
445 COM
[port
].inbuf
= malloc(cbInQueue
);
446 if (COM
[port
].inbuf
) {
447 COM
[port
].outbuf
= malloc(cbOutQueue
);
448 if (!COM
[port
].outbuf
)
449 free(COM
[port
].inbuf
);
450 } else COM
[port
].outbuf
= NULL
;
451 if (!COM
[port
].outbuf
) {
452 /* not enough memory */
453 tcsetattr(COM
[port
].fd
,TCSANOW
,&m_stat
[port
]);
455 ERR("out of memory");
459 COM
[port
].service
= SERVICE_AddObject( FILE_DupUnixHandle( COM
[port
].fd
,
460 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
),
462 (ULONG_PTR
)&COM
[port
] );
463 /* bootstrap notifications, just in case */
464 comm_notification( (ULONG_PTR
)&COM
[port
] );
469 if (!lstrncmpiA(device
,"LPT",3)) {
471 if (!ValidLPTPort(port
))
477 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
482 LPT
[port
].commerror
= 0;
483 LPT
[port
].eventmask
= 0;
484 return port
|FLAG_LPT
;
490 /*****************************************************************************
491 * CloseComm (USER.207)
493 INT16 WINAPI
CloseComm16(INT16 cid
)
495 struct DosDeviceStruct
*ptr
;
497 TRACE("cid=%d\n", cid
);
498 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
501 if (!(cid
&FLAG_LPT
)) {
503 SEGPTR_FREE(unknown
[cid
]); /* [LW] */
505 SERVICE_Delete( COM
[cid
].service
);
510 /* reset modem lines */
511 tcsetattr(ptr
->fd
,TCSANOW
,&m_stat
[cid
]);
514 if (close(ptr
->fd
) == -1) {
515 ptr
->commerror
= WinError();
516 /* FIXME: should we clear ptr->fd here? */
525 /*****************************************************************************
526 * SetCommBreak (USER.210)
528 INT16 WINAPI
SetCommBreak16(INT16 cid
)
530 struct DosDeviceStruct
*ptr
;
532 TRACE("cid=%d\n", cid
);
533 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
542 /*****************************************************************************
543 * ClearCommBreak (USER.211)
545 INT16 WINAPI
ClearCommBreak16(INT16 cid
)
547 struct DosDeviceStruct
*ptr
;
549 TRACE("cid=%d\n", cid
);
550 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
559 /*****************************************************************************
560 * EscapeCommFunction (USER.214)
562 LONG WINAPI
EscapeCommFunction16(UINT16 cid
,UINT16 nFunction
)
565 struct DosDeviceStruct
*ptr
;
568 TRACE("cid=%d, function=%d\n", cid
, nFunction
);
569 if ((nFunction
!= GETMAXCOM
) && (nFunction
!= GETMAXLPT
)) {
570 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
571 TRACE("GetDeviceStruct failed\n");
574 if (tcgetattr(ptr
->fd
,&port
) == -1) {
575 TRACE("tcgetattr failed\n");
576 ptr
->commerror
=WinError();
587 TRACE("GETMAXCOM\n");
588 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
594 TRACE("GETMAXLPT\n");
595 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
597 return FLAG_LPT
+ max
;
601 TRACE("GETBASEIRQ\n");
602 /* FIXME: use tables */
603 /* just fake something for now */
604 if (cid
& FLAG_LPT
) {
605 /* LPT1: irq 7, LPT2: irq 5 */
606 return (cid
& 0x7f) ? 5 : 7;
608 /* COM1: irq 4, COM2: irq 3,
609 COM3: irq 4, COM4: irq 3 */
610 return 4 - (cid
& 1);
617 return COMM_WhackModem(ptr
->fd
, ~TIOCM_DTR
, 0);
622 return COMM_WhackModem(ptr
->fd
, ~TIOCM_RTS
, 0);
628 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_DTR
);
634 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_RTS
);
639 port
.c_iflag
|= IXOFF
;
644 port
.c_iflag
|= IXON
;
648 WARN("(cid=%d,nFunction=%d): Unknown function\n",
653 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
654 ptr
->commerror
= WinError();
662 /*****************************************************************************
663 * FlushComm (USER.215)
665 INT16 WINAPI
FlushComm16(INT16 cid
,INT16 fnQueue
)
668 struct DosDeviceStruct
*ptr
;
670 TRACE("cid=%d, queue=%d\n", cid
, fnQueue
);
671 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
677 ptr
->obuf_tail
= ptr
->obuf_head
;
681 ptr
->ibuf_head
= ptr
->ibuf_tail
;
684 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
688 if (tcflush(ptr
->fd
, queue
)) {
689 ptr
->commerror
= WinError();
697 /********************************************************************
698 * GetCommError (USER.203)
700 INT16 WINAPI
GetCommError16(INT16 cid
,LPCOMSTAT16 lpStat
)
703 struct DosDeviceStruct
*ptr
;
707 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
711 WARN(" cid %d not comm port\n",cid
);
714 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
715 ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
716 if( mstat
&TIOCM_CAR
)
724 lpStat
->cbOutQue
= comm_outbuf(ptr
);
725 lpStat
->cbInQue
= comm_inbuf(ptr
);
727 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
728 cid
, ptr
->commerror
, lpStat
->status
, lpStat
->cbInQue
,
729 lpStat
->cbOutQue
, *stol
);
732 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
733 cid
, ptr
->commerror
, *stol
);
735 /* Return any errors and clear it */
736 temperror
= ptr
->commerror
;
741 /*****************************************************************************
742 * SetCommEventMask (USER.208)
744 SEGPTR WINAPI
SetCommEventMask16(INT16 cid
,UINT16 fuEvtMask
)
746 struct DosDeviceStruct
*ptr
;
751 TRACE("cid %d,mask %d\n",cid
,fuEvtMask
);
752 if ((ptr
= GetDeviceStruct(cid
)) == NULL
)
755 ptr
->eventmask
= fuEvtMask
;
757 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
758 WARN(" cid %d not comm port\n",cid
);
761 /* it's a COM port ? -> modify flags */
762 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
763 repid
= ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
764 TRACE(" ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[cid
]);
765 if ((mstat
&TIOCM_CAR
))
770 TRACE(" modem dcd construct %x\n",*stol
);
771 return SEGPTR_GET(unknown
[cid
]);
774 /*****************************************************************************
775 * GetCommEventMask (USER.209)
777 UINT16 WINAPI
GetCommEventMask16(INT16 cid
,UINT16 fnEvtClear
)
779 struct DosDeviceStruct
*ptr
;
782 TRACE("cid %d, mask %d\n", cid
, fnEvtClear
);
783 if ((ptr
= GetDeviceStruct(cid
)) == NULL
)
786 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
787 WARN(" cid %d not comm port\n",cid
);
791 events
= *(WORD
*)(unknown
[cid
]) & fnEvtClear
;
792 *(WORD
*)(unknown
[cid
]) &= ~fnEvtClear
;
796 /*****************************************************************************
797 * SetCommState16 (USER.201)
799 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
802 struct DosDeviceStruct
*ptr
;
804 TRACE("cid %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
805 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
808 if (tcgetattr(ptr
->fd
, &port
) == -1) {
809 ptr
->commerror
= WinError();
814 port
.c_cc
[VTIME
] = 1;
817 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
819 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
821 port
.c_iflag
|= (IGNBRK
);
823 port
.c_oflag
&= ~(OPOST
);
825 port
.c_cflag
&= ~(HUPCL
);
826 port
.c_cflag
|= CLOCAL
| CREAD
;
828 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
829 port
.c_lflag
|= NOFLSH
;
831 TRACE("baudrate %d\n",lpdcb
->BaudRate
);
833 port
.c_cflag
&= ~CBAUD
;
834 switch (lpdcb
->BaudRate
) {
837 port
.c_cflag
|= B110
;
841 port
.c_cflag
|= B300
;
845 port
.c_cflag
|= B600
;
849 port
.c_cflag
|= B1200
;
853 port
.c_cflag
|= B2400
;
857 port
.c_cflag
|= B4800
;
861 port
.c_cflag
|= B9600
;
865 port
.c_cflag
|= B19200
;
869 port
.c_cflag
|= B38400
;
873 port
.c_cflag
|= B57600
;
878 port
.c_cflag
|= B115200
;
882 ptr
->commerror
= IE_BAUDRATE
;
885 #elif !defined(__EMX__)
886 switch (lpdcb
->BaudRate
) {
889 port
.c_ospeed
= B110
;
893 port
.c_ospeed
= B300
;
897 port
.c_ospeed
= B600
;
901 port
.c_ospeed
= B1200
;
905 port
.c_ospeed
= B2400
;
909 port
.c_ospeed
= B4800
;
913 port
.c_ospeed
= B9600
;
917 port
.c_ospeed
= B19200
;
921 port
.c_ospeed
= B38400
;
924 ptr
->commerror
= IE_BAUDRATE
;
927 port
.c_ispeed
= port
.c_ospeed
;
929 TRACE("bytesize %d\n",lpdcb
->ByteSize
);
930 port
.c_cflag
&= ~CSIZE
;
931 switch (lpdcb
->ByteSize
) {
945 ptr
->commerror
= IE_BYTESIZE
;
949 TRACE("fParity %d Parity %d\n",lpdcb
->fParity
, lpdcb
->Parity
);
950 port
.c_cflag
&= ~(PARENB
| PARODD
);
952 port
.c_iflag
|= INPCK
;
954 port
.c_iflag
&= ~INPCK
;
955 switch (lpdcb
->Parity
) {
959 port
.c_cflag
|= (PARENB
| PARODD
);
962 port
.c_cflag
|= PARENB
;
965 ptr
->commerror
= IE_BYTESIZE
;
970 TRACE("stopbits %d\n",lpdcb
->StopBits
);
972 switch (lpdcb
->StopBits
) {
974 port
.c_cflag
&= ~CSTOPB
;
977 port
.c_cflag
|= CSTOPB
;
980 ptr
->commerror
= IE_BYTESIZE
;
985 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
986 port
.c_cflag
|= CRTSCTS
;
988 if (lpdcb
->fDtrDisable
)
989 port
.c_cflag
&= ~CRTSCTS
;
992 port
.c_iflag
|= IXON
;
994 port
.c_iflag
&= ~IXON
;
996 port
.c_iflag
|= IXOFF
;
998 port
.c_iflag
&= ~IXOFF
;
1000 ptr
->evtchar
= lpdcb
->EvtChar
;
1002 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
1003 ptr
->commerror
= WinError();
1011 /*****************************************************************************
1012 * GetCommState (USER.202)
1014 INT16 WINAPI
GetCommState16(INT16 cid
, LPDCB16 lpdcb
)
1017 struct DosDeviceStruct
*ptr
;
1018 struct termios port
;
1020 TRACE("cid %d, ptr %p\n", cid
, lpdcb
);
1021 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1024 if (tcgetattr(ptr
->fd
, &port
) == -1) {
1025 ptr
->commerror
= WinError();
1031 speed
= port
.c_cflag
& CBAUD
;
1033 speed
= port
.c_ospeed
;
1037 lpdcb
->BaudRate
= 110;
1040 lpdcb
->BaudRate
= 300;
1043 lpdcb
->BaudRate
= 600;
1046 lpdcb
->BaudRate
= 1200;
1049 lpdcb
->BaudRate
= 2400;
1052 lpdcb
->BaudRate
= 4800;
1055 lpdcb
->BaudRate
= 9600;
1058 lpdcb
->BaudRate
= 19200;
1061 lpdcb
->BaudRate
= 38400;
1065 lpdcb
->BaudRate
= 57600;
1070 lpdcb
->BaudRate
= 57601;
1075 switch (port
.c_cflag
& CSIZE
) {
1077 lpdcb
->ByteSize
= 5;
1080 lpdcb
->ByteSize
= 6;
1083 lpdcb
->ByteSize
= 7;
1086 lpdcb
->ByteSize
= 8;
1090 if(port
.c_iflag
& INPCK
)
1091 lpdcb
->fParity
= TRUE
;
1093 lpdcb
->fParity
= FALSE
;
1094 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1096 lpdcb
->Parity
= NOPARITY
;
1099 lpdcb
->Parity
= EVENPARITY
;
1101 case (PARENB
| PARODD
):
1102 lpdcb
->Parity
= ODDPARITY
;
1106 if (port
.c_cflag
& CSTOPB
)
1107 lpdcb
->StopBits
= TWOSTOPBITS
;
1109 lpdcb
->StopBits
= ONESTOPBIT
;
1111 lpdcb
->RlsTimeout
= 50;
1112 lpdcb
->CtsTimeout
= 50;
1113 lpdcb
->DsrTimeout
= 50;
1117 lpdcb
->fDtrDisable
= 0;
1121 if (port
.c_cflag
& CRTSCTS
) {
1122 lpdcb
->fDtrflow
= 1;
1123 lpdcb
->fRtsflow
= 1;
1124 lpdcb
->fOutxCtsFlow
= 1;
1125 lpdcb
->fOutxDsrFlow
= 1;
1128 lpdcb
->fDtrDisable
= 1;
1130 if (port
.c_iflag
& IXON
)
1135 if (port
.c_iflag
& IXOFF
)
1144 lpdcb
->XoffLim
= 10;
1146 lpdcb
->EvtChar
= ptr
->evtchar
;
1152 /*****************************************************************************
1153 * TransmitCommChar (USER.206)
1155 INT16 WINAPI
TransmitCommChar16(INT16 cid
,CHAR chTransmit
)
1157 struct DosDeviceStruct
*ptr
;
1159 TRACE("cid %d, data %d \n", cid
, chTransmit
);
1160 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1164 if (ptr
->suspended
) {
1165 ptr
->commerror
= IE_HARDWARE
;
1169 if (ptr
->xmit
>= 0) {
1170 /* character already queued */
1171 /* FIXME: which error would Windows return? */
1172 ptr
->commerror
= CE_TXFULL
;
1176 if (ptr
->obuf_head
== ptr
->obuf_tail
) {
1177 /* transmit queue empty, try to transmit directly */
1178 if (write(ptr
->fd
, &chTransmit
, 1) == -1) {
1179 /* didn't work, queue it */
1180 ptr
->xmit
= chTransmit
;
1183 /* data in queue, let this char be transmitted next */
1184 ptr
->xmit
= chTransmit
;
1191 /*****************************************************************************
1192 * UngetCommChar (USER.212)
1194 INT16 WINAPI
UngetCommChar16(INT16 cid
,CHAR chUnget
)
1196 struct DosDeviceStruct
*ptr
;
1198 TRACE("cid %d (char %d)\n", cid
, chUnget
);
1199 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1203 if (ptr
->suspended
) {
1204 ptr
->commerror
= IE_HARDWARE
;
1208 if (ptr
->unget
>=0) {
1209 /* character already queued */
1210 /* FIXME: which error would Windows return? */
1211 ptr
->commerror
= CE_RXOVER
;
1215 ptr
->unget
= chUnget
;
1221 /*****************************************************************************
1222 * ReadComm (USER.204)
1224 INT16 WINAPI
ReadComm16(INT16 cid
,LPSTR lpvBuf
,INT16 cbRead
)
1227 struct DosDeviceStruct
*ptr
;
1228 LPSTR orgBuf
= lpvBuf
;
1230 TRACE("cid %d, ptr %p, length %d\n", cid
, lpvBuf
, cbRead
);
1231 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1235 if (ptr
->suspended
) {
1236 ptr
->commerror
= IE_HARDWARE
;
1240 /* read unget character */
1241 if (ptr
->unget
>=0) {
1242 *lpvBuf
++ = ptr
->unget
;
1249 /* read from receive buffer */
1250 while (length
< cbRead
) {
1251 status
= ((ptr
->ibuf_head
< ptr
->ibuf_tail
) ?
1252 ptr
->ibuf_size
: ptr
->ibuf_head
) - ptr
->ibuf_tail
;
1254 if ((cbRead
- length
) < status
)
1255 status
= cbRead
- length
;
1257 memcpy(lpvBuf
, ptr
->inbuf
+ ptr
->ibuf_tail
, status
);
1258 ptr
->ibuf_tail
+= status
;
1259 if (ptr
->ibuf_tail
>= ptr
->ibuf_size
)
1265 TRACE("%.*s\n", length
, orgBuf
);
1270 /*****************************************************************************
1271 * WriteComm (USER.205)
1273 INT16 WINAPI
WriteComm16(INT16 cid
, LPSTR lpvBuf
, INT16 cbWrite
)
1276 struct DosDeviceStruct
*ptr
;
1278 TRACE("cid %d, ptr %p, length %d\n",
1279 cid
, lpvBuf
, cbWrite
);
1280 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1284 if (ptr
->suspended
) {
1285 ptr
->commerror
= IE_HARDWARE
;
1289 TRACE("%.*s\n", cbWrite
, lpvBuf
);
1292 while (length
< cbWrite
) {
1293 if ((ptr
->obuf_head
== ptr
->obuf_tail
) && (ptr
->xmit
< 0)) {
1294 /* no data queued, try to write directly */
1295 status
= write(ptr
->fd
, lpvBuf
, cbWrite
- length
);
1302 /* can't write directly, put into transmit buffer */
1303 status
= ((ptr
->obuf_tail
> ptr
->obuf_head
) ?
1304 (ptr
->obuf_tail
-1) : ptr
->obuf_size
) - ptr
->obuf_head
;
1306 if ((cbWrite
- length
) < status
)
1307 status
= cbWrite
- length
;
1308 memcpy(lpvBuf
, ptr
->outbuf
+ ptr
->obuf_head
, status
);
1309 ptr
->obuf_head
+= status
;
1310 if (ptr
->obuf_head
>= ptr
->obuf_size
)
1320 /***********************************************************************
1321 * EnableCommNotification (USER.246)
1323 BOOL16 WINAPI
EnableCommNotification16( INT16 cid
, HWND16 hwnd
,
1324 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1326 struct DosDeviceStruct
*ptr
;
1328 TRACE("(%d, %x, %d, %d)\n", cid
, hwnd
, cbWriteNotify
, cbOutQueue
);
1329 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1330 ptr
->commerror
= IE_BADID
;
1334 ptr
->n_read
= cbWriteNotify
;
1335 ptr
->n_write
= cbOutQueue
;
1340 /**************************************************************************
1341 * BuildCommDCBA (KERNEL32.14)
1343 BOOL WINAPI
BuildCommDCBA(LPCSTR device
,LPDCB lpdcb
)
1345 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
1348 /**************************************************************************
1349 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1351 BOOL WINAPI
BuildCommDCBAndTimeoutsA(LPCSTR device
, LPDCB lpdcb
,
1352 LPCOMMTIMEOUTS lptimeouts
)
1357 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
1359 if (!lstrncmpiA(device
,"COM",3)) {
1362 ERR("BUG! COM0 can't exists!.\n");
1365 if (!ValidCOMPort(port
))
1367 if (*(device
+4)!=':')
1369 temp
=(LPSTR
)(device
+5);
1373 memset(lpdcb
, 0, sizeof(DCB
)); /* initialize */
1375 lpdcb
->DCBlength
= sizeof(DCB
);
1376 if (strchr(temp
,',')) { /* old style */
1379 char last
=temp
[strlen(temp
)-1];
1381 ret
=BuildCommDCB16(device
,&dcb16
);
1384 lpdcb
->BaudRate
= dcb16
.BaudRate
;
1385 lpdcb
->ByteSize
= dcb16
.ByteSize
;
1386 lpdcb
->fBinary
= dcb16
.fBinary
;
1387 lpdcb
->Parity
= dcb16
.Parity
;
1388 lpdcb
->fParity
= dcb16
.fParity
;
1389 lpdcb
->fNull
= dcb16
.fNull
;
1390 lpdcb
->StopBits
= dcb16
.StopBits
;
1393 lpdcb
->fOutX
= TRUE
;
1394 lpdcb
->fOutxCtsFlow
= FALSE
;
1395 lpdcb
->fOutxDsrFlow
= FALSE
;
1396 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1397 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1398 } else if (last
=='p') {
1399 lpdcb
->fInX
= FALSE
;
1400 lpdcb
->fOutX
= FALSE
;
1401 lpdcb
->fOutxCtsFlow
= TRUE
;
1402 lpdcb
->fOutxDsrFlow
= TRUE
;
1403 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1404 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1406 lpdcb
->fInX
= FALSE
;
1407 lpdcb
->fOutX
= FALSE
;
1408 lpdcb
->fOutxCtsFlow
= FALSE
;
1409 lpdcb
->fOutxDsrFlow
= FALSE
;
1410 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1411 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1413 lpdcb
->XonChar
= dcb16
.XonChar
;
1414 lpdcb
->XoffChar
= dcb16
.XoffChar
;
1415 lpdcb
->ErrorChar
= dcb16
.PeChar
;
1416 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
1417 lpdcb
->EofChar
= dcb16
.EofChar
;
1418 lpdcb
->EvtChar
= dcb16
.EvtChar
;
1419 lpdcb
->XonLim
= dcb16
.XonLim
;
1420 lpdcb
->XoffLim
= dcb16
.XoffLim
;
1423 ptr
=strtok(temp
," ");
1428 if (!strncmp("baud=",ptr
,5)) {
1429 if (!sscanf(ptr
+5,"%ld",&x
))
1430 WARN("Couldn't parse %s\n",ptr
);
1431 lpdcb
->BaudRate
= x
;
1434 if (!strncmp("stop=",ptr
,5)) {
1435 if (!sscanf(ptr
+5,"%ld",&x
))
1436 WARN("Couldn't parse %s\n",ptr
);
1437 lpdcb
->StopBits
= x
;
1440 if (!strncmp("data=",ptr
,5)) {
1441 if (!sscanf(ptr
+5,"%ld",&x
))
1442 WARN("Couldn't parse %s\n",ptr
);
1443 lpdcb
->ByteSize
= x
;
1446 if (!strncmp("parity=",ptr
,7)) {
1447 lpdcb
->fParity
= TRUE
;
1450 lpdcb
->fParity
= FALSE
;
1451 lpdcb
->Parity
= NOPARITY
;
1454 lpdcb
->Parity
= EVENPARITY
;
1457 lpdcb
->Parity
= ODDPARITY
;
1460 lpdcb
->Parity
= MARKPARITY
;
1466 ERR("Unhandled specifier '%s', please report.\n",ptr
);
1467 ptr
=strtok(NULL
," ");
1469 if (lpdcb
->BaudRate
==110)
1470 lpdcb
->StopBits
= 2;
1474 /**************************************************************************
1475 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1477 BOOL WINAPI
BuildCommDCBAndTimeoutsW( LPCWSTR devid
, LPDCB lpdcb
,
1478 LPCOMMTIMEOUTS lptimeouts
)
1483 TRACE("(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
1484 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
1485 ret
=BuildCommDCBAndTimeoutsA(devidA
,lpdcb
,lptimeouts
);
1486 HeapFree( GetProcessHeap(), 0, devidA
);
1490 /**************************************************************************
1491 * BuildCommDCBW (KERNEL32.17)
1493 BOOL WINAPI
BuildCommDCBW(LPCWSTR devid
,LPDCB lpdcb
)
1495 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
1498 /*****************************************************************************
1500 * Returns a file descriptor for reading.
1501 * Make sure to close the handle afterwards!
1503 static int COMM_GetReadFd( HANDLE handle
)
1506 struct get_read_fd_request
*req
= get_req_buffer();
1507 req
->handle
= handle
;
1508 server_call_fd( REQ_GET_READ_FD
, -1, &fd
);
1512 /*****************************************************************************
1514 * Returns a file descriptor for writing.
1515 * Make sure to close the handle afterwards!
1517 static int COMM_GetWriteFd( HANDLE handle
)
1520 struct get_write_fd_request
*req
= get_req_buffer();
1521 req
->handle
= handle
;
1522 server_call_fd( REQ_GET_WRITE_FD
, -1, &fd
);
1526 /* FIXME: having these global for win32 for now */
1527 int commerror
=0,eventmask
=0;
1529 /*****************************************************************************
1530 * SetCommBreak (KERNEL32.449)
1532 BOOL WINAPI
SetCommBreak(HANDLE handle
)
1534 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1537 fd
= COMM_GetWriteFd(handle
);
1539 TRACE("COMM_GetWriteFd failed\n");
1542 result
= ioctl(fd
,TIOCSBRK
,0);
1546 TRACE("ioctl failed\n");
1547 SetLastError(ERROR_NOT_SUPPORTED
);
1552 FIXME("ioctl not available\n");
1553 SetLastError(ERROR_NOT_SUPPORTED
);
1558 /*****************************************************************************
1559 * ClearCommBreak (KERNEL32.20)
1561 BOOL WINAPI
ClearCommBreak(HANDLE handle
)
1563 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1566 fd
= COMM_GetWriteFd(handle
);
1568 TRACE("COMM_GetWriteFd failed\n");
1571 result
= ioctl(fd
,TIOCCBRK
,0);
1575 TRACE("ioctl failed\n");
1576 SetLastError(ERROR_NOT_SUPPORTED
);
1581 FIXME("ioctl not available\n");
1582 SetLastError(ERROR_NOT_SUPPORTED
);
1587 /*****************************************************************************
1588 * EscapeCommFunction (KERNEL32.214)
1590 BOOL WINAPI
EscapeCommFunction(HANDLE handle
,UINT nFunction
)
1592 int fd
,direct
=FALSE
,result
=FALSE
;
1593 struct termios port
;
1595 TRACE("handle %d, function=%d\n", handle
, nFunction
);
1596 fd
= COMM_GetWriteFd(handle
);
1600 if (tcgetattr(fd
,&port
) == -1) {
1601 commerror
=WinError();
1606 switch (nFunction
) {
1615 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1623 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1631 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1639 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1645 port
.c_iflag
|= IXOFF
;
1650 port
.c_iflag
|= IXON
;
1653 TRACE("setbreak\n");
1656 result
= ioctl(fd
,TIOCSBRK
,0);
1660 TRACE("clrbreak\n");
1663 result
= ioctl(fd
,TIOCCBRK
,0);
1667 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1673 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
1674 commerror
= WinError();
1684 commerror
=WinError();
1693 /********************************************************************
1694 * PurgeComm (KERNEL32.557)
1696 BOOL WINAPI
PurgeComm( HANDLE handle
, DWORD flags
)
1700 TRACE("handle %d, flags %lx\n", handle
, flags
);
1702 fd
= COMM_GetWriteFd(handle
);
1707 ** not exactly sure how these are different
1708 ** Perhaps if we had our own internal queues, one flushes them
1709 ** and the other flushes the kernel's buffers.
1711 if(flags
&PURGE_TXABORT
)
1713 tcflush(fd
,TCOFLUSH
);
1715 if(flags
&PURGE_RXABORT
)
1717 tcflush(fd
,TCIFLUSH
);
1719 if(flags
&PURGE_TXCLEAR
)
1721 tcflush(fd
,TCOFLUSH
);
1723 if(flags
&PURGE_RXCLEAR
)
1725 tcflush(fd
,TCIFLUSH
);
1732 /*****************************************************************************
1733 * ClearCommError (KERNEL32.21)
1735 BOOL WINAPI
ClearCommError(INT handle
,LPDWORD errors
,LPCOMSTAT lpStat
)
1739 fd
=COMM_GetReadFd(handle
);
1749 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
1750 WARN("ioctl returned error\n");
1752 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
1753 WARN("ioctl returned error\n");
1755 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1756 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
1765 ** After an asynchronous write opperation, the
1766 ** app will call ClearCommError to see if the
1767 ** results are ready yet. It waits for ERROR_IO_PENDING
1769 commerror
= ERROR_IO_PENDING
;
1774 /*****************************************************************************
1775 * SetupComm (KERNEL32.676)
1777 BOOL WINAPI
SetupComm( HANDLE handle
, DWORD insize
, DWORD outsize
)
1781 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
1782 fd
=COMM_GetWriteFd(handle
);
1791 /*****************************************************************************
1792 * GetCommMask (KERNEL32.156)
1794 BOOL WINAPI
GetCommMask(HANDLE handle
,LPDWORD evtmask
)
1798 TRACE("handle %d, mask %p\n", handle
, evtmask
);
1799 if(0>(fd
=COMM_GetReadFd(handle
)))
1804 *evtmask
= eventmask
;
1805 TRACE("%s%s%s%s%s%s%s%s%s\n",
1806 (eventmask
&EV_BREAK
)?"EV_BREAK":"",
1807 (eventmask
&EV_CTS
)?"EV_CTS":"",
1808 (eventmask
&EV_DSR
)?"EV_DSR":"",
1809 (eventmask
&EV_ERR
)?"EV_ERR":"",
1810 (eventmask
&EV_RING
)?"EV_RING":"",
1811 (eventmask
&EV_RLSD
)?"EV_RLSD":"",
1812 (eventmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1813 (eventmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1814 (eventmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1819 /*****************************************************************************
1820 * SetCommMask (KERNEL32.451)
1822 BOOL WINAPI
SetCommMask(INT handle
,DWORD evtmask
)
1826 TRACE("handle %d, mask %lx\n", handle
, evtmask
);
1827 TRACE("%s%s%s%s%s%s%s%s%s\n",
1828 (evtmask
&EV_BREAK
)?"EV_BREAK":"",
1829 (evtmask
&EV_CTS
)?"EV_CTS":"",
1830 (evtmask
&EV_DSR
)?"EV_DSR":"",
1831 (evtmask
&EV_ERR
)?"EV_ERR":"",
1832 (evtmask
&EV_RING
)?"EV_RING":"",
1833 (evtmask
&EV_RLSD
)?"EV_RLSD":"",
1834 (evtmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1835 (evtmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1836 (evtmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1838 if(0>(fd
=COMM_GetWriteFd(handle
))) {
1842 eventmask
= evtmask
;
1846 /*****************************************************************************
1847 * SetCommState (KERNEL32.452)
1849 BOOL WINAPI
SetCommState(INT handle
,LPDCB lpdcb
)
1851 struct termios port
;
1854 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
1855 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1856 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1857 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1858 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1859 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1860 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1862 if ((fd
= COMM_GetWriteFd(handle
)) < 0) return FALSE
;
1864 if ((tcgetattr(fd
,&port
)) == -1) {
1865 int save_error
= errno
;
1866 commerror
= WinError();
1868 #ifdef HAVE_STRERROR
1869 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1871 ERR("tcgetattr error %d\n", save_error
);
1876 port
.c_cc
[VMIN
] = 0;
1877 port
.c_cc
[VTIME
] = 1;
1880 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1882 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1884 port
.c_iflag
|= (IGNBRK
);
1886 port
.c_oflag
&= ~(OPOST
);
1888 port
.c_cflag
&= ~(HUPCL
);
1889 port
.c_cflag
|= CLOCAL
| CREAD
;
1891 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1892 port
.c_lflag
|= NOFLSH
;
1895 ** MJM - removed default baudrate settings
1896 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1899 port
.c_cflag
&= ~CBAUD
;
1900 switch (lpdcb
->BaudRate
) {
1903 port
.c_cflag
|= B110
;
1907 port
.c_cflag
|= B300
;
1911 port
.c_cflag
|= B600
;
1915 port
.c_cflag
|= B1200
;
1919 port
.c_cflag
|= B2400
;
1923 port
.c_cflag
|= B4800
;
1927 port
.c_cflag
|= B9600
;
1931 port
.c_cflag
|= B19200
;
1935 port
.c_cflag
|= B38400
;
1939 port
.c_cflag
|= B57600
;
1944 port
.c_cflag
|= B115200
;
1949 port
.c_cflag
|= B230400
;
1954 port
.c_cflag
|= B460800
;
1958 commerror
= IE_BAUDRATE
;
1960 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
1963 #elif !defined(__EMX__)
1964 switch (lpdcb
->BaudRate
) {
1967 port
.c_ospeed
= B110
;
1971 port
.c_ospeed
= B300
;
1975 port
.c_ospeed
= B600
;
1979 port
.c_ospeed
= B1200
;
1983 port
.c_ospeed
= B2400
;
1987 port
.c_ospeed
= B4800
;
1991 port
.c_ospeed
= B9600
;
1995 port
.c_ospeed
= B19200
;
1999 port
.c_ospeed
= B38400
;
2002 commerror
= IE_BAUDRATE
;
2004 ERR("baudrate %d \n",lpdcb
->BaudRate
);
2007 port
.c_ispeed
= port
.c_ospeed
;
2009 port
.c_cflag
&= ~CSIZE
;
2010 switch (lpdcb
->ByteSize
) {
2012 port
.c_cflag
|= CS5
;
2015 port
.c_cflag
|= CS6
;
2018 port
.c_cflag
|= CS7
;
2021 port
.c_cflag
|= CS8
;
2024 commerror
= IE_BYTESIZE
;
2030 port
.c_cflag
&= ~(PARENB
| PARODD
);
2032 port
.c_iflag
|= INPCK
;
2034 port
.c_iflag
&= ~INPCK
;
2035 switch (lpdcb
->Parity
) {
2039 port
.c_cflag
|= (PARENB
| PARODD
);
2042 port
.c_cflag
|= PARENB
;
2045 commerror
= IE_BYTESIZE
;
2052 switch (lpdcb
->StopBits
) {
2054 port
.c_cflag
&= ~CSTOPB
;
2057 port
.c_cflag
|= CSTOPB
;
2060 commerror
= IE_BYTESIZE
;
2066 if ( lpdcb
->fOutxCtsFlow
||
2067 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2068 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2071 port
.c_cflag
|= CRTSCTS
;
2075 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2077 port
.c_cflag
&= ~CRTSCTS
;
2078 TRACE("~CRTSCTS\n");
2083 port
.c_iflag
|= IXON
;
2085 port
.c_iflag
&= ~IXON
;
2087 port
.c_iflag
|= IXOFF
;
2089 port
.c_iflag
&= ~IXOFF
;
2091 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
2092 int save_error
=errno
;
2093 commerror
= WinError();
2095 #ifdef HAVE_STRERROR
2096 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2098 ERR("tcgetattr error %d\n", save_error
);
2109 /*****************************************************************************
2110 * GetCommState (KERNEL32.159)
2112 BOOL WINAPI
GetCommState(INT handle
, LPDCB lpdcb
)
2114 struct termios port
;
2117 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2119 if ((fd
= COMM_GetReadFd(handle
)) < 0)
2121 ERR("can't get COMM_GetReadFd\n");
2124 if (tcgetattr(fd
, &port
) == -1) {
2125 int save_error
=errno
;
2126 #ifdef HAVE_STRERROR
2127 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2129 ERR("tcgetattr error %d\n", save_error
);
2131 commerror
= WinError();
2138 speed
= (port
.c_cflag
& CBAUD
);
2140 speed
= (cfgetospeed(&port
));
2144 lpdcb
->BaudRate
= 110;
2147 lpdcb
->BaudRate
= 300;
2150 lpdcb
->BaudRate
= 600;
2153 lpdcb
->BaudRate
= 1200;
2156 lpdcb
->BaudRate
= 2400;
2159 lpdcb
->BaudRate
= 4800;
2162 lpdcb
->BaudRate
= 9600;
2165 lpdcb
->BaudRate
= 19200;
2168 lpdcb
->BaudRate
= 38400;
2172 lpdcb
->BaudRate
= 57600;
2177 lpdcb
->BaudRate
= 115200;
2182 lpdcb
->BaudRate
= 230400;
2187 lpdcb
->BaudRate
= 460800;
2191 ERR("unknown speed %x \n",speed
);
2194 switch (port
.c_cflag
& CSIZE
) {
2196 lpdcb
->ByteSize
= 5;
2199 lpdcb
->ByteSize
= 6;
2202 lpdcb
->ByteSize
= 7;
2205 lpdcb
->ByteSize
= 8;
2208 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
2211 if(port
.c_iflag
& INPCK
)
2212 lpdcb
->fParity
= TRUE
;
2214 lpdcb
->fParity
= FALSE
;
2215 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
2217 lpdcb
->Parity
= NOPARITY
;
2220 lpdcb
->Parity
= EVENPARITY
;
2222 case (PARENB
| PARODD
):
2223 lpdcb
->Parity
= ODDPARITY
;
2227 if (port
.c_cflag
& CSTOPB
)
2228 lpdcb
->StopBits
= TWOSTOPBITS
;
2230 lpdcb
->StopBits
= ONESTOPBIT
;
2237 if (port
.c_cflag
& CRTSCTS
) {
2238 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
2239 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
2240 lpdcb
->fOutxCtsFlow
= 1;
2241 lpdcb
->fOutxDsrFlow
= 1;
2245 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
2246 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
2248 if (port
.c_iflag
& IXON
)
2253 if (port
.c_iflag
& IXOFF
)
2262 lpdcb
->XoffLim
= 10;
2268 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2269 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2270 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2271 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2272 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2273 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2275 if ( lpdcb
->fOutxCtsFlow
||
2276 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2277 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2281 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2282 TRACE("~CRTSCTS\n");
2288 /*****************************************************************************
2289 * TransmitCommChar (KERNEL32.535)
2291 BOOL WINAPI
TransmitCommChar(INT cid
,CHAR chTransmit
)
2293 struct DosDeviceStruct
*ptr
;
2295 FIXME("(%d,'%c'), use win32 handle!\n",cid
,chTransmit
);
2296 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
2300 if (ptr
->suspended
) {
2301 ptr
->commerror
= IE_HARDWARE
;
2304 if (write(ptr
->fd
, (void *) &chTransmit
, 1) == -1) {
2305 ptr
->commerror
= WinError();
2313 /*****************************************************************************
2314 * GetCommTimeouts (KERNEL32.160)
2316 BOOL WINAPI
GetCommTimeouts(INT cid
,LPCOMMTIMEOUTS lptimeouts
)
2318 FIXME("(%x,%p):stub.\n",cid
,lptimeouts
);
2322 /*****************************************************************************
2323 * SetCommTimeouts (KERNEL32.453)
2325 BOOL WINAPI
SetCommTimeouts(INT cid
,LPCOMMTIMEOUTS lptimeouts
) {
2326 FIXME("(%x,%p):stub.\n",cid
,lptimeouts
);
2327 TRACE("ReadIntervalTimeout %ld\n",lptimeouts
->ReadIntervalTimeout
);
2328 TRACE("ReadTotalTimeoutMultiplier %ld\n",
2329 lptimeouts
->ReadTotalTimeoutMultiplier
);
2330 TRACE("ReadTotalTimeoutConstant %ld\n",
2331 lptimeouts
->ReadTotalTimeoutConstant
);
2332 TRACE("WriteTotalTimeoutMultiplier %ld\n",
2333 lptimeouts
->WriteTotalTimeoutMultiplier
);
2334 TRACE("WriteTotalTimeoutConstant %ld\n",
2335 lptimeouts
->WriteTotalTimeoutConstant
);
2339 /***********************************************************************
2340 * GetCommModemStatus (KERNEL32.285)
2342 BOOL WINAPI
GetCommModemStatus(HANDLE hFile
,LPDWORD lpModemStat
)
2344 int fd
,mstat
, result
=FALSE
;
2348 fd
= COMM_GetWriteFd(hFile
);
2351 result
= ioctl(fd
, TIOCMGET
, &mstat
);
2355 TRACE("ioctl failed\n");
2358 if (mstat
& TIOCM_CTS
)
2359 *lpModemStat
|= MS_CTS_ON
;
2360 if (mstat
& TIOCM_DSR
)
2361 *lpModemStat
|= MS_DSR_ON
;
2362 if (mstat
& TIOCM_RNG
)
2363 *lpModemStat
|= MS_RING_ON
;
2364 /*FIXME: Not really sure about RLSD UB 990810*/
2365 if (mstat
& TIOCM_CAR
)
2366 *lpModemStat
|= MS_RLSD_ON
;
2368 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
2369 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
2370 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
2371 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
2377 /***********************************************************************
2378 * WaitCommEvent (KERNEL32.719)
2380 BOOL WINAPI
WaitCommEvent(HANDLE hFile
,LPDWORD eventmask
,LPOVERLAPPED overlapped
)
2382 FIXME("(%d %p %p )\n",hFile
, eventmask
,overlapped
);
2386 /***********************************************************************
2387 * GetCommProperties (KERNEL32.???)
2389 BOOL WINAPI
GetCommProperties(HANDLE hFile
, LPDCB
*dcb
)
2391 FIXME("(%d %p )\n",hFile
,dcb
);
2395 /***********************************************************************
2396 * SetCommProperties (KERNEL32.???)
2398 BOOL WINAPI
SetCommProperties(HANDLE hFile
, LPDCB dcb
)
2400 FIXME("(%d %p )\n",hFile
,dcb
);