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
81 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
84 struct DosDeviceStruct COM
[MAX_PORTS
];
85 struct DosDeviceStruct LPT
[MAX_PORTS
];
86 /* pointers to unknown(==undocumented) comm structure */
87 LPCVOID
*unknown
[MAX_PORTS
];
88 /* save terminal states */
89 static struct termios m_stat
[MAX_PORTS
];
94 char option
[10], temp
[256], *btemp
;
97 for (x
=0; x
!=MAX_PORTS
; x
++) {
98 strcpy(option
,"COMx");
102 PROFILE_GetWineIniString( "serialports", option
, "*",
103 temp
, sizeof(temp
) );
104 if (!strcmp(temp
, "*") || *temp
== '\0')
105 COM
[x
].devicename
= NULL
;
107 btemp
= strchr(temp
,',');
110 COM
[x
].baudrate
= atoi(btemp
);
112 COM
[x
].baudrate
= -1;
115 if (!S_ISCHR(st
.st_mode
))
116 WARN("Can't use `%s' as %s !\n", temp
, option
);
118 if ((COM
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
119 WARN("Can't malloc for device info!\n");
122 strcpy(COM
[x
].devicename
, temp
);
124 TRACE("%s = %s\n", option
, COM
[x
].devicename
);
127 strcpy(option
, "LPTx");
131 PROFILE_GetWineIniString( "parallelports", option
, "*",
132 temp
, sizeof(temp
) );
133 if (!strcmp(temp
, "*") || *temp
== '\0')
134 LPT
[x
].devicename
= NULL
;
137 if (!S_ISCHR(st
.st_mode
))
138 WARN("Can't use `%s' as %s !\n", temp
, option
);
140 if ((LPT
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
141 WARN("Can't malloc for device info!\n");
144 strcpy(LPT
[x
].devicename
, temp
);
146 TRACE("%s = %s\n", option
, LPT
[x
].devicename
);
153 static struct DosDeviceStruct
*GetDeviceStruct(int fd
)
155 if ((fd
&0x7F)<=MAX_PORTS
) {
156 if (!(fd
&FLAG_LPT
)) {
169 static int GetCommPort_fd(int fd
)
173 for (x
=0; x
<MAX_PORTS
; x
++) {
181 static int ValidCOMPort(int x
)
183 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
186 static int ValidLPTPort(int x
)
188 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
191 static int WinError(void)
193 TRACE("errno = %d\n", errno
);
200 static unsigned comm_inbuf(struct DosDeviceStruct
*ptr
)
202 return ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? ptr
->ibuf_size
: 0)
203 + ptr
->ibuf_head
- ptr
->ibuf_tail
;
206 static unsigned comm_outbuf(struct DosDeviceStruct
*ptr
)
208 return ((ptr
->obuf_tail
> ptr
->obuf_head
) ? ptr
->obuf_size
: 0)
209 + ptr
->obuf_head
- ptr
->obuf_tail
;
212 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
214 unsigned int mstat
, okay
;
215 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
216 if (okay
) return okay
;
217 if (andy
) mstat
&= andy
;
219 return ioctl(fd
, TIOCMSET
, &mstat
);
222 static void CALLBACK
comm_notification( ULONG_PTR
private )
224 struct DosDeviceStruct
*ptr
= (struct DosDeviceStruct
*)private;
225 int prev
, bleft
, len
;
227 int cid
= GetCommPort_fd(ptr
->fd
);
229 TRACE("async notification\n");
230 /* read data from comm port */
231 prev
= comm_inbuf(ptr
);
233 bleft
= ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? (ptr
->ibuf_tail
-1) : ptr
->ibuf_size
)
235 len
= read(ptr
->fd
, ptr
->inbuf
+ ptr
->ibuf_head
, bleft
?bleft
:1);
238 ptr
->commerror
= CE_RXOVER
;
240 /* check for events */
241 if ((ptr
->eventmask
& EV_RXFLAG
) &&
242 memchr(ptr
->inbuf
+ ptr
->ibuf_head
, ptr
->evtchar
, len
)) {
243 *(WORD
*)(unknown
[cid
]) |= EV_RXFLAG
;
246 if (ptr
->eventmask
& EV_RXCHAR
) {
247 *(WORD
*)(unknown
[cid
]) |= EV_RXCHAR
;
250 /* advance buffer position */
251 ptr
->ibuf_head
+= len
;
252 if (ptr
->ibuf_head
>= ptr
->ibuf_size
)
257 /* check for notification */
258 if (ptr
->wnd
&& (ptr
->n_read
>0) && (prev
<ptr
->n_read
) &&
259 (comm_inbuf(ptr
)>=ptr
->n_read
)) {
260 /* passed the receive notification threshold */
264 /* write any TransmitCommChar character */
266 len
= write(ptr
->fd
, &(ptr
->xmit
), 1);
267 if (len
> 0) ptr
->xmit
= -1;
269 /* write from output queue */
270 prev
= comm_outbuf(ptr
);
272 bleft
= ((ptr
->obuf_tail
<= ptr
->obuf_head
) ? ptr
->obuf_head
: ptr
->obuf_size
)
274 len
= bleft
? write(ptr
->fd
, ptr
->outbuf
+ ptr
->obuf_tail
, bleft
) : 0;
276 ptr
->obuf_tail
+= len
;
277 if (ptr
->obuf_tail
>= ptr
->obuf_size
)
280 if (ptr
->obuf_tail
== ptr
->obuf_head
) {
282 SERVICE_Delete( ptr
->s_write
);
283 ptr
->s_write
= INVALID_HANDLE_VALUE
;
285 if (ptr
->eventmask
& EV_TXEMPTY
) {
286 *(WORD
*)(unknown
[cid
]) |= EV_TXEMPTY
;
292 /* check for notification */
293 if (ptr
->wnd
&& (ptr
->n_write
>0) && (prev
>=ptr
->n_write
) &&
294 (comm_outbuf(ptr
)<ptr
->n_write
)) {
295 /* passed the transmit notification threshold */
299 /* send notifications, if any */
300 if (ptr
->wnd
&& mask
) {
301 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr
->wnd
, cid
, mask
);
302 Callout
.PostMessage16(ptr
->wnd
, WM_COMMNOTIFY
, cid
, mask
);
306 static void comm_waitread(struct DosDeviceStruct
*ptr
)
308 if (ptr
->s_read
!= INVALID_HANDLE_VALUE
) return;
309 ptr
->s_read
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
310 GENERIC_READ
| SYNCHRONIZE
),
315 static void comm_waitwrite(struct DosDeviceStruct
*ptr
)
317 if (ptr
->s_write
!= INVALID_HANDLE_VALUE
) return;
318 ptr
->s_write
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
319 GENERIC_WRITE
| SYNCHRONIZE
),
324 /**************************************************************************
325 * BuildCommDCB (USER.213)
327 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
329 /* "COM1:9600,n,8,1" */
332 char *ptr
, temp
[256];
334 TRACE("(%s), ptr %p\n", device
, lpdcb
);
336 if (!lstrncmpiA(device
,"COM",3)) {
337 port
= device
[3] - '0';
341 ERR("BUG ! COM0 can't exist!.\n");
345 if (!ValidCOMPort(port
)) {
346 FIXME("invalid COM port %d?\n",port
);
350 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
357 if (*(device
+4) != ':')
360 strcpy(temp
,device
+5);
361 ptr
= strtok(temp
, ", ");
363 if (COM
[port
].baudrate
> 0)
364 lpdcb
->BaudRate
= COM
[port
].baudrate
;
366 lpdcb
->BaudRate
= atoi(ptr
);
367 TRACE("baudrate (%d)\n", lpdcb
->BaudRate
);
369 ptr
= strtok(NULL
, ", ");
371 *ptr
= toupper(*ptr
);
373 TRACE("parity (%c)\n", *ptr
);
374 lpdcb
->fParity
= TRUE
;
377 lpdcb
->Parity
= NOPARITY
;
378 lpdcb
->fParity
= FALSE
;
381 lpdcb
->Parity
= EVENPARITY
;
384 lpdcb
->Parity
= MARKPARITY
;
387 lpdcb
->Parity
= ODDPARITY
;
390 WARN("Unknown parity `%c'!\n", *ptr
);
394 ptr
= strtok(NULL
, ", ");
395 TRACE("charsize (%c)\n", *ptr
);
396 lpdcb
->ByteSize
= *ptr
- '0';
398 ptr
= strtok(NULL
, ", ");
399 TRACE("stopbits (%c)\n", *ptr
);
402 lpdcb
->StopBits
= ONESTOPBIT
;
405 lpdcb
->StopBits
= TWOSTOPBITS
;
408 WARN("Unknown # of stopbits `%c'!\n", *ptr
);
416 /*****************************************************************************
417 * OpenComm (USER.200)
419 INT16 WINAPI
OpenComm16(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
423 TRACE("%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
425 if (strlen(device
) < 4)
428 port
= device
[3] - '0';
431 ERR("BUG ! COM0 or LPT0 don't exist !\n");
433 if (!lstrncmpiA(device
,"COM",3)) {
435 TRACE("%s = %s\n", device
, COM
[port
].devicename
);
437 if (!ValidCOMPort(port
))
443 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
445 ERR("error=%d\n", errno
);
448 unknown
[port
] = SEGPTR_ALLOC(40);
449 bzero(unknown
[port
],40);
451 COM
[port
].commerror
= 0;
452 COM
[port
].eventmask
= 0;
453 COM
[port
].evtchar
= 0; /* FIXME: default? */
454 /* save terminal state */
455 tcgetattr(fd
,&m_stat
[port
]);
456 /* set default parameters */
457 if(COM
[port
].baudrate
>-1){
459 GetCommState16(port
, &dcb
);
460 dcb
.BaudRate
=COM
[port
].baudrate
;
462 * databits, parity, stopbits
464 SetCommState16( &dcb
);
466 /* init priority characters */
467 COM
[port
].unget
= -1;
469 /* allocate buffers */
470 COM
[port
].ibuf_size
= cbInQueue
;
471 COM
[port
].ibuf_head
= COM
[port
].ibuf_tail
= 0;
472 COM
[port
].obuf_size
= cbOutQueue
;
473 COM
[port
].obuf_head
= COM
[port
].obuf_tail
= 0;
475 COM
[port
].inbuf
= malloc(cbInQueue
);
476 if (COM
[port
].inbuf
) {
477 COM
[port
].outbuf
= malloc(cbOutQueue
);
478 if (!COM
[port
].outbuf
)
479 free(COM
[port
].inbuf
);
480 } else COM
[port
].outbuf
= NULL
;
481 if (!COM
[port
].outbuf
) {
482 /* not enough memory */
483 tcsetattr(COM
[port
].fd
,TCSANOW
,&m_stat
[port
]);
485 ERR("out of memory");
489 COM
[port
].s_read
= INVALID_HANDLE_VALUE
;
490 COM
[port
].s_write
= INVALID_HANDLE_VALUE
;
491 comm_waitread( &COM
[port
] );
496 if (!lstrncmpiA(device
,"LPT",3)) {
498 if (!ValidLPTPort(port
))
504 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
509 LPT
[port
].commerror
= 0;
510 LPT
[port
].eventmask
= 0;
511 return port
|FLAG_LPT
;
517 /*****************************************************************************
518 * CloseComm (USER.207)
520 INT16 WINAPI
CloseComm16(INT16 cid
)
522 struct DosDeviceStruct
*ptr
;
524 TRACE("cid=%d\n", cid
);
525 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
526 FIXME("no cid=%d found!\n", cid
);
529 if (!(cid
&FLAG_LPT
)) {
531 SEGPTR_FREE(unknown
[cid
]); /* [LW] */
533 SERVICE_Delete( COM
[cid
].s_write
);
534 SERVICE_Delete( COM
[cid
].s_read
);
539 /* reset modem lines */
540 tcsetattr(ptr
->fd
,TCSANOW
,&m_stat
[cid
]);
543 if (close(ptr
->fd
) == -1) {
544 ptr
->commerror
= WinError();
545 /* FIXME: should we clear ptr->fd here? */
554 /*****************************************************************************
555 * SetCommBreak (USER.210)
557 INT16 WINAPI
SetCommBreak16(INT16 cid
)
559 struct DosDeviceStruct
*ptr
;
561 TRACE("cid=%d\n", cid
);
562 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
563 FIXME("no cid=%d found!\n", cid
);
572 /*****************************************************************************
573 * ClearCommBreak (USER.211)
575 INT16 WINAPI
ClearCommBreak16(INT16 cid
)
577 struct DosDeviceStruct
*ptr
;
579 TRACE("cid=%d\n", cid
);
580 if (!(ptr
= GetDeviceStruct(cid
))) {
581 FIXME("no cid=%d found!\n", cid
);
589 /*****************************************************************************
590 * EscapeCommFunction (USER.214)
592 LONG WINAPI
EscapeCommFunction16(UINT16 cid
,UINT16 nFunction
)
595 struct DosDeviceStruct
*ptr
;
598 TRACE("cid=%d, function=%d\n", cid
, nFunction
);
599 if ((nFunction
!= GETMAXCOM
) && (nFunction
!= GETMAXLPT
)) {
600 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
601 FIXME("no cid=%d found!\n", cid
);
604 if (tcgetattr(ptr
->fd
,&port
) == -1) {
605 TRACE("tcgetattr failed\n");
606 ptr
->commerror
=WinError();
617 TRACE("GETMAXCOM\n");
618 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
624 TRACE("GETMAXLPT\n");
625 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
627 return FLAG_LPT
+ max
;
631 TRACE("GETBASEIRQ\n");
632 /* FIXME: use tables */
633 /* just fake something for now */
634 if (cid
& FLAG_LPT
) {
635 /* LPT1: irq 7, LPT2: irq 5 */
636 return (cid
& 0x7f) ? 5 : 7;
638 /* COM1: irq 4, COM2: irq 3,
639 COM3: irq 4, COM4: irq 3 */
640 return 4 - (cid
& 1);
647 return COMM_WhackModem(ptr
->fd
, ~TIOCM_DTR
, 0);
652 return COMM_WhackModem(ptr
->fd
, ~TIOCM_RTS
, 0);
658 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_DTR
);
664 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_RTS
);
669 port
.c_iflag
|= IXOFF
;
674 port
.c_iflag
|= IXON
;
678 WARN("(cid=%d,nFunction=%d): Unknown function\n",
683 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
684 ptr
->commerror
= WinError();
692 /*****************************************************************************
693 * FlushComm (USER.215)
695 INT16 WINAPI
FlushComm16(INT16 cid
,INT16 fnQueue
)
698 struct DosDeviceStruct
*ptr
;
700 TRACE("cid=%d, queue=%d\n", cid
, fnQueue
);
701 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
702 FIXME("no cid=%d found!\n", cid
);
708 ptr
->obuf_tail
= ptr
->obuf_head
;
712 ptr
->ibuf_head
= ptr
->ibuf_tail
;
715 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
719 if (tcflush(ptr
->fd
, queue
)) {
720 ptr
->commerror
= WinError();
728 /********************************************************************
729 * GetCommError (USER.203)
731 INT16 WINAPI
GetCommError16(INT16 cid
,LPCOMSTAT16 lpStat
)
734 struct DosDeviceStruct
*ptr
;
738 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
739 FIXME("no handle for cid = %0x!.\n",cid
);
743 WARN(" cid %d not comm port\n",cid
);
746 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
747 ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
748 if( mstat
&TIOCM_CAR
)
756 lpStat
->cbOutQue
= comm_outbuf(ptr
);
757 lpStat
->cbInQue
= comm_inbuf(ptr
);
759 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
760 cid
, ptr
->commerror
, lpStat
->status
, lpStat
->cbInQue
,
761 lpStat
->cbOutQue
, *stol
);
764 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
765 cid
, ptr
->commerror
, *stol
);
767 /* Return any errors and clear it */
768 temperror
= ptr
->commerror
;
773 /*****************************************************************************
774 * SetCommEventMask (USER.208)
776 SEGPTR WINAPI
SetCommEventMask16(INT16 cid
,UINT16 fuEvtMask
)
778 struct DosDeviceStruct
*ptr
;
783 TRACE("cid %d,mask %d\n",cid
,fuEvtMask
);
784 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
785 FIXME("no handle for cid = %0x!.\n",cid
);
789 ptr
->eventmask
= fuEvtMask
;
791 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
792 WARN(" cid %d not comm port\n",cid
);
795 /* it's a COM port ? -> modify flags */
796 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
797 repid
= ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
798 TRACE(" ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[cid
]);
799 if ((mstat
&TIOCM_CAR
))
804 TRACE(" modem dcd construct %x\n",*stol
);
805 return SEGPTR_GET(unknown
[cid
]);
808 /*****************************************************************************
809 * GetCommEventMask (USER.209)
811 UINT16 WINAPI
GetCommEventMask16(INT16 cid
,UINT16 fnEvtClear
)
813 struct DosDeviceStruct
*ptr
;
816 TRACE("cid %d, mask %d\n", cid
, fnEvtClear
);
817 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
818 FIXME("no handle for cid = %0x!.\n",cid
);
822 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
823 WARN(" cid %d not comm port\n",cid
);
827 events
= *(WORD
*)(unknown
[cid
]) & fnEvtClear
;
828 *(WORD
*)(unknown
[cid
]) &= ~fnEvtClear
;
832 /*****************************************************************************
833 * SetCommState16 (USER.201)
835 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
838 struct DosDeviceStruct
*ptr
;
840 TRACE("cid %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
841 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
842 FIXME("no handle for cid = %0x!.\n",lpdcb
->Id
);
845 if (tcgetattr(ptr
->fd
, &port
) == -1) {
846 ptr
->commerror
= WinError();
851 port
.c_cc
[VTIME
] = 1;
854 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
856 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
858 port
.c_iflag
|= (IGNBRK
);
860 port
.c_oflag
&= ~(OPOST
);
862 port
.c_cflag
&= ~(HUPCL
);
863 port
.c_cflag
|= CLOCAL
| CREAD
;
865 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
866 port
.c_lflag
|= NOFLSH
;
868 TRACE("baudrate %d\n",lpdcb
->BaudRate
);
870 port
.c_cflag
&= ~CBAUD
;
871 switch (lpdcb
->BaudRate
) {
874 port
.c_cflag
|= B110
;
878 port
.c_cflag
|= B300
;
882 port
.c_cflag
|= B600
;
886 port
.c_cflag
|= B1200
;
890 port
.c_cflag
|= B2400
;
894 port
.c_cflag
|= B4800
;
898 port
.c_cflag
|= B9600
;
902 port
.c_cflag
|= B19200
;
906 port
.c_cflag
|= B38400
;
910 port
.c_cflag
|= B57600
;
915 port
.c_cflag
|= B115200
;
919 ptr
->commerror
= IE_BAUDRATE
;
922 #elif !defined(__EMX__)
923 switch (lpdcb
->BaudRate
) {
926 port
.c_ospeed
= B110
;
930 port
.c_ospeed
= B300
;
934 port
.c_ospeed
= B600
;
938 port
.c_ospeed
= B1200
;
942 port
.c_ospeed
= B2400
;
946 port
.c_ospeed
= B4800
;
950 port
.c_ospeed
= B9600
;
954 port
.c_ospeed
= B19200
;
958 port
.c_ospeed
= B38400
;
961 ptr
->commerror
= IE_BAUDRATE
;
964 port
.c_ispeed
= port
.c_ospeed
;
966 TRACE("bytesize %d\n",lpdcb
->ByteSize
);
967 port
.c_cflag
&= ~CSIZE
;
968 switch (lpdcb
->ByteSize
) {
982 ptr
->commerror
= IE_BYTESIZE
;
986 TRACE("fParity %d Parity %d\n",lpdcb
->fParity
, lpdcb
->Parity
);
987 port
.c_cflag
&= ~(PARENB
| PARODD
);
989 port
.c_iflag
|= INPCK
;
991 port
.c_iflag
&= ~INPCK
;
992 switch (lpdcb
->Parity
) {
996 port
.c_cflag
|= (PARENB
| PARODD
);
999 port
.c_cflag
|= PARENB
;
1002 ptr
->commerror
= IE_BYTESIZE
;
1007 TRACE("stopbits %d\n",lpdcb
->StopBits
);
1009 switch (lpdcb
->StopBits
) {
1011 port
.c_cflag
&= ~CSTOPB
;
1014 port
.c_cflag
|= CSTOPB
;
1017 ptr
->commerror
= IE_BYTESIZE
;
1022 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
1023 port
.c_cflag
|= CRTSCTS
;
1025 if (lpdcb
->fDtrDisable
)
1026 port
.c_cflag
&= ~CRTSCTS
;
1029 port
.c_iflag
|= IXON
;
1031 port
.c_iflag
&= ~IXON
;
1033 port
.c_iflag
|= IXOFF
;
1035 port
.c_iflag
&= ~IXOFF
;
1037 ptr
->evtchar
= lpdcb
->EvtChar
;
1039 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
1040 ptr
->commerror
= WinError();
1048 /*****************************************************************************
1049 * GetCommState (USER.202)
1051 INT16 WINAPI
GetCommState16(INT16 cid
, LPDCB16 lpdcb
)
1054 struct DosDeviceStruct
*ptr
;
1055 struct termios port
;
1057 TRACE("cid %d, ptr %p\n", cid
, lpdcb
);
1058 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1059 FIXME("no handle for cid = %0x!.\n",cid
);
1062 if (tcgetattr(ptr
->fd
, &port
) == -1) {
1063 ptr
->commerror
= WinError();
1069 speed
= port
.c_cflag
& CBAUD
;
1071 speed
= port
.c_ospeed
;
1075 lpdcb
->BaudRate
= 110;
1078 lpdcb
->BaudRate
= 300;
1081 lpdcb
->BaudRate
= 600;
1084 lpdcb
->BaudRate
= 1200;
1087 lpdcb
->BaudRate
= 2400;
1090 lpdcb
->BaudRate
= 4800;
1093 lpdcb
->BaudRate
= 9600;
1096 lpdcb
->BaudRate
= 19200;
1099 lpdcb
->BaudRate
= 38400;
1103 lpdcb
->BaudRate
= 57600;
1108 lpdcb
->BaudRate
= 57601;
1113 switch (port
.c_cflag
& CSIZE
) {
1115 lpdcb
->ByteSize
= 5;
1118 lpdcb
->ByteSize
= 6;
1121 lpdcb
->ByteSize
= 7;
1124 lpdcb
->ByteSize
= 8;
1128 if(port
.c_iflag
& INPCK
)
1129 lpdcb
->fParity
= TRUE
;
1131 lpdcb
->fParity
= FALSE
;
1132 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1134 lpdcb
->Parity
= NOPARITY
;
1137 lpdcb
->Parity
= EVENPARITY
;
1139 case (PARENB
| PARODD
):
1140 lpdcb
->Parity
= ODDPARITY
;
1144 if (port
.c_cflag
& CSTOPB
)
1145 lpdcb
->StopBits
= TWOSTOPBITS
;
1147 lpdcb
->StopBits
= ONESTOPBIT
;
1149 lpdcb
->RlsTimeout
= 50;
1150 lpdcb
->CtsTimeout
= 50;
1151 lpdcb
->DsrTimeout
= 50;
1155 lpdcb
->fDtrDisable
= 0;
1159 if (port
.c_cflag
& CRTSCTS
) {
1160 lpdcb
->fDtrflow
= 1;
1161 lpdcb
->fRtsflow
= 1;
1162 lpdcb
->fOutxCtsFlow
= 1;
1163 lpdcb
->fOutxDsrFlow
= 1;
1166 lpdcb
->fDtrDisable
= 1;
1168 if (port
.c_iflag
& IXON
)
1173 if (port
.c_iflag
& IXOFF
)
1182 lpdcb
->XoffLim
= 10;
1184 lpdcb
->EvtChar
= ptr
->evtchar
;
1190 /*****************************************************************************
1191 * TransmitCommChar (USER.206)
1193 INT16 WINAPI
TransmitCommChar16(INT16 cid
,CHAR chTransmit
)
1195 struct DosDeviceStruct
*ptr
;
1197 TRACE("cid %d, data %d \n", cid
, chTransmit
);
1198 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1199 FIXME("no handle for cid = %0x!.\n",cid
);
1203 if (ptr
->suspended
) {
1204 ptr
->commerror
= IE_HARDWARE
;
1208 if (ptr
->xmit
>= 0) {
1209 /* character already queued */
1210 /* FIXME: which error would Windows return? */
1211 ptr
->commerror
= CE_TXFULL
;
1215 if (ptr
->obuf_head
== ptr
->obuf_tail
) {
1216 /* transmit queue empty, try to transmit directly */
1217 if (write(ptr
->fd
, &chTransmit
, 1) == -1) {
1218 /* didn't work, queue it */
1219 ptr
->xmit
= chTransmit
;
1220 comm_waitwrite(ptr
);
1223 /* data in queue, let this char be transmitted next */
1224 ptr
->xmit
= chTransmit
;
1225 comm_waitwrite(ptr
);
1232 /*****************************************************************************
1233 * UngetCommChar (USER.212)
1235 INT16 WINAPI
UngetCommChar16(INT16 cid
,CHAR chUnget
)
1237 struct DosDeviceStruct
*ptr
;
1239 TRACE("cid %d (char %d)\n", cid
, chUnget
);
1240 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1241 FIXME("no handle for cid = %0x!.\n",cid
);
1245 if (ptr
->suspended
) {
1246 ptr
->commerror
= IE_HARDWARE
;
1250 if (ptr
->unget
>=0) {
1251 /* character already queued */
1252 /* FIXME: which error would Windows return? */
1253 ptr
->commerror
= CE_RXOVER
;
1257 ptr
->unget
= chUnget
;
1263 /*****************************************************************************
1264 * ReadComm (USER.204)
1266 INT16 WINAPI
ReadComm16(INT16 cid
,LPSTR lpvBuf
,INT16 cbRead
)
1269 struct DosDeviceStruct
*ptr
;
1270 LPSTR orgBuf
= lpvBuf
;
1272 TRACE("cid %d, ptr %p, length %d\n", cid
, lpvBuf
, cbRead
);
1273 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1274 FIXME("no handle for cid = %0x!.\n",cid
);
1278 if (ptr
->suspended
) {
1279 ptr
->commerror
= IE_HARDWARE
;
1283 /* read unget character */
1284 if (ptr
->unget
>=0) {
1285 *lpvBuf
++ = ptr
->unget
;
1292 /* read from receive buffer */
1293 while (length
< cbRead
) {
1294 status
= ((ptr
->ibuf_head
< ptr
->ibuf_tail
) ?
1295 ptr
->ibuf_size
: ptr
->ibuf_head
) - ptr
->ibuf_tail
;
1297 if ((cbRead
- length
) < status
)
1298 status
= cbRead
- length
;
1300 memcpy(lpvBuf
, ptr
->inbuf
+ ptr
->ibuf_tail
, status
);
1301 ptr
->ibuf_tail
+= status
;
1302 if (ptr
->ibuf_tail
>= ptr
->ibuf_size
)
1308 TRACE("%.*s\n", length
, orgBuf
);
1313 /*****************************************************************************
1314 * WriteComm (USER.205)
1316 INT16 WINAPI
WriteComm16(INT16 cid
, LPSTR lpvBuf
, INT16 cbWrite
)
1319 struct DosDeviceStruct
*ptr
;
1321 TRACE("cid %d, ptr %p, length %d\n",
1322 cid
, lpvBuf
, cbWrite
);
1323 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1324 FIXME("no handle for cid = %0x!.\n",cid
);
1328 if (ptr
->suspended
) {
1329 ptr
->commerror
= IE_HARDWARE
;
1333 TRACE("%.*s\n", cbWrite
, lpvBuf
);
1336 while (length
< cbWrite
) {
1337 if ((ptr
->obuf_head
== ptr
->obuf_tail
) && (ptr
->xmit
< 0)) {
1338 /* no data queued, try to write directly */
1339 status
= write(ptr
->fd
, lpvBuf
, cbWrite
- length
);
1346 /* can't write directly, put into transmit buffer */
1347 status
= ((ptr
->obuf_tail
> ptr
->obuf_head
) ?
1348 (ptr
->obuf_tail
-1) : ptr
->obuf_size
) - ptr
->obuf_head
;
1350 if ((cbWrite
- length
) < status
)
1351 status
= cbWrite
- length
;
1352 memcpy(lpvBuf
, ptr
->outbuf
+ ptr
->obuf_head
, status
);
1353 ptr
->obuf_head
+= status
;
1354 if (ptr
->obuf_head
>= ptr
->obuf_size
)
1358 comm_waitwrite(ptr
);
1365 /***********************************************************************
1366 * EnableCommNotification (USER.246)
1368 BOOL16 WINAPI
EnableCommNotification16( INT16 cid
, HWND16 hwnd
,
1369 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1371 struct DosDeviceStruct
*ptr
;
1373 TRACE("(%d, %x, %d, %d)\n", cid
, hwnd
, cbWriteNotify
, cbOutQueue
);
1374 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1375 FIXME("no handle for cid = %0x!.\n",cid
);
1376 ptr
->commerror
= IE_BADID
;
1380 ptr
->n_read
= cbWriteNotify
;
1381 ptr
->n_write
= cbOutQueue
;
1386 /**************************************************************************
1387 * BuildCommDCBA (KERNEL32.14)
1389 BOOL WINAPI
BuildCommDCBA(LPCSTR device
,LPDCB lpdcb
)
1391 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
1394 /**************************************************************************
1395 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1397 BOOL WINAPI
BuildCommDCBAndTimeoutsA(LPCSTR device
, LPDCB lpdcb
,
1398 LPCOMMTIMEOUTS lptimeouts
)
1403 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
1405 if (!lstrncmpiA(device
,"COM",3)) {
1408 ERR("BUG! COM0 can't exists!.\n");
1411 if (!ValidCOMPort(port
))
1413 if (*(device
+4)!=':')
1415 temp
=(LPSTR
)(device
+5);
1419 memset(lpdcb
, 0, sizeof(DCB
)); /* initialize */
1421 lpdcb
->DCBlength
= sizeof(DCB
);
1422 if (strchr(temp
,',')) { /* old style */
1425 char last
=temp
[strlen(temp
)-1];
1427 ret
=BuildCommDCB16(device
,&dcb16
);
1430 lpdcb
->BaudRate
= dcb16
.BaudRate
;
1431 lpdcb
->ByteSize
= dcb16
.ByteSize
;
1432 lpdcb
->fBinary
= dcb16
.fBinary
;
1433 lpdcb
->Parity
= dcb16
.Parity
;
1434 lpdcb
->fParity
= dcb16
.fParity
;
1435 lpdcb
->fNull
= dcb16
.fNull
;
1436 lpdcb
->StopBits
= dcb16
.StopBits
;
1439 lpdcb
->fOutX
= TRUE
;
1440 lpdcb
->fOutxCtsFlow
= FALSE
;
1441 lpdcb
->fOutxDsrFlow
= FALSE
;
1442 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1443 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1444 } else if (last
=='p') {
1445 lpdcb
->fInX
= FALSE
;
1446 lpdcb
->fOutX
= FALSE
;
1447 lpdcb
->fOutxCtsFlow
= TRUE
;
1448 lpdcb
->fOutxDsrFlow
= TRUE
;
1449 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1450 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1452 lpdcb
->fInX
= FALSE
;
1453 lpdcb
->fOutX
= FALSE
;
1454 lpdcb
->fOutxCtsFlow
= FALSE
;
1455 lpdcb
->fOutxDsrFlow
= FALSE
;
1456 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1457 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1459 lpdcb
->XonChar
= dcb16
.XonChar
;
1460 lpdcb
->XoffChar
= dcb16
.XoffChar
;
1461 lpdcb
->ErrorChar
= dcb16
.PeChar
;
1462 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
1463 lpdcb
->EofChar
= dcb16
.EofChar
;
1464 lpdcb
->EvtChar
= dcb16
.EvtChar
;
1465 lpdcb
->XonLim
= dcb16
.XonLim
;
1466 lpdcb
->XoffLim
= dcb16
.XoffLim
;
1469 ptr
=strtok(temp
," ");
1474 if (!strncmp("baud=",ptr
,5)) {
1475 if (!sscanf(ptr
+5,"%ld",&x
))
1476 WARN("Couldn't parse %s\n",ptr
);
1477 lpdcb
->BaudRate
= x
;
1480 if (!strncmp("stop=",ptr
,5)) {
1481 if (!sscanf(ptr
+5,"%ld",&x
))
1482 WARN("Couldn't parse %s\n",ptr
);
1483 lpdcb
->StopBits
= x
;
1486 if (!strncmp("data=",ptr
,5)) {
1487 if (!sscanf(ptr
+5,"%ld",&x
))
1488 WARN("Couldn't parse %s\n",ptr
);
1489 lpdcb
->ByteSize
= x
;
1492 if (!strncmp("parity=",ptr
,7)) {
1493 lpdcb
->fParity
= TRUE
;
1496 lpdcb
->fParity
= FALSE
;
1497 lpdcb
->Parity
= NOPARITY
;
1500 lpdcb
->Parity
= EVENPARITY
;
1503 lpdcb
->Parity
= ODDPARITY
;
1506 lpdcb
->Parity
= MARKPARITY
;
1512 ERR("Unhandled specifier '%s', please report.\n",ptr
);
1513 ptr
=strtok(NULL
," ");
1515 if (lpdcb
->BaudRate
==110)
1516 lpdcb
->StopBits
= 2;
1520 /**************************************************************************
1521 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1523 BOOL WINAPI
BuildCommDCBAndTimeoutsW( LPCWSTR devid
, LPDCB lpdcb
,
1524 LPCOMMTIMEOUTS lptimeouts
)
1529 TRACE("(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
1530 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
1531 ret
=BuildCommDCBAndTimeoutsA(devidA
,lpdcb
,lptimeouts
);
1532 HeapFree( GetProcessHeap(), 0, devidA
);
1536 /**************************************************************************
1537 * BuildCommDCBW (KERNEL32.17)
1539 BOOL WINAPI
BuildCommDCBW(LPCWSTR devid
,LPDCB lpdcb
)
1541 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
1544 /*****************************************************************************
1546 * Returns a file descriptor for reading.
1547 * Make sure to close the handle afterwards!
1549 static int COMM_GetReadFd( HANDLE handle
)
1552 struct get_read_fd_request
*req
= get_req_buffer();
1553 req
->handle
= handle
;
1554 server_call_fd( REQ_GET_READ_FD
, -1, &fd
);
1558 /*****************************************************************************
1560 * Returns a file descriptor for writing.
1561 * Make sure to close the handle afterwards!
1563 static int COMM_GetWriteFd( HANDLE handle
)
1566 struct get_write_fd_request
*req
= get_req_buffer();
1567 req
->handle
= handle
;
1568 server_call_fd( REQ_GET_WRITE_FD
, -1, &fd
);
1572 /* FIXME: having these global for win32 for now */
1573 int commerror
=0,eventmask
=0;
1575 /*****************************************************************************
1576 * SetCommBreak (KERNEL32.449)
1578 BOOL WINAPI
SetCommBreak(HANDLE handle
)
1580 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1583 fd
= COMM_GetWriteFd(handle
);
1585 TRACE("COMM_GetWriteFd failed\n");
1588 result
= ioctl(fd
,TIOCSBRK
,0);
1592 TRACE("ioctl failed\n");
1593 SetLastError(ERROR_NOT_SUPPORTED
);
1598 FIXME("ioctl not available\n");
1599 SetLastError(ERROR_NOT_SUPPORTED
);
1604 /*****************************************************************************
1605 * ClearCommBreak (KERNEL32.20)
1607 BOOL WINAPI
ClearCommBreak(HANDLE handle
)
1609 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1612 fd
= COMM_GetWriteFd(handle
);
1614 TRACE("COMM_GetWriteFd failed\n");
1617 result
= ioctl(fd
,TIOCCBRK
,0);
1621 TRACE("ioctl failed\n");
1622 SetLastError(ERROR_NOT_SUPPORTED
);
1627 FIXME("ioctl not available\n");
1628 SetLastError(ERROR_NOT_SUPPORTED
);
1633 /*****************************************************************************
1634 * EscapeCommFunction (KERNEL32.214)
1636 BOOL WINAPI
EscapeCommFunction(HANDLE handle
,UINT nFunction
)
1638 int fd
,direct
=FALSE
,result
=FALSE
;
1639 struct termios port
;
1641 TRACE("handle %d, function=%d\n", handle
, nFunction
);
1642 fd
= COMM_GetWriteFd(handle
);
1644 FIXME("handle %d not found.\n",handle
);
1648 if (tcgetattr(fd
,&port
) == -1) {
1649 commerror
=WinError();
1654 switch (nFunction
) {
1663 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1671 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1679 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1687 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1693 port
.c_iflag
|= IXOFF
;
1698 port
.c_iflag
|= IXON
;
1701 TRACE("setbreak\n");
1704 result
= ioctl(fd
,TIOCSBRK
,0);
1708 TRACE("clrbreak\n");
1711 result
= ioctl(fd
,TIOCCBRK
,0);
1715 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1721 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
1722 commerror
= WinError();
1732 commerror
=WinError();
1741 /********************************************************************
1742 * PurgeComm (KERNEL32.557)
1744 BOOL WINAPI
PurgeComm( HANDLE handle
, DWORD flags
)
1748 TRACE("handle %d, flags %lx\n", handle
, flags
);
1750 fd
= COMM_GetWriteFd(handle
);
1752 FIXME("no handle %d found\n",handle
);
1757 ** not exactly sure how these are different
1758 ** Perhaps if we had our own internal queues, one flushes them
1759 ** and the other flushes the kernel's buffers.
1761 if(flags
&PURGE_TXABORT
)
1762 tcflush(fd
,TCOFLUSH
);
1763 if(flags
&PURGE_RXABORT
)
1764 tcflush(fd
,TCIFLUSH
);
1765 if(flags
&PURGE_TXCLEAR
)
1766 tcflush(fd
,TCOFLUSH
);
1767 if(flags
&PURGE_RXCLEAR
)
1768 tcflush(fd
,TCIFLUSH
);
1774 /*****************************************************************************
1775 * ClearCommError (KERNEL32.21)
1777 BOOL WINAPI
ClearCommError(INT handle
,LPDWORD errors
,LPCOMSTAT lpStat
)
1781 fd
=COMM_GetReadFd(handle
);
1784 FIXME("no handle %d found\n",handle
);
1793 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
1794 WARN("ioctl returned error\n");
1796 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
1799 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
1800 WARN("ioctl returned error\n");
1802 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1803 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
1812 ** After an asynchronous write opperation, the
1813 ** app will call ClearCommError to see if the
1814 ** results are ready yet. It waits for ERROR_IO_PENDING
1816 commerror
= ERROR_IO_PENDING
;
1821 /*****************************************************************************
1822 * SetupComm (KERNEL32.676)
1824 BOOL WINAPI
SetupComm( HANDLE handle
, DWORD insize
, DWORD outsize
)
1828 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
1829 fd
=COMM_GetWriteFd(handle
);
1831 FIXME("handle %d not found?\n",handle
);
1838 /*****************************************************************************
1839 * GetCommMask (KERNEL32.156)
1841 BOOL WINAPI
GetCommMask(HANDLE handle
,LPDWORD evtmask
)
1845 TRACE("handle %d, mask %p\n", handle
, evtmask
);
1846 if(0>(fd
=COMM_GetReadFd(handle
)))
1848 FIXME("no handle %d found\n",handle
);
1852 *evtmask
= eventmask
;
1853 TRACE("%s%s%s%s%s%s%s%s%s\n",
1854 (eventmask
&EV_BREAK
)?"EV_BREAK":"",
1855 (eventmask
&EV_CTS
)?"EV_CTS":"",
1856 (eventmask
&EV_DSR
)?"EV_DSR":"",
1857 (eventmask
&EV_ERR
)?"EV_ERR":"",
1858 (eventmask
&EV_RING
)?"EV_RING":"",
1859 (eventmask
&EV_RLSD
)?"EV_RLSD":"",
1860 (eventmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1861 (eventmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1862 (eventmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1867 /*****************************************************************************
1868 * SetCommMask (KERNEL32.451)
1870 BOOL WINAPI
SetCommMask(INT handle
,DWORD evtmask
)
1874 TRACE("handle %d, mask %lx\n", handle
, evtmask
);
1875 TRACE("%s%s%s%s%s%s%s%s%s\n",
1876 (evtmask
&EV_BREAK
)?"EV_BREAK":"",
1877 (evtmask
&EV_CTS
)?"EV_CTS":"",
1878 (evtmask
&EV_DSR
)?"EV_DSR":"",
1879 (evtmask
&EV_ERR
)?"EV_ERR":"",
1880 (evtmask
&EV_RING
)?"EV_RING":"",
1881 (evtmask
&EV_RLSD
)?"EV_RLSD":"",
1882 (evtmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1883 (evtmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1884 (evtmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1886 if(0>(fd
=COMM_GetWriteFd(handle
))) {
1887 FIXME("no handle %d found\n",handle
);
1891 eventmask
= evtmask
;
1895 /*****************************************************************************
1896 * SetCommState (KERNEL32.452)
1898 BOOL WINAPI
SetCommState(INT handle
,LPDCB lpdcb
)
1900 struct termios port
;
1903 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
1904 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1905 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1906 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1907 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1908 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1909 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1911 if ((fd
= COMM_GetWriteFd(handle
)) < 0) {
1912 FIXME("no handle %d found\n",handle
);
1916 if ((tcgetattr(fd
,&port
)) == -1) {
1917 int save_error
= errno
;
1918 commerror
= WinError();
1920 #ifdef HAVE_STRERROR
1921 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1923 ERR("tcgetattr error %d\n", save_error
);
1928 port
.c_cc
[VMIN
] = 0;
1929 port
.c_cc
[VTIME
] = 1;
1932 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
1934 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
1936 port
.c_iflag
|= (IGNBRK
);
1938 port
.c_oflag
&= ~(OPOST
);
1940 port
.c_cflag
&= ~(HUPCL
);
1941 port
.c_cflag
|= CLOCAL
| CREAD
;
1943 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
1944 port
.c_lflag
|= NOFLSH
;
1947 ** MJM - removed default baudrate settings
1948 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1951 port
.c_cflag
&= ~CBAUD
;
1952 switch (lpdcb
->BaudRate
) {
1955 port
.c_cflag
|= B110
;
1959 port
.c_cflag
|= B300
;
1963 port
.c_cflag
|= B600
;
1967 port
.c_cflag
|= B1200
;
1971 port
.c_cflag
|= B2400
;
1975 port
.c_cflag
|= B4800
;
1979 port
.c_cflag
|= B9600
;
1983 port
.c_cflag
|= B19200
;
1987 port
.c_cflag
|= B38400
;
1991 port
.c_cflag
|= B57600
;
1996 port
.c_cflag
|= B115200
;
2001 port
.c_cflag
|= B230400
;
2006 port
.c_cflag
|= B460800
;
2010 commerror
= IE_BAUDRATE
;
2012 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
2015 #elif !defined(__EMX__)
2016 switch (lpdcb
->BaudRate
) {
2019 port
.c_ospeed
= B110
;
2023 port
.c_ospeed
= B300
;
2027 port
.c_ospeed
= B600
;
2031 port
.c_ospeed
= B1200
;
2035 port
.c_ospeed
= B2400
;
2039 port
.c_ospeed
= B4800
;
2043 port
.c_ospeed
= B9600
;
2047 port
.c_ospeed
= B19200
;
2051 port
.c_ospeed
= B38400
;
2054 commerror
= IE_BAUDRATE
;
2056 ERR("baudrate %d \n",lpdcb
->BaudRate
);
2059 port
.c_ispeed
= port
.c_ospeed
;
2061 port
.c_cflag
&= ~CSIZE
;
2062 switch (lpdcb
->ByteSize
) {
2064 port
.c_cflag
|= CS5
;
2067 port
.c_cflag
|= CS6
;
2070 port
.c_cflag
|= CS7
;
2073 port
.c_cflag
|= CS8
;
2076 commerror
= IE_BYTESIZE
;
2082 port
.c_cflag
&= ~(PARENB
| PARODD
);
2084 port
.c_iflag
|= INPCK
;
2086 port
.c_iflag
&= ~INPCK
;
2087 switch (lpdcb
->Parity
) {
2091 port
.c_cflag
|= (PARENB
| PARODD
);
2094 port
.c_cflag
|= PARENB
;
2097 commerror
= IE_BYTESIZE
;
2104 switch (lpdcb
->StopBits
) {
2106 port
.c_cflag
&= ~CSTOPB
;
2109 port
.c_cflag
|= CSTOPB
;
2112 commerror
= IE_BYTESIZE
;
2118 if ( lpdcb
->fOutxCtsFlow
||
2119 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2120 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2123 port
.c_cflag
|= CRTSCTS
;
2127 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2129 port
.c_cflag
&= ~CRTSCTS
;
2130 TRACE("~CRTSCTS\n");
2135 port
.c_iflag
|= IXON
;
2137 port
.c_iflag
&= ~IXON
;
2139 port
.c_iflag
|= IXOFF
;
2141 port
.c_iflag
&= ~IXOFF
;
2143 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
2144 int save_error
=errno
;
2145 commerror
= WinError();
2147 #ifdef HAVE_STRERROR
2148 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2150 ERR("tcgetattr error %d\n", save_error
);
2161 /*****************************************************************************
2162 * GetCommState (KERNEL32.159)
2164 BOOL WINAPI
GetCommState(INT handle
, LPDCB lpdcb
)
2166 struct termios port
;
2169 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2171 if ((fd
= COMM_GetReadFd(handle
)) < 0)
2173 ERR("can't get COMM_GetReadFd\n");
2176 if (tcgetattr(fd
, &port
) == -1) {
2177 int save_error
=errno
;
2178 #ifdef HAVE_STRERROR
2179 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2181 ERR("tcgetattr error %d\n", save_error
);
2183 commerror
= WinError();
2190 speed
= (port
.c_cflag
& CBAUD
);
2192 speed
= (cfgetospeed(&port
));
2196 lpdcb
->BaudRate
= 110;
2199 lpdcb
->BaudRate
= 300;
2202 lpdcb
->BaudRate
= 600;
2205 lpdcb
->BaudRate
= 1200;
2208 lpdcb
->BaudRate
= 2400;
2211 lpdcb
->BaudRate
= 4800;
2214 lpdcb
->BaudRate
= 9600;
2217 lpdcb
->BaudRate
= 19200;
2220 lpdcb
->BaudRate
= 38400;
2224 lpdcb
->BaudRate
= 57600;
2229 lpdcb
->BaudRate
= 115200;
2234 lpdcb
->BaudRate
= 230400;
2239 lpdcb
->BaudRate
= 460800;
2243 ERR("unknown speed %x \n",speed
);
2246 switch (port
.c_cflag
& CSIZE
) {
2248 lpdcb
->ByteSize
= 5;
2251 lpdcb
->ByteSize
= 6;
2254 lpdcb
->ByteSize
= 7;
2257 lpdcb
->ByteSize
= 8;
2260 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
2263 if(port
.c_iflag
& INPCK
)
2264 lpdcb
->fParity
= TRUE
;
2266 lpdcb
->fParity
= FALSE
;
2267 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
2269 lpdcb
->Parity
= NOPARITY
;
2272 lpdcb
->Parity
= EVENPARITY
;
2274 case (PARENB
| PARODD
):
2275 lpdcb
->Parity
= ODDPARITY
;
2279 if (port
.c_cflag
& CSTOPB
)
2280 lpdcb
->StopBits
= TWOSTOPBITS
;
2282 lpdcb
->StopBits
= ONESTOPBIT
;
2289 if (port
.c_cflag
& CRTSCTS
) {
2290 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
2291 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
2292 lpdcb
->fOutxCtsFlow
= 1;
2293 lpdcb
->fOutxDsrFlow
= 1;
2297 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
2298 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
2300 if (port
.c_iflag
& IXON
)
2305 if (port
.c_iflag
& IXOFF
)
2314 lpdcb
->XoffLim
= 10;
2320 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2321 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2322 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2323 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2324 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2325 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2327 if ( lpdcb
->fOutxCtsFlow
||
2328 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2329 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2333 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2334 TRACE("~CRTSCTS\n");
2340 /*****************************************************************************
2341 * TransmitCommChar (KERNEL32.535)
2343 BOOL WINAPI
TransmitCommChar(INT cid
,CHAR chTransmit
)
2345 struct DosDeviceStruct
*ptr
;
2347 FIXME("(%d,'%c'), use win32 handle!\n",cid
,chTransmit
);
2348 if ((ptr
= GetDeviceStruct(cid
)) == NULL
)
2349 FIXME("no handle for cid = %0x!.\n",cid
);
2352 if (ptr
->suspended
) {
2353 ptr
->commerror
= IE_HARDWARE
;
2356 if (write(ptr
->fd
, (void *) &chTransmit
, 1) == -1) {
2357 ptr
->commerror
= WinError();
2365 /*****************************************************************************
2366 * GetCommTimeouts (KERNEL32.160)
2368 BOOL WINAPI
GetCommTimeouts(HANDLE hcom
,LPCOMMTIMEOUTS lptimeouts
)
2370 FIXME("(%x,%p):stub.\n",hcom
,lptimeouts
);
2374 /*****************************************************************************
2375 * SetCommTimeouts (KERNEL32.453)
2377 BOOL WINAPI
SetCommTimeouts(HANDLE hcom
,LPCOMMTIMEOUTS lptimeouts
) {
2378 /* struct DosDeviceStruct *ptr; */
2379 struct termios tios
;
2382 FIXME("(%x,%p):stub.\n",hcom
,lptimeouts
);
2384 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2385 FIXME("no handle for cid = %0x!.\n",hcom);
2390 fd
= COMM_GetWriteFd(hcom
);
2392 FIXME("no fd for cid = %0x!.\n",hcom
);
2397 FIXME("ReadIntervalTimeout %ld\n",lptimeouts
->ReadIntervalTimeout
);
2398 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts
->ReadTotalTimeoutMultiplier
);
2399 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts
->ReadTotalTimeoutConstant
);
2400 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts
->WriteTotalTimeoutMultiplier
);
2401 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts
->WriteTotalTimeoutConstant
);
2404 if (-1==tcgetattr(fd
,&tios
)) {
2405 FIXME("tcgetattr on fd %d failed!\n",fd
);
2408 /* VTIME is in 1/10 seconds */
2409 tios
.c_cc
[VTIME
]= (lptimeouts
->ReadIntervalTimeout
+99)/100;
2410 if (-1==tcsetattr(fd
,0,&tios
)) {
2411 FIXME("tcsetattr on fd %d failed!\n",fd
);
2417 /***********************************************************************
2418 * GetCommModemStatus (KERNEL32.285)
2420 BOOL WINAPI
GetCommModemStatus(HANDLE hFile
,LPDWORD lpModemStat
)
2422 int fd
,mstat
, result
=FALSE
;
2426 fd
= COMM_GetWriteFd(hFile
);
2429 result
= ioctl(fd
, TIOCMGET
, &mstat
);
2433 TRACE("ioctl failed\n");
2436 if (mstat
& TIOCM_CTS
)
2437 *lpModemStat
|= MS_CTS_ON
;
2438 if (mstat
& TIOCM_DSR
)
2439 *lpModemStat
|= MS_DSR_ON
;
2440 if (mstat
& TIOCM_RNG
)
2441 *lpModemStat
|= MS_RING_ON
;
2442 /*FIXME: Not really sure about RLSD UB 990810*/
2443 if (mstat
& TIOCM_CAR
)
2444 *lpModemStat
|= MS_RLSD_ON
;
2446 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
2447 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
2448 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
2449 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
2455 /***********************************************************************
2456 * WaitCommEvent (KERNEL32.719)
2458 BOOL WINAPI
WaitCommEvent(HANDLE hFile
,LPDWORD eventmask
,LPOVERLAPPED overlapped
)
2460 FIXME("(%d %p %p )\n",hFile
, eventmask
,overlapped
);
2464 /***********************************************************************
2465 * GetCommProperties (KERNEL32.???)
2467 BOOL WINAPI
GetCommProperties(HANDLE hFile
, LPDCB
*dcb
)
2469 FIXME("(%d %p )\n",hFile
,dcb
);
2473 /***********************************************************************
2474 * SetCommProperties (KERNEL32.???)
2476 BOOL WINAPI
SetCommProperties(HANDLE hFile
, LPDCB dcb
)
2478 FIXME("(%d %p )\n",hFile
,dcb
);