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.
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
51 #include <sys/ioctl.h>
56 #include "wine/winuser16.h"
58 #ifdef HAVE_SYS_MODEM_H
59 # include <sys/modem.h>
61 #ifdef HAVE_SYS_STRTIO_H
62 # include <sys/strtio.h>
74 #include "debugtools.h"
76 DEFAULT_DEBUG_CHANNEL(comm
);
79 #define TIOCINQ FIONREAD
82 /* window's semi documented modem status register */
83 #define COMM_MSR_OFFSET 35
88 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
92 struct DosDeviceStruct COM
[MAX_PORTS
];
93 struct DosDeviceStruct LPT
[MAX_PORTS
];
94 /* pointers to unknown(==undocumented) comm structure */
95 LPCVOID
*unknown
[MAX_PORTS
];
96 /* save terminal states */
97 static struct termios m_stat
[MAX_PORTS
];
99 /* update window's semi documented modem status register */
100 /* see knowledge base Q101417 */
101 static void COMM_MSRUpdate( UCHAR
* pMsr
, unsigned int mstat
)
104 if(mstat
& TIOCM_CTS
) tmpmsr
|= MSR_CTS
;
105 if(mstat
& TIOCM_DSR
) tmpmsr
|= MSR_DSR
;
106 if(mstat
& TIOCM_RI
) tmpmsr
|= MSR_RI
;
107 if(mstat
& TIOCM_CAR
) tmpmsr
|= MSR_RLSD
;
108 *pMsr
= (*pMsr
& ~MSR_MASK
) | tmpmsr
;
114 char option
[10], temp
[256], *btemp
;
117 for (x
=0; x
!=MAX_PORTS
; x
++) {
118 strcpy(option
,"COMx");
122 PROFILE_GetWineIniString( "serialports", option
, "*",
123 temp
, sizeof(temp
) );
124 if (!strcmp(temp
, "*") || *temp
== '\0')
125 COM
[x
].devicename
= NULL
;
127 btemp
= strchr(temp
,',');
130 COM
[x
].baudrate
= atoi(btemp
);
132 COM
[x
].baudrate
= -1;
135 if (!S_ISCHR(st
.st_mode
))
136 WARN("Can't use `%s' as %s !\n", temp
, option
);
138 if ((COM
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
139 WARN("Can't malloc for device info!\n");
142 strcpy(COM
[x
].devicename
, temp
);
144 TRACE("%s = %s\n", option
, COM
[x
].devicename
);
147 strcpy(option
, "LPTx");
151 PROFILE_GetWineIniString( "parallelports", option
, "*",
152 temp
, sizeof(temp
) );
153 if (!strcmp(temp
, "*") || *temp
== '\0')
154 LPT
[x
].devicename
= NULL
;
157 if (!S_ISCHR(st
.st_mode
))
158 WARN("Can't use `%s' as %s !\n", temp
, option
);
160 if ((LPT
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
161 WARN("Can't malloc for device info!\n");
164 strcpy(LPT
[x
].devicename
, temp
);
166 TRACE("%s = %s\n", option
, LPT
[x
].devicename
);
173 static struct DosDeviceStruct
*GetDeviceStruct(int fd
)
175 if ((fd
&0x7F)<=MAX_PORTS
) {
176 if (!(fd
&FLAG_LPT
)) {
189 static int GetCommPort_fd(int fd
)
193 for (x
=0; x
<MAX_PORTS
; x
++) {
201 static int ValidCOMPort(int x
)
203 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
206 static int ValidLPTPort(int x
)
208 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
211 static int WinError(void)
213 TRACE("errno = %d\n", errno
);
220 static unsigned comm_inbuf(struct DosDeviceStruct
*ptr
)
222 return ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? ptr
->ibuf_size
: 0)
223 + ptr
->ibuf_head
- ptr
->ibuf_tail
;
226 static unsigned comm_outbuf(struct DosDeviceStruct
*ptr
)
228 return ((ptr
->obuf_tail
> ptr
->obuf_head
) ? ptr
->obuf_size
: 0)
229 + ptr
->obuf_head
- ptr
->obuf_tail
;
232 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
234 unsigned int mstat
, okay
;
235 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
236 if (okay
) return okay
;
237 if (andy
) mstat
&= andy
;
239 return ioctl(fd
, TIOCMSET
, &mstat
);
242 static void CALLBACK
comm_notification( ULONG_PTR
private )
244 struct DosDeviceStruct
*ptr
= (struct DosDeviceStruct
*)private;
245 int prev
, bleft
, len
;
247 int cid
= GetCommPort_fd(ptr
->fd
);
249 TRACE("async notification\n");
250 /* read data from comm port */
251 prev
= comm_inbuf(ptr
);
253 bleft
= ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? (ptr
->ibuf_tail
-1) : ptr
->ibuf_size
)
255 len
= read(ptr
->fd
, ptr
->inbuf
+ ptr
->ibuf_head
, bleft
?bleft
:1);
258 ptr
->commerror
= CE_RXOVER
;
260 /* check for events */
261 if ((ptr
->eventmask
& EV_RXFLAG
) &&
262 memchr(ptr
->inbuf
+ ptr
->ibuf_head
, ptr
->evtchar
, len
)) {
263 *(WORD
*)(unknown
[cid
]) |= EV_RXFLAG
;
266 if (ptr
->eventmask
& EV_RXCHAR
) {
267 *(WORD
*)(unknown
[cid
]) |= EV_RXCHAR
;
270 /* advance buffer position */
271 ptr
->ibuf_head
+= len
;
272 if (ptr
->ibuf_head
>= ptr
->ibuf_size
)
277 /* check for notification */
278 if (ptr
->wnd
&& (ptr
->n_read
>0) && (prev
<ptr
->n_read
) &&
279 (comm_inbuf(ptr
)>=ptr
->n_read
)) {
280 /* passed the receive notification threshold */
284 /* write any TransmitCommChar character */
286 len
= write(ptr
->fd
, &(ptr
->xmit
), 1);
287 if (len
> 0) ptr
->xmit
= -1;
289 /* write from output queue */
290 prev
= comm_outbuf(ptr
);
292 bleft
= ((ptr
->obuf_tail
<= ptr
->obuf_head
) ? ptr
->obuf_head
: ptr
->obuf_size
)
294 len
= bleft
? write(ptr
->fd
, ptr
->outbuf
+ ptr
->obuf_tail
, bleft
) : 0;
296 ptr
->obuf_tail
+= len
;
297 if (ptr
->obuf_tail
>= ptr
->obuf_size
)
300 if (ptr
->obuf_tail
== ptr
->obuf_head
) {
302 SERVICE_Delete( ptr
->s_write
);
303 ptr
->s_write
= INVALID_HANDLE_VALUE
;
305 if (ptr
->eventmask
& EV_TXEMPTY
) {
306 *(WORD
*)(unknown
[cid
]) |= EV_TXEMPTY
;
312 /* check for notification */
313 if (ptr
->wnd
&& (ptr
->n_write
>0) && (prev
>=ptr
->n_write
) &&
314 (comm_outbuf(ptr
)<ptr
->n_write
)) {
315 /* passed the transmit notification threshold */
319 /* send notifications, if any */
320 if (ptr
->wnd
&& mask
) {
321 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr
->wnd
, cid
, mask
);
322 Callout
.PostMessage16(ptr
->wnd
, WM_COMMNOTIFY
, cid
, mask
);
326 static void comm_waitread(struct DosDeviceStruct
*ptr
)
328 if (ptr
->s_read
!= INVALID_HANDLE_VALUE
) return;
329 ptr
->s_read
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
330 GENERIC_READ
| SYNCHRONIZE
),
335 static void comm_waitwrite(struct DosDeviceStruct
*ptr
)
337 if (ptr
->s_write
!= INVALID_HANDLE_VALUE
) return;
338 ptr
->s_write
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
339 GENERIC_WRITE
| SYNCHRONIZE
),
344 /**************************************************************************
345 * BuildCommDCB (USER.213)
347 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
349 /* "COM1:9600,n,8,1" */
352 char *ptr
, temp
[256];
354 TRACE("(%s), ptr %p\n", device
, lpdcb
);
356 if (!lstrncmpiA(device
,"COM",3)) {
357 port
= device
[3] - '0';
361 ERR("BUG ! COM0 can't exist!.\n");
365 if (!ValidCOMPort(port
)) {
366 FIXME("invalid COM port %d?\n",port
);
370 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
377 if (*(device
+4) != ':')
380 strcpy(temp
,device
+5);
381 ptr
= strtok(temp
, ", ");
383 if (COM
[port
].baudrate
> 0)
384 lpdcb
->BaudRate
= COM
[port
].baudrate
;
386 lpdcb
->BaudRate
= atoi(ptr
);
387 TRACE("baudrate (%d)\n", lpdcb
->BaudRate
);
389 ptr
= strtok(NULL
, ", ");
391 *ptr
= toupper(*ptr
);
393 TRACE("parity (%c)\n", *ptr
);
394 lpdcb
->fParity
= TRUE
;
397 lpdcb
->Parity
= NOPARITY
;
398 lpdcb
->fParity
= FALSE
;
401 lpdcb
->Parity
= EVENPARITY
;
404 lpdcb
->Parity
= MARKPARITY
;
407 lpdcb
->Parity
= ODDPARITY
;
410 WARN("Unknown parity `%c'!\n", *ptr
);
414 ptr
= strtok(NULL
, ", ");
415 TRACE("charsize (%c)\n", *ptr
);
416 lpdcb
->ByteSize
= *ptr
- '0';
418 ptr
= strtok(NULL
, ", ");
419 TRACE("stopbits (%c)\n", *ptr
);
422 lpdcb
->StopBits
= ONESTOPBIT
;
425 lpdcb
->StopBits
= TWOSTOPBITS
;
428 WARN("Unknown # of stopbits `%c'!\n", *ptr
);
436 /*****************************************************************************
437 * OpenComm (USER.200)
439 INT16 WINAPI
OpenComm16(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
443 TRACE("%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
445 if (strlen(device
) < 4)
448 port
= device
[3] - '0';
451 ERR("BUG ! COM0 or LPT0 don't exist !\n");
453 if (!lstrncmpiA(device
,"COM",3)) {
455 TRACE("%s = %s\n", device
, COM
[port
].devicename
);
457 if (!ValidCOMPort(port
))
463 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
465 ERR("error=%d\n", errno
);
468 unknown
[port
] = SEGPTR_ALLOC(40);
469 bzero(unknown
[port
],40);
471 COM
[port
].commerror
= 0;
472 COM
[port
].eventmask
= 0;
473 COM
[port
].evtchar
= 0; /* FIXME: default? */
474 /* save terminal state */
475 tcgetattr(fd
,&m_stat
[port
]);
476 /* set default parameters */
477 if(COM
[port
].baudrate
>-1){
479 GetCommState16(port
, &dcb
);
480 dcb
.BaudRate
=COM
[port
].baudrate
;
482 * databits, parity, stopbits
484 SetCommState16( &dcb
);
486 /* init priority characters */
487 COM
[port
].unget
= -1;
489 /* allocate buffers */
490 COM
[port
].ibuf_size
= cbInQueue
;
491 COM
[port
].ibuf_head
= COM
[port
].ibuf_tail
= 0;
492 COM
[port
].obuf_size
= cbOutQueue
;
493 COM
[port
].obuf_head
= COM
[port
].obuf_tail
= 0;
495 COM
[port
].inbuf
= malloc(cbInQueue
);
496 if (COM
[port
].inbuf
) {
497 COM
[port
].outbuf
= malloc(cbOutQueue
);
498 if (!COM
[port
].outbuf
)
499 free(COM
[port
].inbuf
);
500 } else COM
[port
].outbuf
= NULL
;
501 if (!COM
[port
].outbuf
) {
502 /* not enough memory */
503 tcsetattr(COM
[port
].fd
,TCSANOW
,&m_stat
[port
]);
505 ERR("out of memory");
509 COM
[port
].s_read
= INVALID_HANDLE_VALUE
;
510 COM
[port
].s_write
= INVALID_HANDLE_VALUE
;
511 comm_waitread( &COM
[port
] );
516 if (!lstrncmpiA(device
,"LPT",3)) {
518 if (!ValidLPTPort(port
))
524 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
529 LPT
[port
].commerror
= 0;
530 LPT
[port
].eventmask
= 0;
531 return port
|FLAG_LPT
;
537 /*****************************************************************************
538 * CloseComm (USER.207)
540 INT16 WINAPI
CloseComm16(INT16 cid
)
542 struct DosDeviceStruct
*ptr
;
544 TRACE("cid=%d\n", cid
);
545 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
546 FIXME("no cid=%d found!\n", cid
);
549 if (!(cid
&FLAG_LPT
)) {
551 SEGPTR_FREE(unknown
[cid
]); /* [LW] */
553 SERVICE_Delete( COM
[cid
].s_write
);
554 SERVICE_Delete( COM
[cid
].s_read
);
559 /* reset modem lines */
560 tcsetattr(ptr
->fd
,TCSANOW
,&m_stat
[cid
]);
563 if (close(ptr
->fd
) == -1) {
564 ptr
->commerror
= WinError();
565 /* FIXME: should we clear ptr->fd here? */
574 /*****************************************************************************
575 * SetCommBreak (USER.210)
577 INT16 WINAPI
SetCommBreak16(INT16 cid
)
579 struct DosDeviceStruct
*ptr
;
581 TRACE("cid=%d\n", cid
);
582 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
583 FIXME("no cid=%d found!\n", cid
);
592 /*****************************************************************************
593 * ClearCommBreak (USER.211)
595 INT16 WINAPI
ClearCommBreak16(INT16 cid
)
597 struct DosDeviceStruct
*ptr
;
599 TRACE("cid=%d\n", cid
);
600 if (!(ptr
= GetDeviceStruct(cid
))) {
601 FIXME("no cid=%d found!\n", cid
);
609 /*****************************************************************************
610 * EscapeCommFunction (USER.214)
612 LONG WINAPI
EscapeCommFunction16(UINT16 cid
,UINT16 nFunction
)
615 struct DosDeviceStruct
*ptr
;
618 TRACE("cid=%d, function=%d\n", cid
, nFunction
);
619 if ((nFunction
!= GETMAXCOM
) && (nFunction
!= GETMAXLPT
)) {
620 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
621 FIXME("no cid=%d found!\n", cid
);
624 if (tcgetattr(ptr
->fd
,&port
) == -1) {
625 TRACE("tcgetattr failed\n");
626 ptr
->commerror
=WinError();
637 TRACE("GETMAXCOM\n");
638 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
644 TRACE("GETMAXLPT\n");
645 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
647 return FLAG_LPT
+ max
;
651 TRACE("GETBASEIRQ\n");
652 /* FIXME: use tables */
653 /* just fake something for now */
654 if (cid
& FLAG_LPT
) {
655 /* LPT1: irq 7, LPT2: irq 5 */
656 return (cid
& 0x7f) ? 5 : 7;
658 /* COM1: irq 4, COM2: irq 3,
659 COM3: irq 4, COM4: irq 3 */
660 return 4 - (cid
& 1);
667 return COMM_WhackModem(ptr
->fd
, ~TIOCM_DTR
, 0);
672 return COMM_WhackModem(ptr
->fd
, ~TIOCM_RTS
, 0);
678 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_DTR
);
684 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_RTS
);
689 port
.c_iflag
|= IXOFF
;
694 port
.c_iflag
|= IXON
;
698 WARN("(cid=%d,nFunction=%d): Unknown function\n",
703 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
704 ptr
->commerror
= WinError();
712 /*****************************************************************************
713 * FlushComm (USER.215)
715 INT16 WINAPI
FlushComm16(INT16 cid
,INT16 fnQueue
)
718 struct DosDeviceStruct
*ptr
;
720 TRACE("cid=%d, queue=%d\n", cid
, fnQueue
);
721 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
722 FIXME("no cid=%d found!\n", cid
);
728 ptr
->obuf_tail
= ptr
->obuf_head
;
732 ptr
->ibuf_head
= ptr
->ibuf_tail
;
735 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
739 if (tcflush(ptr
->fd
, queue
)) {
740 ptr
->commerror
= WinError();
748 /********************************************************************
749 * GetCommError (USER.203)
751 INT16 WINAPI
GetCommError16(INT16 cid
,LPCOMSTAT16 lpStat
)
754 struct DosDeviceStruct
*ptr
;
758 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
759 FIXME("no handle for cid = %0x!.\n",cid
);
763 WARN(" cid %d not comm port\n",cid
);
766 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
767 ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
768 COMM_MSRUpdate( stol
, mstat
);
773 lpStat
->cbOutQue
= comm_outbuf(ptr
);
774 lpStat
->cbInQue
= comm_inbuf(ptr
);
776 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
777 cid
, ptr
->commerror
, lpStat
->status
, lpStat
->cbInQue
,
778 lpStat
->cbOutQue
, *stol
);
781 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
782 cid
, ptr
->commerror
, *stol
);
784 /* Return any errors and clear it */
785 temperror
= ptr
->commerror
;
790 /*****************************************************************************
791 * SetCommEventMask (USER.208)
793 SEGPTR WINAPI
SetCommEventMask16(INT16 cid
,UINT16 fuEvtMask
)
795 struct DosDeviceStruct
*ptr
;
800 TRACE("cid %d,mask %d\n",cid
,fuEvtMask
);
801 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
802 FIXME("no handle for cid = %0x!.\n",cid
);
806 ptr
->eventmask
= fuEvtMask
;
808 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
809 WARN(" cid %d not comm port\n",cid
);
812 /* it's a COM port ? -> modify flags */
813 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
814 repid
= ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
815 TRACE(" ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[cid
]);
816 COMM_MSRUpdate( stol
, mstat
);
818 TRACE(" modem dcd construct %x\n",*stol
);
819 return SEGPTR_GET(unknown
[cid
]);
822 /*****************************************************************************
823 * GetCommEventMask (USER.209)
825 UINT16 WINAPI
GetCommEventMask16(INT16 cid
,UINT16 fnEvtClear
)
827 struct DosDeviceStruct
*ptr
;
830 TRACE("cid %d, mask %d\n", cid
, fnEvtClear
);
831 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
832 FIXME("no handle for cid = %0x!.\n",cid
);
836 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
837 WARN(" cid %d not comm port\n",cid
);
841 events
= *(WORD
*)(unknown
[cid
]) & fnEvtClear
;
842 *(WORD
*)(unknown
[cid
]) &= ~fnEvtClear
;
846 /*****************************************************************************
847 * SetCommState16 (USER.201)
849 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
852 struct DosDeviceStruct
*ptr
;
854 TRACE("cid %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
855 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
856 FIXME("no handle for cid = %0x!.\n",lpdcb
->Id
);
859 if (tcgetattr(ptr
->fd
, &port
) == -1) {
860 ptr
->commerror
= WinError();
865 port
.c_cc
[VTIME
] = 1;
868 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
870 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
872 port
.c_iflag
|= (IGNBRK
);
874 port
.c_oflag
&= ~(OPOST
);
876 port
.c_cflag
&= ~(HUPCL
);
877 port
.c_cflag
|= CLOCAL
| CREAD
;
879 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
880 port
.c_lflag
|= NOFLSH
;
882 TRACE("baudrate %d\n",lpdcb
->BaudRate
);
884 port
.c_cflag
&= ~CBAUD
;
885 switch (lpdcb
->BaudRate
) {
888 port
.c_cflag
|= B110
;
892 port
.c_cflag
|= B300
;
896 port
.c_cflag
|= B600
;
900 port
.c_cflag
|= B1200
;
904 port
.c_cflag
|= B2400
;
908 port
.c_cflag
|= B4800
;
912 port
.c_cflag
|= B9600
;
916 port
.c_cflag
|= B19200
;
920 port
.c_cflag
|= B38400
;
924 port
.c_cflag
|= B57600
;
929 port
.c_cflag
|= B115200
;
933 ptr
->commerror
= IE_BAUDRATE
;
936 #elif !defined(__EMX__)
937 switch (lpdcb
->BaudRate
) {
940 port
.c_ospeed
= B110
;
944 port
.c_ospeed
= B300
;
948 port
.c_ospeed
= B600
;
952 port
.c_ospeed
= B1200
;
956 port
.c_ospeed
= B2400
;
960 port
.c_ospeed
= B4800
;
964 port
.c_ospeed
= B9600
;
968 port
.c_ospeed
= B19200
;
972 port
.c_ospeed
= B38400
;
975 ptr
->commerror
= IE_BAUDRATE
;
978 port
.c_ispeed
= port
.c_ospeed
;
980 TRACE("bytesize %d\n",lpdcb
->ByteSize
);
981 port
.c_cflag
&= ~CSIZE
;
982 switch (lpdcb
->ByteSize
) {
996 ptr
->commerror
= IE_BYTESIZE
;
1000 TRACE("fParity %d Parity %d\n",lpdcb
->fParity
, lpdcb
->Parity
);
1001 port
.c_cflag
&= ~(PARENB
| PARODD
);
1003 port
.c_iflag
|= INPCK
;
1005 port
.c_iflag
&= ~INPCK
;
1006 switch (lpdcb
->Parity
) {
1010 port
.c_cflag
|= (PARENB
| PARODD
);
1013 port
.c_cflag
|= PARENB
;
1016 ptr
->commerror
= IE_BYTESIZE
;
1021 TRACE("stopbits %d\n",lpdcb
->StopBits
);
1023 switch (lpdcb
->StopBits
) {
1025 port
.c_cflag
&= ~CSTOPB
;
1028 port
.c_cflag
|= CSTOPB
;
1031 ptr
->commerror
= IE_BYTESIZE
;
1036 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
1037 port
.c_cflag
|= CRTSCTS
;
1039 if (lpdcb
->fDtrDisable
)
1040 port
.c_cflag
&= ~CRTSCTS
;
1043 port
.c_iflag
|= IXON
;
1045 port
.c_iflag
&= ~IXON
;
1047 port
.c_iflag
|= IXOFF
;
1049 port
.c_iflag
&= ~IXOFF
;
1051 ptr
->evtchar
= lpdcb
->EvtChar
;
1053 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
1054 ptr
->commerror
= WinError();
1062 /*****************************************************************************
1063 * GetCommState (USER.202)
1065 INT16 WINAPI
GetCommState16(INT16 cid
, LPDCB16 lpdcb
)
1068 struct DosDeviceStruct
*ptr
;
1069 struct termios port
;
1071 TRACE("cid %d, ptr %p\n", cid
, lpdcb
);
1072 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1073 FIXME("no handle for cid = %0x!.\n",cid
);
1076 if (tcgetattr(ptr
->fd
, &port
) == -1) {
1077 ptr
->commerror
= WinError();
1083 speed
= port
.c_cflag
& CBAUD
;
1085 speed
= port
.c_ospeed
;
1089 lpdcb
->BaudRate
= 110;
1092 lpdcb
->BaudRate
= 300;
1095 lpdcb
->BaudRate
= 600;
1098 lpdcb
->BaudRate
= 1200;
1101 lpdcb
->BaudRate
= 2400;
1104 lpdcb
->BaudRate
= 4800;
1107 lpdcb
->BaudRate
= 9600;
1110 lpdcb
->BaudRate
= 19200;
1113 lpdcb
->BaudRate
= 38400;
1117 lpdcb
->BaudRate
= 57600;
1122 lpdcb
->BaudRate
= 57601;
1127 switch (port
.c_cflag
& CSIZE
) {
1129 lpdcb
->ByteSize
= 5;
1132 lpdcb
->ByteSize
= 6;
1135 lpdcb
->ByteSize
= 7;
1138 lpdcb
->ByteSize
= 8;
1142 if(port
.c_iflag
& INPCK
)
1143 lpdcb
->fParity
= TRUE
;
1145 lpdcb
->fParity
= FALSE
;
1146 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1148 lpdcb
->Parity
= NOPARITY
;
1151 lpdcb
->Parity
= EVENPARITY
;
1153 case (PARENB
| PARODD
):
1154 lpdcb
->Parity
= ODDPARITY
;
1158 if (port
.c_cflag
& CSTOPB
)
1159 lpdcb
->StopBits
= TWOSTOPBITS
;
1161 lpdcb
->StopBits
= ONESTOPBIT
;
1163 lpdcb
->RlsTimeout
= 50;
1164 lpdcb
->CtsTimeout
= 50;
1165 lpdcb
->DsrTimeout
= 50;
1169 lpdcb
->fDtrDisable
= 0;
1173 if (port
.c_cflag
& CRTSCTS
) {
1174 lpdcb
->fDtrflow
= 1;
1175 lpdcb
->fRtsflow
= 1;
1176 lpdcb
->fOutxCtsFlow
= 1;
1177 lpdcb
->fOutxDsrFlow
= 1;
1180 lpdcb
->fDtrDisable
= 1;
1182 if (port
.c_iflag
& IXON
)
1187 if (port
.c_iflag
& IXOFF
)
1196 lpdcb
->XoffLim
= 10;
1198 lpdcb
->EvtChar
= ptr
->evtchar
;
1204 /*****************************************************************************
1205 * TransmitCommChar (USER.206)
1207 INT16 WINAPI
TransmitCommChar16(INT16 cid
,CHAR chTransmit
)
1209 struct DosDeviceStruct
*ptr
;
1211 TRACE("cid %d, data %d \n", cid
, chTransmit
);
1212 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1213 FIXME("no handle for cid = %0x!.\n",cid
);
1217 if (ptr
->suspended
) {
1218 ptr
->commerror
= IE_HARDWARE
;
1222 if (ptr
->xmit
>= 0) {
1223 /* character already queued */
1224 /* FIXME: which error would Windows return? */
1225 ptr
->commerror
= CE_TXFULL
;
1229 if (ptr
->obuf_head
== ptr
->obuf_tail
) {
1230 /* transmit queue empty, try to transmit directly */
1231 if (write(ptr
->fd
, &chTransmit
, 1) == -1) {
1232 /* didn't work, queue it */
1233 ptr
->xmit
= chTransmit
;
1234 comm_waitwrite(ptr
);
1237 /* data in queue, let this char be transmitted next */
1238 ptr
->xmit
= chTransmit
;
1239 comm_waitwrite(ptr
);
1246 /*****************************************************************************
1247 * UngetCommChar (USER.212)
1249 INT16 WINAPI
UngetCommChar16(INT16 cid
,CHAR chUnget
)
1251 struct DosDeviceStruct
*ptr
;
1253 TRACE("cid %d (char %d)\n", cid
, chUnget
);
1254 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1255 FIXME("no handle for cid = %0x!.\n",cid
);
1259 if (ptr
->suspended
) {
1260 ptr
->commerror
= IE_HARDWARE
;
1264 if (ptr
->unget
>=0) {
1265 /* character already queued */
1266 /* FIXME: which error would Windows return? */
1267 ptr
->commerror
= CE_RXOVER
;
1271 ptr
->unget
= chUnget
;
1277 /*****************************************************************************
1278 * ReadComm (USER.204)
1280 INT16 WINAPI
ReadComm16(INT16 cid
,LPSTR lpvBuf
,INT16 cbRead
)
1283 struct DosDeviceStruct
*ptr
;
1284 LPSTR orgBuf
= lpvBuf
;
1286 TRACE("cid %d, ptr %p, length %d\n", cid
, lpvBuf
, cbRead
);
1287 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1288 FIXME("no handle for cid = %0x!.\n",cid
);
1292 if (ptr
->suspended
) {
1293 ptr
->commerror
= IE_HARDWARE
;
1297 /* read unget character */
1298 if (ptr
->unget
>=0) {
1299 *lpvBuf
++ = ptr
->unget
;
1306 /* read from receive buffer */
1307 while (length
< cbRead
) {
1308 status
= ((ptr
->ibuf_head
< ptr
->ibuf_tail
) ?
1309 ptr
->ibuf_size
: ptr
->ibuf_head
) - ptr
->ibuf_tail
;
1311 if ((cbRead
- length
) < status
)
1312 status
= cbRead
- length
;
1314 memcpy(lpvBuf
, ptr
->inbuf
+ ptr
->ibuf_tail
, status
);
1315 ptr
->ibuf_tail
+= status
;
1316 if (ptr
->ibuf_tail
>= ptr
->ibuf_size
)
1322 TRACE("%.*s\n", length
, orgBuf
);
1327 /*****************************************************************************
1328 * WriteComm (USER.205)
1330 INT16 WINAPI
WriteComm16(INT16 cid
, LPSTR lpvBuf
, INT16 cbWrite
)
1333 struct DosDeviceStruct
*ptr
;
1335 TRACE("cid %d, ptr %p, length %d\n",
1336 cid
, lpvBuf
, cbWrite
);
1337 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1338 FIXME("no handle for cid = %0x!.\n",cid
);
1342 if (ptr
->suspended
) {
1343 ptr
->commerror
= IE_HARDWARE
;
1347 TRACE("%.*s\n", cbWrite
, lpvBuf
);
1350 while (length
< cbWrite
) {
1351 if ((ptr
->obuf_head
== ptr
->obuf_tail
) && (ptr
->xmit
< 0)) {
1352 /* no data queued, try to write directly */
1353 status
= write(ptr
->fd
, lpvBuf
, cbWrite
- length
);
1360 /* can't write directly, put into transmit buffer */
1361 status
= ((ptr
->obuf_tail
> ptr
->obuf_head
) ?
1362 (ptr
->obuf_tail
-1) : ptr
->obuf_size
) - ptr
->obuf_head
;
1364 if ((cbWrite
- length
) < status
)
1365 status
= cbWrite
- length
;
1366 memcpy(lpvBuf
, ptr
->outbuf
+ ptr
->obuf_head
, status
);
1367 ptr
->obuf_head
+= status
;
1368 if (ptr
->obuf_head
>= ptr
->obuf_size
)
1372 comm_waitwrite(ptr
);
1379 /***********************************************************************
1380 * EnableCommNotification (USER.246)
1382 BOOL16 WINAPI
EnableCommNotification16( INT16 cid
, HWND16 hwnd
,
1383 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1385 struct DosDeviceStruct
*ptr
;
1387 TRACE("(%d, %x, %d, %d)\n", cid
, hwnd
, cbWriteNotify
, cbOutQueue
);
1388 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1389 FIXME("no handle for cid = %0x!.\n",cid
);
1390 ptr
->commerror
= IE_BADID
;
1394 ptr
->n_read
= cbWriteNotify
;
1395 ptr
->n_write
= cbOutQueue
;
1400 /**************************************************************************
1401 * BuildCommDCBA (KERNEL32.14)
1403 BOOL WINAPI
BuildCommDCBA(LPCSTR device
,LPDCB lpdcb
)
1405 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
1408 /**************************************************************************
1409 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1411 BOOL WINAPI
BuildCommDCBAndTimeoutsA(LPCSTR device
, LPDCB lpdcb
,
1412 LPCOMMTIMEOUTS lptimeouts
)
1417 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
1419 if (!lstrncmpiA(device
,"COM",3)) {
1422 ERR("BUG! COM0 can't exists!.\n");
1425 if (!ValidCOMPort(port
))
1427 if (*(device
+4)!=':')
1429 temp
=(LPSTR
)(device
+5);
1433 memset(lpdcb
, 0, sizeof(DCB
)); /* initialize */
1435 lpdcb
->DCBlength
= sizeof(DCB
);
1436 if (strchr(temp
,',')) { /* old style */
1439 char last
=temp
[strlen(temp
)-1];
1441 ret
=BuildCommDCB16(device
,&dcb16
);
1444 lpdcb
->BaudRate
= dcb16
.BaudRate
;
1445 lpdcb
->ByteSize
= dcb16
.ByteSize
;
1446 lpdcb
->fBinary
= dcb16
.fBinary
;
1447 lpdcb
->Parity
= dcb16
.Parity
;
1448 lpdcb
->fParity
= dcb16
.fParity
;
1449 lpdcb
->fNull
= dcb16
.fNull
;
1450 lpdcb
->StopBits
= dcb16
.StopBits
;
1453 lpdcb
->fOutX
= TRUE
;
1454 lpdcb
->fOutxCtsFlow
= FALSE
;
1455 lpdcb
->fOutxDsrFlow
= FALSE
;
1456 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1457 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1458 } else if (last
=='p') {
1459 lpdcb
->fInX
= FALSE
;
1460 lpdcb
->fOutX
= FALSE
;
1461 lpdcb
->fOutxCtsFlow
= TRUE
;
1462 lpdcb
->fOutxDsrFlow
= TRUE
;
1463 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1464 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1466 lpdcb
->fInX
= FALSE
;
1467 lpdcb
->fOutX
= FALSE
;
1468 lpdcb
->fOutxCtsFlow
= FALSE
;
1469 lpdcb
->fOutxDsrFlow
= FALSE
;
1470 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1471 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1473 lpdcb
->XonChar
= dcb16
.XonChar
;
1474 lpdcb
->XoffChar
= dcb16
.XoffChar
;
1475 lpdcb
->ErrorChar
= dcb16
.PeChar
;
1476 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
1477 lpdcb
->EofChar
= dcb16
.EofChar
;
1478 lpdcb
->EvtChar
= dcb16
.EvtChar
;
1479 lpdcb
->XonLim
= dcb16
.XonLim
;
1480 lpdcb
->XoffLim
= dcb16
.XoffLim
;
1483 ptr
=strtok(temp
," ");
1488 if (!strncmp("baud=",ptr
,5)) {
1489 if (!sscanf(ptr
+5,"%ld",&x
))
1490 WARN("Couldn't parse %s\n",ptr
);
1491 lpdcb
->BaudRate
= x
;
1494 if (!strncmp("stop=",ptr
,5)) {
1495 if (!sscanf(ptr
+5,"%ld",&x
))
1496 WARN("Couldn't parse %s\n",ptr
);
1497 lpdcb
->StopBits
= x
;
1500 if (!strncmp("data=",ptr
,5)) {
1501 if (!sscanf(ptr
+5,"%ld",&x
))
1502 WARN("Couldn't parse %s\n",ptr
);
1503 lpdcb
->ByteSize
= x
;
1506 if (!strncmp("parity=",ptr
,7)) {
1507 lpdcb
->fParity
= TRUE
;
1510 lpdcb
->fParity
= FALSE
;
1511 lpdcb
->Parity
= NOPARITY
;
1514 lpdcb
->Parity
= EVENPARITY
;
1517 lpdcb
->Parity
= ODDPARITY
;
1520 lpdcb
->Parity
= MARKPARITY
;
1526 ERR("Unhandled specifier '%s', please report.\n",ptr
);
1527 ptr
=strtok(NULL
," ");
1529 if (lpdcb
->BaudRate
==110)
1530 lpdcb
->StopBits
= 2;
1534 /**************************************************************************
1535 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1537 BOOL WINAPI
BuildCommDCBAndTimeoutsW( LPCWSTR devid
, LPDCB lpdcb
,
1538 LPCOMMTIMEOUTS lptimeouts
)
1543 TRACE("(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
1544 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
1545 ret
=BuildCommDCBAndTimeoutsA(devidA
,lpdcb
,lptimeouts
);
1546 HeapFree( GetProcessHeap(), 0, devidA
);
1550 /**************************************************************************
1551 * BuildCommDCBW (KERNEL32.17)
1553 BOOL WINAPI
BuildCommDCBW(LPCWSTR devid
,LPDCB lpdcb
)
1555 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
1558 /*****************************************************************************
1560 * Returns a file descriptor for reading.
1561 * Make sure to close the handle afterwards!
1563 static int COMM_GetReadFd( HANDLE handle
)
1566 struct get_read_fd_request
*req
= get_req_buffer();
1567 req
->handle
= handle
;
1568 server_call_fd( REQ_GET_READ_FD
, -1, &fd
);
1572 /*****************************************************************************
1574 * Returns a file descriptor for writing.
1575 * Make sure to close the handle afterwards!
1577 static int COMM_GetWriteFd( HANDLE handle
)
1580 struct get_write_fd_request
*req
= get_req_buffer();
1581 req
->handle
= handle
;
1582 server_call_fd( REQ_GET_WRITE_FD
, -1, &fd
);
1586 /* FIXME: having these global for win32 for now */
1587 int commerror
=0,eventmask
=0;
1589 /*****************************************************************************
1590 * SetCommBreak (KERNEL32.449)
1592 BOOL WINAPI
SetCommBreak(HANDLE handle
)
1594 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1597 fd
= COMM_GetWriteFd(handle
);
1599 TRACE("COMM_GetWriteFd failed\n");
1602 result
= ioctl(fd
,TIOCSBRK
,0);
1606 TRACE("ioctl failed\n");
1607 SetLastError(ERROR_NOT_SUPPORTED
);
1612 FIXME("ioctl not available\n");
1613 SetLastError(ERROR_NOT_SUPPORTED
);
1618 /*****************************************************************************
1619 * ClearCommBreak (KERNEL32.20)
1621 BOOL WINAPI
ClearCommBreak(HANDLE handle
)
1623 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1626 fd
= COMM_GetWriteFd(handle
);
1628 TRACE("COMM_GetWriteFd failed\n");
1631 result
= ioctl(fd
,TIOCCBRK
,0);
1635 TRACE("ioctl failed\n");
1636 SetLastError(ERROR_NOT_SUPPORTED
);
1641 FIXME("ioctl not available\n");
1642 SetLastError(ERROR_NOT_SUPPORTED
);
1647 /*****************************************************************************
1648 * EscapeCommFunction (KERNEL32.214)
1650 BOOL WINAPI
EscapeCommFunction(HANDLE handle
,UINT nFunction
)
1652 int fd
,direct
=FALSE
,result
=FALSE
;
1653 struct termios port
;
1655 TRACE("handle %d, function=%d\n", handle
, nFunction
);
1656 fd
= COMM_GetWriteFd(handle
);
1658 FIXME("handle %d not found.\n",handle
);
1662 if (tcgetattr(fd
,&port
) == -1) {
1663 commerror
=WinError();
1668 switch (nFunction
) {
1677 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1685 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1693 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1701 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1707 port
.c_iflag
|= IXOFF
;
1712 port
.c_iflag
|= IXON
;
1715 TRACE("setbreak\n");
1718 result
= ioctl(fd
,TIOCSBRK
,0);
1722 TRACE("clrbreak\n");
1725 result
= ioctl(fd
,TIOCCBRK
,0);
1729 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1735 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
1736 commerror
= WinError();
1746 commerror
=WinError();
1755 /********************************************************************
1756 * PurgeComm (KERNEL32.557)
1758 BOOL WINAPI
PurgeComm( HANDLE handle
, DWORD flags
)
1762 TRACE("handle %d, flags %lx\n", handle
, flags
);
1764 fd
= COMM_GetWriteFd(handle
);
1766 FIXME("no handle %d found\n",handle
);
1771 ** not exactly sure how these are different
1772 ** Perhaps if we had our own internal queues, one flushes them
1773 ** and the other flushes the kernel's buffers.
1775 if(flags
&PURGE_TXABORT
)
1776 tcflush(fd
,TCOFLUSH
);
1777 if(flags
&PURGE_RXABORT
)
1778 tcflush(fd
,TCIFLUSH
);
1779 if(flags
&PURGE_TXCLEAR
)
1780 tcflush(fd
,TCOFLUSH
);
1781 if(flags
&PURGE_RXCLEAR
)
1782 tcflush(fd
,TCIFLUSH
);
1788 /*****************************************************************************
1789 * ClearCommError (KERNEL32.21)
1791 BOOL WINAPI
ClearCommError(INT handle
,LPDWORD errors
,LPCOMSTAT lpStat
)
1795 fd
=COMM_GetReadFd(handle
);
1798 FIXME("no handle %d found\n",handle
);
1807 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
1808 WARN("ioctl returned error\n");
1810 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
1813 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
1814 WARN("ioctl returned error\n");
1816 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1817 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
1826 ** After an asynchronous write opperation, the
1827 ** app will call ClearCommError to see if the
1828 ** results are ready yet. It waits for ERROR_IO_PENDING
1830 commerror
= ERROR_IO_PENDING
;
1835 /*****************************************************************************
1836 * SetupComm (KERNEL32.676)
1838 BOOL WINAPI
SetupComm( HANDLE handle
, DWORD insize
, DWORD outsize
)
1842 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
1843 fd
=COMM_GetWriteFd(handle
);
1845 FIXME("handle %d not found?\n",handle
);
1852 /*****************************************************************************
1853 * GetCommMask (KERNEL32.156)
1855 BOOL WINAPI
GetCommMask(HANDLE handle
,LPDWORD evtmask
)
1859 TRACE("handle %d, mask %p\n", handle
, evtmask
);
1860 if(0>(fd
=COMM_GetReadFd(handle
)))
1862 FIXME("no handle %d found\n",handle
);
1866 *evtmask
= eventmask
;
1867 TRACE("%s%s%s%s%s%s%s%s%s\n",
1868 (eventmask
&EV_BREAK
)?"EV_BREAK":"",
1869 (eventmask
&EV_CTS
)?"EV_CTS":"",
1870 (eventmask
&EV_DSR
)?"EV_DSR":"",
1871 (eventmask
&EV_ERR
)?"EV_ERR":"",
1872 (eventmask
&EV_RING
)?"EV_RING":"",
1873 (eventmask
&EV_RLSD
)?"EV_RLSD":"",
1874 (eventmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1875 (eventmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1876 (eventmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1881 /*****************************************************************************
1882 * SetCommMask (KERNEL32.451)
1884 BOOL WINAPI
SetCommMask(INT handle
,DWORD evtmask
)
1888 TRACE("handle %d, mask %lx\n", handle
, evtmask
);
1889 TRACE("%s%s%s%s%s%s%s%s%s\n",
1890 (evtmask
&EV_BREAK
)?"EV_BREAK":"",
1891 (evtmask
&EV_CTS
)?"EV_CTS":"",
1892 (evtmask
&EV_DSR
)?"EV_DSR":"",
1893 (evtmask
&EV_ERR
)?"EV_ERR":"",
1894 (evtmask
&EV_RING
)?"EV_RING":"",
1895 (evtmask
&EV_RLSD
)?"EV_RLSD":"",
1896 (evtmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1897 (evtmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1898 (evtmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1900 if(0>(fd
=COMM_GetWriteFd(handle
))) {
1901 FIXME("no handle %d found\n",handle
);
1905 eventmask
= evtmask
;
1909 /*****************************************************************************
1910 * SetCommState (KERNEL32.452)
1912 BOOL WINAPI
SetCommState(INT handle
,LPDCB lpdcb
)
1914 struct termios port
;
1917 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
1918 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1919 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1920 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1921 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1922 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1923 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1925 if ((fd
= COMM_GetWriteFd(handle
)) < 0) {
1926 FIXME("no handle %d found\n",handle
);
1930 if ((tcgetattr(fd
,&port
)) == -1) {
1931 int save_error
= errno
;
1932 commerror
= WinError();
1934 #ifdef HAVE_STRERROR
1935 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1937 ERR("tcgetattr error %d\n", save_error
);
1942 port
.c_cc
[VMIN
] = 0;
1943 port
.c_cc
[VTIME
] = 1;
1946 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1948 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1950 port
.c_iflag
|= (IGNBRK
);
1952 port
.c_oflag
&= ~(OPOST
);
1954 port
.c_cflag
&= ~(HUPCL
);
1955 port
.c_cflag
|= CLOCAL
| CREAD
;
1957 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1958 port
.c_lflag
|= NOFLSH
;
1961 ** MJM - removed default baudrate settings
1962 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1965 port
.c_cflag
&= ~CBAUD
;
1966 switch (lpdcb
->BaudRate
) {
1969 port
.c_cflag
|= B110
;
1973 port
.c_cflag
|= B300
;
1977 port
.c_cflag
|= B600
;
1981 port
.c_cflag
|= B1200
;
1985 port
.c_cflag
|= B2400
;
1989 port
.c_cflag
|= B4800
;
1993 port
.c_cflag
|= B9600
;
1997 port
.c_cflag
|= B19200
;
2001 port
.c_cflag
|= B38400
;
2005 port
.c_cflag
|= B57600
;
2010 port
.c_cflag
|= B115200
;
2015 port
.c_cflag
|= B230400
;
2020 port
.c_cflag
|= B460800
;
2024 commerror
= IE_BAUDRATE
;
2026 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
2029 #elif !defined(__EMX__)
2030 switch (lpdcb
->BaudRate
) {
2033 port
.c_ospeed
= B110
;
2037 port
.c_ospeed
= B300
;
2041 port
.c_ospeed
= B600
;
2045 port
.c_ospeed
= B1200
;
2049 port
.c_ospeed
= B2400
;
2053 port
.c_ospeed
= B4800
;
2057 port
.c_ospeed
= B9600
;
2061 port
.c_ospeed
= B19200
;
2065 port
.c_ospeed
= B38400
;
2068 commerror
= IE_BAUDRATE
;
2070 ERR("baudrate %d \n",lpdcb
->BaudRate
);
2073 port
.c_ispeed
= port
.c_ospeed
;
2075 port
.c_cflag
&= ~CSIZE
;
2076 switch (lpdcb
->ByteSize
) {
2078 port
.c_cflag
|= CS5
;
2081 port
.c_cflag
|= CS6
;
2084 port
.c_cflag
|= CS7
;
2087 port
.c_cflag
|= CS8
;
2090 commerror
= IE_BYTESIZE
;
2096 port
.c_cflag
&= ~(PARENB
| PARODD
);
2098 port
.c_iflag
|= INPCK
;
2100 port
.c_iflag
&= ~INPCK
;
2101 switch (lpdcb
->Parity
) {
2105 port
.c_cflag
|= (PARENB
| PARODD
);
2108 port
.c_cflag
|= PARENB
;
2111 commerror
= IE_BYTESIZE
;
2118 switch (lpdcb
->StopBits
) {
2120 port
.c_cflag
&= ~CSTOPB
;
2123 port
.c_cflag
|= CSTOPB
;
2126 commerror
= IE_BYTESIZE
;
2132 if ( lpdcb
->fOutxCtsFlow
||
2133 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2134 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2137 port
.c_cflag
|= CRTSCTS
;
2141 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2143 port
.c_cflag
&= ~CRTSCTS
;
2144 TRACE("~CRTSCTS\n");
2149 port
.c_iflag
|= IXON
;
2151 port
.c_iflag
&= ~IXON
;
2153 port
.c_iflag
|= IXOFF
;
2155 port
.c_iflag
&= ~IXOFF
;
2157 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
2158 int save_error
=errno
;
2159 commerror
= WinError();
2161 #ifdef HAVE_STRERROR
2162 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2164 ERR("tcgetattr error %d\n", save_error
);
2175 /*****************************************************************************
2176 * GetCommState (KERNEL32.159)
2178 BOOL WINAPI
GetCommState(INT handle
, LPDCB lpdcb
)
2180 struct termios port
;
2183 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2185 if ((fd
= COMM_GetReadFd(handle
)) < 0)
2187 ERR("can't get COMM_GetReadFd\n");
2190 if (tcgetattr(fd
, &port
) == -1) {
2191 int save_error
=errno
;
2192 #ifdef HAVE_STRERROR
2193 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2195 ERR("tcgetattr error %d\n", save_error
);
2197 commerror
= WinError();
2204 speed
= (port
.c_cflag
& CBAUD
);
2206 speed
= (cfgetospeed(&port
));
2210 lpdcb
->BaudRate
= 110;
2213 lpdcb
->BaudRate
= 300;
2216 lpdcb
->BaudRate
= 600;
2219 lpdcb
->BaudRate
= 1200;
2222 lpdcb
->BaudRate
= 2400;
2225 lpdcb
->BaudRate
= 4800;
2228 lpdcb
->BaudRate
= 9600;
2231 lpdcb
->BaudRate
= 19200;
2234 lpdcb
->BaudRate
= 38400;
2238 lpdcb
->BaudRate
= 57600;
2243 lpdcb
->BaudRate
= 115200;
2248 lpdcb
->BaudRate
= 230400;
2253 lpdcb
->BaudRate
= 460800;
2257 ERR("unknown speed %x \n",speed
);
2260 switch (port
.c_cflag
& CSIZE
) {
2262 lpdcb
->ByteSize
= 5;
2265 lpdcb
->ByteSize
= 6;
2268 lpdcb
->ByteSize
= 7;
2271 lpdcb
->ByteSize
= 8;
2274 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
2277 if(port
.c_iflag
& INPCK
)
2278 lpdcb
->fParity
= TRUE
;
2280 lpdcb
->fParity
= FALSE
;
2281 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
2283 lpdcb
->Parity
= NOPARITY
;
2286 lpdcb
->Parity
= EVENPARITY
;
2288 case (PARENB
| PARODD
):
2289 lpdcb
->Parity
= ODDPARITY
;
2293 if (port
.c_cflag
& CSTOPB
)
2294 lpdcb
->StopBits
= TWOSTOPBITS
;
2296 lpdcb
->StopBits
= ONESTOPBIT
;
2303 if (port
.c_cflag
& CRTSCTS
) {
2304 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
2305 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
2306 lpdcb
->fOutxCtsFlow
= 1;
2307 lpdcb
->fOutxDsrFlow
= 1;
2311 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
2312 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
2314 if (port
.c_iflag
& IXON
)
2319 if (port
.c_iflag
& IXOFF
)
2328 lpdcb
->XoffLim
= 10;
2334 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2335 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2336 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2337 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2338 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2339 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2341 if ( lpdcb
->fOutxCtsFlow
||
2342 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2343 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2347 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2348 TRACE("~CRTSCTS\n");
2354 /*****************************************************************************
2355 * TransmitCommChar (KERNEL32.535)
2357 BOOL WINAPI
TransmitCommChar(INT cid
,CHAR chTransmit
)
2359 struct DosDeviceStruct
*ptr
;
2361 FIXME("(%d,'%c'), use win32 handle!\n",cid
,chTransmit
);
2362 if ((ptr
= GetDeviceStruct(cid
)) == NULL
)
2363 FIXME("no handle for cid = %0x!.\n",cid
);
2366 if (ptr
->suspended
) {
2367 ptr
->commerror
= IE_HARDWARE
;
2370 if (write(ptr
->fd
, (void *) &chTransmit
, 1) == -1) {
2371 ptr
->commerror
= WinError();
2379 /*****************************************************************************
2380 * GetCommTimeouts (KERNEL32.160)
2382 BOOL WINAPI
GetCommTimeouts(HANDLE hcom
,LPCOMMTIMEOUTS lptimeouts
)
2384 FIXME("(%x,%p):stub.\n",hcom
,lptimeouts
);
2388 /*****************************************************************************
2389 * SetCommTimeouts (KERNEL32.453)
2391 BOOL WINAPI
SetCommTimeouts(HANDLE hcom
,LPCOMMTIMEOUTS lptimeouts
) {
2392 /* struct DosDeviceStruct *ptr; */
2393 struct termios tios
;
2396 FIXME("(%x,%p):stub.\n",hcom
,lptimeouts
);
2398 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2399 FIXME("no handle for cid = %0x!.\n",hcom);
2404 fd
= COMM_GetWriteFd(hcom
);
2406 FIXME("no fd for cid = %0x!.\n",hcom
);
2411 FIXME("ReadIntervalTimeout %ld\n",lptimeouts
->ReadIntervalTimeout
);
2412 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts
->ReadTotalTimeoutMultiplier
);
2413 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts
->ReadTotalTimeoutConstant
);
2414 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts
->WriteTotalTimeoutMultiplier
);
2415 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts
->WriteTotalTimeoutConstant
);
2418 if (-1==tcgetattr(fd
,&tios
)) {
2419 FIXME("tcgetattr on fd %d failed!\n",fd
);
2422 /* VTIME is in 1/10 seconds */
2423 tios
.c_cc
[VTIME
]= (lptimeouts
->ReadIntervalTimeout
+99)/100;
2424 if (-1==tcsetattr(fd
,0,&tios
)) {
2425 FIXME("tcsetattr on fd %d failed!\n",fd
);
2431 /***********************************************************************
2432 * GetCommModemStatus (KERNEL32.285)
2434 BOOL WINAPI
GetCommModemStatus(HANDLE hFile
,LPDWORD lpModemStat
)
2436 int fd
,mstat
, result
=FALSE
;
2440 fd
= COMM_GetWriteFd(hFile
);
2443 result
= ioctl(fd
, TIOCMGET
, &mstat
);
2447 TRACE("ioctl failed\n");
2450 if (mstat
& TIOCM_CTS
)
2451 *lpModemStat
|= MS_CTS_ON
;
2452 if (mstat
& TIOCM_DSR
)
2453 *lpModemStat
|= MS_DSR_ON
;
2454 if (mstat
& TIOCM_RNG
)
2455 *lpModemStat
|= MS_RING_ON
;
2456 /*FIXME: Not really sure about RLSD UB 990810*/
2457 if (mstat
& TIOCM_CAR
)
2458 *lpModemStat
|= MS_RLSD_ON
;
2460 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
2461 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
2462 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
2463 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
2469 /***********************************************************************
2470 * WaitCommEvent (KERNEL32.719)
2472 BOOL WINAPI
WaitCommEvent(HANDLE hFile
,LPDWORD eventmask
,LPOVERLAPPED overlapped
)
2474 FIXME("(%d %p %p )\n",hFile
, eventmask
,overlapped
);
2478 /***********************************************************************
2479 * GetCommProperties (KERNEL32.???)
2481 BOOL WINAPI
GetCommProperties(HANDLE hFile
, LPDCB
*dcb
)
2483 FIXME("(%d %p )\n",hFile
,dcb
);
2487 /***********************************************************************
2488 * SetCommProperties (KERNEL32.???)
2490 BOOL WINAPI
SetCommProperties(HANDLE hFile
, LPDCB dcb
)
2492 FIXME("(%d %p )\n",hFile
,dcb
);