Added missing configuration #if:s and #includes:s.
[wine/dcerpc.git] / misc / comm.c
blob37dee77456805d505eca80b8ee33654420408cf6
1 /*
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.
35 #include "config.h"
37 #include <stdlib.h>
38 #include <termios.h>
39 #include <fcntl.h>
40 #include <string.h>
41 #ifdef HAVE_STRINGS_H
42 # include <strings.h>
43 #endif
44 #include <errno.h>
45 #include <ctype.h>
46 #include <sys/stat.h>
47 #ifdef HAVE_SYS_FILIO_H
48 # include <sys/filio.h>
49 #endif
50 #include <sys/ioctl.h>
51 #include <unistd.h>
53 #include "wine/winuser16.h"
54 #include "comm.h"
55 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
57 #endif
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
60 #endif
61 #include "heap.h"
62 #include "options.h"
64 #include "server.h"
65 #include "process.h"
66 #include "winerror.h"
67 #include "services.h"
68 #include "file.h"
70 #include "debugtools.h"
72 DEFAULT_DEBUG_CHANNEL(comm)
74 #ifndef TIOCINQ
75 #define TIOCINQ FIONREAD
76 #endif
77 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
78 #define FLAG_LPT 0x80
80 struct DosDeviceStruct COM[MAX_PORTS];
81 struct DosDeviceStruct LPT[MAX_PORTS];
82 /* pointers to unknown(==undocumented) comm structure */
83 LPCVOID *unknown[MAX_PORTS];
84 /* save terminal states */
85 static struct termios m_stat[MAX_PORTS];
87 void COMM_Init(void)
89 int x;
90 char option[10], temp[256], *btemp;
91 struct stat st;
93 for (x=0; x!=MAX_PORTS; x++) {
94 strcpy(option,"COMx");
95 option[3] = '1' + x;
96 option[4] = '\0';
98 PROFILE_GetWineIniString( "serialports", option, "*",
99 temp, sizeof(temp) );
100 if (!strcmp(temp, "*") || *temp == '\0')
101 COM[x].devicename = NULL;
102 else {
103 btemp = strchr(temp,',');
104 if (btemp != NULL) {
105 *btemp++ = '\0';
106 COM[x].baudrate = atoi(btemp);
107 } else {
108 COM[x].baudrate = -1;
110 stat(temp, &st);
111 if (!S_ISCHR(st.st_mode))
112 WARN("Can't use `%s' as %s !\n", temp, option);
113 else
114 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
115 WARN("Can't malloc for device info!\n");
116 else {
117 COM[x].fd = 0;
118 strcpy(COM[x].devicename, temp);
120 TRACE("%s = %s\n", option, COM[x].devicename);
123 strcpy(option, "LPTx");
124 option[3] = '1' + x;
125 option[4] = '\0';
127 PROFILE_GetWineIniString( "parallelports", option, "*",
128 temp, sizeof(temp) );
129 if (!strcmp(temp, "*") || *temp == '\0')
130 LPT[x].devicename = NULL;
131 else {
132 stat(temp, &st);
133 if (!S_ISCHR(st.st_mode))
134 WARN("Can't use `%s' as %s !\n", temp, option);
135 else
136 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
137 WARN("Can't malloc for device info!\n");
138 else {
139 LPT[x].fd = 0;
140 strcpy(LPT[x].devicename, temp);
142 TRACE("%s = %s\n", option, LPT[x].devicename);
149 static struct DosDeviceStruct *GetDeviceStruct(int fd)
151 if ((fd&0x7F)<=MAX_PORTS) {
152 if (!(fd&FLAG_LPT)) {
153 if (COM[fd].fd)
154 return &COM[fd];
155 } else {
156 if (LPT[fd].fd)
157 return &LPT[fd];
161 return NULL;
164 static int GetCommPort_fd(int fd)
166 int x;
168 for (x=0; x<MAX_PORTS; x++) {
169 if (COM[x].fd == fd)
170 return x;
173 return -1;
176 static int ValidCOMPort(int x)
178 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
181 static int ValidLPTPort(int x)
183 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
186 static int WinError(void)
188 TRACE("errno = %d\n", errno);
189 switch (errno) {
190 default:
191 return CE_IOE;
195 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
197 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
198 + ptr->ibuf_head - ptr->ibuf_tail;
201 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
203 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
204 + ptr->obuf_head - ptr->obuf_tail;
207 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
209 unsigned int mstat, okay;
210 okay = ioctl(fd, TIOCMGET, &mstat);
211 if (okay) return okay;
212 if (andy) mstat &= andy;
213 mstat |= orrie;
214 return ioctl(fd, TIOCMSET, &mstat);
217 static void CALLBACK comm_notification( ULONG_PTR private )
219 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
220 int prev, bleft, len;
221 WORD mask = 0;
222 int cid = GetCommPort_fd(ptr->fd);
224 TRACE("async notification\n");
225 /* read data from comm port */
226 prev = comm_inbuf(ptr);
227 do {
228 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
229 - ptr->ibuf_head;
230 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
231 if (len > 0) {
232 if (!bleft) {
233 ptr->commerror = CE_RXOVER;
234 } else {
235 /* check for events */
236 if ((ptr->eventmask & EV_RXFLAG) &&
237 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
238 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
239 mask |= CN_EVENT;
241 if (ptr->eventmask & EV_RXCHAR) {
242 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
243 mask |= CN_EVENT;
245 /* advance buffer position */
246 ptr->ibuf_head += len;
247 if (ptr->ibuf_head >= ptr->ibuf_size)
248 ptr->ibuf_head = 0;
251 } while (len > 0);
252 /* check for notification */
253 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
254 (comm_inbuf(ptr)>=ptr->n_read)) {
255 /* passed the receive notification threshold */
256 mask |= CN_RECEIVE;
259 /* write any TransmitCommChar character */
260 if (ptr->xmit>=0) {
261 len = write(ptr->fd, &(ptr->xmit), 1);
262 if (len > 0) ptr->xmit = -1;
264 /* write from output queue */
265 prev = comm_outbuf(ptr);
266 do {
267 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
268 - ptr->obuf_tail;
269 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
270 if (len > 0) {
271 ptr->obuf_tail += len;
272 if (ptr->obuf_tail >= ptr->obuf_size)
273 ptr->obuf_tail = 0;
274 /* flag event */
275 if ((ptr->obuf_tail == ptr->obuf_head) && (ptr->eventmask & EV_TXEMPTY)) {
276 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
277 mask |= CN_EVENT;
280 } while (len > 0);
281 /* check for notification */
282 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
283 (comm_outbuf(ptr)<ptr->n_write)) {
284 /* passed the transmit notification threshold */
285 mask |= CN_TRANSMIT;
288 /* send notifications, if any */
289 if (ptr->wnd && mask) {
290 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
291 PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
295 /**************************************************************************
296 * BuildCommDCB (USER.213)
298 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
300 /* "COM1:9600,n,8,1" */
301 /* 012345 */
302 int port;
303 char *ptr, temp[256];
305 TRACE("(%s), ptr %p\n", device, lpdcb);
307 if (!lstrncmpiA(device,"COM",3)) {
308 port = device[3] - '0';
311 if (port-- == 0) {
312 ERR("BUG ! COM0 can't exist!.\n");
313 return -1;
316 if (!ValidCOMPort(port)) {
317 return -1;
320 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
322 lpdcb->Id = port;
324 if (!*(device+4))
325 return 0;
327 if (*(device+4) != ':')
328 return -1;
330 strcpy(temp,device+5);
331 ptr = strtok(temp, ", ");
333 if (COM[port].baudrate > 0)
334 lpdcb->BaudRate = COM[port].baudrate;
335 else
336 lpdcb->BaudRate = atoi(ptr);
337 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
339 ptr = strtok(NULL, ", ");
340 if (islower(*ptr))
341 *ptr = toupper(*ptr);
343 TRACE("parity (%c)\n", *ptr);
344 lpdcb->fParity = TRUE;
345 switch (*ptr) {
346 case 'N':
347 lpdcb->Parity = NOPARITY;
348 lpdcb->fParity = FALSE;
349 break;
350 case 'E':
351 lpdcb->Parity = EVENPARITY;
352 break;
353 case 'M':
354 lpdcb->Parity = MARKPARITY;
355 break;
356 case 'O':
357 lpdcb->Parity = ODDPARITY;
358 break;
359 default:
360 WARN("Unknown parity `%c'!\n", *ptr);
361 return -1;
364 ptr = strtok(NULL, ", ");
365 TRACE("charsize (%c)\n", *ptr);
366 lpdcb->ByteSize = *ptr - '0';
368 ptr = strtok(NULL, ", ");
369 TRACE("stopbits (%c)\n", *ptr);
370 switch (*ptr) {
371 case '1':
372 lpdcb->StopBits = ONESTOPBIT;
373 break;
374 case '2':
375 lpdcb->StopBits = TWOSTOPBITS;
376 break;
377 default:
378 WARN("Unknown # of stopbits `%c'!\n", *ptr);
379 return -1;
383 return 0;
386 /*****************************************************************************
387 * OpenComm (USER.200)
389 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
391 int port,fd;
393 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
395 if (strlen(device) < 4)
396 return IE_BADID;
398 port = device[3] - '0';
400 if (port-- == 0)
401 ERR("BUG ! COM0 or LPT0 don't exist !\n");
403 if (!lstrncmpiA(device,"COM",3)) {
405 TRACE("%s = %s\n", device, COM[port].devicename);
407 if (!ValidCOMPort(port))
408 return IE_BADID;
410 if (COM[port].fd)
411 return IE_OPEN;
413 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
414 if (fd == -1) {
415 ERR("error=%d\n", errno);
416 return IE_HARDWARE;
417 } else {
418 unknown[port] = SEGPTR_ALLOC(40);
419 bzero(unknown[port],40);
420 COM[port].fd = fd;
421 COM[port].commerror = 0;
422 COM[port].eventmask = 0;
423 COM[port].evtchar = 0; /* FIXME: default? */
424 /* save terminal state */
425 tcgetattr(fd,&m_stat[port]);
426 /* set default parameters */
427 if(COM[port].baudrate>-1){
428 DCB16 dcb;
429 GetCommState16(port, &dcb);
430 dcb.BaudRate=COM[port].baudrate;
431 /* more defaults:
432 * databits, parity, stopbits
434 SetCommState16( &dcb);
436 /* init priority characters */
437 COM[port].unget = -1;
438 COM[port].xmit = -1;
439 /* allocate buffers */
440 COM[port].ibuf_size = cbInQueue;
441 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
442 COM[port].obuf_size = cbOutQueue;
443 COM[port].obuf_head = COM[port].obuf_tail = 0;
445 COM[port].inbuf = malloc(cbInQueue);
446 if (COM[port].inbuf) {
447 COM[port].outbuf = malloc(cbOutQueue);
448 if (!COM[port].outbuf)
449 free(COM[port].inbuf);
450 } else COM[port].outbuf = NULL;
451 if (!COM[port].outbuf) {
452 /* not enough memory */
453 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
454 close(COM[port].fd);
455 ERR("out of memory");
456 return IE_MEMORY;
459 COM[port].service = SERVICE_AddObject( FILE_DupUnixHandle( COM[port].fd,
460 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE ),
461 comm_notification,
462 (ULONG_PTR)&COM[port] );
463 /* bootstrap notifications, just in case */
464 comm_notification( (ULONG_PTR)&COM[port] );
465 return port;
468 else
469 if (!lstrncmpiA(device,"LPT",3)) {
471 if (!ValidLPTPort(port))
472 return IE_BADID;
474 if (LPT[port].fd)
475 return IE_OPEN;
477 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
478 if (fd == -1) {
479 return IE_HARDWARE;
480 } else {
481 LPT[port].fd = fd;
482 LPT[port].commerror = 0;
483 LPT[port].eventmask = 0;
484 return port|FLAG_LPT;
487 return 0;
490 /*****************************************************************************
491 * CloseComm (USER.207)
493 INT16 WINAPI CloseComm16(INT16 cid)
495 struct DosDeviceStruct *ptr;
497 TRACE("cid=%d\n", cid);
498 if ((ptr = GetDeviceStruct(cid)) == NULL) {
499 return -1;
501 if (!(cid&FLAG_LPT)) {
502 /* COM port */
503 SEGPTR_FREE(unknown[cid]); /* [LW] */
505 SERVICE_Delete( COM[cid].service );
506 /* free buffers */
507 free(ptr->outbuf);
508 free(ptr->inbuf);
510 /* reset modem lines */
511 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
514 if (close(ptr->fd) == -1) {
515 ptr->commerror = WinError();
516 /* FIXME: should we clear ptr->fd here? */
517 return -1;
518 } else {
519 ptr->commerror = 0;
520 ptr->fd = 0;
521 return 0;
525 /*****************************************************************************
526 * SetCommBreak (USER.210)
528 INT16 WINAPI SetCommBreak16(INT16 cid)
530 struct DosDeviceStruct *ptr;
532 TRACE("cid=%d\n", cid);
533 if ((ptr = GetDeviceStruct(cid)) == NULL) {
534 return -1;
537 ptr->suspended = 1;
538 ptr->commerror = 0;
539 return 0;
542 /*****************************************************************************
543 * ClearCommBreak (USER.211)
545 INT16 WINAPI ClearCommBreak16(INT16 cid)
547 struct DosDeviceStruct *ptr;
549 TRACE("cid=%d\n", cid);
550 if ((ptr = GetDeviceStruct(cid)) == NULL) {
551 return -1;
554 ptr->suspended = 0;
555 ptr->commerror = 0;
556 return 0;
559 /*****************************************************************************
560 * EscapeCommFunction (USER.214)
562 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
564 int max;
565 struct DosDeviceStruct *ptr;
566 struct termios port;
568 TRACE("cid=%d, function=%d\n", cid, nFunction);
569 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
570 if ((ptr = GetDeviceStruct(cid)) == NULL) {
571 TRACE("GetDeviceStruct failed\n");
572 return -1;
574 if (tcgetattr(ptr->fd,&port) == -1) {
575 TRACE("tcgetattr failed\n");
576 ptr->commerror=WinError();
577 return -1;
579 } else ptr = NULL;
581 switch (nFunction) {
582 case RESETDEV:
583 TRACE("RESETDEV\n");
584 break;
586 case GETMAXCOM:
587 TRACE("GETMAXCOM\n");
588 for (max = MAX_PORTS;!COM[max].devicename;max--)
590 return max;
591 break;
593 case GETMAXLPT:
594 TRACE("GETMAXLPT\n");
595 for (max = MAX_PORTS;!LPT[max].devicename;max--)
597 return FLAG_LPT + max;
598 break;
600 case GETBASEIRQ:
601 TRACE("GETBASEIRQ\n");
602 /* FIXME: use tables */
603 /* just fake something for now */
604 if (cid & FLAG_LPT) {
605 /* LPT1: irq 7, LPT2: irq 5 */
606 return (cid & 0x7f) ? 5 : 7;
607 } else {
608 /* COM1: irq 4, COM2: irq 3,
609 COM3: irq 4, COM4: irq 3 */
610 return 4 - (cid & 1);
612 break;
614 case CLRDTR:
615 TRACE("CLRDTR\n");
616 #ifdef TIOCM_DTR
617 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
618 #endif
619 case CLRRTS:
620 TRACE("CLRRTS\n");
621 #ifdef TIOCM_RTS
622 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
623 #endif
625 case SETDTR:
626 TRACE("SETDTR\n");
627 #ifdef TIOCM_DTR
628 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
629 #endif
631 case SETRTS:
632 TRACE("SETRTS\n");
633 #ifdef TIOCM_RTS
634 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
635 #endif
637 case SETXOFF:
638 TRACE("SETXOFF\n");
639 port.c_iflag |= IXOFF;
640 break;
642 case SETXON:
643 TRACE("SETXON\n");
644 port.c_iflag |= IXON;
645 break;
647 default:
648 WARN("(cid=%d,nFunction=%d): Unknown function\n",
649 cid, nFunction);
650 break;
653 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
654 ptr->commerror = WinError();
655 return -1;
656 } else {
657 ptr->commerror = 0;
658 return 0;
662 /*****************************************************************************
663 * FlushComm (USER.215)
665 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
667 int queue;
668 struct DosDeviceStruct *ptr;
670 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
671 if ((ptr = GetDeviceStruct(cid)) == NULL) {
672 return -1;
674 switch (fnQueue) {
675 case 0:
676 queue = TCOFLUSH;
677 ptr->obuf_tail = ptr->obuf_head;
678 break;
679 case 1:
680 queue = TCIFLUSH;
681 ptr->ibuf_head = ptr->ibuf_tail;
682 break;
683 default:
684 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
685 cid, fnQueue);
686 return -1;
688 if (tcflush(ptr->fd, queue)) {
689 ptr->commerror = WinError();
690 return -1;
691 } else {
692 ptr->commerror = 0;
693 return 0;
697 /********************************************************************
698 * GetCommError (USER.203)
700 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
702 int temperror;
703 struct DosDeviceStruct *ptr;
704 unsigned char *stol;
705 unsigned int mstat;
707 if ((ptr = GetDeviceStruct(cid)) == NULL) {
708 return -1;
710 if (cid&FLAG_LPT) {
711 WARN(" cid %d not comm port\n",cid);
712 return CE_MODE;
714 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
715 ioctl(ptr->fd,TIOCMGET,&mstat);
716 if( mstat&TIOCM_CAR )
717 *stol |= 0x80;
718 else
719 *stol &=0x7f;
721 if (lpStat) {
722 lpStat->status = 0;
724 lpStat->cbOutQue = comm_outbuf(ptr);
725 lpStat->cbInQue = comm_inbuf(ptr);
727 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
728 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
729 lpStat->cbOutQue, *stol);
731 else
732 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
733 cid, ptr->commerror, *stol);
735 /* Return any errors and clear it */
736 temperror = ptr->commerror;
737 ptr->commerror = 0;
738 return(temperror);
741 /*****************************************************************************
742 * SetCommEventMask (USER.208)
744 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
746 struct DosDeviceStruct *ptr;
747 unsigned char *stol;
748 int repid;
749 unsigned int mstat;
751 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
752 if ((ptr = GetDeviceStruct(cid)) == NULL)
753 return (SEGPTR)NULL;
755 ptr->eventmask = fuEvtMask;
757 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
758 WARN(" cid %d not comm port\n",cid);
759 return (SEGPTR)NULL;
761 /* it's a COM port ? -> modify flags */
762 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
763 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
764 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
765 if ((mstat&TIOCM_CAR))
766 *stol |= 0x80;
767 else
768 *stol &=0x7f;
770 TRACE(" modem dcd construct %x\n",*stol);
771 return SEGPTR_GET(unknown[cid]);
774 /*****************************************************************************
775 * GetCommEventMask (USER.209)
777 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
779 struct DosDeviceStruct *ptr;
780 WORD events;
782 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
783 if ((ptr = GetDeviceStruct(cid)) == NULL)
784 return 0;
786 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
787 WARN(" cid %d not comm port\n",cid);
788 return 0;
791 events = *(WORD*)(unknown[cid]) & fnEvtClear;
792 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
793 return events;
796 /*****************************************************************************
797 * SetCommState16 (USER.201)
799 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
801 struct termios port;
802 struct DosDeviceStruct *ptr;
804 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
805 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
806 return -1;
808 if (tcgetattr(ptr->fd, &port) == -1) {
809 ptr->commerror = WinError();
810 return -1;
813 port.c_cc[VMIN] = 0;
814 port.c_cc[VTIME] = 1;
816 #ifdef IMAXBEL
817 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
818 #else
819 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
820 #endif
821 port.c_iflag |= (IGNBRK);
823 port.c_oflag &= ~(OPOST);
825 port.c_cflag &= ~(HUPCL);
826 port.c_cflag |= CLOCAL | CREAD;
828 port.c_lflag &= ~(ICANON|ECHO|ISIG);
829 port.c_lflag |= NOFLSH;
831 TRACE("baudrate %d\n",lpdcb->BaudRate);
832 #ifdef CBAUD
833 port.c_cflag &= ~CBAUD;
834 switch (lpdcb->BaudRate) {
835 case 110:
836 case CBR_110:
837 port.c_cflag |= B110;
838 break;
839 case 300:
840 case CBR_300:
841 port.c_cflag |= B300;
842 break;
843 case 600:
844 case CBR_600:
845 port.c_cflag |= B600;
846 break;
847 case 1200:
848 case CBR_1200:
849 port.c_cflag |= B1200;
850 break;
851 case 2400:
852 case CBR_2400:
853 port.c_cflag |= B2400;
854 break;
855 case 4800:
856 case CBR_4800:
857 port.c_cflag |= B4800;
858 break;
859 case 9600:
860 case CBR_9600:
861 port.c_cflag |= B9600;
862 break;
863 case 19200:
864 case CBR_19200:
865 port.c_cflag |= B19200;
866 break;
867 case 38400:
868 case CBR_38400:
869 port.c_cflag |= B38400;
870 break;
871 #ifdef B57600
872 case 57600:
873 port.c_cflag |= B57600;
874 break;
875 #endif
876 #ifdef B115200
877 case 57601:
878 port.c_cflag |= B115200;
879 break;
880 #endif
881 default:
882 ptr->commerror = IE_BAUDRATE;
883 return -1;
885 #elif !defined(__EMX__)
886 switch (lpdcb->BaudRate) {
887 case 110:
888 case CBR_110:
889 port.c_ospeed = B110;
890 break;
891 case 300:
892 case CBR_300:
893 port.c_ospeed = B300;
894 break;
895 case 600:
896 case CBR_600:
897 port.c_ospeed = B600;
898 break;
899 case 1200:
900 case CBR_1200:
901 port.c_ospeed = B1200;
902 break;
903 case 2400:
904 case CBR_2400:
905 port.c_ospeed = B2400;
906 break;
907 case 4800:
908 case CBR_4800:
909 port.c_ospeed = B4800;
910 break;
911 case 9600:
912 case CBR_9600:
913 port.c_ospeed = B9600;
914 break;
915 case 19200:
916 case CBR_19200:
917 port.c_ospeed = B19200;
918 break;
919 case 38400:
920 case CBR_38400:
921 port.c_ospeed = B38400;
922 break;
923 default:
924 ptr->commerror = IE_BAUDRATE;
925 return -1;
927 port.c_ispeed = port.c_ospeed;
928 #endif
929 TRACE("bytesize %d\n",lpdcb->ByteSize);
930 port.c_cflag &= ~CSIZE;
931 switch (lpdcb->ByteSize) {
932 case 5:
933 port.c_cflag |= CS5;
934 break;
935 case 6:
936 port.c_cflag |= CS6;
937 break;
938 case 7:
939 port.c_cflag |= CS7;
940 break;
941 case 8:
942 port.c_cflag |= CS8;
943 break;
944 default:
945 ptr->commerror = IE_BYTESIZE;
946 return -1;
949 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
950 port.c_cflag &= ~(PARENB | PARODD);
951 if (lpdcb->fParity)
952 port.c_iflag |= INPCK;
953 else
954 port.c_iflag &= ~INPCK;
955 switch (lpdcb->Parity) {
956 case NOPARITY:
957 break;
958 case ODDPARITY:
959 port.c_cflag |= (PARENB | PARODD);
960 break;
961 case EVENPARITY:
962 port.c_cflag |= PARENB;
963 break;
964 default:
965 ptr->commerror = IE_BYTESIZE;
966 return -1;
970 TRACE("stopbits %d\n",lpdcb->StopBits);
972 switch (lpdcb->StopBits) {
973 case ONESTOPBIT:
974 port.c_cflag &= ~CSTOPB;
975 break;
976 case TWOSTOPBITS:
977 port.c_cflag |= CSTOPB;
978 break;
979 default:
980 ptr->commerror = IE_BYTESIZE;
981 return -1;
983 #ifdef CRTSCTS
985 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
986 port.c_cflag |= CRTSCTS;
988 if (lpdcb->fDtrDisable)
989 port.c_cflag &= ~CRTSCTS;
990 #endif
991 if (lpdcb->fInX)
992 port.c_iflag |= IXON;
993 else
994 port.c_iflag &= ~IXON;
995 if (lpdcb->fOutX)
996 port.c_iflag |= IXOFF;
997 else
998 port.c_iflag &= ~IXOFF;
1000 ptr->evtchar = lpdcb->EvtChar;
1002 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1003 ptr->commerror = WinError();
1004 return FALSE;
1005 } else {
1006 ptr->commerror = 0;
1007 return 0;
1011 /*****************************************************************************
1012 * GetCommState (USER.202)
1014 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1016 int speed;
1017 struct DosDeviceStruct *ptr;
1018 struct termios port;
1020 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1021 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1022 return -1;
1024 if (tcgetattr(ptr->fd, &port) == -1) {
1025 ptr->commerror = WinError();
1026 return -1;
1028 lpdcb->Id = cid;
1029 #ifndef __EMX__
1030 #ifdef CBAUD
1031 speed = port.c_cflag & CBAUD;
1032 #else
1033 speed = port.c_ospeed;
1034 #endif
1035 switch(speed) {
1036 case B110:
1037 lpdcb->BaudRate = 110;
1038 break;
1039 case B300:
1040 lpdcb->BaudRate = 300;
1041 break;
1042 case B600:
1043 lpdcb->BaudRate = 600;
1044 break;
1045 case B1200:
1046 lpdcb->BaudRate = 1200;
1047 break;
1048 case B2400:
1049 lpdcb->BaudRate = 2400;
1050 break;
1051 case B4800:
1052 lpdcb->BaudRate = 4800;
1053 break;
1054 case B9600:
1055 lpdcb->BaudRate = 9600;
1056 break;
1057 case B19200:
1058 lpdcb->BaudRate = 19200;
1059 break;
1060 case B38400:
1061 lpdcb->BaudRate = 38400;
1062 break;
1063 #ifdef B57600
1064 case B57600:
1065 lpdcb->BaudRate = 57600;
1066 break;
1067 #endif
1068 #ifdef B115200
1069 case B115200:
1070 lpdcb->BaudRate = 57601;
1071 break;
1072 #endif
1074 #endif
1075 switch (port.c_cflag & CSIZE) {
1076 case CS5:
1077 lpdcb->ByteSize = 5;
1078 break;
1079 case CS6:
1080 lpdcb->ByteSize = 6;
1081 break;
1082 case CS7:
1083 lpdcb->ByteSize = 7;
1084 break;
1085 case CS8:
1086 lpdcb->ByteSize = 8;
1087 break;
1090 if(port.c_iflag & INPCK)
1091 lpdcb->fParity = TRUE;
1092 else
1093 lpdcb->fParity = FALSE;
1094 switch (port.c_cflag & (PARENB | PARODD)) {
1095 case 0:
1096 lpdcb->Parity = NOPARITY;
1097 break;
1098 case PARENB:
1099 lpdcb->Parity = EVENPARITY;
1100 break;
1101 case (PARENB | PARODD):
1102 lpdcb->Parity = ODDPARITY;
1103 break;
1106 if (port.c_cflag & CSTOPB)
1107 lpdcb->StopBits = TWOSTOPBITS;
1108 else
1109 lpdcb->StopBits = ONESTOPBIT;
1111 lpdcb->RlsTimeout = 50;
1112 lpdcb->CtsTimeout = 50;
1113 lpdcb->DsrTimeout = 50;
1114 lpdcb->fNull = 0;
1115 lpdcb->fChEvt = 0;
1116 lpdcb->fBinary = 1;
1117 lpdcb->fDtrDisable = 0;
1119 #ifdef CRTSCTS
1121 if (port.c_cflag & CRTSCTS) {
1122 lpdcb->fDtrflow = 1;
1123 lpdcb->fRtsflow = 1;
1124 lpdcb->fOutxCtsFlow = 1;
1125 lpdcb->fOutxDsrFlow = 1;
1126 } else
1127 #endif
1128 lpdcb->fDtrDisable = 1;
1130 if (port.c_iflag & IXON)
1131 lpdcb->fInX = 1;
1132 else
1133 lpdcb->fInX = 0;
1135 if (port.c_iflag & IXOFF)
1136 lpdcb->fOutX = 1;
1137 else
1138 lpdcb->fOutX = 0;
1140 lpdcb->XonChar =
1141 lpdcb->XoffChar =
1143 lpdcb->XonLim = 10;
1144 lpdcb->XoffLim = 10;
1146 lpdcb->EvtChar = ptr->evtchar;
1148 ptr->commerror = 0;
1149 return 0;
1152 /*****************************************************************************
1153 * TransmitCommChar (USER.206)
1155 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1157 struct DosDeviceStruct *ptr;
1159 TRACE("cid %d, data %d \n", cid, chTransmit);
1160 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1161 return -1;
1164 if (ptr->suspended) {
1165 ptr->commerror = IE_HARDWARE;
1166 return -1;
1169 if (ptr->xmit >= 0) {
1170 /* character already queued */
1171 /* FIXME: which error would Windows return? */
1172 ptr->commerror = CE_TXFULL;
1173 return -1;
1176 if (ptr->obuf_head == ptr->obuf_tail) {
1177 /* transmit queue empty, try to transmit directly */
1178 if (write(ptr->fd, &chTransmit, 1) == -1) {
1179 /* didn't work, queue it */
1180 ptr->xmit = chTransmit;
1182 } else {
1183 /* data in queue, let this char be transmitted next */
1184 ptr->xmit = chTransmit;
1187 ptr->commerror = 0;
1188 return 0;
1191 /*****************************************************************************
1192 * UngetCommChar (USER.212)
1194 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1196 struct DosDeviceStruct *ptr;
1198 TRACE("cid %d (char %d)\n", cid, chUnget);
1199 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1200 return -1;
1203 if (ptr->suspended) {
1204 ptr->commerror = IE_HARDWARE;
1205 return -1;
1208 if (ptr->unget>=0) {
1209 /* character already queued */
1210 /* FIXME: which error would Windows return? */
1211 ptr->commerror = CE_RXOVER;
1212 return -1;
1215 ptr->unget = chUnget;
1217 ptr->commerror = 0;
1218 return 0;
1221 /*****************************************************************************
1222 * ReadComm (USER.204)
1224 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1226 int status, length;
1227 struct DosDeviceStruct *ptr;
1228 LPSTR orgBuf = lpvBuf;
1230 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1231 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1232 return -1;
1235 if (ptr->suspended) {
1236 ptr->commerror = IE_HARDWARE;
1237 return -1;
1240 /* read unget character */
1241 if (ptr->unget>=0) {
1242 *lpvBuf++ = ptr->unget;
1243 ptr->unget = -1;
1245 length = 1;
1246 } else
1247 length = 0;
1249 /* read from receive buffer */
1250 while (length < cbRead) {
1251 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1252 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1253 if (!status) break;
1254 if ((cbRead - length) < status)
1255 status = cbRead - length;
1257 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1258 ptr->ibuf_tail += status;
1259 if (ptr->ibuf_tail >= ptr->ibuf_size)
1260 ptr->ibuf_tail = 0;
1261 lpvBuf += status;
1262 length += status;
1265 TRACE("%.*s\n", length, orgBuf);
1266 ptr->commerror = 0;
1267 return length;
1270 /*****************************************************************************
1271 * WriteComm (USER.205)
1273 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1275 int status, length;
1276 struct DosDeviceStruct *ptr;
1278 TRACE("cid %d, ptr %p, length %d\n",
1279 cid, lpvBuf, cbWrite);
1280 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1281 return -1;
1284 if (ptr->suspended) {
1285 ptr->commerror = IE_HARDWARE;
1286 return -1;
1289 TRACE("%.*s\n", cbWrite, lpvBuf );
1291 length = 0;
1292 while (length < cbWrite) {
1293 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1294 /* no data queued, try to write directly */
1295 status = write(ptr->fd, lpvBuf, cbWrite - length);
1296 if (status > 0) {
1297 lpvBuf += status;
1298 length += status;
1299 continue;
1302 /* can't write directly, put into transmit buffer */
1303 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1304 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1305 if (!status) break;
1306 if ((cbWrite - length) < status)
1307 status = cbWrite - length;
1308 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1309 ptr->obuf_head += status;
1310 if (ptr->obuf_head >= ptr->obuf_size)
1311 ptr->obuf_head = 0;
1312 lpvBuf += status;
1313 length += status;
1316 ptr->commerror = 0;
1317 return length;
1320 /***********************************************************************
1321 * EnableCommNotification (USER.246)
1323 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1324 INT16 cbWriteNotify, INT16 cbOutQueue )
1326 struct DosDeviceStruct *ptr;
1328 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1329 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1330 ptr->commerror = IE_BADID;
1331 return -1;
1333 ptr->wnd = hwnd;
1334 ptr->n_read = cbWriteNotify;
1335 ptr->n_write = cbOutQueue;
1336 return TRUE;
1340 /**************************************************************************
1341 * BuildCommDCBA (KERNEL32.14)
1343 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1345 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1348 /**************************************************************************
1349 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1351 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1352 LPCOMMTIMEOUTS lptimeouts)
1354 int port;
1355 char *ptr,*temp;
1357 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1359 if (!lstrncmpiA(device,"COM",3)) {
1360 port=device[3]-'0';
1361 if (port--==0) {
1362 ERR("BUG! COM0 can't exists!.\n");
1363 return FALSE;
1365 if (!ValidCOMPort(port))
1366 return FALSE;
1367 if (*(device+4)!=':')
1368 return FALSE;
1369 temp=(LPSTR)(device+5);
1370 } else
1371 temp=(LPSTR)device;
1373 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1375 lpdcb->DCBlength = sizeof(DCB);
1376 if (strchr(temp,',')) { /* old style */
1377 DCB16 dcb16;
1378 BOOL16 ret;
1379 char last=temp[strlen(temp)-1];
1381 ret=BuildCommDCB16(device,&dcb16);
1382 if (!ret)
1383 return FALSE;
1384 lpdcb->BaudRate = dcb16.BaudRate;
1385 lpdcb->ByteSize = dcb16.ByteSize;
1386 lpdcb->fBinary = dcb16.fBinary;
1387 lpdcb->Parity = dcb16.Parity;
1388 lpdcb->fParity = dcb16.fParity;
1389 lpdcb->fNull = dcb16.fNull;
1390 lpdcb->StopBits = dcb16.StopBits;
1391 if (last == 'x') {
1392 lpdcb->fInX = TRUE;
1393 lpdcb->fOutX = TRUE;
1394 lpdcb->fOutxCtsFlow = FALSE;
1395 lpdcb->fOutxDsrFlow = FALSE;
1396 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1397 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1398 } else if (last=='p') {
1399 lpdcb->fInX = FALSE;
1400 lpdcb->fOutX = FALSE;
1401 lpdcb->fOutxCtsFlow = TRUE;
1402 lpdcb->fOutxDsrFlow = TRUE;
1403 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1404 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1405 } else {
1406 lpdcb->fInX = FALSE;
1407 lpdcb->fOutX = FALSE;
1408 lpdcb->fOutxCtsFlow = FALSE;
1409 lpdcb->fOutxDsrFlow = FALSE;
1410 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1411 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1413 lpdcb->XonChar = dcb16.XonChar;
1414 lpdcb->XoffChar = dcb16.XoffChar;
1415 lpdcb->ErrorChar= dcb16.PeChar;
1416 lpdcb->fErrorChar= dcb16.fPeChar;
1417 lpdcb->EofChar = dcb16.EofChar;
1418 lpdcb->EvtChar = dcb16.EvtChar;
1419 lpdcb->XonLim = dcb16.XonLim;
1420 lpdcb->XoffLim = dcb16.XoffLim;
1421 return TRUE;
1423 ptr=strtok(temp," ");
1424 while (ptr) {
1425 DWORD flag,x;
1427 flag=0;
1428 if (!strncmp("baud=",ptr,5)) {
1429 if (!sscanf(ptr+5,"%ld",&x))
1430 WARN("Couldn't parse %s\n",ptr);
1431 lpdcb->BaudRate = x;
1432 flag=1;
1434 if (!strncmp("stop=",ptr,5)) {
1435 if (!sscanf(ptr+5,"%ld",&x))
1436 WARN("Couldn't parse %s\n",ptr);
1437 lpdcb->StopBits = x;
1438 flag=1;
1440 if (!strncmp("data=",ptr,5)) {
1441 if (!sscanf(ptr+5,"%ld",&x))
1442 WARN("Couldn't parse %s\n",ptr);
1443 lpdcb->ByteSize = x;
1444 flag=1;
1446 if (!strncmp("parity=",ptr,7)) {
1447 lpdcb->fParity = TRUE;
1448 switch (ptr[8]) {
1449 case 'N':case 'n':
1450 lpdcb->fParity = FALSE;
1451 lpdcb->Parity = NOPARITY;
1452 break;
1453 case 'E':case 'e':
1454 lpdcb->Parity = EVENPARITY;
1455 break;
1456 case 'O':case 'o':
1457 lpdcb->Parity = ODDPARITY;
1458 break;
1459 case 'M':case 'm':
1460 lpdcb->Parity = MARKPARITY;
1461 break;
1463 flag=1;
1465 if (!flag)
1466 ERR("Unhandled specifier '%s', please report.\n",ptr);
1467 ptr=strtok(NULL," ");
1469 if (lpdcb->BaudRate==110)
1470 lpdcb->StopBits = 2;
1471 return TRUE;
1474 /**************************************************************************
1475 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1477 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1478 LPCOMMTIMEOUTS lptimeouts )
1480 LPSTR devidA;
1481 BOOL ret;
1483 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1484 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1485 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1486 HeapFree( GetProcessHeap(), 0, devidA );
1487 return ret;
1490 /**************************************************************************
1491 * BuildCommDCBW (KERNEL32.17)
1493 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1495 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1498 /*****************************************************************************
1499 * COMM_GetReadFd
1500 * Returns a file descriptor for reading.
1501 * Make sure to close the handle afterwards!
1503 static int COMM_GetReadFd( HANDLE handle)
1505 int fd;
1506 struct get_read_fd_request *req = get_req_buffer();
1507 req->handle = handle;
1508 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1509 return fd;
1512 /*****************************************************************************
1513 * COMM_GetWriteFd
1514 * Returns a file descriptor for writing.
1515 * Make sure to close the handle afterwards!
1517 static int COMM_GetWriteFd( HANDLE handle)
1519 int fd;
1520 struct get_write_fd_request *req = get_req_buffer();
1521 req->handle = handle;
1522 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1523 return fd;
1526 /* FIXME: having these global for win32 for now */
1527 int commerror=0,eventmask=0;
1529 /*****************************************************************************
1530 * SetCommBreak (KERNEL32.449)
1532 BOOL WINAPI SetCommBreak(HANDLE handle)
1534 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1535 int fd,result;
1537 fd = COMM_GetWriteFd(handle);
1538 if(fd<0) {
1539 TRACE("COMM_GetWriteFd failed\n");
1540 return FALSE;
1542 result = ioctl(fd,TIOCSBRK,0);
1543 close(fd);
1544 if (result ==-1)
1546 TRACE("ioctl failed\n");
1547 SetLastError(ERROR_NOT_SUPPORTED);
1548 return FALSE;
1550 return TRUE;
1551 #else
1552 FIXME("ioctl not available\n");
1553 SetLastError(ERROR_NOT_SUPPORTED);
1554 return FALSE;
1555 #endif
1558 /*****************************************************************************
1559 * ClearCommBreak (KERNEL32.20)
1561 BOOL WINAPI ClearCommBreak(HANDLE handle)
1563 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1564 int fd,result;
1566 fd = COMM_GetWriteFd(handle);
1567 if(fd<0) {
1568 TRACE("COMM_GetWriteFd failed\n");
1569 return FALSE;
1571 result = ioctl(fd,TIOCCBRK,0);
1572 close(fd);
1573 if (result ==-1)
1575 TRACE("ioctl failed\n");
1576 SetLastError(ERROR_NOT_SUPPORTED);
1577 return FALSE;
1579 return TRUE;
1580 #else
1581 FIXME("ioctl not available\n");
1582 SetLastError(ERROR_NOT_SUPPORTED);
1583 return FALSE;
1584 #endif
1587 /*****************************************************************************
1588 * EscapeCommFunction (KERNEL32.214)
1590 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1592 int fd,direct=FALSE,result=FALSE;
1593 struct termios port;
1595 TRACE("handle %d, function=%d\n", handle, nFunction);
1596 fd = COMM_GetWriteFd(handle);
1597 if(fd<0)
1598 return FALSE;
1600 if (tcgetattr(fd,&port) == -1) {
1601 commerror=WinError();
1602 close(fd);
1603 return FALSE;
1606 switch (nFunction) {
1607 case RESETDEV:
1608 TRACE("\n");
1609 break;
1611 case CLRDTR:
1612 TRACE("CLRDTR\n");
1613 #ifdef TIOCM_DTR
1614 direct=TRUE;
1615 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1616 break;
1617 #endif
1619 case CLRRTS:
1620 TRACE("CLRRTS\n");
1621 #ifdef TIOCM_RTS
1622 direct=TRUE;
1623 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1624 break;
1625 #endif
1627 case SETDTR:
1628 TRACE("SETDTR\n");
1629 #ifdef TIOCM_DTR
1630 direct=TRUE;
1631 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1632 break;
1633 #endif
1635 case SETRTS:
1636 TRACE("SETRTS\n");
1637 #ifdef TIOCM_DTR
1638 direct=TRUE;
1639 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1640 break;
1641 #endif
1643 case SETXOFF:
1644 TRACE("SETXOFF\n");
1645 port.c_iflag |= IXOFF;
1646 break;
1648 case SETXON:
1649 TRACE("SETXON\n");
1650 port.c_iflag |= IXON;
1651 break;
1652 case SETBREAK:
1653 TRACE("setbreak\n");
1654 #ifdef TIOCSBRK
1655 direct=TRUE;
1656 result = ioctl(fd,TIOCSBRK,0);
1657 break;
1658 #endif
1659 case CLRBREAK:
1660 TRACE("clrbreak\n");
1661 #ifdef TIOCSBRK
1662 direct=TRUE;
1663 result = ioctl(fd,TIOCCBRK,0);
1664 break;
1665 #endif
1666 default:
1667 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1668 handle, nFunction);
1669 break;
1672 if (!direct)
1673 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1674 commerror = WinError();
1675 close(fd);
1676 return FALSE;
1677 } else
1678 result= TRUE;
1679 else
1681 if (result == -1)
1683 result= FALSE;
1684 commerror=WinError();
1686 else
1687 result = TRUE;
1689 close(fd);
1690 return result;
1693 /********************************************************************
1694 * PurgeComm (KERNEL32.557)
1696 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1698 int fd;
1700 TRACE("handle %d, flags %lx\n", handle, flags);
1702 fd = COMM_GetWriteFd(handle);
1703 if(fd<0)
1704 return FALSE;
1707 ** not exactly sure how these are different
1708 ** Perhaps if we had our own internal queues, one flushes them
1709 ** and the other flushes the kernel's buffers.
1711 if(flags&PURGE_TXABORT)
1713 tcflush(fd,TCOFLUSH);
1715 if(flags&PURGE_RXABORT)
1717 tcflush(fd,TCIFLUSH);
1719 if(flags&PURGE_TXCLEAR)
1721 tcflush(fd,TCOFLUSH);
1723 if(flags&PURGE_RXCLEAR)
1725 tcflush(fd,TCIFLUSH);
1727 close(fd);
1729 return 1;
1732 /*****************************************************************************
1733 * ClearCommError (KERNEL32.21)
1735 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1737 int fd;
1739 fd=COMM_GetReadFd(handle);
1740 if(0>fd)
1742 return FALSE;
1745 if (lpStat)
1747 lpStat->status = 0;
1749 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1750 WARN("ioctl returned error\n");
1752 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1753 WARN("ioctl returned error\n");
1755 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1756 handle, lpStat->cbInQue, lpStat->cbOutQue);
1759 close(fd);
1761 if(errors)
1762 *errors = 0;
1765 ** After an asynchronous write opperation, the
1766 ** app will call ClearCommError to see if the
1767 ** results are ready yet. It waits for ERROR_IO_PENDING
1769 commerror = ERROR_IO_PENDING;
1771 return TRUE;
1774 /*****************************************************************************
1775 * SetupComm (KERNEL32.676)
1777 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1779 int fd;
1781 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1782 fd=COMM_GetWriteFd(handle);
1783 if(0>fd)
1785 return FALSE;
1787 close(fd);
1788 return TRUE;
1791 /*****************************************************************************
1792 * GetCommMask (KERNEL32.156)
1794 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1796 int fd;
1798 TRACE("handle %d, mask %p\n", handle, evtmask);
1799 if(0>(fd=COMM_GetReadFd(handle)))
1801 return FALSE;
1803 close(fd);
1804 *evtmask = eventmask;
1805 TRACE("%s%s%s%s%s%s%s%s%s\n",
1806 (eventmask&EV_BREAK)?"EV_BREAK":"",
1807 (eventmask&EV_CTS)?"EV_CTS":"",
1808 (eventmask&EV_DSR)?"EV_DSR":"",
1809 (eventmask&EV_ERR)?"EV_ERR":"",
1810 (eventmask&EV_RING)?"EV_RING":"",
1811 (eventmask&EV_RLSD)?"EV_RLSD":"",
1812 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1813 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1814 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1816 return TRUE;
1819 /*****************************************************************************
1820 * SetCommMask (KERNEL32.451)
1822 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1824 int fd;
1826 TRACE("handle %d, mask %lx\n", handle, evtmask);
1827 TRACE("%s%s%s%s%s%s%s%s%s\n",
1828 (evtmask&EV_BREAK)?"EV_BREAK":"",
1829 (evtmask&EV_CTS)?"EV_CTS":"",
1830 (evtmask&EV_DSR)?"EV_DSR":"",
1831 (evtmask&EV_ERR)?"EV_ERR":"",
1832 (evtmask&EV_RING)?"EV_RING":"",
1833 (evtmask&EV_RLSD)?"EV_RLSD":"",
1834 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1835 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1836 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1838 if(0>(fd=COMM_GetWriteFd(handle))) {
1839 return FALSE;
1841 close(fd);
1842 eventmask = evtmask;
1843 return TRUE;
1846 /*****************************************************************************
1847 * SetCommState (KERNEL32.452)
1849 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1851 struct termios port;
1852 int fd;
1854 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1855 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1856 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1857 (lpdcb->StopBits == ONESTOPBIT)?1:
1858 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1859 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1860 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1862 if ((fd = COMM_GetWriteFd(handle)) < 0) return FALSE;
1864 if ((tcgetattr(fd,&port)) == -1) {
1865 int save_error = errno;
1866 commerror = WinError();
1867 close( fd );
1868 #ifdef HAVE_STRERROR
1869 ERR("tcgetattr error '%s'\n", strerror(save_error));
1870 #else
1871 ERR("tcgetattr error %d\n", save_error);
1872 #endif
1873 return FALSE;
1876 port.c_cc[VMIN] = 0;
1877 port.c_cc[VTIME] = 1;
1879 #ifdef IMAXBEL
1880 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1881 #else
1882 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1883 #endif
1884 port.c_iflag |= (IGNBRK);
1886 port.c_oflag &= ~(OPOST);
1888 port.c_cflag &= ~(HUPCL);
1889 port.c_cflag |= CLOCAL | CREAD;
1891 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1892 port.c_lflag |= NOFLSH;
1895 ** MJM - removed default baudrate settings
1896 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1898 #ifdef CBAUD
1899 port.c_cflag &= ~CBAUD;
1900 switch (lpdcb->BaudRate) {
1901 case 110:
1902 case CBR_110:
1903 port.c_cflag |= B110;
1904 break;
1905 case 300:
1906 case CBR_300:
1907 port.c_cflag |= B300;
1908 break;
1909 case 600:
1910 case CBR_600:
1911 port.c_cflag |= B600;
1912 break;
1913 case 1200:
1914 case CBR_1200:
1915 port.c_cflag |= B1200;
1916 break;
1917 case 2400:
1918 case CBR_2400:
1919 port.c_cflag |= B2400;
1920 break;
1921 case 4800:
1922 case CBR_4800:
1923 port.c_cflag |= B4800;
1924 break;
1925 case 9600:
1926 case CBR_9600:
1927 port.c_cflag |= B9600;
1928 break;
1929 case 19200:
1930 case CBR_19200:
1931 port.c_cflag |= B19200;
1932 break;
1933 case 38400:
1934 case CBR_38400:
1935 port.c_cflag |= B38400;
1936 break;
1937 #ifdef B57600
1938 case 57600:
1939 port.c_cflag |= B57600;
1940 break;
1941 #endif
1942 #ifdef B115200
1943 case 115200:
1944 port.c_cflag |= B115200;
1945 break;
1946 #endif
1947 #ifdef B230400
1948 case 230400:
1949 port.c_cflag |= B230400;
1950 break;
1951 #endif
1952 #ifdef B460800
1953 case 460600:
1954 port.c_cflag |= B460800;
1955 break;
1956 #endif
1957 default:
1958 commerror = IE_BAUDRATE;
1959 close( fd );
1960 ERR("baudrate %ld\n",lpdcb->BaudRate);
1961 return FALSE;
1963 #elif !defined(__EMX__)
1964 switch (lpdcb->BaudRate) {
1965 case 110:
1966 case CBR_110:
1967 port.c_ospeed = B110;
1968 break;
1969 case 300:
1970 case CBR_300:
1971 port.c_ospeed = B300;
1972 break;
1973 case 600:
1974 case CBR_600:
1975 port.c_ospeed = B600;
1976 break;
1977 case 1200:
1978 case CBR_1200:
1979 port.c_ospeed = B1200;
1980 break;
1981 case 2400:
1982 case CBR_2400:
1983 port.c_ospeed = B2400;
1984 break;
1985 case 4800:
1986 case CBR_4800:
1987 port.c_ospeed = B4800;
1988 break;
1989 case 9600:
1990 case CBR_9600:
1991 port.c_ospeed = B9600;
1992 break;
1993 case 19200:
1994 case CBR_19200:
1995 port.c_ospeed = B19200;
1996 break;
1997 case 38400:
1998 case CBR_38400:
1999 port.c_ospeed = B38400;
2000 break;
2001 default:
2002 commerror = IE_BAUDRATE;
2003 close( fd );
2004 ERR("baudrate %d \n",lpdcb->BaudRate);
2005 return FALSE;
2007 port.c_ispeed = port.c_ospeed;
2008 #endif
2009 port.c_cflag &= ~CSIZE;
2010 switch (lpdcb->ByteSize) {
2011 case 5:
2012 port.c_cflag |= CS5;
2013 break;
2014 case 6:
2015 port.c_cflag |= CS6;
2016 break;
2017 case 7:
2018 port.c_cflag |= CS7;
2019 break;
2020 case 8:
2021 port.c_cflag |= CS8;
2022 break;
2023 default:
2024 commerror = IE_BYTESIZE;
2025 close( fd );
2026 ERR("ByteSize\n");
2027 return FALSE;
2030 port.c_cflag &= ~(PARENB | PARODD);
2031 if (lpdcb->fParity)
2032 port.c_iflag |= INPCK;
2033 else
2034 port.c_iflag &= ~INPCK;
2035 switch (lpdcb->Parity) {
2036 case NOPARITY:
2037 break;
2038 case ODDPARITY:
2039 port.c_cflag |= (PARENB | PARODD);
2040 break;
2041 case EVENPARITY:
2042 port.c_cflag |= PARENB;
2043 break;
2044 default:
2045 commerror = IE_BYTESIZE;
2046 close( fd );
2047 ERR("Parity\n");
2048 return FALSE;
2052 switch (lpdcb->StopBits) {
2053 case ONESTOPBIT:
2054 port.c_cflag &= ~CSTOPB;
2055 break;
2056 case TWOSTOPBITS:
2057 port.c_cflag |= CSTOPB;
2058 break;
2059 default:
2060 commerror = IE_BYTESIZE;
2061 close( fd );
2062 ERR("StopBits\n");
2063 return FALSE;
2065 #ifdef CRTSCTS
2066 if ( lpdcb->fOutxCtsFlow ||
2067 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2068 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2071 port.c_cflag |= CRTSCTS;
2072 TRACE("CRTSCTS\n");
2075 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2077 port.c_cflag &= ~CRTSCTS;
2078 TRACE("~CRTSCTS\n");
2081 #endif
2082 if (lpdcb->fInX)
2083 port.c_iflag |= IXON;
2084 else
2085 port.c_iflag &= ~IXON;
2086 if (lpdcb->fOutX)
2087 port.c_iflag |= IXOFF;
2088 else
2089 port.c_iflag &= ~IXOFF;
2091 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2092 int save_error=errno;
2093 commerror = WinError();
2094 close( fd );
2095 #ifdef HAVE_STRERROR
2096 ERR("tcgetattr error '%s'\n", strerror(save_error));
2097 #else
2098 ERR("tcgetattr error %d\n", save_error);
2099 #endif
2100 return FALSE;
2101 } else {
2102 commerror = 0;
2103 close( fd );
2104 return TRUE;
2109 /*****************************************************************************
2110 * GetCommState (KERNEL32.159)
2112 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2114 struct termios port;
2115 int fd,speed;
2117 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2119 if ((fd = COMM_GetReadFd(handle)) < 0)
2121 ERR("can't get COMM_GetReadFd\n");
2122 return FALSE;
2124 if (tcgetattr(fd, &port) == -1) {
2125 int save_error=errno;
2126 #ifdef HAVE_STRERROR
2127 ERR("tcgetattr error '%s'\n", strerror(save_error));
2128 #else
2129 ERR("tcgetattr error %d\n", save_error);
2130 #endif
2131 commerror = WinError();
2132 close( fd );
2133 return FALSE;
2135 close( fd );
2136 #ifndef __EMX__
2137 #ifdef CBAUD
2138 speed= (port.c_cflag & CBAUD);
2139 #else
2140 speed= (cfgetospeed(&port));
2141 #endif
2142 switch (speed) {
2143 case B110:
2144 lpdcb->BaudRate = 110;
2145 break;
2146 case B300:
2147 lpdcb->BaudRate = 300;
2148 break;
2149 case B600:
2150 lpdcb->BaudRate = 600;
2151 break;
2152 case B1200:
2153 lpdcb->BaudRate = 1200;
2154 break;
2155 case B2400:
2156 lpdcb->BaudRate = 2400;
2157 break;
2158 case B4800:
2159 lpdcb->BaudRate = 4800;
2160 break;
2161 case B9600:
2162 lpdcb->BaudRate = 9600;
2163 break;
2164 case B19200:
2165 lpdcb->BaudRate = 19200;
2166 break;
2167 case B38400:
2168 lpdcb->BaudRate = 38400;
2169 break;
2170 #ifdef B57600
2171 case B57600:
2172 lpdcb->BaudRate = 57600;
2173 break;
2174 #endif
2175 #ifdef B115200
2176 case B115200:
2177 lpdcb->BaudRate = 115200;
2178 break;
2179 #endif
2180 #ifdef B230400
2181 case B230400:
2182 lpdcb->BaudRate = 230400;
2183 break;
2184 #endif
2185 #ifdef B460800
2186 case B460800:
2187 lpdcb->BaudRate = 460800;
2188 break;
2189 #endif
2190 default:
2191 ERR("unknown speed %x \n",speed);
2193 #endif
2194 switch (port.c_cflag & CSIZE) {
2195 case CS5:
2196 lpdcb->ByteSize = 5;
2197 break;
2198 case CS6:
2199 lpdcb->ByteSize = 6;
2200 break;
2201 case CS7:
2202 lpdcb->ByteSize = 7;
2203 break;
2204 case CS8:
2205 lpdcb->ByteSize = 8;
2206 break;
2207 default:
2208 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2211 if(port.c_iflag & INPCK)
2212 lpdcb->fParity = TRUE;
2213 else
2214 lpdcb->fParity = FALSE;
2215 switch (port.c_cflag & (PARENB | PARODD)) {
2216 case 0:
2217 lpdcb->Parity = NOPARITY;
2218 break;
2219 case PARENB:
2220 lpdcb->Parity = EVENPARITY;
2221 break;
2222 case (PARENB | PARODD):
2223 lpdcb->Parity = ODDPARITY;
2224 break;
2227 if (port.c_cflag & CSTOPB)
2228 lpdcb->StopBits = TWOSTOPBITS;
2229 else
2230 lpdcb->StopBits = ONESTOPBIT;
2232 lpdcb->fNull = 0;
2233 lpdcb->fBinary = 1;
2235 #ifdef CRTSCTS
2237 if (port.c_cflag & CRTSCTS) {
2238 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2239 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2240 lpdcb->fOutxCtsFlow = 1;
2241 lpdcb->fOutxDsrFlow = 1;
2242 } else
2243 #endif
2245 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2246 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2248 if (port.c_iflag & IXON)
2249 lpdcb->fInX = 1;
2250 else
2251 lpdcb->fInX = 0;
2253 if (port.c_iflag & IXOFF)
2254 lpdcb->fOutX = 1;
2255 else
2256 lpdcb->fOutX = 0;
2258 lpdcb->XonChar =
2259 lpdcb->XoffChar =
2261 lpdcb->XonLim = 10;
2262 lpdcb->XoffLim = 10;
2264 commerror = 0;
2266 TRACE("OK\n");
2268 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2269 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2270 (lpdcb->StopBits == ONESTOPBIT)?1:
2271 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2272 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2273 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2274 #ifdef CRTSCTS
2275 if ( lpdcb->fOutxCtsFlow ||
2276 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2277 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2279 TRACE("CRTSCTS\n");
2281 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2282 TRACE("~CRTSCTS\n");
2284 #endif
2285 return TRUE;
2288 /*****************************************************************************
2289 * TransmitCommChar (KERNEL32.535)
2291 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2293 struct DosDeviceStruct *ptr;
2295 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2296 if ((ptr = GetDeviceStruct(cid)) == NULL) {
2297 return FALSE;
2300 if (ptr->suspended) {
2301 ptr->commerror = IE_HARDWARE;
2302 return FALSE;
2304 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2305 ptr->commerror = WinError();
2306 return FALSE;
2307 } else {
2308 ptr->commerror = 0;
2309 return TRUE;
2313 /*****************************************************************************
2314 * GetCommTimeouts (KERNEL32.160)
2316 BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
2318 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2319 return TRUE;
2322 /*****************************************************************************
2323 * SetCommTimeouts (KERNEL32.453)
2325 BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
2326 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2327 TRACE("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2328 TRACE("ReadTotalTimeoutMultiplier %ld\n",
2329 lptimeouts->ReadTotalTimeoutMultiplier);
2330 TRACE("ReadTotalTimeoutConstant %ld\n",
2331 lptimeouts->ReadTotalTimeoutConstant);
2332 TRACE("WriteTotalTimeoutMultiplier %ld\n",
2333 lptimeouts->WriteTotalTimeoutMultiplier);
2334 TRACE("WriteTotalTimeoutConstant %ld\n",
2335 lptimeouts->WriteTotalTimeoutConstant);
2336 return TRUE;
2339 /***********************************************************************
2340 * GetCommModemStatus (KERNEL32.285)
2342 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2344 int fd,mstat, result=FALSE;
2346 *lpModemStat=0;
2347 #ifdef TIOCMGET
2348 fd = COMM_GetWriteFd(hFile);
2349 if(fd<0)
2350 return FALSE;
2351 result = ioctl(fd, TIOCMGET, &mstat);
2352 close(fd);
2353 if (result == -1)
2355 TRACE("ioctl failed\n");
2356 return FALSE;
2358 if (mstat & TIOCM_CTS)
2359 *lpModemStat |= MS_CTS_ON;
2360 if (mstat & TIOCM_DSR)
2361 *lpModemStat |= MS_DSR_ON;
2362 if (mstat & TIOCM_RNG)
2363 *lpModemStat |= MS_RING_ON;
2364 /*FIXME: Not really sure about RLSD UB 990810*/
2365 if (mstat & TIOCM_CAR)
2366 *lpModemStat |= MS_RLSD_ON;
2367 TRACE("%s%s%s%s\n",
2368 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2369 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2370 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2371 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2372 return TRUE;
2373 #else
2374 return FALSE;
2375 #endif
2377 /***********************************************************************
2378 * WaitCommEvent (KERNEL32.719)
2380 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2382 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2383 return TRUE;
2386 /***********************************************************************
2387 * GetCommProperties (KERNEL32.???)
2389 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2391 FIXME("(%d %p )\n",hFile,dcb);
2392 return TRUE;
2395 /***********************************************************************
2396 * SetCommProperties (KERNEL32.???)
2398 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2400 FIXME("(%d %p )\n",hFile,dcb);
2401 return TRUE;