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)
93 #define CMSPAR 0x40000000 /* stick parity */
96 struct DosDeviceStruct COM
[MAX_PORTS
];
97 struct DosDeviceStruct LPT
[MAX_PORTS
];
98 /* pointers to unknown(==undocumented) comm structure */
99 LPCVOID
*unknown
[MAX_PORTS
];
100 /* save terminal states */
101 static struct termios m_stat
[MAX_PORTS
];
103 /* update window's semi documented modem status register */
104 /* see knowledge base Q101417 */
105 static void COMM_MSRUpdate( UCHAR
* pMsr
, unsigned int mstat
)
108 if(mstat
& TIOCM_CTS
) tmpmsr
|= MSR_CTS
;
109 if(mstat
& TIOCM_DSR
) tmpmsr
|= MSR_DSR
;
110 if(mstat
& TIOCM_RI
) tmpmsr
|= MSR_RI
;
111 if(mstat
& TIOCM_CAR
) tmpmsr
|= MSR_RLSD
;
112 *pMsr
= (*pMsr
& ~MSR_MASK
) | tmpmsr
;
118 char option
[10], temp
[256], *btemp
;
121 for (x
=0; x
!=MAX_PORTS
; x
++) {
122 strcpy(option
,"COMx");
126 PROFILE_GetWineIniString( "serialports", option
, "*",
127 temp
, sizeof(temp
) );
128 if (!strcmp(temp
, "*") || *temp
== '\0')
129 COM
[x
].devicename
= NULL
;
131 btemp
= strchr(temp
,',');
134 COM
[x
].baudrate
= atoi(btemp
);
136 COM
[x
].baudrate
= -1;
139 if (!S_ISCHR(st
.st_mode
))
140 WARN("Can't use `%s' as %s !\n", temp
, option
);
142 if ((COM
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
143 WARN("Can't malloc for device info!\n");
146 strcpy(COM
[x
].devicename
, temp
);
148 TRACE("%s = %s\n", option
, COM
[x
].devicename
);
151 strcpy(option
, "LPTx");
155 PROFILE_GetWineIniString( "parallelports", option
, "*",
156 temp
, sizeof(temp
) );
157 if (!strcmp(temp
, "*") || *temp
== '\0')
158 LPT
[x
].devicename
= NULL
;
161 if (!S_ISCHR(st
.st_mode
))
162 WARN("Can't use `%s' as %s !\n", temp
, option
);
164 if ((LPT
[x
].devicename
= malloc(strlen(temp
)+1)) == NULL
)
165 WARN("Can't malloc for device info!\n");
168 strcpy(LPT
[x
].devicename
, temp
);
170 TRACE("%s = %s\n", option
, LPT
[x
].devicename
);
177 static struct DosDeviceStruct
*GetDeviceStruct(int fd
)
179 if ((fd
&0x7F)<=MAX_PORTS
) {
180 if (!(fd
&FLAG_LPT
)) {
193 static int GetCommPort_fd(int fd
)
197 for (x
=0; x
<MAX_PORTS
; x
++) {
205 static int ValidCOMPort(int x
)
207 return(x
< MAX_PORTS
? (int) COM
[x
].devicename
: 0);
210 static int ValidLPTPort(int x
)
212 return(x
< MAX_PORTS
? (int) LPT
[x
].devicename
: 0);
215 static int WinError(void)
217 TRACE("errno = %d\n", errno
);
224 static unsigned comm_inbuf(struct DosDeviceStruct
*ptr
)
226 return ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? ptr
->ibuf_size
: 0)
227 + ptr
->ibuf_head
- ptr
->ibuf_tail
;
230 static unsigned comm_outbuf(struct DosDeviceStruct
*ptr
)
232 return ((ptr
->obuf_tail
> ptr
->obuf_head
) ? ptr
->obuf_size
: 0)
233 + ptr
->obuf_head
- ptr
->obuf_tail
;
236 static int COMM_WhackModem(int fd
, unsigned int andy
, unsigned int orrie
)
238 unsigned int mstat
, okay
;
239 okay
= ioctl(fd
, TIOCMGET
, &mstat
);
240 if (okay
) return okay
;
241 if (andy
) mstat
&= andy
;
243 return ioctl(fd
, TIOCMSET
, &mstat
);
246 static void CALLBACK
comm_notification( ULONG_PTR
private )
248 struct DosDeviceStruct
*ptr
= (struct DosDeviceStruct
*)private;
249 int prev
, bleft
, len
;
251 int cid
= GetCommPort_fd(ptr
->fd
);
253 TRACE("async notification\n");
254 /* read data from comm port */
255 prev
= comm_inbuf(ptr
);
257 bleft
= ((ptr
->ibuf_tail
> ptr
->ibuf_head
) ? (ptr
->ibuf_tail
-1) : ptr
->ibuf_size
)
259 len
= read(ptr
->fd
, ptr
->inbuf
+ ptr
->ibuf_head
, bleft
?bleft
:1);
262 ptr
->commerror
= CE_RXOVER
;
264 /* check for events */
265 if ((ptr
->eventmask
& EV_RXFLAG
) &&
266 memchr(ptr
->inbuf
+ ptr
->ibuf_head
, ptr
->evtchar
, len
)) {
267 *(WORD
*)(unknown
[cid
]) |= EV_RXFLAG
;
270 if (ptr
->eventmask
& EV_RXCHAR
) {
271 *(WORD
*)(unknown
[cid
]) |= EV_RXCHAR
;
274 /* advance buffer position */
275 ptr
->ibuf_head
+= len
;
276 if (ptr
->ibuf_head
>= ptr
->ibuf_size
)
281 /* check for notification */
282 if (ptr
->wnd
&& (ptr
->n_read
>0) && (prev
<ptr
->n_read
) &&
283 (comm_inbuf(ptr
)>=ptr
->n_read
)) {
284 /* passed the receive notification threshold */
288 /* write any TransmitCommChar character */
290 len
= write(ptr
->fd
, &(ptr
->xmit
), 1);
291 if (len
> 0) ptr
->xmit
= -1;
293 /* write from output queue */
294 prev
= comm_outbuf(ptr
);
296 bleft
= ((ptr
->obuf_tail
<= ptr
->obuf_head
) ? ptr
->obuf_head
: ptr
->obuf_size
)
298 len
= bleft
? write(ptr
->fd
, ptr
->outbuf
+ ptr
->obuf_tail
, bleft
) : 0;
300 ptr
->obuf_tail
+= len
;
301 if (ptr
->obuf_tail
>= ptr
->obuf_size
)
304 if (ptr
->obuf_tail
== ptr
->obuf_head
) {
306 SERVICE_Delete( ptr
->s_write
);
307 ptr
->s_write
= INVALID_HANDLE_VALUE
;
309 if (ptr
->eventmask
& EV_TXEMPTY
) {
310 *(WORD
*)(unknown
[cid
]) |= EV_TXEMPTY
;
316 /* check for notification */
317 if (ptr
->wnd
&& (ptr
->n_write
>0) && (prev
>=ptr
->n_write
) &&
318 (comm_outbuf(ptr
)<ptr
->n_write
)) {
319 /* passed the transmit notification threshold */
323 /* send notifications, if any */
324 if (ptr
->wnd
&& mask
) {
325 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr
->wnd
, cid
, mask
);
326 Callout
.PostMessage16(ptr
->wnd
, WM_COMMNOTIFY
, cid
, mask
);
330 static void comm_waitread(struct DosDeviceStruct
*ptr
)
332 if (ptr
->s_read
!= INVALID_HANDLE_VALUE
) return;
333 ptr
->s_read
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
334 GENERIC_READ
| SYNCHRONIZE
),
339 static void comm_waitwrite(struct DosDeviceStruct
*ptr
)
341 if (ptr
->s_write
!= INVALID_HANDLE_VALUE
) return;
342 ptr
->s_write
= SERVICE_AddObject( FILE_DupUnixHandle( ptr
->fd
,
343 GENERIC_WRITE
| SYNCHRONIZE
),
348 /**************************************************************************
349 * BuildCommDCB (USER.213)
351 BOOL16 WINAPI
BuildCommDCB16(LPCSTR device
, LPDCB16 lpdcb
)
353 /* "COM1:9600,n,8,1" */
356 char *ptr
, temp
[256];
358 TRACE("(%s), ptr %p\n", device
, lpdcb
);
360 if (!lstrncmpiA(device
,"COM",3)) {
361 port
= device
[3] - '0';
365 ERR("BUG ! COM0 can't exist!.\n");
369 if (!ValidCOMPort(port
)) {
370 FIXME("invalid COM port %d?\n",port
);
374 memset(lpdcb
, 0, sizeof(DCB16
)); /* initialize */
381 if (*(device
+4) != ':')
384 strcpy(temp
,device
+5);
385 ptr
= strtok(temp
, ", ");
387 if (COM
[port
].baudrate
> 0)
388 lpdcb
->BaudRate
= COM
[port
].baudrate
;
390 lpdcb
->BaudRate
= atoi(ptr
);
391 TRACE("baudrate (%d)\n", lpdcb
->BaudRate
);
393 ptr
= strtok(NULL
, ", ");
395 *ptr
= toupper(*ptr
);
397 TRACE("parity (%c)\n", *ptr
);
398 lpdcb
->fParity
= TRUE
;
401 lpdcb
->Parity
= NOPARITY
;
402 lpdcb
->fParity
= FALSE
;
405 lpdcb
->Parity
= EVENPARITY
;
408 lpdcb
->Parity
= MARKPARITY
;
411 lpdcb
->Parity
= ODDPARITY
;
414 WARN("Unknown parity `%c'!\n", *ptr
);
418 ptr
= strtok(NULL
, ", ");
419 TRACE("charsize (%c)\n", *ptr
);
420 lpdcb
->ByteSize
= *ptr
- '0';
422 ptr
= strtok(NULL
, ", ");
423 TRACE("stopbits (%c)\n", *ptr
);
426 lpdcb
->StopBits
= ONESTOPBIT
;
429 lpdcb
->StopBits
= TWOSTOPBITS
;
432 WARN("Unknown # of stopbits `%c'!\n", *ptr
);
440 /*****************************************************************************
441 * OpenComm (USER.200)
443 INT16 WINAPI
OpenComm16(LPCSTR device
,UINT16 cbInQueue
,UINT16 cbOutQueue
)
447 TRACE("%s, %d, %d\n", device
, cbInQueue
, cbOutQueue
);
449 if (strlen(device
) < 4)
452 port
= device
[3] - '0';
455 ERR("BUG ! COM0 or LPT0 don't exist !\n");
457 if (!lstrncmpiA(device
,"COM",3)) {
459 TRACE("%s = %s\n", device
, COM
[port
].devicename
);
461 if (!ValidCOMPort(port
))
467 fd
= open(COM
[port
].devicename
, O_RDWR
| O_NONBLOCK
);
469 ERR("error=%d\n", errno
);
472 unknown
[port
] = SEGPTR_ALLOC(40);
473 bzero(unknown
[port
],40);
475 COM
[port
].commerror
= 0;
476 COM
[port
].eventmask
= 0;
477 COM
[port
].evtchar
= 0; /* FIXME: default? */
478 /* save terminal state */
479 tcgetattr(fd
,&m_stat
[port
]);
480 /* set default parameters */
481 if(COM
[port
].baudrate
>-1){
483 GetCommState16(port
, &dcb
);
484 dcb
.BaudRate
=COM
[port
].baudrate
;
486 * databits, parity, stopbits
488 SetCommState16( &dcb
);
490 /* init priority characters */
491 COM
[port
].unget
= -1;
493 /* allocate buffers */
494 COM
[port
].ibuf_size
= cbInQueue
;
495 COM
[port
].ibuf_head
= COM
[port
].ibuf_tail
= 0;
496 COM
[port
].obuf_size
= cbOutQueue
;
497 COM
[port
].obuf_head
= COM
[port
].obuf_tail
= 0;
499 COM
[port
].inbuf
= malloc(cbInQueue
);
500 if (COM
[port
].inbuf
) {
501 COM
[port
].outbuf
= malloc(cbOutQueue
);
502 if (!COM
[port
].outbuf
)
503 free(COM
[port
].inbuf
);
504 } else COM
[port
].outbuf
= NULL
;
505 if (!COM
[port
].outbuf
) {
506 /* not enough memory */
507 tcsetattr(COM
[port
].fd
,TCSANOW
,&m_stat
[port
]);
509 ERR("out of memory");
513 COM
[port
].s_read
= INVALID_HANDLE_VALUE
;
514 COM
[port
].s_write
= INVALID_HANDLE_VALUE
;
515 comm_waitread( &COM
[port
] );
520 if (!lstrncmpiA(device
,"LPT",3)) {
522 if (!ValidLPTPort(port
))
528 fd
= open(LPT
[port
].devicename
, O_RDWR
| O_NONBLOCK
, 0);
533 LPT
[port
].commerror
= 0;
534 LPT
[port
].eventmask
= 0;
535 return port
|FLAG_LPT
;
541 /*****************************************************************************
542 * CloseComm (USER.207)
544 INT16 WINAPI
CloseComm16(INT16 cid
)
546 struct DosDeviceStruct
*ptr
;
548 TRACE("cid=%d\n", cid
);
549 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
550 FIXME("no cid=%d found!\n", cid
);
553 if (!(cid
&FLAG_LPT
)) {
555 SEGPTR_FREE(unknown
[cid
]); /* [LW] */
557 SERVICE_Delete( COM
[cid
].s_write
);
558 SERVICE_Delete( COM
[cid
].s_read
);
563 /* reset modem lines */
564 tcsetattr(ptr
->fd
,TCSANOW
,&m_stat
[cid
]);
567 if (close(ptr
->fd
) == -1) {
568 ptr
->commerror
= WinError();
569 /* FIXME: should we clear ptr->fd here? */
578 /*****************************************************************************
579 * SetCommBreak (USER.210)
581 INT16 WINAPI
SetCommBreak16(INT16 cid
)
583 struct DosDeviceStruct
*ptr
;
585 TRACE("cid=%d\n", cid
);
586 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
587 FIXME("no cid=%d found!\n", cid
);
596 /*****************************************************************************
597 * ClearCommBreak (USER.211)
599 INT16 WINAPI
ClearCommBreak16(INT16 cid
)
601 struct DosDeviceStruct
*ptr
;
603 TRACE("cid=%d\n", cid
);
604 if (!(ptr
= GetDeviceStruct(cid
))) {
605 FIXME("no cid=%d found!\n", cid
);
613 /*****************************************************************************
614 * EscapeCommFunction (USER.214)
616 LONG WINAPI
EscapeCommFunction16(UINT16 cid
,UINT16 nFunction
)
619 struct DosDeviceStruct
*ptr
;
622 TRACE("cid=%d, function=%d\n", cid
, nFunction
);
623 if ((nFunction
!= GETMAXCOM
) && (nFunction
!= GETMAXLPT
)) {
624 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
625 FIXME("no cid=%d found!\n", cid
);
628 if (tcgetattr(ptr
->fd
,&port
) == -1) {
629 TRACE("tcgetattr failed\n");
630 ptr
->commerror
=WinError();
641 TRACE("GETMAXCOM\n");
642 for (max
= MAX_PORTS
;!COM
[max
].devicename
;max
--)
648 TRACE("GETMAXLPT\n");
649 for (max
= MAX_PORTS
;!LPT
[max
].devicename
;max
--)
651 return FLAG_LPT
+ max
;
655 TRACE("GETBASEIRQ\n");
656 /* FIXME: use tables */
657 /* just fake something for now */
658 if (cid
& FLAG_LPT
) {
659 /* LPT1: irq 7, LPT2: irq 5 */
660 return (cid
& 0x7f) ? 5 : 7;
662 /* COM1: irq 4, COM2: irq 3,
663 COM3: irq 4, COM4: irq 3 */
664 return 4 - (cid
& 1);
671 return COMM_WhackModem(ptr
->fd
, ~TIOCM_DTR
, 0);
676 return COMM_WhackModem(ptr
->fd
, ~TIOCM_RTS
, 0);
682 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_DTR
);
688 return COMM_WhackModem(ptr
->fd
, 0, TIOCM_RTS
);
693 port
.c_iflag
|= IXOFF
;
698 port
.c_iflag
|= IXON
;
702 WARN("(cid=%d,nFunction=%d): Unknown function\n",
707 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
708 ptr
->commerror
= WinError();
716 /*****************************************************************************
717 * FlushComm (USER.215)
719 INT16 WINAPI
FlushComm16(INT16 cid
,INT16 fnQueue
)
722 struct DosDeviceStruct
*ptr
;
724 TRACE("cid=%d, queue=%d\n", cid
, fnQueue
);
725 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
726 FIXME("no cid=%d found!\n", cid
);
732 ptr
->obuf_tail
= ptr
->obuf_head
;
736 ptr
->ibuf_head
= ptr
->ibuf_tail
;
739 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
743 if (tcflush(ptr
->fd
, queue
)) {
744 ptr
->commerror
= WinError();
752 /********************************************************************
753 * GetCommError (USER.203)
755 INT16 WINAPI
GetCommError16(INT16 cid
,LPCOMSTAT16 lpStat
)
758 struct DosDeviceStruct
*ptr
;
762 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
763 FIXME("no handle for cid = %0x!.\n",cid
);
767 WARN(" cid %d not comm port\n",cid
);
770 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
771 ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
772 COMM_MSRUpdate( stol
, mstat
);
777 lpStat
->cbOutQue
= comm_outbuf(ptr
);
778 lpStat
->cbInQue
= comm_inbuf(ptr
);
780 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
781 cid
, ptr
->commerror
, lpStat
->status
, lpStat
->cbInQue
,
782 lpStat
->cbOutQue
, *stol
);
785 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
786 cid
, ptr
->commerror
, *stol
);
788 /* Return any errors and clear it */
789 temperror
= ptr
->commerror
;
794 /*****************************************************************************
795 * SetCommEventMask (USER.208)
797 SEGPTR WINAPI
SetCommEventMask16(INT16 cid
,UINT16 fuEvtMask
)
799 struct DosDeviceStruct
*ptr
;
804 TRACE("cid %d,mask %d\n",cid
,fuEvtMask
);
805 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
806 FIXME("no handle for cid = %0x!.\n",cid
);
810 ptr
->eventmask
= fuEvtMask
;
812 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
813 WARN(" cid %d not comm port\n",cid
);
816 /* it's a COM port ? -> modify flags */
817 stol
= (unsigned char *)unknown
[cid
] + COMM_MSR_OFFSET
;
818 repid
= ioctl(ptr
->fd
,TIOCMGET
,&mstat
);
819 TRACE(" ioctl %d, msr %x at %p %p\n",repid
,mstat
,stol
,unknown
[cid
]);
820 COMM_MSRUpdate( stol
, mstat
);
822 TRACE(" modem dcd construct %x\n",*stol
);
823 return SEGPTR_GET(unknown
[cid
]);
826 /*****************************************************************************
827 * GetCommEventMask (USER.209)
829 UINT16 WINAPI
GetCommEventMask16(INT16 cid
,UINT16 fnEvtClear
)
831 struct DosDeviceStruct
*ptr
;
834 TRACE("cid %d, mask %d\n", cid
, fnEvtClear
);
835 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
836 FIXME("no handle for cid = %0x!.\n",cid
);
840 if ((cid
&FLAG_LPT
) || !ValidCOMPort(cid
)) {
841 WARN(" cid %d not comm port\n",cid
);
845 events
= *(WORD
*)(unknown
[cid
]) & fnEvtClear
;
846 *(WORD
*)(unknown
[cid
]) &= ~fnEvtClear
;
850 /*****************************************************************************
851 * SetCommState16 (USER.201)
853 INT16 WINAPI
SetCommState16(LPDCB16 lpdcb
)
856 struct DosDeviceStruct
*ptr
;
857 int bytesize
, stopbits
;
860 TRACE("cid %d, ptr %p\n", lpdcb
->Id
, lpdcb
);
861 if ((ptr
= GetDeviceStruct(lpdcb
->Id
)) == NULL
) {
862 FIXME("no handle for cid = %0x!.\n",lpdcb
->Id
);
865 if (tcgetattr(ptr
->fd
, &port
) == -1) {
866 ptr
->commerror
= WinError();
871 port
.c_cc
[VTIME
] = 1;
874 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
876 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
878 port
.c_iflag
|= (IGNBRK
);
880 port
.c_oflag
&= ~(OPOST
);
882 port
.c_cflag
&= ~(HUPCL
);
883 port
.c_cflag
|= CLOCAL
| CREAD
;
885 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
886 port
.c_lflag
|= NOFLSH
;
888 TRACE("baudrate %d\n",lpdcb
->BaudRate
);
890 port
.c_cflag
&= ~CBAUD
;
891 switch (lpdcb
->BaudRate
) {
894 port
.c_cflag
|= B110
;
898 port
.c_cflag
|= B300
;
902 port
.c_cflag
|= B600
;
906 port
.c_cflag
|= B1200
;
910 port
.c_cflag
|= B2400
;
914 port
.c_cflag
|= B4800
;
918 port
.c_cflag
|= B9600
;
922 port
.c_cflag
|= B19200
;
926 port
.c_cflag
|= B38400
;
930 port
.c_cflag
|= B57600
;
935 port
.c_cflag
|= B115200
;
939 ptr
->commerror
= IE_BAUDRATE
;
942 #elif !defined(__EMX__)
943 switch (lpdcb
->BaudRate
) {
946 port
.c_ospeed
= B110
;
950 port
.c_ospeed
= B300
;
954 port
.c_ospeed
= B600
;
958 port
.c_ospeed
= B1200
;
962 port
.c_ospeed
= B2400
;
966 port
.c_ospeed
= B4800
;
970 port
.c_ospeed
= B9600
;
974 port
.c_ospeed
= B19200
;
978 port
.c_ospeed
= B38400
;
981 ptr
->commerror
= IE_BAUDRATE
;
984 port
.c_ispeed
= port
.c_ospeed
;
986 bytesize
=lpdcb
->ByteSize
;
987 stopbits
=lpdcb
->StopBits
;
989 TRACE("fParity %d Parity %d\n",lpdcb
->fParity
, lpdcb
->Parity
);
991 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
993 port
.c_cflag
&= ~(PARENB
| PARODD
);
996 port
.c_iflag
|= INPCK
;
998 port
.c_iflag
&= ~INPCK
;
999 switch (lpdcb
->Parity
) {
1003 port
.c_cflag
|= (PARENB
| PARODD
);
1006 port
.c_cflag
|= PARENB
;
1009 /* Linux defines mark/space (stick) parity */
1011 port
.c_cflag
|= (PARENB
| CMSPAR
);
1014 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
1017 /* try the POSIX way */
1019 if( stopbits
== ONESTOPBIT
) {
1020 stopbits
= TWOSTOPBITS
;
1021 port
.c_iflag
&= ~INPCK
;
1023 ptr
->commerror
= IE_BYTESIZE
;
1030 port
.c_iflag
&= ~INPCK
;
1032 ptr
->commerror
= IE_BYTESIZE
;
1038 ptr
->commerror
= IE_BYTESIZE
;
1042 TRACE("bytesize %d\n",bytesize
);
1043 port
.c_cflag
&= ~CSIZE
;
1046 port
.c_cflag
|= CS5
;
1049 port
.c_cflag
|= CS6
;
1052 port
.c_cflag
|= CS7
;
1055 port
.c_cflag
|= CS8
;
1058 ptr
->commerror
= IE_BYTESIZE
;
1062 TRACE("stopbits %d\n",stopbits
);
1066 port
.c_cflag
&= ~CSTOPB
;
1068 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
1070 port
.c_cflag
|= CSTOPB
;
1073 ptr
->commerror
= IE_BYTESIZE
;
1078 if (lpdcb
->fDtrflow
|| lpdcb
->fRtsflow
|| lpdcb
->fOutxCtsFlow
)
1079 port
.c_cflag
|= CRTSCTS
;
1081 if (lpdcb
->fDtrDisable
)
1082 port
.c_cflag
&= ~CRTSCTS
;
1085 port
.c_iflag
|= IXON
;
1087 port
.c_iflag
&= ~IXON
;
1089 port
.c_iflag
|= IXOFF
;
1091 port
.c_iflag
&= ~IXOFF
;
1093 ptr
->evtchar
= lpdcb
->EvtChar
;
1098 if (tcsetattr(ptr
->fd
, TCSADRAIN
, &port
) == -1) {
1099 ptr
->commerror
= WinError();
1107 /*****************************************************************************
1108 * GetCommState (USER.202)
1110 INT16 WINAPI
GetCommState16(INT16 cid
, LPDCB16 lpdcb
)
1113 struct DosDeviceStruct
*ptr
;
1114 struct termios port
;
1116 TRACE("cid %d, ptr %p\n", cid
, lpdcb
);
1117 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1118 FIXME("no handle for cid = %0x!.\n",cid
);
1121 if (tcgetattr(ptr
->fd
, &port
) == -1) {
1122 ptr
->commerror
= WinError();
1128 speed
= port
.c_cflag
& CBAUD
;
1130 speed
= port
.c_ospeed
;
1134 lpdcb
->BaudRate
= 110;
1137 lpdcb
->BaudRate
= 300;
1140 lpdcb
->BaudRate
= 600;
1143 lpdcb
->BaudRate
= 1200;
1146 lpdcb
->BaudRate
= 2400;
1149 lpdcb
->BaudRate
= 4800;
1152 lpdcb
->BaudRate
= 9600;
1155 lpdcb
->BaudRate
= 19200;
1158 lpdcb
->BaudRate
= 38400;
1162 lpdcb
->BaudRate
= 57600;
1167 lpdcb
->BaudRate
= 57601;
1172 switch (port
.c_cflag
& CSIZE
) {
1174 lpdcb
->ByteSize
= 5;
1177 lpdcb
->ByteSize
= 6;
1180 lpdcb
->ByteSize
= 7;
1183 lpdcb
->ByteSize
= 8;
1187 if(port
.c_iflag
& INPCK
)
1188 lpdcb
->fParity
= TRUE
;
1190 lpdcb
->fParity
= FALSE
;
1192 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
)) {
1194 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
1197 lpdcb
->Parity
= NOPARITY
;
1200 lpdcb
->Parity
= EVENPARITY
;
1202 case (PARENB
| PARODD
):
1203 lpdcb
->Parity
= ODDPARITY
;
1206 case (PARENB
| CMSPAR
):
1207 lpdcb
->Parity
= MARKPARITY
;
1209 case (PARENB
| PARODD
| CMSPAR
):
1210 lpdcb
->Parity
= SPACEPARITY
;
1215 if (port
.c_cflag
& CSTOPB
)
1216 if(lpdcb
->ByteSize
== 5)
1217 lpdcb
->StopBits
= ONE5STOPBITS
;
1219 lpdcb
->StopBits
= TWOSTOPBITS
;
1221 lpdcb
->StopBits
= ONESTOPBIT
;
1223 lpdcb
->RlsTimeout
= 50;
1224 lpdcb
->CtsTimeout
= 50;
1225 lpdcb
->DsrTimeout
= 50;
1229 lpdcb
->fDtrDisable
= 0;
1233 if (port
.c_cflag
& CRTSCTS
) {
1234 lpdcb
->fDtrflow
= 1;
1235 lpdcb
->fRtsflow
= 1;
1236 lpdcb
->fOutxCtsFlow
= 1;
1237 lpdcb
->fOutxDsrFlow
= 1;
1240 lpdcb
->fDtrDisable
= 1;
1242 if (port
.c_iflag
& IXON
)
1247 if (port
.c_iflag
& IXOFF
)
1256 lpdcb
->XoffLim
= 10;
1258 lpdcb
->EvtChar
= ptr
->evtchar
;
1264 /*****************************************************************************
1265 * TransmitCommChar (USER.206)
1267 INT16 WINAPI
TransmitCommChar16(INT16 cid
,CHAR chTransmit
)
1269 struct DosDeviceStruct
*ptr
;
1271 TRACE("cid %d, data %d \n", cid
, chTransmit
);
1272 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1273 FIXME("no handle for cid = %0x!.\n",cid
);
1277 if (ptr
->suspended
) {
1278 ptr
->commerror
= IE_HARDWARE
;
1282 if (ptr
->xmit
>= 0) {
1283 /* character already queued */
1284 /* FIXME: which error would Windows return? */
1285 ptr
->commerror
= CE_TXFULL
;
1289 if (ptr
->obuf_head
== ptr
->obuf_tail
) {
1290 /* transmit queue empty, try to transmit directly */
1291 if (write(ptr
->fd
, &chTransmit
, 1) == -1) {
1292 /* didn't work, queue it */
1293 ptr
->xmit
= chTransmit
;
1294 comm_waitwrite(ptr
);
1297 /* data in queue, let this char be transmitted next */
1298 ptr
->xmit
= chTransmit
;
1299 comm_waitwrite(ptr
);
1306 /*****************************************************************************
1307 * UngetCommChar (USER.212)
1309 INT16 WINAPI
UngetCommChar16(INT16 cid
,CHAR chUnget
)
1311 struct DosDeviceStruct
*ptr
;
1313 TRACE("cid %d (char %d)\n", cid
, chUnget
);
1314 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1315 FIXME("no handle for cid = %0x!.\n",cid
);
1319 if (ptr
->suspended
) {
1320 ptr
->commerror
= IE_HARDWARE
;
1324 if (ptr
->unget
>=0) {
1325 /* character already queued */
1326 /* FIXME: which error would Windows return? */
1327 ptr
->commerror
= CE_RXOVER
;
1331 ptr
->unget
= chUnget
;
1337 /*****************************************************************************
1338 * ReadComm (USER.204)
1340 INT16 WINAPI
ReadComm16(INT16 cid
,LPSTR lpvBuf
,INT16 cbRead
)
1343 struct DosDeviceStruct
*ptr
;
1344 LPSTR orgBuf
= lpvBuf
;
1346 TRACE("cid %d, ptr %p, length %d\n", cid
, lpvBuf
, cbRead
);
1347 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1348 FIXME("no handle for cid = %0x!.\n",cid
);
1352 if (ptr
->suspended
) {
1353 ptr
->commerror
= IE_HARDWARE
;
1357 /* read unget character */
1358 if (ptr
->unget
>=0) {
1359 *lpvBuf
++ = ptr
->unget
;
1366 /* read from receive buffer */
1367 while (length
< cbRead
) {
1368 status
= ((ptr
->ibuf_head
< ptr
->ibuf_tail
) ?
1369 ptr
->ibuf_size
: ptr
->ibuf_head
) - ptr
->ibuf_tail
;
1371 if ((cbRead
- length
) < status
)
1372 status
= cbRead
- length
;
1374 memcpy(lpvBuf
, ptr
->inbuf
+ ptr
->ibuf_tail
, status
);
1375 ptr
->ibuf_tail
+= status
;
1376 if (ptr
->ibuf_tail
>= ptr
->ibuf_size
)
1382 TRACE("%.*s\n", length
, orgBuf
);
1387 /*****************************************************************************
1388 * WriteComm (USER.205)
1390 INT16 WINAPI
WriteComm16(INT16 cid
, LPSTR lpvBuf
, INT16 cbWrite
)
1393 struct DosDeviceStruct
*ptr
;
1395 TRACE("cid %d, ptr %p, length %d\n",
1396 cid
, lpvBuf
, cbWrite
);
1397 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1398 FIXME("no handle for cid = %0x!.\n",cid
);
1402 if (ptr
->suspended
) {
1403 ptr
->commerror
= IE_HARDWARE
;
1407 TRACE("%.*s\n", cbWrite
, lpvBuf
);
1410 while (length
< cbWrite
) {
1411 if ((ptr
->obuf_head
== ptr
->obuf_tail
) && (ptr
->xmit
< 0)) {
1412 /* no data queued, try to write directly */
1413 status
= write(ptr
->fd
, lpvBuf
, cbWrite
- length
);
1420 /* can't write directly, put into transmit buffer */
1421 status
= ((ptr
->obuf_tail
> ptr
->obuf_head
) ?
1422 (ptr
->obuf_tail
-1) : ptr
->obuf_size
) - ptr
->obuf_head
;
1424 if ((cbWrite
- length
) < status
)
1425 status
= cbWrite
- length
;
1426 memcpy(lpvBuf
, ptr
->outbuf
+ ptr
->obuf_head
, status
);
1427 ptr
->obuf_head
+= status
;
1428 if (ptr
->obuf_head
>= ptr
->obuf_size
)
1432 comm_waitwrite(ptr
);
1439 /***********************************************************************
1440 * EnableCommNotification (USER.246)
1442 BOOL16 WINAPI
EnableCommNotification16( INT16 cid
, HWND16 hwnd
,
1443 INT16 cbWriteNotify
, INT16 cbOutQueue
)
1445 struct DosDeviceStruct
*ptr
;
1447 TRACE("(%d, %x, %d, %d)\n", cid
, hwnd
, cbWriteNotify
, cbOutQueue
);
1448 if ((ptr
= GetDeviceStruct(cid
)) == NULL
) {
1449 FIXME("no handle for cid = %0x!.\n",cid
);
1453 ptr
->n_read
= cbWriteNotify
;
1454 ptr
->n_write
= cbOutQueue
;
1459 /**************************************************************************
1460 * BuildCommDCBA (KERNEL32.14)
1462 BOOL WINAPI
BuildCommDCBA(LPCSTR device
,LPDCB lpdcb
)
1464 return BuildCommDCBAndTimeoutsA(device
,lpdcb
,NULL
);
1467 /**************************************************************************
1468 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1470 BOOL WINAPI
BuildCommDCBAndTimeoutsA(LPCSTR device
, LPDCB lpdcb
,
1471 LPCOMMTIMEOUTS lptimeouts
)
1476 TRACE("(%s,%p,%p)\n",device
,lpdcb
,lptimeouts
);
1478 if (!lstrncmpiA(device
,"COM",3)) {
1481 ERR("BUG! COM0 can't exists!.\n");
1484 if (!ValidCOMPort(port
))
1486 if (*(device
+4)!=':')
1488 temp
=(LPSTR
)(device
+5);
1492 lpdcb
->DCBlength
= sizeof(DCB
);
1493 if (strchr(temp
,',')) { /* old style */
1496 char last
=temp
[strlen(temp
)-1];
1498 ret
=BuildCommDCB16(device
,&dcb16
);
1501 lpdcb
->BaudRate
= dcb16
.BaudRate
;
1502 lpdcb
->ByteSize
= dcb16
.ByteSize
;
1503 lpdcb
->fBinary
= dcb16
.fBinary
;
1504 lpdcb
->Parity
= dcb16
.Parity
;
1505 lpdcb
->fParity
= dcb16
.fParity
;
1506 lpdcb
->fNull
= dcb16
.fNull
;
1507 lpdcb
->StopBits
= dcb16
.StopBits
;
1510 lpdcb
->fOutX
= TRUE
;
1511 lpdcb
->fOutxCtsFlow
= FALSE
;
1512 lpdcb
->fOutxDsrFlow
= FALSE
;
1513 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1514 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1515 } else if (last
=='p') {
1516 lpdcb
->fInX
= FALSE
;
1517 lpdcb
->fOutX
= FALSE
;
1518 lpdcb
->fOutxCtsFlow
= TRUE
;
1519 lpdcb
->fOutxDsrFlow
= TRUE
;
1520 lpdcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
;
1521 lpdcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
;
1523 lpdcb
->fInX
= FALSE
;
1524 lpdcb
->fOutX
= FALSE
;
1525 lpdcb
->fOutxCtsFlow
= FALSE
;
1526 lpdcb
->fOutxDsrFlow
= FALSE
;
1527 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
1528 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
1530 lpdcb
->XonChar
= dcb16
.XonChar
;
1531 lpdcb
->XoffChar
= dcb16
.XoffChar
;
1532 lpdcb
->ErrorChar
= dcb16
.PeChar
;
1533 lpdcb
->fErrorChar
= dcb16
.fPeChar
;
1534 lpdcb
->EofChar
= dcb16
.EofChar
;
1535 lpdcb
->EvtChar
= dcb16
.EvtChar
;
1536 lpdcb
->XonLim
= dcb16
.XonLim
;
1537 lpdcb
->XoffLim
= dcb16
.XoffLim
;
1540 ptr
=strtok(temp
," ");
1545 if (!strncmp("baud=",ptr
,5)) {
1546 if (!sscanf(ptr
+5,"%ld",&x
))
1547 WARN("Couldn't parse %s\n",ptr
);
1548 lpdcb
->BaudRate
= x
;
1551 if (!strncmp("stop=",ptr
,5)) {
1552 if (!sscanf(ptr
+5,"%ld",&x
))
1553 WARN("Couldn't parse %s\n",ptr
);
1554 lpdcb
->StopBits
= x
;
1557 if (!strncmp("data=",ptr
,5)) {
1558 if (!sscanf(ptr
+5,"%ld",&x
))
1559 WARN("Couldn't parse %s\n",ptr
);
1560 lpdcb
->ByteSize
= x
;
1563 if (!strncmp("parity=",ptr
,7)) {
1564 lpdcb
->fParity
= TRUE
;
1567 lpdcb
->fParity
= FALSE
;
1568 lpdcb
->Parity
= NOPARITY
;
1571 lpdcb
->Parity
= EVENPARITY
;
1574 lpdcb
->Parity
= ODDPARITY
;
1577 lpdcb
->Parity
= MARKPARITY
;
1583 ERR("Unhandled specifier '%s', please report.\n",ptr
);
1584 ptr
=strtok(NULL
," ");
1586 if (lpdcb
->BaudRate
==110)
1587 lpdcb
->StopBits
= 2;
1591 /**************************************************************************
1592 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1594 BOOL WINAPI
BuildCommDCBAndTimeoutsW( LPCWSTR devid
, LPDCB lpdcb
,
1595 LPCOMMTIMEOUTS lptimeouts
)
1600 TRACE("(%p,%p,%p)\n",devid
,lpdcb
,lptimeouts
);
1601 devidA
= HEAP_strdupWtoA( GetProcessHeap(), 0, devid
);
1602 ret
=BuildCommDCBAndTimeoutsA(devidA
,lpdcb
,lptimeouts
);
1603 HeapFree( GetProcessHeap(), 0, devidA
);
1607 /**************************************************************************
1608 * BuildCommDCBW (KERNEL32.17)
1610 BOOL WINAPI
BuildCommDCBW(LPCWSTR devid
,LPDCB lpdcb
)
1612 return BuildCommDCBAndTimeoutsW(devid
,lpdcb
,NULL
);
1615 /*****************************************************************************
1617 * Returns a file descriptor for reading.
1618 * Make sure to close the handle afterwards!
1620 static int COMM_GetReadFd( HANDLE handle
)
1623 struct get_read_fd_request
*req
= get_req_buffer();
1624 req
->handle
= handle
;
1625 server_call_fd( REQ_GET_READ_FD
, -1, &fd
);
1629 /*****************************************************************************
1631 * Returns a file descriptor for writing.
1632 * Make sure to close the handle afterwards!
1634 static int COMM_GetWriteFd( HANDLE handle
)
1637 struct get_write_fd_request
*req
= get_req_buffer();
1638 req
->handle
= handle
;
1639 server_call_fd( REQ_GET_WRITE_FD
, -1, &fd
);
1643 /* FIXME: having these global for win32 for now */
1644 int commerror
=0,eventmask
=0;
1646 /*****************************************************************************
1647 * SetCommBreak (KERNEL32.449)
1649 BOOL WINAPI
SetCommBreak(HANDLE handle
)
1651 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1654 fd
= COMM_GetWriteFd(handle
);
1656 TRACE("COMM_GetWriteFd failed\n");
1659 result
= ioctl(fd
,TIOCSBRK
,0);
1663 TRACE("ioctl failed\n");
1664 SetLastError(ERROR_NOT_SUPPORTED
);
1669 FIXME("ioctl not available\n");
1670 SetLastError(ERROR_NOT_SUPPORTED
);
1675 /*****************************************************************************
1676 * ClearCommBreak (KERNEL32.20)
1678 BOOL WINAPI
ClearCommBreak(HANDLE handle
)
1680 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1683 fd
= COMM_GetWriteFd(handle
);
1685 TRACE("COMM_GetWriteFd failed\n");
1688 result
= ioctl(fd
,TIOCCBRK
,0);
1692 TRACE("ioctl failed\n");
1693 SetLastError(ERROR_NOT_SUPPORTED
);
1698 FIXME("ioctl not available\n");
1699 SetLastError(ERROR_NOT_SUPPORTED
);
1704 /*****************************************************************************
1705 * EscapeCommFunction (KERNEL32.214)
1707 BOOL WINAPI
EscapeCommFunction(HANDLE handle
,UINT nFunction
)
1709 int fd
,direct
=FALSE
,result
=FALSE
;
1710 struct termios port
;
1712 TRACE("handle %d, function=%d\n", handle
, nFunction
);
1713 fd
= COMM_GetWriteFd(handle
);
1715 FIXME("handle %d not found.\n",handle
);
1719 if (tcgetattr(fd
,&port
) == -1) {
1720 commerror
=WinError();
1725 switch (nFunction
) {
1734 result
= COMM_WhackModem(fd
, ~TIOCM_DTR
, 0);
1742 result
= COMM_WhackModem(fd
, ~TIOCM_RTS
, 0);
1750 result
= COMM_WhackModem(fd
, 0, TIOCM_DTR
);
1758 result
= COMM_WhackModem(fd
, 0, TIOCM_RTS
);
1764 port
.c_iflag
|= IXOFF
;
1769 port
.c_iflag
|= IXON
;
1772 TRACE("setbreak\n");
1775 result
= ioctl(fd
,TIOCSBRK
,0);
1779 TRACE("clrbreak\n");
1782 result
= ioctl(fd
,TIOCCBRK
,0);
1786 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1792 if (tcsetattr(fd
, TCSADRAIN
, &port
) == -1) {
1793 commerror
= WinError();
1803 commerror
=WinError();
1812 /********************************************************************
1813 * PurgeComm (KERNEL32.557)
1815 BOOL WINAPI
PurgeComm( HANDLE handle
, DWORD flags
)
1819 TRACE("handle %d, flags %lx\n", handle
, flags
);
1821 fd
= COMM_GetWriteFd(handle
);
1823 FIXME("no handle %d found\n",handle
);
1828 ** not exactly sure how these are different
1829 ** Perhaps if we had our own internal queues, one flushes them
1830 ** and the other flushes the kernel's buffers.
1832 if(flags
&PURGE_TXABORT
)
1833 tcflush(fd
,TCOFLUSH
);
1834 if(flags
&PURGE_RXABORT
)
1835 tcflush(fd
,TCIFLUSH
);
1836 if(flags
&PURGE_TXCLEAR
)
1837 tcflush(fd
,TCOFLUSH
);
1838 if(flags
&PURGE_RXCLEAR
)
1839 tcflush(fd
,TCIFLUSH
);
1845 /*****************************************************************************
1846 * ClearCommError (KERNEL32.21)
1848 BOOL WINAPI
ClearCommError(INT handle
,LPDWORD errors
,LPCOMSTAT lpStat
)
1852 fd
=COMM_GetReadFd(handle
);
1855 FIXME("no handle %d found\n",handle
);
1864 if(ioctl(fd
, TIOCOUTQ
, &lpStat
->cbOutQue
))
1865 WARN("ioctl returned error\n");
1867 lpStat
->cbOutQue
= 0; /* FIXME: find a different way to find out */
1870 if(ioctl(fd
, TIOCINQ
, &lpStat
->cbInQue
))
1871 WARN("ioctl returned error\n");
1873 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1874 handle
, lpStat
->cbInQue
, lpStat
->cbOutQue
);
1883 ** After an asynchronous write opperation, the
1884 ** app will call ClearCommError to see if the
1885 ** results are ready yet. It waits for ERROR_IO_PENDING
1887 commerror
= ERROR_IO_PENDING
;
1892 /*****************************************************************************
1893 * SetupComm (KERNEL32.676)
1895 BOOL WINAPI
SetupComm( HANDLE handle
, DWORD insize
, DWORD outsize
)
1899 FIXME("insize %ld outsize %ld unimplemented stub\n", insize
, outsize
);
1900 fd
=COMM_GetWriteFd(handle
);
1902 FIXME("handle %d not found?\n",handle
);
1909 /*****************************************************************************
1910 * GetCommMask (KERNEL32.156)
1912 BOOL WINAPI
GetCommMask(HANDLE handle
,LPDWORD evtmask
)
1916 TRACE("handle %d, mask %p\n", handle
, evtmask
);
1917 if(0>(fd
=COMM_GetReadFd(handle
)))
1919 FIXME("no handle %d found\n",handle
);
1923 *evtmask
= eventmask
;
1924 TRACE("%s%s%s%s%s%s%s%s%s\n",
1925 (eventmask
&EV_BREAK
)?"EV_BREAK":"",
1926 (eventmask
&EV_CTS
)?"EV_CTS":"",
1927 (eventmask
&EV_DSR
)?"EV_DSR":"",
1928 (eventmask
&EV_ERR
)?"EV_ERR":"",
1929 (eventmask
&EV_RING
)?"EV_RING":"",
1930 (eventmask
&EV_RLSD
)?"EV_RLSD":"",
1931 (eventmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1932 (eventmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1933 (eventmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1938 /*****************************************************************************
1939 * SetCommMask (KERNEL32.451)
1941 BOOL WINAPI
SetCommMask(INT handle
,DWORD evtmask
)
1945 TRACE("handle %d, mask %lx\n", handle
, evtmask
);
1946 TRACE("%s%s%s%s%s%s%s%s%s\n",
1947 (evtmask
&EV_BREAK
)?"EV_BREAK":"",
1948 (evtmask
&EV_CTS
)?"EV_CTS":"",
1949 (evtmask
&EV_DSR
)?"EV_DSR":"",
1950 (evtmask
&EV_ERR
)?"EV_ERR":"",
1951 (evtmask
&EV_RING
)?"EV_RING":"",
1952 (evtmask
&EV_RLSD
)?"EV_RLSD":"",
1953 (evtmask
&EV_RXCHAR
)?"EV_RXCHAR":"",
1954 (evtmask
&EV_RXFLAG
)?"EV_RXFLAG":"",
1955 (evtmask
&EV_TXEMPTY
)?"EV_TXEMPTY":"");
1957 if(0>(fd
=COMM_GetWriteFd(handle
))) {
1958 FIXME("no handle %d found\n",handle
);
1962 eventmask
= evtmask
;
1966 /*****************************************************************************
1967 * SetCommState (KERNEL32.452)
1969 BOOL WINAPI
SetCommState(INT handle
,LPDCB lpdcb
)
1971 struct termios port
;
1973 int bytesize
, stopbits
;
1975 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
1976 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1977 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
1978 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
1979 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
1980 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
1981 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
1983 if ((fd
= COMM_GetWriteFd(handle
)) < 0) {
1984 FIXME("no handle %d found\n",handle
);
1988 if ((tcgetattr(fd
,&port
)) == -1) {
1989 int save_error
= errno
;
1990 commerror
= WinError();
1992 #ifdef HAVE_STRERROR
1993 ERR("tcgetattr error '%s'\n", strerror(save_error
));
1995 ERR("tcgetattr error %d\n", save_error
);
2000 port
.c_cc
[VMIN
] = 0;
2001 port
.c_cc
[VTIME
] = 1;
2004 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
|IMAXBEL
);
2006 port
.c_iflag
&= ~(ISTRIP
|BRKINT
|IGNCR
|ICRNL
|INLCR
);
2008 port
.c_iflag
|= (IGNBRK
);
2010 port
.c_oflag
&= ~(OPOST
);
2012 port
.c_cflag
&= ~(HUPCL
);
2013 port
.c_cflag
|= CLOCAL
| CREAD
;
2015 port
.c_lflag
&= ~(ICANON
|ECHO
|ISIG
);
2016 port
.c_lflag
|= NOFLSH
;
2019 ** MJM - removed default baudrate settings
2020 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2023 port
.c_cflag
&= ~CBAUD
;
2024 switch (lpdcb
->BaudRate
) {
2027 port
.c_cflag
|= B110
;
2031 port
.c_cflag
|= B300
;
2035 port
.c_cflag
|= B600
;
2039 port
.c_cflag
|= B1200
;
2043 port
.c_cflag
|= B2400
;
2047 port
.c_cflag
|= B4800
;
2051 port
.c_cflag
|= B9600
;
2055 port
.c_cflag
|= B19200
;
2059 port
.c_cflag
|= B38400
;
2063 port
.c_cflag
|= B57600
;
2068 port
.c_cflag
|= B115200
;
2073 port
.c_cflag
|= B230400
;
2078 port
.c_cflag
|= B460800
;
2082 commerror
= IE_BAUDRATE
;
2084 ERR("baudrate %ld\n",lpdcb
->BaudRate
);
2087 #elif !defined(__EMX__)
2088 switch (lpdcb
->BaudRate
) {
2091 port
.c_ospeed
= B110
;
2095 port
.c_ospeed
= B300
;
2099 port
.c_ospeed
= B600
;
2103 port
.c_ospeed
= B1200
;
2107 port
.c_ospeed
= B2400
;
2111 port
.c_ospeed
= B4800
;
2115 port
.c_ospeed
= B9600
;
2119 port
.c_ospeed
= B19200
;
2123 port
.c_ospeed
= B38400
;
2126 commerror
= IE_BAUDRATE
;
2128 ERR("baudrate %d \n",lpdcb
->BaudRate
);
2131 port
.c_ispeed
= port
.c_ospeed
;
2133 bytesize
=lpdcb
->ByteSize
;
2134 stopbits
=lpdcb
->StopBits
;
2137 port
.c_cflag
&= ~(PARENB
| PARODD
| CMSPAR
);
2139 port
.c_cflag
&= ~(PARENB
| PARODD
);
2142 port
.c_iflag
|= INPCK
;
2144 port
.c_iflag
&= ~INPCK
;
2145 switch (lpdcb
->Parity
) {
2149 port
.c_cflag
|= (PARENB
| PARODD
);
2152 port
.c_cflag
|= PARENB
;
2155 /* Linux defines mark/space (stick) parity */
2157 port
.c_cflag
|= (PARENB
| CMSPAR
);
2160 port
.c_cflag
|= (PARENB
| PARODD
| CMSPAR
);
2163 /* try the POSIX way */
2165 if( stopbits
== ONESTOPBIT
) {
2166 stopbits
= TWOSTOPBITS
;
2167 port
.c_iflag
&= ~INPCK
;
2169 commerror
= IE_BYTESIZE
;
2171 ERR("Cannot set MARK Parity\n");
2178 port
.c_iflag
&= ~INPCK
;
2180 commerror
= IE_BYTESIZE
;
2182 ERR("Cannot set SPACE Parity\n");
2188 commerror
= IE_BYTESIZE
;
2195 port
.c_cflag
&= ~CSIZE
;
2198 port
.c_cflag
|= CS5
;
2201 port
.c_cflag
|= CS6
;
2204 port
.c_cflag
|= CS7
;
2207 port
.c_cflag
|= CS8
;
2210 commerror
= IE_BYTESIZE
;
2218 port
.c_cflag
&= ~CSTOPB
;
2220 case ONE5STOPBITS
: /* wil be selected if bytesize is 5 */
2222 port
.c_cflag
|= CSTOPB
;
2225 commerror
= IE_BYTESIZE
;
2231 if ( lpdcb
->fOutxCtsFlow
||
2232 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2233 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2236 port
.c_cflag
|= CRTSCTS
;
2240 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2242 port
.c_cflag
&= ~CRTSCTS
;
2243 TRACE("~CRTSCTS\n");
2248 port
.c_iflag
|= IXON
;
2250 port
.c_iflag
&= ~IXON
;
2252 port
.c_iflag
|= IXOFF
;
2254 port
.c_iflag
&= ~IXOFF
;
2256 if (tcsetattr(fd
,TCSANOW
,&port
)==-1) { /* otherwise it hangs with pending input*/
2257 int save_error
=errno
;
2258 commerror
= WinError();
2260 #ifdef HAVE_STRERROR
2261 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2263 ERR("tcgetattr error %d\n", save_error
);
2274 /*****************************************************************************
2275 * GetCommState (KERNEL32.159)
2277 BOOL WINAPI
GetCommState(INT handle
, LPDCB lpdcb
)
2279 struct termios port
;
2282 TRACE("handle %d, ptr %p\n", handle
, lpdcb
);
2284 if ((fd
= COMM_GetReadFd(handle
)) < 0)
2286 ERR("can't get COMM_GetReadFd\n");
2289 if (tcgetattr(fd
, &port
) == -1) {
2290 int save_error
=errno
;
2291 #ifdef HAVE_STRERROR
2292 ERR("tcgetattr error '%s'\n", strerror(save_error
));
2294 ERR("tcgetattr error %d\n", save_error
);
2296 commerror
= WinError();
2303 speed
= (port
.c_cflag
& CBAUD
);
2305 speed
= (cfgetospeed(&port
));
2309 lpdcb
->BaudRate
= 110;
2312 lpdcb
->BaudRate
= 300;
2315 lpdcb
->BaudRate
= 600;
2318 lpdcb
->BaudRate
= 1200;
2321 lpdcb
->BaudRate
= 2400;
2324 lpdcb
->BaudRate
= 4800;
2327 lpdcb
->BaudRate
= 9600;
2330 lpdcb
->BaudRate
= 19200;
2333 lpdcb
->BaudRate
= 38400;
2337 lpdcb
->BaudRate
= 57600;
2342 lpdcb
->BaudRate
= 115200;
2347 lpdcb
->BaudRate
= 230400;
2352 lpdcb
->BaudRate
= 460800;
2356 ERR("unknown speed %x \n",speed
);
2359 switch (port
.c_cflag
& CSIZE
) {
2361 lpdcb
->ByteSize
= 5;
2364 lpdcb
->ByteSize
= 6;
2367 lpdcb
->ByteSize
= 7;
2370 lpdcb
->ByteSize
= 8;
2373 ERR("unknown size %x \n",port
.c_cflag
& CSIZE
);
2376 if(port
.c_iflag
& INPCK
)
2377 lpdcb
->fParity
= TRUE
;
2379 lpdcb
->fParity
= FALSE
;
2381 switch (port
.c_cflag
& (PARENB
| PARODD
| CMSPAR
)) {
2383 switch (port
.c_cflag
& (PARENB
| PARODD
)) {
2386 lpdcb
->Parity
= NOPARITY
;
2389 lpdcb
->Parity
= EVENPARITY
;
2391 case (PARENB
| PARODD
):
2392 lpdcb
->Parity
= ODDPARITY
;
2395 case (PARENB
| CMSPAR
):
2396 lpdcb
->Parity
= MARKPARITY
;
2398 case (PARENB
| PARODD
| CMSPAR
):
2399 lpdcb
->Parity
= SPACEPARITY
;
2404 if (port
.c_cflag
& CSTOPB
)
2405 if(lpdcb
->ByteSize
== 5)
2406 lpdcb
->StopBits
= ONE5STOPBITS
;
2408 lpdcb
->StopBits
= TWOSTOPBITS
;
2410 lpdcb
->StopBits
= ONESTOPBIT
;
2417 if (port
.c_cflag
& CRTSCTS
) {
2418 lpdcb
->fDtrControl
= DTR_CONTROL_ENABLE
;
2419 lpdcb
->fRtsControl
= RTS_CONTROL_ENABLE
;
2420 lpdcb
->fOutxCtsFlow
= 1;
2421 lpdcb
->fOutxDsrFlow
= 1;
2425 lpdcb
->fDtrControl
= DTR_CONTROL_DISABLE
;
2426 lpdcb
->fRtsControl
= RTS_CONTROL_DISABLE
;
2428 if (port
.c_iflag
& IXON
)
2433 if (port
.c_iflag
& IXOFF
)
2442 lpdcb
->XoffLim
= 10;
2448 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2449 lpdcb
->ByteSize
,lpdcb
->BaudRate
,lpdcb
->fParity
, lpdcb
->Parity
,
2450 (lpdcb
->StopBits
== ONESTOPBIT
)?1:
2451 (lpdcb
->StopBits
== TWOSTOPBITS
)?2:0);
2452 TRACE("%s %s\n",(lpdcb
->fInX
)?"IXON":"~IXON",
2453 (lpdcb
->fOutX
)?"IXOFF":"~IXOFF");
2455 if ( lpdcb
->fOutxCtsFlow
||
2456 lpdcb
->fDtrControl
== DTR_CONTROL_ENABLE
||
2457 lpdcb
->fRtsControl
== RTS_CONTROL_ENABLE
2461 if (lpdcb
->fDtrControl
== DTR_CONTROL_DISABLE
)
2462 TRACE("~CRTSCTS\n");
2468 /*****************************************************************************
2469 * TransmitCommChar (KERNEL32.535)
2471 BOOL WINAPI
TransmitCommChar(INT cid
,CHAR chTransmit
)
2473 struct DosDeviceStruct
*ptr
;
2475 FIXME("(%d,'%c'), use win32 handle!\n",cid
,chTransmit
);
2476 if ((ptr
= GetDeviceStruct(cid
)) == NULL
)
2477 FIXME("no handle for cid = %0x!.\n",cid
);
2480 if (ptr
->suspended
) {
2481 ptr
->commerror
= IE_HARDWARE
;
2484 if (write(ptr
->fd
, (void *) &chTransmit
, 1) == -1) {
2485 ptr
->commerror
= WinError();
2493 /*****************************************************************************
2494 * GetCommTimeouts (KERNEL32.160)
2496 BOOL WINAPI
GetCommTimeouts(HANDLE hcom
,LPCOMMTIMEOUTS lptimeouts
)
2498 FIXME("(%x,%p):stub.\n",hcom
,lptimeouts
);
2502 /*****************************************************************************
2503 * SetCommTimeouts (KERNEL32.453)
2505 BOOL WINAPI
SetCommTimeouts(HANDLE hcom
,LPCOMMTIMEOUTS lptimeouts
) {
2506 /* struct DosDeviceStruct *ptr; */
2507 struct termios tios
;
2510 FIXME("(%x,%p):stub.\n",hcom
,lptimeouts
);
2512 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2513 FIXME("no handle for cid = %0x!.\n",hcom);
2518 fd
= COMM_GetWriteFd(hcom
);
2520 FIXME("no fd for cid = %0x!.\n",hcom
);
2525 FIXME("ReadIntervalTimeout %ld\n",lptimeouts
->ReadIntervalTimeout
);
2526 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts
->ReadTotalTimeoutMultiplier
);
2527 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts
->ReadTotalTimeoutConstant
);
2528 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts
->WriteTotalTimeoutMultiplier
);
2529 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts
->WriteTotalTimeoutConstant
);
2532 if (-1==tcgetattr(fd
,&tios
)) {
2533 FIXME("tcgetattr on fd %d failed!\n",fd
);
2536 /* VTIME is in 1/10 seconds */
2537 tios
.c_cc
[VTIME
]= (lptimeouts
->ReadIntervalTimeout
+99)/100;
2538 if (-1==tcsetattr(fd
,0,&tios
)) {
2539 FIXME("tcsetattr on fd %d failed!\n",fd
);
2545 /***********************************************************************
2546 * GetCommModemStatus (KERNEL32.285)
2548 BOOL WINAPI
GetCommModemStatus(HANDLE hFile
,LPDWORD lpModemStat
)
2550 int fd
,mstat
, result
=FALSE
;
2554 fd
= COMM_GetWriteFd(hFile
);
2557 result
= ioctl(fd
, TIOCMGET
, &mstat
);
2561 TRACE("ioctl failed\n");
2564 if (mstat
& TIOCM_CTS
)
2565 *lpModemStat
|= MS_CTS_ON
;
2566 if (mstat
& TIOCM_DSR
)
2567 *lpModemStat
|= MS_DSR_ON
;
2568 if (mstat
& TIOCM_RNG
)
2569 *lpModemStat
|= MS_RING_ON
;
2570 /*FIXME: Not really sure about RLSD UB 990810*/
2571 if (mstat
& TIOCM_CAR
)
2572 *lpModemStat
|= MS_RLSD_ON
;
2574 (*lpModemStat
&MS_RLSD_ON
)?"MS_RLSD_ON ":"",
2575 (*lpModemStat
&MS_RING_ON
)?"MS_RING_ON ":"",
2576 (*lpModemStat
&MS_DSR_ON
)?"MS_DSR_ON ":"",
2577 (*lpModemStat
&MS_CTS_ON
)?"MS_CTS_ON ":"");
2583 /***********************************************************************
2584 * WaitCommEvent (KERNEL32.719)
2586 BOOL WINAPI
WaitCommEvent(HANDLE hFile
,LPDWORD eventmask
,LPOVERLAPPED overlapped
)
2588 FIXME("(%d %p %p )\n",hFile
, eventmask
,overlapped
);
2592 /***********************************************************************
2593 * GetCommProperties (KERNEL32.???)
2595 BOOL WINAPI
GetCommProperties(HANDLE hFile
, LPDCB
*dcb
)
2597 FIXME("(%d %p )\n",hFile
,dcb
);
2601 /***********************************************************************
2602 * SetCommProperties (KERNEL32.???)
2604 BOOL WINAPI
SetCommProperties(HANDLE hFile
, LPDCB dcb
)
2606 FIXME("(%d %p )\n",hFile
,dcb
);