Made GetSystemTimeAsFileTime return value more precise.
[wine/multimedia.git] / misc / comm.c
blob30fa5545d204e2491379351280027833122a72f7
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) {
276 if (ptr->s_write) {
277 SERVICE_Delete( ptr->s_write );
278 ptr->s_write = INVALID_HANDLE_VALUE;
280 if (ptr->eventmask & EV_TXEMPTY) {
281 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
282 mask |= CN_EVENT;
286 } while (len > 0);
287 /* check for notification */
288 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
289 (comm_outbuf(ptr)<ptr->n_write)) {
290 /* passed the transmit notification threshold */
291 mask |= CN_TRANSMIT;
294 /* send notifications, if any */
295 if (ptr->wnd && mask) {
296 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
297 PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
301 static void comm_waitread(struct DosDeviceStruct *ptr)
303 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
304 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
305 GENERIC_READ | SYNCHRONIZE ),
306 comm_notification,
307 (ULONG_PTR)ptr );
310 static void comm_waitwrite(struct DosDeviceStruct *ptr)
312 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
313 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
314 GENERIC_WRITE | SYNCHRONIZE ),
315 comm_notification,
316 (ULONG_PTR)ptr );
319 /**************************************************************************
320 * BuildCommDCB (USER.213)
322 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
324 /* "COM1:9600,n,8,1" */
325 /* 012345 */
326 int port;
327 char *ptr, temp[256];
329 TRACE("(%s), ptr %p\n", device, lpdcb);
331 if (!lstrncmpiA(device,"COM",3)) {
332 port = device[3] - '0';
335 if (port-- == 0) {
336 ERR("BUG ! COM0 can't exist!.\n");
337 return -1;
340 if (!ValidCOMPort(port)) {
341 return -1;
344 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
346 lpdcb->Id = port;
348 if (!*(device+4))
349 return 0;
351 if (*(device+4) != ':')
352 return -1;
354 strcpy(temp,device+5);
355 ptr = strtok(temp, ", ");
357 if (COM[port].baudrate > 0)
358 lpdcb->BaudRate = COM[port].baudrate;
359 else
360 lpdcb->BaudRate = atoi(ptr);
361 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
363 ptr = strtok(NULL, ", ");
364 if (islower(*ptr))
365 *ptr = toupper(*ptr);
367 TRACE("parity (%c)\n", *ptr);
368 lpdcb->fParity = TRUE;
369 switch (*ptr) {
370 case 'N':
371 lpdcb->Parity = NOPARITY;
372 lpdcb->fParity = FALSE;
373 break;
374 case 'E':
375 lpdcb->Parity = EVENPARITY;
376 break;
377 case 'M':
378 lpdcb->Parity = MARKPARITY;
379 break;
380 case 'O':
381 lpdcb->Parity = ODDPARITY;
382 break;
383 default:
384 WARN("Unknown parity `%c'!\n", *ptr);
385 return -1;
388 ptr = strtok(NULL, ", ");
389 TRACE("charsize (%c)\n", *ptr);
390 lpdcb->ByteSize = *ptr - '0';
392 ptr = strtok(NULL, ", ");
393 TRACE("stopbits (%c)\n", *ptr);
394 switch (*ptr) {
395 case '1':
396 lpdcb->StopBits = ONESTOPBIT;
397 break;
398 case '2':
399 lpdcb->StopBits = TWOSTOPBITS;
400 break;
401 default:
402 WARN("Unknown # of stopbits `%c'!\n", *ptr);
403 return -1;
407 return 0;
410 /*****************************************************************************
411 * OpenComm (USER.200)
413 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
415 int port,fd;
417 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
419 if (strlen(device) < 4)
420 return IE_BADID;
422 port = device[3] - '0';
424 if (port-- == 0)
425 ERR("BUG ! COM0 or LPT0 don't exist !\n");
427 if (!lstrncmpiA(device,"COM",3)) {
429 TRACE("%s = %s\n", device, COM[port].devicename);
431 if (!ValidCOMPort(port))
432 return IE_BADID;
434 if (COM[port].fd)
435 return IE_OPEN;
437 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
438 if (fd == -1) {
439 ERR("error=%d\n", errno);
440 return IE_HARDWARE;
441 } else {
442 unknown[port] = SEGPTR_ALLOC(40);
443 bzero(unknown[port],40);
444 COM[port].fd = fd;
445 COM[port].commerror = 0;
446 COM[port].eventmask = 0;
447 COM[port].evtchar = 0; /* FIXME: default? */
448 /* save terminal state */
449 tcgetattr(fd,&m_stat[port]);
450 /* set default parameters */
451 if(COM[port].baudrate>-1){
452 DCB16 dcb;
453 GetCommState16(port, &dcb);
454 dcb.BaudRate=COM[port].baudrate;
455 /* more defaults:
456 * databits, parity, stopbits
458 SetCommState16( &dcb);
460 /* init priority characters */
461 COM[port].unget = -1;
462 COM[port].xmit = -1;
463 /* allocate buffers */
464 COM[port].ibuf_size = cbInQueue;
465 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
466 COM[port].obuf_size = cbOutQueue;
467 COM[port].obuf_head = COM[port].obuf_tail = 0;
469 COM[port].inbuf = malloc(cbInQueue);
470 if (COM[port].inbuf) {
471 COM[port].outbuf = malloc(cbOutQueue);
472 if (!COM[port].outbuf)
473 free(COM[port].inbuf);
474 } else COM[port].outbuf = NULL;
475 if (!COM[port].outbuf) {
476 /* not enough memory */
477 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
478 close(COM[port].fd);
479 ERR("out of memory");
480 return IE_MEMORY;
483 COM[port].s_read = INVALID_HANDLE_VALUE;
484 COM[port].s_write = INVALID_HANDLE_VALUE;
485 comm_waitread( &COM[port] );
486 return port;
489 else
490 if (!lstrncmpiA(device,"LPT",3)) {
492 if (!ValidLPTPort(port))
493 return IE_BADID;
495 if (LPT[port].fd)
496 return IE_OPEN;
498 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
499 if (fd == -1) {
500 return IE_HARDWARE;
501 } else {
502 LPT[port].fd = fd;
503 LPT[port].commerror = 0;
504 LPT[port].eventmask = 0;
505 return port|FLAG_LPT;
508 return 0;
511 /*****************************************************************************
512 * CloseComm (USER.207)
514 INT16 WINAPI CloseComm16(INT16 cid)
516 struct DosDeviceStruct *ptr;
518 TRACE("cid=%d\n", cid);
519 if ((ptr = GetDeviceStruct(cid)) == NULL) {
520 return -1;
522 if (!(cid&FLAG_LPT)) {
523 /* COM port */
524 SEGPTR_FREE(unknown[cid]); /* [LW] */
526 SERVICE_Delete( COM[cid].s_write );
527 SERVICE_Delete( COM[cid].s_read );
528 /* free buffers */
529 free(ptr->outbuf);
530 free(ptr->inbuf);
532 /* reset modem lines */
533 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
536 if (close(ptr->fd) == -1) {
537 ptr->commerror = WinError();
538 /* FIXME: should we clear ptr->fd here? */
539 return -1;
540 } else {
541 ptr->commerror = 0;
542 ptr->fd = 0;
543 return 0;
547 /*****************************************************************************
548 * SetCommBreak (USER.210)
550 INT16 WINAPI SetCommBreak16(INT16 cid)
552 struct DosDeviceStruct *ptr;
554 TRACE("cid=%d\n", cid);
555 if ((ptr = GetDeviceStruct(cid)) == NULL) {
556 return -1;
559 ptr->suspended = 1;
560 ptr->commerror = 0;
561 return 0;
564 /*****************************************************************************
565 * ClearCommBreak (USER.211)
567 INT16 WINAPI ClearCommBreak16(INT16 cid)
569 struct DosDeviceStruct *ptr;
571 TRACE("cid=%d\n", cid);
572 if ((ptr = GetDeviceStruct(cid)) == NULL) {
573 return -1;
576 ptr->suspended = 0;
577 ptr->commerror = 0;
578 return 0;
581 /*****************************************************************************
582 * EscapeCommFunction (USER.214)
584 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
586 int max;
587 struct DosDeviceStruct *ptr;
588 struct termios port;
590 TRACE("cid=%d, function=%d\n", cid, nFunction);
591 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
592 if ((ptr = GetDeviceStruct(cid)) == NULL) {
593 TRACE("GetDeviceStruct failed\n");
594 return -1;
596 if (tcgetattr(ptr->fd,&port) == -1) {
597 TRACE("tcgetattr failed\n");
598 ptr->commerror=WinError();
599 return -1;
601 } else ptr = NULL;
603 switch (nFunction) {
604 case RESETDEV:
605 TRACE("RESETDEV\n");
606 break;
608 case GETMAXCOM:
609 TRACE("GETMAXCOM\n");
610 for (max = MAX_PORTS;!COM[max].devicename;max--)
612 return max;
613 break;
615 case GETMAXLPT:
616 TRACE("GETMAXLPT\n");
617 for (max = MAX_PORTS;!LPT[max].devicename;max--)
619 return FLAG_LPT + max;
620 break;
622 case GETBASEIRQ:
623 TRACE("GETBASEIRQ\n");
624 /* FIXME: use tables */
625 /* just fake something for now */
626 if (cid & FLAG_LPT) {
627 /* LPT1: irq 7, LPT2: irq 5 */
628 return (cid & 0x7f) ? 5 : 7;
629 } else {
630 /* COM1: irq 4, COM2: irq 3,
631 COM3: irq 4, COM4: irq 3 */
632 return 4 - (cid & 1);
634 break;
636 case CLRDTR:
637 TRACE("CLRDTR\n");
638 #ifdef TIOCM_DTR
639 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
640 #endif
641 case CLRRTS:
642 TRACE("CLRRTS\n");
643 #ifdef TIOCM_RTS
644 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
645 #endif
647 case SETDTR:
648 TRACE("SETDTR\n");
649 #ifdef TIOCM_DTR
650 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
651 #endif
653 case SETRTS:
654 TRACE("SETRTS\n");
655 #ifdef TIOCM_RTS
656 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
657 #endif
659 case SETXOFF:
660 TRACE("SETXOFF\n");
661 port.c_iflag |= IXOFF;
662 break;
664 case SETXON:
665 TRACE("SETXON\n");
666 port.c_iflag |= IXON;
667 break;
669 default:
670 WARN("(cid=%d,nFunction=%d): Unknown function\n",
671 cid, nFunction);
672 break;
675 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
676 ptr->commerror = WinError();
677 return -1;
678 } else {
679 ptr->commerror = 0;
680 return 0;
684 /*****************************************************************************
685 * FlushComm (USER.215)
687 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
689 int queue;
690 struct DosDeviceStruct *ptr;
692 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
693 if ((ptr = GetDeviceStruct(cid)) == NULL) {
694 return -1;
696 switch (fnQueue) {
697 case 0:
698 queue = TCOFLUSH;
699 ptr->obuf_tail = ptr->obuf_head;
700 break;
701 case 1:
702 queue = TCIFLUSH;
703 ptr->ibuf_head = ptr->ibuf_tail;
704 break;
705 default:
706 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
707 cid, fnQueue);
708 return -1;
710 if (tcflush(ptr->fd, queue)) {
711 ptr->commerror = WinError();
712 return -1;
713 } else {
714 ptr->commerror = 0;
715 return 0;
719 /********************************************************************
720 * GetCommError (USER.203)
722 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
724 int temperror;
725 struct DosDeviceStruct *ptr;
726 unsigned char *stol;
727 unsigned int mstat;
729 if ((ptr = GetDeviceStruct(cid)) == NULL) {
730 return -1;
732 if (cid&FLAG_LPT) {
733 WARN(" cid %d not comm port\n",cid);
734 return CE_MODE;
736 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
737 ioctl(ptr->fd,TIOCMGET,&mstat);
738 if( mstat&TIOCM_CAR )
739 *stol |= 0x80;
740 else
741 *stol &=0x7f;
743 if (lpStat) {
744 lpStat->status = 0;
746 lpStat->cbOutQue = comm_outbuf(ptr);
747 lpStat->cbInQue = comm_inbuf(ptr);
749 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
750 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
751 lpStat->cbOutQue, *stol);
753 else
754 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
755 cid, ptr->commerror, *stol);
757 /* Return any errors and clear it */
758 temperror = ptr->commerror;
759 ptr->commerror = 0;
760 return(temperror);
763 /*****************************************************************************
764 * SetCommEventMask (USER.208)
766 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
768 struct DosDeviceStruct *ptr;
769 unsigned char *stol;
770 int repid;
771 unsigned int mstat;
773 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
774 if ((ptr = GetDeviceStruct(cid)) == NULL)
775 return (SEGPTR)NULL;
777 ptr->eventmask = fuEvtMask;
779 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
780 WARN(" cid %d not comm port\n",cid);
781 return (SEGPTR)NULL;
783 /* it's a COM port ? -> modify flags */
784 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
785 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
786 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
787 if ((mstat&TIOCM_CAR))
788 *stol |= 0x80;
789 else
790 *stol &=0x7f;
792 TRACE(" modem dcd construct %x\n",*stol);
793 return SEGPTR_GET(unknown[cid]);
796 /*****************************************************************************
797 * GetCommEventMask (USER.209)
799 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
801 struct DosDeviceStruct *ptr;
802 WORD events;
804 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
805 if ((ptr = GetDeviceStruct(cid)) == NULL)
806 return 0;
808 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
809 WARN(" cid %d not comm port\n",cid);
810 return 0;
813 events = *(WORD*)(unknown[cid]) & fnEvtClear;
814 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
815 return events;
818 /*****************************************************************************
819 * SetCommState16 (USER.201)
821 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
823 struct termios port;
824 struct DosDeviceStruct *ptr;
826 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
827 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
828 return -1;
830 if (tcgetattr(ptr->fd, &port) == -1) {
831 ptr->commerror = WinError();
832 return -1;
835 port.c_cc[VMIN] = 0;
836 port.c_cc[VTIME] = 1;
838 #ifdef IMAXBEL
839 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
840 #else
841 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
842 #endif
843 port.c_iflag |= (IGNBRK);
845 port.c_oflag &= ~(OPOST);
847 port.c_cflag &= ~(HUPCL);
848 port.c_cflag |= CLOCAL | CREAD;
850 port.c_lflag &= ~(ICANON|ECHO|ISIG);
851 port.c_lflag |= NOFLSH;
853 TRACE("baudrate %d\n",lpdcb->BaudRate);
854 #ifdef CBAUD
855 port.c_cflag &= ~CBAUD;
856 switch (lpdcb->BaudRate) {
857 case 110:
858 case CBR_110:
859 port.c_cflag |= B110;
860 break;
861 case 300:
862 case CBR_300:
863 port.c_cflag |= B300;
864 break;
865 case 600:
866 case CBR_600:
867 port.c_cflag |= B600;
868 break;
869 case 1200:
870 case CBR_1200:
871 port.c_cflag |= B1200;
872 break;
873 case 2400:
874 case CBR_2400:
875 port.c_cflag |= B2400;
876 break;
877 case 4800:
878 case CBR_4800:
879 port.c_cflag |= B4800;
880 break;
881 case 9600:
882 case CBR_9600:
883 port.c_cflag |= B9600;
884 break;
885 case 19200:
886 case CBR_19200:
887 port.c_cflag |= B19200;
888 break;
889 case 38400:
890 case CBR_38400:
891 port.c_cflag |= B38400;
892 break;
893 #ifdef B57600
894 case 57600:
895 port.c_cflag |= B57600;
896 break;
897 #endif
898 #ifdef B115200
899 case 57601:
900 port.c_cflag |= B115200;
901 break;
902 #endif
903 default:
904 ptr->commerror = IE_BAUDRATE;
905 return -1;
907 #elif !defined(__EMX__)
908 switch (lpdcb->BaudRate) {
909 case 110:
910 case CBR_110:
911 port.c_ospeed = B110;
912 break;
913 case 300:
914 case CBR_300:
915 port.c_ospeed = B300;
916 break;
917 case 600:
918 case CBR_600:
919 port.c_ospeed = B600;
920 break;
921 case 1200:
922 case CBR_1200:
923 port.c_ospeed = B1200;
924 break;
925 case 2400:
926 case CBR_2400:
927 port.c_ospeed = B2400;
928 break;
929 case 4800:
930 case CBR_4800:
931 port.c_ospeed = B4800;
932 break;
933 case 9600:
934 case CBR_9600:
935 port.c_ospeed = B9600;
936 break;
937 case 19200:
938 case CBR_19200:
939 port.c_ospeed = B19200;
940 break;
941 case 38400:
942 case CBR_38400:
943 port.c_ospeed = B38400;
944 break;
945 default:
946 ptr->commerror = IE_BAUDRATE;
947 return -1;
949 port.c_ispeed = port.c_ospeed;
950 #endif
951 TRACE("bytesize %d\n",lpdcb->ByteSize);
952 port.c_cflag &= ~CSIZE;
953 switch (lpdcb->ByteSize) {
954 case 5:
955 port.c_cflag |= CS5;
956 break;
957 case 6:
958 port.c_cflag |= CS6;
959 break;
960 case 7:
961 port.c_cflag |= CS7;
962 break;
963 case 8:
964 port.c_cflag |= CS8;
965 break;
966 default:
967 ptr->commerror = IE_BYTESIZE;
968 return -1;
971 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
972 port.c_cflag &= ~(PARENB | PARODD);
973 if (lpdcb->fParity)
974 port.c_iflag |= INPCK;
975 else
976 port.c_iflag &= ~INPCK;
977 switch (lpdcb->Parity) {
978 case NOPARITY:
979 break;
980 case ODDPARITY:
981 port.c_cflag |= (PARENB | PARODD);
982 break;
983 case EVENPARITY:
984 port.c_cflag |= PARENB;
985 break;
986 default:
987 ptr->commerror = IE_BYTESIZE;
988 return -1;
992 TRACE("stopbits %d\n",lpdcb->StopBits);
994 switch (lpdcb->StopBits) {
995 case ONESTOPBIT:
996 port.c_cflag &= ~CSTOPB;
997 break;
998 case TWOSTOPBITS:
999 port.c_cflag |= CSTOPB;
1000 break;
1001 default:
1002 ptr->commerror = IE_BYTESIZE;
1003 return -1;
1005 #ifdef CRTSCTS
1007 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1008 port.c_cflag |= CRTSCTS;
1010 if (lpdcb->fDtrDisable)
1011 port.c_cflag &= ~CRTSCTS;
1012 #endif
1013 if (lpdcb->fInX)
1014 port.c_iflag |= IXON;
1015 else
1016 port.c_iflag &= ~IXON;
1017 if (lpdcb->fOutX)
1018 port.c_iflag |= IXOFF;
1019 else
1020 port.c_iflag &= ~IXOFF;
1022 ptr->evtchar = lpdcb->EvtChar;
1024 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1025 ptr->commerror = WinError();
1026 return FALSE;
1027 } else {
1028 ptr->commerror = 0;
1029 return 0;
1033 /*****************************************************************************
1034 * GetCommState (USER.202)
1036 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1038 int speed;
1039 struct DosDeviceStruct *ptr;
1040 struct termios port;
1042 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1043 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1044 return -1;
1046 if (tcgetattr(ptr->fd, &port) == -1) {
1047 ptr->commerror = WinError();
1048 return -1;
1050 lpdcb->Id = cid;
1051 #ifndef __EMX__
1052 #ifdef CBAUD
1053 speed = port.c_cflag & CBAUD;
1054 #else
1055 speed = port.c_ospeed;
1056 #endif
1057 switch(speed) {
1058 case B110:
1059 lpdcb->BaudRate = 110;
1060 break;
1061 case B300:
1062 lpdcb->BaudRate = 300;
1063 break;
1064 case B600:
1065 lpdcb->BaudRate = 600;
1066 break;
1067 case B1200:
1068 lpdcb->BaudRate = 1200;
1069 break;
1070 case B2400:
1071 lpdcb->BaudRate = 2400;
1072 break;
1073 case B4800:
1074 lpdcb->BaudRate = 4800;
1075 break;
1076 case B9600:
1077 lpdcb->BaudRate = 9600;
1078 break;
1079 case B19200:
1080 lpdcb->BaudRate = 19200;
1081 break;
1082 case B38400:
1083 lpdcb->BaudRate = 38400;
1084 break;
1085 #ifdef B57600
1086 case B57600:
1087 lpdcb->BaudRate = 57600;
1088 break;
1089 #endif
1090 #ifdef B115200
1091 case B115200:
1092 lpdcb->BaudRate = 57601;
1093 break;
1094 #endif
1096 #endif
1097 switch (port.c_cflag & CSIZE) {
1098 case CS5:
1099 lpdcb->ByteSize = 5;
1100 break;
1101 case CS6:
1102 lpdcb->ByteSize = 6;
1103 break;
1104 case CS7:
1105 lpdcb->ByteSize = 7;
1106 break;
1107 case CS8:
1108 lpdcb->ByteSize = 8;
1109 break;
1112 if(port.c_iflag & INPCK)
1113 lpdcb->fParity = TRUE;
1114 else
1115 lpdcb->fParity = FALSE;
1116 switch (port.c_cflag & (PARENB | PARODD)) {
1117 case 0:
1118 lpdcb->Parity = NOPARITY;
1119 break;
1120 case PARENB:
1121 lpdcb->Parity = EVENPARITY;
1122 break;
1123 case (PARENB | PARODD):
1124 lpdcb->Parity = ODDPARITY;
1125 break;
1128 if (port.c_cflag & CSTOPB)
1129 lpdcb->StopBits = TWOSTOPBITS;
1130 else
1131 lpdcb->StopBits = ONESTOPBIT;
1133 lpdcb->RlsTimeout = 50;
1134 lpdcb->CtsTimeout = 50;
1135 lpdcb->DsrTimeout = 50;
1136 lpdcb->fNull = 0;
1137 lpdcb->fChEvt = 0;
1138 lpdcb->fBinary = 1;
1139 lpdcb->fDtrDisable = 0;
1141 #ifdef CRTSCTS
1143 if (port.c_cflag & CRTSCTS) {
1144 lpdcb->fDtrflow = 1;
1145 lpdcb->fRtsflow = 1;
1146 lpdcb->fOutxCtsFlow = 1;
1147 lpdcb->fOutxDsrFlow = 1;
1148 } else
1149 #endif
1150 lpdcb->fDtrDisable = 1;
1152 if (port.c_iflag & IXON)
1153 lpdcb->fInX = 1;
1154 else
1155 lpdcb->fInX = 0;
1157 if (port.c_iflag & IXOFF)
1158 lpdcb->fOutX = 1;
1159 else
1160 lpdcb->fOutX = 0;
1162 lpdcb->XonChar =
1163 lpdcb->XoffChar =
1165 lpdcb->XonLim = 10;
1166 lpdcb->XoffLim = 10;
1168 lpdcb->EvtChar = ptr->evtchar;
1170 ptr->commerror = 0;
1171 return 0;
1174 /*****************************************************************************
1175 * TransmitCommChar (USER.206)
1177 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1179 struct DosDeviceStruct *ptr;
1181 TRACE("cid %d, data %d \n", cid, chTransmit);
1182 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1183 return -1;
1186 if (ptr->suspended) {
1187 ptr->commerror = IE_HARDWARE;
1188 return -1;
1191 if (ptr->xmit >= 0) {
1192 /* character already queued */
1193 /* FIXME: which error would Windows return? */
1194 ptr->commerror = CE_TXFULL;
1195 return -1;
1198 if (ptr->obuf_head == ptr->obuf_tail) {
1199 /* transmit queue empty, try to transmit directly */
1200 if (write(ptr->fd, &chTransmit, 1) == -1) {
1201 /* didn't work, queue it */
1202 ptr->xmit = chTransmit;
1203 comm_waitwrite(ptr);
1205 } else {
1206 /* data in queue, let this char be transmitted next */
1207 ptr->xmit = chTransmit;
1208 comm_waitwrite(ptr);
1211 ptr->commerror = 0;
1212 return 0;
1215 /*****************************************************************************
1216 * UngetCommChar (USER.212)
1218 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1220 struct DosDeviceStruct *ptr;
1222 TRACE("cid %d (char %d)\n", cid, chUnget);
1223 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1224 return -1;
1227 if (ptr->suspended) {
1228 ptr->commerror = IE_HARDWARE;
1229 return -1;
1232 if (ptr->unget>=0) {
1233 /* character already queued */
1234 /* FIXME: which error would Windows return? */
1235 ptr->commerror = CE_RXOVER;
1236 return -1;
1239 ptr->unget = chUnget;
1241 ptr->commerror = 0;
1242 return 0;
1245 /*****************************************************************************
1246 * ReadComm (USER.204)
1248 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1250 int status, length;
1251 struct DosDeviceStruct *ptr;
1252 LPSTR orgBuf = lpvBuf;
1254 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1255 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1256 return -1;
1259 if (ptr->suspended) {
1260 ptr->commerror = IE_HARDWARE;
1261 return -1;
1264 /* read unget character */
1265 if (ptr->unget>=0) {
1266 *lpvBuf++ = ptr->unget;
1267 ptr->unget = -1;
1269 length = 1;
1270 } else
1271 length = 0;
1273 /* read from receive buffer */
1274 while (length < cbRead) {
1275 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1276 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1277 if (!status) break;
1278 if ((cbRead - length) < status)
1279 status = cbRead - length;
1281 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1282 ptr->ibuf_tail += status;
1283 if (ptr->ibuf_tail >= ptr->ibuf_size)
1284 ptr->ibuf_tail = 0;
1285 lpvBuf += status;
1286 length += status;
1289 TRACE("%.*s\n", length, orgBuf);
1290 ptr->commerror = 0;
1291 return length;
1294 /*****************************************************************************
1295 * WriteComm (USER.205)
1297 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1299 int status, length;
1300 struct DosDeviceStruct *ptr;
1302 TRACE("cid %d, ptr %p, length %d\n",
1303 cid, lpvBuf, cbWrite);
1304 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1305 return -1;
1308 if (ptr->suspended) {
1309 ptr->commerror = IE_HARDWARE;
1310 return -1;
1313 TRACE("%.*s\n", cbWrite, lpvBuf );
1315 length = 0;
1316 while (length < cbWrite) {
1317 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1318 /* no data queued, try to write directly */
1319 status = write(ptr->fd, lpvBuf, cbWrite - length);
1320 if (status > 0) {
1321 lpvBuf += status;
1322 length += status;
1323 continue;
1326 /* can't write directly, put into transmit buffer */
1327 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1328 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1329 if (!status) break;
1330 if ((cbWrite - length) < status)
1331 status = cbWrite - length;
1332 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1333 ptr->obuf_head += status;
1334 if (ptr->obuf_head >= ptr->obuf_size)
1335 ptr->obuf_head = 0;
1336 lpvBuf += status;
1337 length += status;
1338 comm_waitwrite(ptr);
1341 ptr->commerror = 0;
1342 return length;
1345 /***********************************************************************
1346 * EnableCommNotification (USER.246)
1348 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1349 INT16 cbWriteNotify, INT16 cbOutQueue )
1351 struct DosDeviceStruct *ptr;
1353 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1354 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1355 ptr->commerror = IE_BADID;
1356 return -1;
1358 ptr->wnd = hwnd;
1359 ptr->n_read = cbWriteNotify;
1360 ptr->n_write = cbOutQueue;
1361 return TRUE;
1365 /**************************************************************************
1366 * BuildCommDCBA (KERNEL32.14)
1368 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1370 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1373 /**************************************************************************
1374 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1376 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1377 LPCOMMTIMEOUTS lptimeouts)
1379 int port;
1380 char *ptr,*temp;
1382 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1384 if (!lstrncmpiA(device,"COM",3)) {
1385 port=device[3]-'0';
1386 if (port--==0) {
1387 ERR("BUG! COM0 can't exists!.\n");
1388 return FALSE;
1390 if (!ValidCOMPort(port))
1391 return FALSE;
1392 if (*(device+4)!=':')
1393 return FALSE;
1394 temp=(LPSTR)(device+5);
1395 } else
1396 temp=(LPSTR)device;
1398 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1400 lpdcb->DCBlength = sizeof(DCB);
1401 if (strchr(temp,',')) { /* old style */
1402 DCB16 dcb16;
1403 BOOL16 ret;
1404 char last=temp[strlen(temp)-1];
1406 ret=BuildCommDCB16(device,&dcb16);
1407 if (!ret)
1408 return FALSE;
1409 lpdcb->BaudRate = dcb16.BaudRate;
1410 lpdcb->ByteSize = dcb16.ByteSize;
1411 lpdcb->fBinary = dcb16.fBinary;
1412 lpdcb->Parity = dcb16.Parity;
1413 lpdcb->fParity = dcb16.fParity;
1414 lpdcb->fNull = dcb16.fNull;
1415 lpdcb->StopBits = dcb16.StopBits;
1416 if (last == 'x') {
1417 lpdcb->fInX = TRUE;
1418 lpdcb->fOutX = TRUE;
1419 lpdcb->fOutxCtsFlow = FALSE;
1420 lpdcb->fOutxDsrFlow = FALSE;
1421 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1422 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1423 } else if (last=='p') {
1424 lpdcb->fInX = FALSE;
1425 lpdcb->fOutX = FALSE;
1426 lpdcb->fOutxCtsFlow = TRUE;
1427 lpdcb->fOutxDsrFlow = TRUE;
1428 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1429 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1430 } else {
1431 lpdcb->fInX = FALSE;
1432 lpdcb->fOutX = FALSE;
1433 lpdcb->fOutxCtsFlow = FALSE;
1434 lpdcb->fOutxDsrFlow = FALSE;
1435 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1436 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1438 lpdcb->XonChar = dcb16.XonChar;
1439 lpdcb->XoffChar = dcb16.XoffChar;
1440 lpdcb->ErrorChar= dcb16.PeChar;
1441 lpdcb->fErrorChar= dcb16.fPeChar;
1442 lpdcb->EofChar = dcb16.EofChar;
1443 lpdcb->EvtChar = dcb16.EvtChar;
1444 lpdcb->XonLim = dcb16.XonLim;
1445 lpdcb->XoffLim = dcb16.XoffLim;
1446 return TRUE;
1448 ptr=strtok(temp," ");
1449 while (ptr) {
1450 DWORD flag,x;
1452 flag=0;
1453 if (!strncmp("baud=",ptr,5)) {
1454 if (!sscanf(ptr+5,"%ld",&x))
1455 WARN("Couldn't parse %s\n",ptr);
1456 lpdcb->BaudRate = x;
1457 flag=1;
1459 if (!strncmp("stop=",ptr,5)) {
1460 if (!sscanf(ptr+5,"%ld",&x))
1461 WARN("Couldn't parse %s\n",ptr);
1462 lpdcb->StopBits = x;
1463 flag=1;
1465 if (!strncmp("data=",ptr,5)) {
1466 if (!sscanf(ptr+5,"%ld",&x))
1467 WARN("Couldn't parse %s\n",ptr);
1468 lpdcb->ByteSize = x;
1469 flag=1;
1471 if (!strncmp("parity=",ptr,7)) {
1472 lpdcb->fParity = TRUE;
1473 switch (ptr[8]) {
1474 case 'N':case 'n':
1475 lpdcb->fParity = FALSE;
1476 lpdcb->Parity = NOPARITY;
1477 break;
1478 case 'E':case 'e':
1479 lpdcb->Parity = EVENPARITY;
1480 break;
1481 case 'O':case 'o':
1482 lpdcb->Parity = ODDPARITY;
1483 break;
1484 case 'M':case 'm':
1485 lpdcb->Parity = MARKPARITY;
1486 break;
1488 flag=1;
1490 if (!flag)
1491 ERR("Unhandled specifier '%s', please report.\n",ptr);
1492 ptr=strtok(NULL," ");
1494 if (lpdcb->BaudRate==110)
1495 lpdcb->StopBits = 2;
1496 return TRUE;
1499 /**************************************************************************
1500 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1502 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1503 LPCOMMTIMEOUTS lptimeouts )
1505 LPSTR devidA;
1506 BOOL ret;
1508 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1509 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1510 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1511 HeapFree( GetProcessHeap(), 0, devidA );
1512 return ret;
1515 /**************************************************************************
1516 * BuildCommDCBW (KERNEL32.17)
1518 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1520 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1523 /*****************************************************************************
1524 * COMM_GetReadFd
1525 * Returns a file descriptor for reading.
1526 * Make sure to close the handle afterwards!
1528 static int COMM_GetReadFd( HANDLE handle)
1530 int fd;
1531 struct get_read_fd_request *req = get_req_buffer();
1532 req->handle = handle;
1533 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1534 return fd;
1537 /*****************************************************************************
1538 * COMM_GetWriteFd
1539 * Returns a file descriptor for writing.
1540 * Make sure to close the handle afterwards!
1542 static int COMM_GetWriteFd( HANDLE handle)
1544 int fd;
1545 struct get_write_fd_request *req = get_req_buffer();
1546 req->handle = handle;
1547 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1548 return fd;
1551 /* FIXME: having these global for win32 for now */
1552 int commerror=0,eventmask=0;
1554 /*****************************************************************************
1555 * SetCommBreak (KERNEL32.449)
1557 BOOL WINAPI SetCommBreak(HANDLE handle)
1559 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1560 int fd,result;
1562 fd = COMM_GetWriteFd(handle);
1563 if(fd<0) {
1564 TRACE("COMM_GetWriteFd failed\n");
1565 return FALSE;
1567 result = ioctl(fd,TIOCSBRK,0);
1568 close(fd);
1569 if (result ==-1)
1571 TRACE("ioctl failed\n");
1572 SetLastError(ERROR_NOT_SUPPORTED);
1573 return FALSE;
1575 return TRUE;
1576 #else
1577 FIXME("ioctl not available\n");
1578 SetLastError(ERROR_NOT_SUPPORTED);
1579 return FALSE;
1580 #endif
1583 /*****************************************************************************
1584 * ClearCommBreak (KERNEL32.20)
1586 BOOL WINAPI ClearCommBreak(HANDLE handle)
1588 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1589 int fd,result;
1591 fd = COMM_GetWriteFd(handle);
1592 if(fd<0) {
1593 TRACE("COMM_GetWriteFd failed\n");
1594 return FALSE;
1596 result = ioctl(fd,TIOCCBRK,0);
1597 close(fd);
1598 if (result ==-1)
1600 TRACE("ioctl failed\n");
1601 SetLastError(ERROR_NOT_SUPPORTED);
1602 return FALSE;
1604 return TRUE;
1605 #else
1606 FIXME("ioctl not available\n");
1607 SetLastError(ERROR_NOT_SUPPORTED);
1608 return FALSE;
1609 #endif
1612 /*****************************************************************************
1613 * EscapeCommFunction (KERNEL32.214)
1615 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1617 int fd,direct=FALSE,result=FALSE;
1618 struct termios port;
1620 TRACE("handle %d, function=%d\n", handle, nFunction);
1621 fd = COMM_GetWriteFd(handle);
1622 if(fd<0)
1623 return FALSE;
1625 if (tcgetattr(fd,&port) == -1) {
1626 commerror=WinError();
1627 close(fd);
1628 return FALSE;
1631 switch (nFunction) {
1632 case RESETDEV:
1633 TRACE("\n");
1634 break;
1636 case CLRDTR:
1637 TRACE("CLRDTR\n");
1638 #ifdef TIOCM_DTR
1639 direct=TRUE;
1640 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1641 break;
1642 #endif
1644 case CLRRTS:
1645 TRACE("CLRRTS\n");
1646 #ifdef TIOCM_RTS
1647 direct=TRUE;
1648 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1649 break;
1650 #endif
1652 case SETDTR:
1653 TRACE("SETDTR\n");
1654 #ifdef TIOCM_DTR
1655 direct=TRUE;
1656 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1657 break;
1658 #endif
1660 case SETRTS:
1661 TRACE("SETRTS\n");
1662 #ifdef TIOCM_DTR
1663 direct=TRUE;
1664 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1665 break;
1666 #endif
1668 case SETXOFF:
1669 TRACE("SETXOFF\n");
1670 port.c_iflag |= IXOFF;
1671 break;
1673 case SETXON:
1674 TRACE("SETXON\n");
1675 port.c_iflag |= IXON;
1676 break;
1677 case SETBREAK:
1678 TRACE("setbreak\n");
1679 #ifdef TIOCSBRK
1680 direct=TRUE;
1681 result = ioctl(fd,TIOCSBRK,0);
1682 break;
1683 #endif
1684 case CLRBREAK:
1685 TRACE("clrbreak\n");
1686 #ifdef TIOCSBRK
1687 direct=TRUE;
1688 result = ioctl(fd,TIOCCBRK,0);
1689 break;
1690 #endif
1691 default:
1692 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1693 handle, nFunction);
1694 break;
1697 if (!direct)
1698 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1699 commerror = WinError();
1700 close(fd);
1701 return FALSE;
1702 } else
1703 result= TRUE;
1704 else
1706 if (result == -1)
1708 result= FALSE;
1709 commerror=WinError();
1711 else
1712 result = TRUE;
1714 close(fd);
1715 return result;
1718 /********************************************************************
1719 * PurgeComm (KERNEL32.557)
1721 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1723 int fd;
1725 TRACE("handle %d, flags %lx\n", handle, flags);
1727 fd = COMM_GetWriteFd(handle);
1728 if(fd<0)
1729 return FALSE;
1732 ** not exactly sure how these are different
1733 ** Perhaps if we had our own internal queues, one flushes them
1734 ** and the other flushes the kernel's buffers.
1736 if(flags&PURGE_TXABORT)
1738 tcflush(fd,TCOFLUSH);
1740 if(flags&PURGE_RXABORT)
1742 tcflush(fd,TCIFLUSH);
1744 if(flags&PURGE_TXCLEAR)
1746 tcflush(fd,TCOFLUSH);
1748 if(flags&PURGE_RXCLEAR)
1750 tcflush(fd,TCIFLUSH);
1752 close(fd);
1754 return 1;
1757 /*****************************************************************************
1758 * ClearCommError (KERNEL32.21)
1760 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1762 int fd;
1764 fd=COMM_GetReadFd(handle);
1765 if(0>fd)
1767 return FALSE;
1770 if (lpStat)
1772 lpStat->status = 0;
1774 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1775 WARN("ioctl returned error\n");
1777 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1778 WARN("ioctl returned error\n");
1780 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1781 handle, lpStat->cbInQue, lpStat->cbOutQue);
1784 close(fd);
1786 if(errors)
1787 *errors = 0;
1790 ** After an asynchronous write opperation, the
1791 ** app will call ClearCommError to see if the
1792 ** results are ready yet. It waits for ERROR_IO_PENDING
1794 commerror = ERROR_IO_PENDING;
1796 return TRUE;
1799 /*****************************************************************************
1800 * SetupComm (KERNEL32.676)
1802 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1804 int fd;
1806 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1807 fd=COMM_GetWriteFd(handle);
1808 if(0>fd)
1810 return FALSE;
1812 close(fd);
1813 return TRUE;
1816 /*****************************************************************************
1817 * GetCommMask (KERNEL32.156)
1819 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1821 int fd;
1823 TRACE("handle %d, mask %p\n", handle, evtmask);
1824 if(0>(fd=COMM_GetReadFd(handle)))
1826 return FALSE;
1828 close(fd);
1829 *evtmask = eventmask;
1830 TRACE("%s%s%s%s%s%s%s%s%s\n",
1831 (eventmask&EV_BREAK)?"EV_BREAK":"",
1832 (eventmask&EV_CTS)?"EV_CTS":"",
1833 (eventmask&EV_DSR)?"EV_DSR":"",
1834 (eventmask&EV_ERR)?"EV_ERR":"",
1835 (eventmask&EV_RING)?"EV_RING":"",
1836 (eventmask&EV_RLSD)?"EV_RLSD":"",
1837 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1838 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1839 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1841 return TRUE;
1844 /*****************************************************************************
1845 * SetCommMask (KERNEL32.451)
1847 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1849 int fd;
1851 TRACE("handle %d, mask %lx\n", handle, evtmask);
1852 TRACE("%s%s%s%s%s%s%s%s%s\n",
1853 (evtmask&EV_BREAK)?"EV_BREAK":"",
1854 (evtmask&EV_CTS)?"EV_CTS":"",
1855 (evtmask&EV_DSR)?"EV_DSR":"",
1856 (evtmask&EV_ERR)?"EV_ERR":"",
1857 (evtmask&EV_RING)?"EV_RING":"",
1858 (evtmask&EV_RLSD)?"EV_RLSD":"",
1859 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1860 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1861 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1863 if(0>(fd=COMM_GetWriteFd(handle))) {
1864 return FALSE;
1866 close(fd);
1867 eventmask = evtmask;
1868 return TRUE;
1871 /*****************************************************************************
1872 * SetCommState (KERNEL32.452)
1874 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1876 struct termios port;
1877 int fd;
1879 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1880 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1881 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1882 (lpdcb->StopBits == ONESTOPBIT)?1:
1883 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1884 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1885 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1887 if ((fd = COMM_GetWriteFd(handle)) < 0) return FALSE;
1889 if ((tcgetattr(fd,&port)) == -1) {
1890 int save_error = errno;
1891 commerror = WinError();
1892 close( fd );
1893 #ifdef HAVE_STRERROR
1894 ERR("tcgetattr error '%s'\n", strerror(save_error));
1895 #else
1896 ERR("tcgetattr error %d\n", save_error);
1897 #endif
1898 return FALSE;
1901 port.c_cc[VMIN] = 0;
1902 port.c_cc[VTIME] = 1;
1904 #ifdef IMAXBEL
1905 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1906 #else
1907 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1908 #endif
1909 port.c_iflag |= (IGNBRK);
1911 port.c_oflag &= ~(OPOST);
1913 port.c_cflag &= ~(HUPCL);
1914 port.c_cflag |= CLOCAL | CREAD;
1916 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1917 port.c_lflag |= NOFLSH;
1920 ** MJM - removed default baudrate settings
1921 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1923 #ifdef CBAUD
1924 port.c_cflag &= ~CBAUD;
1925 switch (lpdcb->BaudRate) {
1926 case 110:
1927 case CBR_110:
1928 port.c_cflag |= B110;
1929 break;
1930 case 300:
1931 case CBR_300:
1932 port.c_cflag |= B300;
1933 break;
1934 case 600:
1935 case CBR_600:
1936 port.c_cflag |= B600;
1937 break;
1938 case 1200:
1939 case CBR_1200:
1940 port.c_cflag |= B1200;
1941 break;
1942 case 2400:
1943 case CBR_2400:
1944 port.c_cflag |= B2400;
1945 break;
1946 case 4800:
1947 case CBR_4800:
1948 port.c_cflag |= B4800;
1949 break;
1950 case 9600:
1951 case CBR_9600:
1952 port.c_cflag |= B9600;
1953 break;
1954 case 19200:
1955 case CBR_19200:
1956 port.c_cflag |= B19200;
1957 break;
1958 case 38400:
1959 case CBR_38400:
1960 port.c_cflag |= B38400;
1961 break;
1962 #ifdef B57600
1963 case 57600:
1964 port.c_cflag |= B57600;
1965 break;
1966 #endif
1967 #ifdef B115200
1968 case 115200:
1969 port.c_cflag |= B115200;
1970 break;
1971 #endif
1972 #ifdef B230400
1973 case 230400:
1974 port.c_cflag |= B230400;
1975 break;
1976 #endif
1977 #ifdef B460800
1978 case 460600:
1979 port.c_cflag |= B460800;
1980 break;
1981 #endif
1982 default:
1983 commerror = IE_BAUDRATE;
1984 close( fd );
1985 ERR("baudrate %ld\n",lpdcb->BaudRate);
1986 return FALSE;
1988 #elif !defined(__EMX__)
1989 switch (lpdcb->BaudRate) {
1990 case 110:
1991 case CBR_110:
1992 port.c_ospeed = B110;
1993 break;
1994 case 300:
1995 case CBR_300:
1996 port.c_ospeed = B300;
1997 break;
1998 case 600:
1999 case CBR_600:
2000 port.c_ospeed = B600;
2001 break;
2002 case 1200:
2003 case CBR_1200:
2004 port.c_ospeed = B1200;
2005 break;
2006 case 2400:
2007 case CBR_2400:
2008 port.c_ospeed = B2400;
2009 break;
2010 case 4800:
2011 case CBR_4800:
2012 port.c_ospeed = B4800;
2013 break;
2014 case 9600:
2015 case CBR_9600:
2016 port.c_ospeed = B9600;
2017 break;
2018 case 19200:
2019 case CBR_19200:
2020 port.c_ospeed = B19200;
2021 break;
2022 case 38400:
2023 case CBR_38400:
2024 port.c_ospeed = B38400;
2025 break;
2026 default:
2027 commerror = IE_BAUDRATE;
2028 close( fd );
2029 ERR("baudrate %d \n",lpdcb->BaudRate);
2030 return FALSE;
2032 port.c_ispeed = port.c_ospeed;
2033 #endif
2034 port.c_cflag &= ~CSIZE;
2035 switch (lpdcb->ByteSize) {
2036 case 5:
2037 port.c_cflag |= CS5;
2038 break;
2039 case 6:
2040 port.c_cflag |= CS6;
2041 break;
2042 case 7:
2043 port.c_cflag |= CS7;
2044 break;
2045 case 8:
2046 port.c_cflag |= CS8;
2047 break;
2048 default:
2049 commerror = IE_BYTESIZE;
2050 close( fd );
2051 ERR("ByteSize\n");
2052 return FALSE;
2055 port.c_cflag &= ~(PARENB | PARODD);
2056 if (lpdcb->fParity)
2057 port.c_iflag |= INPCK;
2058 else
2059 port.c_iflag &= ~INPCK;
2060 switch (lpdcb->Parity) {
2061 case NOPARITY:
2062 break;
2063 case ODDPARITY:
2064 port.c_cflag |= (PARENB | PARODD);
2065 break;
2066 case EVENPARITY:
2067 port.c_cflag |= PARENB;
2068 break;
2069 default:
2070 commerror = IE_BYTESIZE;
2071 close( fd );
2072 ERR("Parity\n");
2073 return FALSE;
2077 switch (lpdcb->StopBits) {
2078 case ONESTOPBIT:
2079 port.c_cflag &= ~CSTOPB;
2080 break;
2081 case TWOSTOPBITS:
2082 port.c_cflag |= CSTOPB;
2083 break;
2084 default:
2085 commerror = IE_BYTESIZE;
2086 close( fd );
2087 ERR("StopBits\n");
2088 return FALSE;
2090 #ifdef CRTSCTS
2091 if ( lpdcb->fOutxCtsFlow ||
2092 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2093 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2096 port.c_cflag |= CRTSCTS;
2097 TRACE("CRTSCTS\n");
2100 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2102 port.c_cflag &= ~CRTSCTS;
2103 TRACE("~CRTSCTS\n");
2106 #endif
2107 if (lpdcb->fInX)
2108 port.c_iflag |= IXON;
2109 else
2110 port.c_iflag &= ~IXON;
2111 if (lpdcb->fOutX)
2112 port.c_iflag |= IXOFF;
2113 else
2114 port.c_iflag &= ~IXOFF;
2116 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2117 int save_error=errno;
2118 commerror = WinError();
2119 close( fd );
2120 #ifdef HAVE_STRERROR
2121 ERR("tcgetattr error '%s'\n", strerror(save_error));
2122 #else
2123 ERR("tcgetattr error %d\n", save_error);
2124 #endif
2125 return FALSE;
2126 } else {
2127 commerror = 0;
2128 close( fd );
2129 return TRUE;
2134 /*****************************************************************************
2135 * GetCommState (KERNEL32.159)
2137 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2139 struct termios port;
2140 int fd,speed;
2142 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2144 if ((fd = COMM_GetReadFd(handle)) < 0)
2146 ERR("can't get COMM_GetReadFd\n");
2147 return FALSE;
2149 if (tcgetattr(fd, &port) == -1) {
2150 int save_error=errno;
2151 #ifdef HAVE_STRERROR
2152 ERR("tcgetattr error '%s'\n", strerror(save_error));
2153 #else
2154 ERR("tcgetattr error %d\n", save_error);
2155 #endif
2156 commerror = WinError();
2157 close( fd );
2158 return FALSE;
2160 close( fd );
2161 #ifndef __EMX__
2162 #ifdef CBAUD
2163 speed= (port.c_cflag & CBAUD);
2164 #else
2165 speed= (cfgetospeed(&port));
2166 #endif
2167 switch (speed) {
2168 case B110:
2169 lpdcb->BaudRate = 110;
2170 break;
2171 case B300:
2172 lpdcb->BaudRate = 300;
2173 break;
2174 case B600:
2175 lpdcb->BaudRate = 600;
2176 break;
2177 case B1200:
2178 lpdcb->BaudRate = 1200;
2179 break;
2180 case B2400:
2181 lpdcb->BaudRate = 2400;
2182 break;
2183 case B4800:
2184 lpdcb->BaudRate = 4800;
2185 break;
2186 case B9600:
2187 lpdcb->BaudRate = 9600;
2188 break;
2189 case B19200:
2190 lpdcb->BaudRate = 19200;
2191 break;
2192 case B38400:
2193 lpdcb->BaudRate = 38400;
2194 break;
2195 #ifdef B57600
2196 case B57600:
2197 lpdcb->BaudRate = 57600;
2198 break;
2199 #endif
2200 #ifdef B115200
2201 case B115200:
2202 lpdcb->BaudRate = 115200;
2203 break;
2204 #endif
2205 #ifdef B230400
2206 case B230400:
2207 lpdcb->BaudRate = 230400;
2208 break;
2209 #endif
2210 #ifdef B460800
2211 case B460800:
2212 lpdcb->BaudRate = 460800;
2213 break;
2214 #endif
2215 default:
2216 ERR("unknown speed %x \n",speed);
2218 #endif
2219 switch (port.c_cflag & CSIZE) {
2220 case CS5:
2221 lpdcb->ByteSize = 5;
2222 break;
2223 case CS6:
2224 lpdcb->ByteSize = 6;
2225 break;
2226 case CS7:
2227 lpdcb->ByteSize = 7;
2228 break;
2229 case CS8:
2230 lpdcb->ByteSize = 8;
2231 break;
2232 default:
2233 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2236 if(port.c_iflag & INPCK)
2237 lpdcb->fParity = TRUE;
2238 else
2239 lpdcb->fParity = FALSE;
2240 switch (port.c_cflag & (PARENB | PARODD)) {
2241 case 0:
2242 lpdcb->Parity = NOPARITY;
2243 break;
2244 case PARENB:
2245 lpdcb->Parity = EVENPARITY;
2246 break;
2247 case (PARENB | PARODD):
2248 lpdcb->Parity = ODDPARITY;
2249 break;
2252 if (port.c_cflag & CSTOPB)
2253 lpdcb->StopBits = TWOSTOPBITS;
2254 else
2255 lpdcb->StopBits = ONESTOPBIT;
2257 lpdcb->fNull = 0;
2258 lpdcb->fBinary = 1;
2260 #ifdef CRTSCTS
2262 if (port.c_cflag & CRTSCTS) {
2263 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2264 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2265 lpdcb->fOutxCtsFlow = 1;
2266 lpdcb->fOutxDsrFlow = 1;
2267 } else
2268 #endif
2270 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2271 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2273 if (port.c_iflag & IXON)
2274 lpdcb->fInX = 1;
2275 else
2276 lpdcb->fInX = 0;
2278 if (port.c_iflag & IXOFF)
2279 lpdcb->fOutX = 1;
2280 else
2281 lpdcb->fOutX = 0;
2283 lpdcb->XonChar =
2284 lpdcb->XoffChar =
2286 lpdcb->XonLim = 10;
2287 lpdcb->XoffLim = 10;
2289 commerror = 0;
2291 TRACE("OK\n");
2293 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2294 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2295 (lpdcb->StopBits == ONESTOPBIT)?1:
2296 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2297 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2298 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2299 #ifdef CRTSCTS
2300 if ( lpdcb->fOutxCtsFlow ||
2301 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2302 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2304 TRACE("CRTSCTS\n");
2306 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2307 TRACE("~CRTSCTS\n");
2309 #endif
2310 return TRUE;
2313 /*****************************************************************************
2314 * TransmitCommChar (KERNEL32.535)
2316 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2318 struct DosDeviceStruct *ptr;
2320 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2321 if ((ptr = GetDeviceStruct(cid)) == NULL) {
2322 return FALSE;
2325 if (ptr->suspended) {
2326 ptr->commerror = IE_HARDWARE;
2327 return FALSE;
2329 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2330 ptr->commerror = WinError();
2331 return FALSE;
2332 } else {
2333 ptr->commerror = 0;
2334 return TRUE;
2338 /*****************************************************************************
2339 * GetCommTimeouts (KERNEL32.160)
2341 BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
2343 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2344 return TRUE;
2347 /*****************************************************************************
2348 * SetCommTimeouts (KERNEL32.453)
2350 BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
2351 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2352 TRACE("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2353 TRACE("ReadTotalTimeoutMultiplier %ld\n",
2354 lptimeouts->ReadTotalTimeoutMultiplier);
2355 TRACE("ReadTotalTimeoutConstant %ld\n",
2356 lptimeouts->ReadTotalTimeoutConstant);
2357 TRACE("WriteTotalTimeoutMultiplier %ld\n",
2358 lptimeouts->WriteTotalTimeoutMultiplier);
2359 TRACE("WriteTotalTimeoutConstant %ld\n",
2360 lptimeouts->WriteTotalTimeoutConstant);
2361 return TRUE;
2364 /***********************************************************************
2365 * GetCommModemStatus (KERNEL32.285)
2367 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2369 int fd,mstat, result=FALSE;
2371 *lpModemStat=0;
2372 #ifdef TIOCMGET
2373 fd = COMM_GetWriteFd(hFile);
2374 if(fd<0)
2375 return FALSE;
2376 result = ioctl(fd, TIOCMGET, &mstat);
2377 close(fd);
2378 if (result == -1)
2380 TRACE("ioctl failed\n");
2381 return FALSE;
2383 if (mstat & TIOCM_CTS)
2384 *lpModemStat |= MS_CTS_ON;
2385 if (mstat & TIOCM_DSR)
2386 *lpModemStat |= MS_DSR_ON;
2387 if (mstat & TIOCM_RNG)
2388 *lpModemStat |= MS_RING_ON;
2389 /*FIXME: Not really sure about RLSD UB 990810*/
2390 if (mstat & TIOCM_CAR)
2391 *lpModemStat |= MS_RLSD_ON;
2392 TRACE("%s%s%s%s\n",
2393 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2394 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2395 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2396 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2397 return TRUE;
2398 #else
2399 return FALSE;
2400 #endif
2402 /***********************************************************************
2403 * WaitCommEvent (KERNEL32.719)
2405 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2407 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2408 return TRUE;
2411 /***********************************************************************
2412 * GetCommProperties (KERNEL32.???)
2414 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2416 FIXME("(%d %p )\n",hFile,dcb);
2417 return TRUE;
2420 /***********************************************************************
2421 * SetCommProperties (KERNEL32.???)
2423 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2425 FIXME("(%d %p )\n",hFile,dcb);
2426 return TRUE;