Moved FatalAppExit functions to win32/except.c.
[wine.git] / misc / comm.c
blob6d49786a1615dc94fdd6a77b202ed37a0f39ed12
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 <stdio.h>
39 #include <termios.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #ifdef HAVE_STRINGS_H
43 # include <strings.h>
44 #endif
45 #include <errno.h>
46 #include <ctype.h>
47 #include <sys/stat.h>
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
50 #endif
51 #include <sys/ioctl.h>
52 #include <unistd.h>
54 #include "windef.h"
55 #include "wingdi.h"
56 #include "wine/winuser16.h"
57 #include "comm.h"
58 #ifdef HAVE_SYS_MODEM_H
59 # include <sys/modem.h>
60 #endif
61 #ifdef HAVE_SYS_STRTIO_H
62 # include <sys/strtio.h>
63 #endif
64 #include "heap.h"
65 #include "options.h"
67 #include "server.h"
68 #include "process.h"
69 #include "winerror.h"
70 #include "services.h"
71 #include "callback.h"
72 #include "file.h"
74 #include "debugtools.h"
76 DEFAULT_DEBUG_CHANNEL(comm);
78 #ifndef TIOCINQ
79 #define TIOCINQ FIONREAD
80 #endif
81 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
82 #define FLAG_LPT 0x80
84 struct DosDeviceStruct COM[MAX_PORTS];
85 struct DosDeviceStruct LPT[MAX_PORTS];
86 /* pointers to unknown(==undocumented) comm structure */
87 LPCVOID *unknown[MAX_PORTS];
88 /* save terminal states */
89 static struct termios m_stat[MAX_PORTS];
91 void COMM_Init(void)
93 int x;
94 char option[10], temp[256], *btemp;
95 struct stat st;
97 for (x=0; x!=MAX_PORTS; x++) {
98 strcpy(option,"COMx");
99 option[3] = '1' + x;
100 option[4] = '\0';
102 PROFILE_GetWineIniString( "serialports", option, "*",
103 temp, sizeof(temp) );
104 if (!strcmp(temp, "*") || *temp == '\0')
105 COM[x].devicename = NULL;
106 else {
107 btemp = strchr(temp,',');
108 if (btemp != NULL) {
109 *btemp++ = '\0';
110 COM[x].baudrate = atoi(btemp);
111 } else {
112 COM[x].baudrate = -1;
114 stat(temp, &st);
115 if (!S_ISCHR(st.st_mode))
116 WARN("Can't use `%s' as %s !\n", temp, option);
117 else
118 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
119 WARN("Can't malloc for device info!\n");
120 else {
121 COM[x].fd = 0;
122 strcpy(COM[x].devicename, temp);
124 TRACE("%s = %s\n", option, COM[x].devicename);
127 strcpy(option, "LPTx");
128 option[3] = '1' + x;
129 option[4] = '\0';
131 PROFILE_GetWineIniString( "parallelports", option, "*",
132 temp, sizeof(temp) );
133 if (!strcmp(temp, "*") || *temp == '\0')
134 LPT[x].devicename = NULL;
135 else {
136 stat(temp, &st);
137 if (!S_ISCHR(st.st_mode))
138 WARN("Can't use `%s' as %s !\n", temp, option);
139 else
140 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
141 WARN("Can't malloc for device info!\n");
142 else {
143 LPT[x].fd = 0;
144 strcpy(LPT[x].devicename, temp);
146 TRACE("%s = %s\n", option, LPT[x].devicename);
153 static struct DosDeviceStruct *GetDeviceStruct(int fd)
155 if ((fd&0x7F)<=MAX_PORTS) {
156 if (!(fd&FLAG_LPT)) {
157 if (COM[fd].fd)
158 return &COM[fd];
159 } else {
160 fd &= 0x7f;
161 if (LPT[fd].fd)
162 return &LPT[fd];
166 return NULL;
169 static int GetCommPort_fd(int fd)
171 int x;
173 for (x=0; x<MAX_PORTS; x++) {
174 if (COM[x].fd == fd)
175 return x;
178 return -1;
181 static int ValidCOMPort(int x)
183 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
186 static int ValidLPTPort(int x)
188 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
191 static int WinError(void)
193 TRACE("errno = %d\n", errno);
194 switch (errno) {
195 default:
196 return CE_IOE;
200 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
202 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
203 + ptr->ibuf_head - ptr->ibuf_tail;
206 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
208 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
209 + ptr->obuf_head - ptr->obuf_tail;
212 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
214 unsigned int mstat, okay;
215 okay = ioctl(fd, TIOCMGET, &mstat);
216 if (okay) return okay;
217 if (andy) mstat &= andy;
218 mstat |= orrie;
219 return ioctl(fd, TIOCMSET, &mstat);
222 static void CALLBACK comm_notification( ULONG_PTR private )
224 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
225 int prev, bleft, len;
226 WORD mask = 0;
227 int cid = GetCommPort_fd(ptr->fd);
229 TRACE("async notification\n");
230 /* read data from comm port */
231 prev = comm_inbuf(ptr);
232 do {
233 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
234 - ptr->ibuf_head;
235 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
236 if (len > 0) {
237 if (!bleft) {
238 ptr->commerror = CE_RXOVER;
239 } else {
240 /* check for events */
241 if ((ptr->eventmask & EV_RXFLAG) &&
242 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
243 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
244 mask |= CN_EVENT;
246 if (ptr->eventmask & EV_RXCHAR) {
247 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
248 mask |= CN_EVENT;
250 /* advance buffer position */
251 ptr->ibuf_head += len;
252 if (ptr->ibuf_head >= ptr->ibuf_size)
253 ptr->ibuf_head = 0;
256 } while (len > 0);
257 /* check for notification */
258 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
259 (comm_inbuf(ptr)>=ptr->n_read)) {
260 /* passed the receive notification threshold */
261 mask |= CN_RECEIVE;
264 /* write any TransmitCommChar character */
265 if (ptr->xmit>=0) {
266 len = write(ptr->fd, &(ptr->xmit), 1);
267 if (len > 0) ptr->xmit = -1;
269 /* write from output queue */
270 prev = comm_outbuf(ptr);
271 do {
272 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
273 - ptr->obuf_tail;
274 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
275 if (len > 0) {
276 ptr->obuf_tail += len;
277 if (ptr->obuf_tail >= ptr->obuf_size)
278 ptr->obuf_tail = 0;
279 /* flag event */
280 if (ptr->obuf_tail == ptr->obuf_head) {
281 if (ptr->s_write) {
282 SERVICE_Delete( ptr->s_write );
283 ptr->s_write = INVALID_HANDLE_VALUE;
285 if (ptr->eventmask & EV_TXEMPTY) {
286 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
287 mask |= CN_EVENT;
291 } while (len > 0);
292 /* check for notification */
293 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
294 (comm_outbuf(ptr)<ptr->n_write)) {
295 /* passed the transmit notification threshold */
296 mask |= CN_TRANSMIT;
299 /* send notifications, if any */
300 if (ptr->wnd && mask) {
301 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
302 Callout.PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
306 static void comm_waitread(struct DosDeviceStruct *ptr)
308 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
309 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
310 GENERIC_READ | SYNCHRONIZE ),
311 comm_notification,
312 (ULONG_PTR)ptr );
315 static void comm_waitwrite(struct DosDeviceStruct *ptr)
317 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
318 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
319 GENERIC_WRITE | SYNCHRONIZE ),
320 comm_notification,
321 (ULONG_PTR)ptr );
324 /**************************************************************************
325 * BuildCommDCB (USER.213)
327 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
329 /* "COM1:9600,n,8,1" */
330 /* 012345 */
331 int port;
332 char *ptr, temp[256];
334 TRACE("(%s), ptr %p\n", device, lpdcb);
336 if (!lstrncmpiA(device,"COM",3)) {
337 port = device[3] - '0';
340 if (port-- == 0) {
341 ERR("BUG ! COM0 can't exist!.\n");
342 return -1;
345 if (!ValidCOMPort(port)) {
346 FIXME("invalid COM port %d?\n",port);
347 return -1;
350 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
352 lpdcb->Id = port;
354 if (!*(device+4))
355 return 0;
357 if (*(device+4) != ':')
358 return -1;
360 strcpy(temp,device+5);
361 ptr = strtok(temp, ", ");
363 if (COM[port].baudrate > 0)
364 lpdcb->BaudRate = COM[port].baudrate;
365 else
366 lpdcb->BaudRate = atoi(ptr);
367 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
369 ptr = strtok(NULL, ", ");
370 if (islower(*ptr))
371 *ptr = toupper(*ptr);
373 TRACE("parity (%c)\n", *ptr);
374 lpdcb->fParity = TRUE;
375 switch (*ptr) {
376 case 'N':
377 lpdcb->Parity = NOPARITY;
378 lpdcb->fParity = FALSE;
379 break;
380 case 'E':
381 lpdcb->Parity = EVENPARITY;
382 break;
383 case 'M':
384 lpdcb->Parity = MARKPARITY;
385 break;
386 case 'O':
387 lpdcb->Parity = ODDPARITY;
388 break;
389 default:
390 WARN("Unknown parity `%c'!\n", *ptr);
391 return -1;
394 ptr = strtok(NULL, ", ");
395 TRACE("charsize (%c)\n", *ptr);
396 lpdcb->ByteSize = *ptr - '0';
398 ptr = strtok(NULL, ", ");
399 TRACE("stopbits (%c)\n", *ptr);
400 switch (*ptr) {
401 case '1':
402 lpdcb->StopBits = ONESTOPBIT;
403 break;
404 case '2':
405 lpdcb->StopBits = TWOSTOPBITS;
406 break;
407 default:
408 WARN("Unknown # of stopbits `%c'!\n", *ptr);
409 return -1;
413 return 0;
416 /*****************************************************************************
417 * OpenComm (USER.200)
419 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
421 int port,fd;
423 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
425 if (strlen(device) < 4)
426 return IE_BADID;
428 port = device[3] - '0';
430 if (port-- == 0)
431 ERR("BUG ! COM0 or LPT0 don't exist !\n");
433 if (!lstrncmpiA(device,"COM",3)) {
435 TRACE("%s = %s\n", device, COM[port].devicename);
437 if (!ValidCOMPort(port))
438 return IE_BADID;
440 if (COM[port].fd)
441 return IE_OPEN;
443 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
444 if (fd == -1) {
445 ERR("error=%d\n", errno);
446 return IE_HARDWARE;
447 } else {
448 unknown[port] = SEGPTR_ALLOC(40);
449 bzero(unknown[port],40);
450 COM[port].fd = fd;
451 COM[port].commerror = 0;
452 COM[port].eventmask = 0;
453 COM[port].evtchar = 0; /* FIXME: default? */
454 /* save terminal state */
455 tcgetattr(fd,&m_stat[port]);
456 /* set default parameters */
457 if(COM[port].baudrate>-1){
458 DCB16 dcb;
459 GetCommState16(port, &dcb);
460 dcb.BaudRate=COM[port].baudrate;
461 /* more defaults:
462 * databits, parity, stopbits
464 SetCommState16( &dcb);
466 /* init priority characters */
467 COM[port].unget = -1;
468 COM[port].xmit = -1;
469 /* allocate buffers */
470 COM[port].ibuf_size = cbInQueue;
471 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
472 COM[port].obuf_size = cbOutQueue;
473 COM[port].obuf_head = COM[port].obuf_tail = 0;
475 COM[port].inbuf = malloc(cbInQueue);
476 if (COM[port].inbuf) {
477 COM[port].outbuf = malloc(cbOutQueue);
478 if (!COM[port].outbuf)
479 free(COM[port].inbuf);
480 } else COM[port].outbuf = NULL;
481 if (!COM[port].outbuf) {
482 /* not enough memory */
483 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
484 close(COM[port].fd);
485 ERR("out of memory");
486 return IE_MEMORY;
489 COM[port].s_read = INVALID_HANDLE_VALUE;
490 COM[port].s_write = INVALID_HANDLE_VALUE;
491 comm_waitread( &COM[port] );
492 return port;
495 else
496 if (!lstrncmpiA(device,"LPT",3)) {
498 if (!ValidLPTPort(port))
499 return IE_BADID;
501 if (LPT[port].fd)
502 return IE_OPEN;
504 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
505 if (fd == -1) {
506 return IE_HARDWARE;
507 } else {
508 LPT[port].fd = fd;
509 LPT[port].commerror = 0;
510 LPT[port].eventmask = 0;
511 return port|FLAG_LPT;
514 return 0;
517 /*****************************************************************************
518 * CloseComm (USER.207)
520 INT16 WINAPI CloseComm16(INT16 cid)
522 struct DosDeviceStruct *ptr;
524 TRACE("cid=%d\n", cid);
525 if ((ptr = GetDeviceStruct(cid)) == NULL) {
526 FIXME("no cid=%d found!\n", cid);
527 return -1;
529 if (!(cid&FLAG_LPT)) {
530 /* COM port */
531 SEGPTR_FREE(unknown[cid]); /* [LW] */
533 SERVICE_Delete( COM[cid].s_write );
534 SERVICE_Delete( COM[cid].s_read );
535 /* free buffers */
536 free(ptr->outbuf);
537 free(ptr->inbuf);
539 /* reset modem lines */
540 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
543 if (close(ptr->fd) == -1) {
544 ptr->commerror = WinError();
545 /* FIXME: should we clear ptr->fd here? */
546 return -1;
547 } else {
548 ptr->commerror = 0;
549 ptr->fd = 0;
550 return 0;
554 /*****************************************************************************
555 * SetCommBreak (USER.210)
557 INT16 WINAPI SetCommBreak16(INT16 cid)
559 struct DosDeviceStruct *ptr;
561 TRACE("cid=%d\n", cid);
562 if ((ptr = GetDeviceStruct(cid)) == NULL) {
563 FIXME("no cid=%d found!\n", cid);
564 return -1;
567 ptr->suspended = 1;
568 ptr->commerror = 0;
569 return 0;
572 /*****************************************************************************
573 * ClearCommBreak (USER.211)
575 INT16 WINAPI ClearCommBreak16(INT16 cid)
577 struct DosDeviceStruct *ptr;
579 TRACE("cid=%d\n", cid);
580 if (!(ptr = GetDeviceStruct(cid))) {
581 FIXME("no cid=%d found!\n", cid);
582 return -1;
584 ptr->suspended = 0;
585 ptr->commerror = 0;
586 return 0;
589 /*****************************************************************************
590 * EscapeCommFunction (USER.214)
592 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
594 int max;
595 struct DosDeviceStruct *ptr;
596 struct termios port;
598 TRACE("cid=%d, function=%d\n", cid, nFunction);
599 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
600 if ((ptr = GetDeviceStruct(cid)) == NULL) {
601 FIXME("no cid=%d found!\n", cid);
602 return -1;
604 if (tcgetattr(ptr->fd,&port) == -1) {
605 TRACE("tcgetattr failed\n");
606 ptr->commerror=WinError();
607 return -1;
609 } else ptr = NULL;
611 switch (nFunction) {
612 case RESETDEV:
613 TRACE("RESETDEV\n");
614 break;
616 case GETMAXCOM:
617 TRACE("GETMAXCOM\n");
618 for (max = MAX_PORTS;!COM[max].devicename;max--)
620 return max;
621 break;
623 case GETMAXLPT:
624 TRACE("GETMAXLPT\n");
625 for (max = MAX_PORTS;!LPT[max].devicename;max--)
627 return FLAG_LPT + max;
628 break;
630 case GETBASEIRQ:
631 TRACE("GETBASEIRQ\n");
632 /* FIXME: use tables */
633 /* just fake something for now */
634 if (cid & FLAG_LPT) {
635 /* LPT1: irq 7, LPT2: irq 5 */
636 return (cid & 0x7f) ? 5 : 7;
637 } else {
638 /* COM1: irq 4, COM2: irq 3,
639 COM3: irq 4, COM4: irq 3 */
640 return 4 - (cid & 1);
642 break;
644 case CLRDTR:
645 TRACE("CLRDTR\n");
646 #ifdef TIOCM_DTR
647 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
648 #endif
649 case CLRRTS:
650 TRACE("CLRRTS\n");
651 #ifdef TIOCM_RTS
652 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
653 #endif
655 case SETDTR:
656 TRACE("SETDTR\n");
657 #ifdef TIOCM_DTR
658 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
659 #endif
661 case SETRTS:
662 TRACE("SETRTS\n");
663 #ifdef TIOCM_RTS
664 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
665 #endif
667 case SETXOFF:
668 TRACE("SETXOFF\n");
669 port.c_iflag |= IXOFF;
670 break;
672 case SETXON:
673 TRACE("SETXON\n");
674 port.c_iflag |= IXON;
675 break;
677 default:
678 WARN("(cid=%d,nFunction=%d): Unknown function\n",
679 cid, nFunction);
680 break;
683 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
684 ptr->commerror = WinError();
685 return -1;
686 } else {
687 ptr->commerror = 0;
688 return 0;
692 /*****************************************************************************
693 * FlushComm (USER.215)
695 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
697 int queue;
698 struct DosDeviceStruct *ptr;
700 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
701 if ((ptr = GetDeviceStruct(cid)) == NULL) {
702 FIXME("no cid=%d found!\n", cid);
703 return -1;
705 switch (fnQueue) {
706 case 0:
707 queue = TCOFLUSH;
708 ptr->obuf_tail = ptr->obuf_head;
709 break;
710 case 1:
711 queue = TCIFLUSH;
712 ptr->ibuf_head = ptr->ibuf_tail;
713 break;
714 default:
715 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
716 cid, fnQueue);
717 return -1;
719 if (tcflush(ptr->fd, queue)) {
720 ptr->commerror = WinError();
721 return -1;
722 } else {
723 ptr->commerror = 0;
724 return 0;
728 /********************************************************************
729 * GetCommError (USER.203)
731 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
733 int temperror;
734 struct DosDeviceStruct *ptr;
735 unsigned char *stol;
736 unsigned int mstat;
738 if ((ptr = GetDeviceStruct(cid)) == NULL) {
739 FIXME("no handle for cid = %0x!.\n",cid);
740 return -1;
742 if (cid&FLAG_LPT) {
743 WARN(" cid %d not comm port\n",cid);
744 return CE_MODE;
746 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
747 ioctl(ptr->fd,TIOCMGET,&mstat);
748 if( mstat&TIOCM_CAR )
749 *stol |= 0x80;
750 else
751 *stol &=0x7f;
753 if (lpStat) {
754 lpStat->status = 0;
756 lpStat->cbOutQue = comm_outbuf(ptr);
757 lpStat->cbInQue = comm_inbuf(ptr);
759 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
760 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
761 lpStat->cbOutQue, *stol);
763 else
764 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
765 cid, ptr->commerror, *stol);
767 /* Return any errors and clear it */
768 temperror = ptr->commerror;
769 ptr->commerror = 0;
770 return(temperror);
773 /*****************************************************************************
774 * SetCommEventMask (USER.208)
776 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
778 struct DosDeviceStruct *ptr;
779 unsigned char *stol;
780 int repid;
781 unsigned int mstat;
783 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
784 if ((ptr = GetDeviceStruct(cid)) == NULL) {
785 FIXME("no handle for cid = %0x!.\n",cid);
786 return (SEGPTR)NULL;
789 ptr->eventmask = fuEvtMask;
791 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
792 WARN(" cid %d not comm port\n",cid);
793 return (SEGPTR)NULL;
795 /* it's a COM port ? -> modify flags */
796 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
797 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
798 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
799 if ((mstat&TIOCM_CAR))
800 *stol |= 0x80;
801 else
802 *stol &=0x7f;
804 TRACE(" modem dcd construct %x\n",*stol);
805 return SEGPTR_GET(unknown[cid]);
808 /*****************************************************************************
809 * GetCommEventMask (USER.209)
811 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
813 struct DosDeviceStruct *ptr;
814 WORD events;
816 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
817 if ((ptr = GetDeviceStruct(cid)) == NULL) {
818 FIXME("no handle for cid = %0x!.\n",cid);
819 return 0;
822 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
823 WARN(" cid %d not comm port\n",cid);
824 return 0;
827 events = *(WORD*)(unknown[cid]) & fnEvtClear;
828 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
829 return events;
832 /*****************************************************************************
833 * SetCommState16 (USER.201)
835 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
837 struct termios port;
838 struct DosDeviceStruct *ptr;
840 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
841 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
842 FIXME("no handle for cid = %0x!.\n",lpdcb->Id);
843 return -1;
845 if (tcgetattr(ptr->fd, &port) == -1) {
846 ptr->commerror = WinError();
847 return -1;
850 port.c_cc[VMIN] = 0;
851 port.c_cc[VTIME] = 1;
853 #ifdef IMAXBEL
854 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
855 #else
856 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
857 #endif
858 port.c_iflag |= (IGNBRK);
860 port.c_oflag &= ~(OPOST);
862 port.c_cflag &= ~(HUPCL);
863 port.c_cflag |= CLOCAL | CREAD;
865 port.c_lflag &= ~(ICANON|ECHO|ISIG);
866 port.c_lflag |= NOFLSH;
868 TRACE("baudrate %d\n",lpdcb->BaudRate);
869 #ifdef CBAUD
870 port.c_cflag &= ~CBAUD;
871 switch (lpdcb->BaudRate) {
872 case 110:
873 case CBR_110:
874 port.c_cflag |= B110;
875 break;
876 case 300:
877 case CBR_300:
878 port.c_cflag |= B300;
879 break;
880 case 600:
881 case CBR_600:
882 port.c_cflag |= B600;
883 break;
884 case 1200:
885 case CBR_1200:
886 port.c_cflag |= B1200;
887 break;
888 case 2400:
889 case CBR_2400:
890 port.c_cflag |= B2400;
891 break;
892 case 4800:
893 case CBR_4800:
894 port.c_cflag |= B4800;
895 break;
896 case 9600:
897 case CBR_9600:
898 port.c_cflag |= B9600;
899 break;
900 case 19200:
901 case CBR_19200:
902 port.c_cflag |= B19200;
903 break;
904 case 38400:
905 case CBR_38400:
906 port.c_cflag |= B38400;
907 break;
908 #ifdef B57600
909 case 57600:
910 port.c_cflag |= B57600;
911 break;
912 #endif
913 #ifdef B115200
914 case 57601:
915 port.c_cflag |= B115200;
916 break;
917 #endif
918 default:
919 ptr->commerror = IE_BAUDRATE;
920 return -1;
922 #elif !defined(__EMX__)
923 switch (lpdcb->BaudRate) {
924 case 110:
925 case CBR_110:
926 port.c_ospeed = B110;
927 break;
928 case 300:
929 case CBR_300:
930 port.c_ospeed = B300;
931 break;
932 case 600:
933 case CBR_600:
934 port.c_ospeed = B600;
935 break;
936 case 1200:
937 case CBR_1200:
938 port.c_ospeed = B1200;
939 break;
940 case 2400:
941 case CBR_2400:
942 port.c_ospeed = B2400;
943 break;
944 case 4800:
945 case CBR_4800:
946 port.c_ospeed = B4800;
947 break;
948 case 9600:
949 case CBR_9600:
950 port.c_ospeed = B9600;
951 break;
952 case 19200:
953 case CBR_19200:
954 port.c_ospeed = B19200;
955 break;
956 case 38400:
957 case CBR_38400:
958 port.c_ospeed = B38400;
959 break;
960 default:
961 ptr->commerror = IE_BAUDRATE;
962 return -1;
964 port.c_ispeed = port.c_ospeed;
965 #endif
966 TRACE("bytesize %d\n",lpdcb->ByteSize);
967 port.c_cflag &= ~CSIZE;
968 switch (lpdcb->ByteSize) {
969 case 5:
970 port.c_cflag |= CS5;
971 break;
972 case 6:
973 port.c_cflag |= CS6;
974 break;
975 case 7:
976 port.c_cflag |= CS7;
977 break;
978 case 8:
979 port.c_cflag |= CS8;
980 break;
981 default:
982 ptr->commerror = IE_BYTESIZE;
983 return -1;
986 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
987 port.c_cflag &= ~(PARENB | PARODD);
988 if (lpdcb->fParity)
989 port.c_iflag |= INPCK;
990 else
991 port.c_iflag &= ~INPCK;
992 switch (lpdcb->Parity) {
993 case NOPARITY:
994 break;
995 case ODDPARITY:
996 port.c_cflag |= (PARENB | PARODD);
997 break;
998 case EVENPARITY:
999 port.c_cflag |= PARENB;
1000 break;
1001 default:
1002 ptr->commerror = IE_BYTESIZE;
1003 return -1;
1007 TRACE("stopbits %d\n",lpdcb->StopBits);
1009 switch (lpdcb->StopBits) {
1010 case ONESTOPBIT:
1011 port.c_cflag &= ~CSTOPB;
1012 break;
1013 case TWOSTOPBITS:
1014 port.c_cflag |= CSTOPB;
1015 break;
1016 default:
1017 ptr->commerror = IE_BYTESIZE;
1018 return -1;
1020 #ifdef CRTSCTS
1022 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1023 port.c_cflag |= CRTSCTS;
1025 if (lpdcb->fDtrDisable)
1026 port.c_cflag &= ~CRTSCTS;
1027 #endif
1028 if (lpdcb->fInX)
1029 port.c_iflag |= IXON;
1030 else
1031 port.c_iflag &= ~IXON;
1032 if (lpdcb->fOutX)
1033 port.c_iflag |= IXOFF;
1034 else
1035 port.c_iflag &= ~IXOFF;
1037 ptr->evtchar = lpdcb->EvtChar;
1039 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1040 ptr->commerror = WinError();
1041 return FALSE;
1042 } else {
1043 ptr->commerror = 0;
1044 return 0;
1048 /*****************************************************************************
1049 * GetCommState (USER.202)
1051 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1053 int speed;
1054 struct DosDeviceStruct *ptr;
1055 struct termios port;
1057 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1058 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1059 FIXME("no handle for cid = %0x!.\n",cid);
1060 return -1;
1062 if (tcgetattr(ptr->fd, &port) == -1) {
1063 ptr->commerror = WinError();
1064 return -1;
1066 lpdcb->Id = cid;
1067 #ifndef __EMX__
1068 #ifdef CBAUD
1069 speed = port.c_cflag & CBAUD;
1070 #else
1071 speed = port.c_ospeed;
1072 #endif
1073 switch(speed) {
1074 case B110:
1075 lpdcb->BaudRate = 110;
1076 break;
1077 case B300:
1078 lpdcb->BaudRate = 300;
1079 break;
1080 case B600:
1081 lpdcb->BaudRate = 600;
1082 break;
1083 case B1200:
1084 lpdcb->BaudRate = 1200;
1085 break;
1086 case B2400:
1087 lpdcb->BaudRate = 2400;
1088 break;
1089 case B4800:
1090 lpdcb->BaudRate = 4800;
1091 break;
1092 case B9600:
1093 lpdcb->BaudRate = 9600;
1094 break;
1095 case B19200:
1096 lpdcb->BaudRate = 19200;
1097 break;
1098 case B38400:
1099 lpdcb->BaudRate = 38400;
1100 break;
1101 #ifdef B57600
1102 case B57600:
1103 lpdcb->BaudRate = 57600;
1104 break;
1105 #endif
1106 #ifdef B115200
1107 case B115200:
1108 lpdcb->BaudRate = 57601;
1109 break;
1110 #endif
1112 #endif
1113 switch (port.c_cflag & CSIZE) {
1114 case CS5:
1115 lpdcb->ByteSize = 5;
1116 break;
1117 case CS6:
1118 lpdcb->ByteSize = 6;
1119 break;
1120 case CS7:
1121 lpdcb->ByteSize = 7;
1122 break;
1123 case CS8:
1124 lpdcb->ByteSize = 8;
1125 break;
1128 if(port.c_iflag & INPCK)
1129 lpdcb->fParity = TRUE;
1130 else
1131 lpdcb->fParity = FALSE;
1132 switch (port.c_cflag & (PARENB | PARODD)) {
1133 case 0:
1134 lpdcb->Parity = NOPARITY;
1135 break;
1136 case PARENB:
1137 lpdcb->Parity = EVENPARITY;
1138 break;
1139 case (PARENB | PARODD):
1140 lpdcb->Parity = ODDPARITY;
1141 break;
1144 if (port.c_cflag & CSTOPB)
1145 lpdcb->StopBits = TWOSTOPBITS;
1146 else
1147 lpdcb->StopBits = ONESTOPBIT;
1149 lpdcb->RlsTimeout = 50;
1150 lpdcb->CtsTimeout = 50;
1151 lpdcb->DsrTimeout = 50;
1152 lpdcb->fNull = 0;
1153 lpdcb->fChEvt = 0;
1154 lpdcb->fBinary = 1;
1155 lpdcb->fDtrDisable = 0;
1157 #ifdef CRTSCTS
1159 if (port.c_cflag & CRTSCTS) {
1160 lpdcb->fDtrflow = 1;
1161 lpdcb->fRtsflow = 1;
1162 lpdcb->fOutxCtsFlow = 1;
1163 lpdcb->fOutxDsrFlow = 1;
1164 } else
1165 #endif
1166 lpdcb->fDtrDisable = 1;
1168 if (port.c_iflag & IXON)
1169 lpdcb->fInX = 1;
1170 else
1171 lpdcb->fInX = 0;
1173 if (port.c_iflag & IXOFF)
1174 lpdcb->fOutX = 1;
1175 else
1176 lpdcb->fOutX = 0;
1178 lpdcb->XonChar =
1179 lpdcb->XoffChar =
1181 lpdcb->XonLim = 10;
1182 lpdcb->XoffLim = 10;
1184 lpdcb->EvtChar = ptr->evtchar;
1186 ptr->commerror = 0;
1187 return 0;
1190 /*****************************************************************************
1191 * TransmitCommChar (USER.206)
1193 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1195 struct DosDeviceStruct *ptr;
1197 TRACE("cid %d, data %d \n", cid, chTransmit);
1198 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1199 FIXME("no handle for cid = %0x!.\n",cid);
1200 return -1;
1203 if (ptr->suspended) {
1204 ptr->commerror = IE_HARDWARE;
1205 return -1;
1208 if (ptr->xmit >= 0) {
1209 /* character already queued */
1210 /* FIXME: which error would Windows return? */
1211 ptr->commerror = CE_TXFULL;
1212 return -1;
1215 if (ptr->obuf_head == ptr->obuf_tail) {
1216 /* transmit queue empty, try to transmit directly */
1217 if (write(ptr->fd, &chTransmit, 1) == -1) {
1218 /* didn't work, queue it */
1219 ptr->xmit = chTransmit;
1220 comm_waitwrite(ptr);
1222 } else {
1223 /* data in queue, let this char be transmitted next */
1224 ptr->xmit = chTransmit;
1225 comm_waitwrite(ptr);
1228 ptr->commerror = 0;
1229 return 0;
1232 /*****************************************************************************
1233 * UngetCommChar (USER.212)
1235 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1237 struct DosDeviceStruct *ptr;
1239 TRACE("cid %d (char %d)\n", cid, chUnget);
1240 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1241 FIXME("no handle for cid = %0x!.\n",cid);
1242 return -1;
1245 if (ptr->suspended) {
1246 ptr->commerror = IE_HARDWARE;
1247 return -1;
1250 if (ptr->unget>=0) {
1251 /* character already queued */
1252 /* FIXME: which error would Windows return? */
1253 ptr->commerror = CE_RXOVER;
1254 return -1;
1257 ptr->unget = chUnget;
1259 ptr->commerror = 0;
1260 return 0;
1263 /*****************************************************************************
1264 * ReadComm (USER.204)
1266 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1268 int status, length;
1269 struct DosDeviceStruct *ptr;
1270 LPSTR orgBuf = lpvBuf;
1272 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1273 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1274 FIXME("no handle for cid = %0x!.\n",cid);
1275 return -1;
1278 if (ptr->suspended) {
1279 ptr->commerror = IE_HARDWARE;
1280 return -1;
1283 /* read unget character */
1284 if (ptr->unget>=0) {
1285 *lpvBuf++ = ptr->unget;
1286 ptr->unget = -1;
1288 length = 1;
1289 } else
1290 length = 0;
1292 /* read from receive buffer */
1293 while (length < cbRead) {
1294 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1295 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1296 if (!status) break;
1297 if ((cbRead - length) < status)
1298 status = cbRead - length;
1300 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1301 ptr->ibuf_tail += status;
1302 if (ptr->ibuf_tail >= ptr->ibuf_size)
1303 ptr->ibuf_tail = 0;
1304 lpvBuf += status;
1305 length += status;
1308 TRACE("%.*s\n", length, orgBuf);
1309 ptr->commerror = 0;
1310 return length;
1313 /*****************************************************************************
1314 * WriteComm (USER.205)
1316 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1318 int status, length;
1319 struct DosDeviceStruct *ptr;
1321 TRACE("cid %d, ptr %p, length %d\n",
1322 cid, lpvBuf, cbWrite);
1323 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1324 FIXME("no handle for cid = %0x!.\n",cid);
1325 return -1;
1328 if (ptr->suspended) {
1329 ptr->commerror = IE_HARDWARE;
1330 return -1;
1333 TRACE("%.*s\n", cbWrite, lpvBuf );
1335 length = 0;
1336 while (length < cbWrite) {
1337 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1338 /* no data queued, try to write directly */
1339 status = write(ptr->fd, lpvBuf, cbWrite - length);
1340 if (status > 0) {
1341 lpvBuf += status;
1342 length += status;
1343 continue;
1346 /* can't write directly, put into transmit buffer */
1347 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1348 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1349 if (!status) break;
1350 if ((cbWrite - length) < status)
1351 status = cbWrite - length;
1352 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1353 ptr->obuf_head += status;
1354 if (ptr->obuf_head >= ptr->obuf_size)
1355 ptr->obuf_head = 0;
1356 lpvBuf += status;
1357 length += status;
1358 comm_waitwrite(ptr);
1361 ptr->commerror = 0;
1362 return length;
1365 /***********************************************************************
1366 * EnableCommNotification (USER.246)
1368 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1369 INT16 cbWriteNotify, INT16 cbOutQueue )
1371 struct DosDeviceStruct *ptr;
1373 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1374 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1375 FIXME("no handle for cid = %0x!.\n",cid);
1376 ptr->commerror = IE_BADID;
1377 return -1;
1379 ptr->wnd = hwnd;
1380 ptr->n_read = cbWriteNotify;
1381 ptr->n_write = cbOutQueue;
1382 return TRUE;
1386 /**************************************************************************
1387 * BuildCommDCBA (KERNEL32.14)
1389 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1391 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1394 /**************************************************************************
1395 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1397 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1398 LPCOMMTIMEOUTS lptimeouts)
1400 int port;
1401 char *ptr,*temp;
1403 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1405 if (!lstrncmpiA(device,"COM",3)) {
1406 port=device[3]-'0';
1407 if (port--==0) {
1408 ERR("BUG! COM0 can't exists!.\n");
1409 return FALSE;
1411 if (!ValidCOMPort(port))
1412 return FALSE;
1413 if (*(device+4)!=':')
1414 return FALSE;
1415 temp=(LPSTR)(device+5);
1416 } else
1417 temp=(LPSTR)device;
1419 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1421 lpdcb->DCBlength = sizeof(DCB);
1422 if (strchr(temp,',')) { /* old style */
1423 DCB16 dcb16;
1424 BOOL16 ret;
1425 char last=temp[strlen(temp)-1];
1427 ret=BuildCommDCB16(device,&dcb16);
1428 if (!ret)
1429 return FALSE;
1430 lpdcb->BaudRate = dcb16.BaudRate;
1431 lpdcb->ByteSize = dcb16.ByteSize;
1432 lpdcb->fBinary = dcb16.fBinary;
1433 lpdcb->Parity = dcb16.Parity;
1434 lpdcb->fParity = dcb16.fParity;
1435 lpdcb->fNull = dcb16.fNull;
1436 lpdcb->StopBits = dcb16.StopBits;
1437 if (last == 'x') {
1438 lpdcb->fInX = TRUE;
1439 lpdcb->fOutX = TRUE;
1440 lpdcb->fOutxCtsFlow = FALSE;
1441 lpdcb->fOutxDsrFlow = FALSE;
1442 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1443 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1444 } else if (last=='p') {
1445 lpdcb->fInX = FALSE;
1446 lpdcb->fOutX = FALSE;
1447 lpdcb->fOutxCtsFlow = TRUE;
1448 lpdcb->fOutxDsrFlow = TRUE;
1449 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1450 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1451 } else {
1452 lpdcb->fInX = FALSE;
1453 lpdcb->fOutX = FALSE;
1454 lpdcb->fOutxCtsFlow = FALSE;
1455 lpdcb->fOutxDsrFlow = FALSE;
1456 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1457 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1459 lpdcb->XonChar = dcb16.XonChar;
1460 lpdcb->XoffChar = dcb16.XoffChar;
1461 lpdcb->ErrorChar= dcb16.PeChar;
1462 lpdcb->fErrorChar= dcb16.fPeChar;
1463 lpdcb->EofChar = dcb16.EofChar;
1464 lpdcb->EvtChar = dcb16.EvtChar;
1465 lpdcb->XonLim = dcb16.XonLim;
1466 lpdcb->XoffLim = dcb16.XoffLim;
1467 return TRUE;
1469 ptr=strtok(temp," ");
1470 while (ptr) {
1471 DWORD flag,x;
1473 flag=0;
1474 if (!strncmp("baud=",ptr,5)) {
1475 if (!sscanf(ptr+5,"%ld",&x))
1476 WARN("Couldn't parse %s\n",ptr);
1477 lpdcb->BaudRate = x;
1478 flag=1;
1480 if (!strncmp("stop=",ptr,5)) {
1481 if (!sscanf(ptr+5,"%ld",&x))
1482 WARN("Couldn't parse %s\n",ptr);
1483 lpdcb->StopBits = x;
1484 flag=1;
1486 if (!strncmp("data=",ptr,5)) {
1487 if (!sscanf(ptr+5,"%ld",&x))
1488 WARN("Couldn't parse %s\n",ptr);
1489 lpdcb->ByteSize = x;
1490 flag=1;
1492 if (!strncmp("parity=",ptr,7)) {
1493 lpdcb->fParity = TRUE;
1494 switch (ptr[8]) {
1495 case 'N':case 'n':
1496 lpdcb->fParity = FALSE;
1497 lpdcb->Parity = NOPARITY;
1498 break;
1499 case 'E':case 'e':
1500 lpdcb->Parity = EVENPARITY;
1501 break;
1502 case 'O':case 'o':
1503 lpdcb->Parity = ODDPARITY;
1504 break;
1505 case 'M':case 'm':
1506 lpdcb->Parity = MARKPARITY;
1507 break;
1509 flag=1;
1511 if (!flag)
1512 ERR("Unhandled specifier '%s', please report.\n",ptr);
1513 ptr=strtok(NULL," ");
1515 if (lpdcb->BaudRate==110)
1516 lpdcb->StopBits = 2;
1517 return TRUE;
1520 /**************************************************************************
1521 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1523 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1524 LPCOMMTIMEOUTS lptimeouts )
1526 LPSTR devidA;
1527 BOOL ret;
1529 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1530 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1531 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1532 HeapFree( GetProcessHeap(), 0, devidA );
1533 return ret;
1536 /**************************************************************************
1537 * BuildCommDCBW (KERNEL32.17)
1539 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1541 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1544 /*****************************************************************************
1545 * COMM_GetReadFd
1546 * Returns a file descriptor for reading.
1547 * Make sure to close the handle afterwards!
1549 static int COMM_GetReadFd( HANDLE handle)
1551 int fd;
1552 struct get_read_fd_request *req = get_req_buffer();
1553 req->handle = handle;
1554 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1555 return fd;
1558 /*****************************************************************************
1559 * COMM_GetWriteFd
1560 * Returns a file descriptor for writing.
1561 * Make sure to close the handle afterwards!
1563 static int COMM_GetWriteFd( HANDLE handle)
1565 int fd = -1;
1566 struct get_write_fd_request *req = get_req_buffer();
1567 req->handle = handle;
1568 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1569 return fd;
1572 /* FIXME: having these global for win32 for now */
1573 int commerror=0,eventmask=0;
1575 /*****************************************************************************
1576 * SetCommBreak (KERNEL32.449)
1578 BOOL WINAPI SetCommBreak(HANDLE handle)
1580 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1581 int fd,result;
1583 fd = COMM_GetWriteFd(handle);
1584 if(fd<0) {
1585 TRACE("COMM_GetWriteFd failed\n");
1586 return FALSE;
1588 result = ioctl(fd,TIOCSBRK,0);
1589 close(fd);
1590 if (result ==-1)
1592 TRACE("ioctl failed\n");
1593 SetLastError(ERROR_NOT_SUPPORTED);
1594 return FALSE;
1596 return TRUE;
1597 #else
1598 FIXME("ioctl not available\n");
1599 SetLastError(ERROR_NOT_SUPPORTED);
1600 return FALSE;
1601 #endif
1604 /*****************************************************************************
1605 * ClearCommBreak (KERNEL32.20)
1607 BOOL WINAPI ClearCommBreak(HANDLE handle)
1609 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1610 int fd,result;
1612 fd = COMM_GetWriteFd(handle);
1613 if(fd<0) {
1614 TRACE("COMM_GetWriteFd failed\n");
1615 return FALSE;
1617 result = ioctl(fd,TIOCCBRK,0);
1618 close(fd);
1619 if (result ==-1)
1621 TRACE("ioctl failed\n");
1622 SetLastError(ERROR_NOT_SUPPORTED);
1623 return FALSE;
1625 return TRUE;
1626 #else
1627 FIXME("ioctl not available\n");
1628 SetLastError(ERROR_NOT_SUPPORTED);
1629 return FALSE;
1630 #endif
1633 /*****************************************************************************
1634 * EscapeCommFunction (KERNEL32.214)
1636 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1638 int fd,direct=FALSE,result=FALSE;
1639 struct termios port;
1641 TRACE("handle %d, function=%d\n", handle, nFunction);
1642 fd = COMM_GetWriteFd(handle);
1643 if(fd<0) {
1644 FIXME("handle %d not found.\n",handle);
1645 return FALSE;
1648 if (tcgetattr(fd,&port) == -1) {
1649 commerror=WinError();
1650 close(fd);
1651 return FALSE;
1654 switch (nFunction) {
1655 case RESETDEV:
1656 TRACE("\n");
1657 break;
1659 case CLRDTR:
1660 TRACE("CLRDTR\n");
1661 #ifdef TIOCM_DTR
1662 direct=TRUE;
1663 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1664 break;
1665 #endif
1667 case CLRRTS:
1668 TRACE("CLRRTS\n");
1669 #ifdef TIOCM_RTS
1670 direct=TRUE;
1671 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1672 break;
1673 #endif
1675 case SETDTR:
1676 TRACE("SETDTR\n");
1677 #ifdef TIOCM_DTR
1678 direct=TRUE;
1679 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1680 break;
1681 #endif
1683 case SETRTS:
1684 TRACE("SETRTS\n");
1685 #ifdef TIOCM_DTR
1686 direct=TRUE;
1687 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1688 break;
1689 #endif
1691 case SETXOFF:
1692 TRACE("SETXOFF\n");
1693 port.c_iflag |= IXOFF;
1694 break;
1696 case SETXON:
1697 TRACE("SETXON\n");
1698 port.c_iflag |= IXON;
1699 break;
1700 case SETBREAK:
1701 TRACE("setbreak\n");
1702 #ifdef TIOCSBRK
1703 direct=TRUE;
1704 result = ioctl(fd,TIOCSBRK,0);
1705 break;
1706 #endif
1707 case CLRBREAK:
1708 TRACE("clrbreak\n");
1709 #ifdef TIOCSBRK
1710 direct=TRUE;
1711 result = ioctl(fd,TIOCCBRK,0);
1712 break;
1713 #endif
1714 default:
1715 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1716 handle, nFunction);
1717 break;
1720 if (!direct)
1721 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1722 commerror = WinError();
1723 close(fd);
1724 return FALSE;
1725 } else
1726 result= TRUE;
1727 else
1729 if (result == -1)
1731 result= FALSE;
1732 commerror=WinError();
1734 else
1735 result = TRUE;
1737 close(fd);
1738 return result;
1741 /********************************************************************
1742 * PurgeComm (KERNEL32.557)
1744 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1746 int fd;
1748 TRACE("handle %d, flags %lx\n", handle, flags);
1750 fd = COMM_GetWriteFd(handle);
1751 if(fd<0) {
1752 FIXME("no handle %d found\n",handle);
1753 return FALSE;
1757 ** not exactly sure how these are different
1758 ** Perhaps if we had our own internal queues, one flushes them
1759 ** and the other flushes the kernel's buffers.
1761 if(flags&PURGE_TXABORT)
1762 tcflush(fd,TCOFLUSH);
1763 if(flags&PURGE_RXABORT)
1764 tcflush(fd,TCIFLUSH);
1765 if(flags&PURGE_TXCLEAR)
1766 tcflush(fd,TCOFLUSH);
1767 if(flags&PURGE_RXCLEAR)
1768 tcflush(fd,TCIFLUSH);
1769 close(fd);
1771 return 1;
1774 /*****************************************************************************
1775 * ClearCommError (KERNEL32.21)
1777 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1779 int fd;
1781 fd=COMM_GetReadFd(handle);
1782 if(0>fd)
1784 FIXME("no handle %d found\n",handle);
1785 return FALSE;
1788 if (lpStat)
1790 lpStat->status = 0;
1792 #ifdef TIOCOUTQ
1793 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1794 WARN("ioctl returned error\n");
1795 #else
1796 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1797 #endif
1799 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1800 WARN("ioctl returned error\n");
1802 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1803 handle, lpStat->cbInQue, lpStat->cbOutQue);
1806 close(fd);
1808 if(errors)
1809 *errors = 0;
1812 ** After an asynchronous write opperation, the
1813 ** app will call ClearCommError to see if the
1814 ** results are ready yet. It waits for ERROR_IO_PENDING
1816 commerror = ERROR_IO_PENDING;
1818 return TRUE;
1821 /*****************************************************************************
1822 * SetupComm (KERNEL32.676)
1824 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1826 int fd;
1828 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1829 fd=COMM_GetWriteFd(handle);
1830 if(0>fd) {
1831 FIXME("handle %d not found?\n",handle);
1832 return FALSE;
1834 close(fd);
1835 return TRUE;
1838 /*****************************************************************************
1839 * GetCommMask (KERNEL32.156)
1841 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1843 int fd;
1845 TRACE("handle %d, mask %p\n", handle, evtmask);
1846 if(0>(fd=COMM_GetReadFd(handle)))
1848 FIXME("no handle %d found\n",handle);
1849 return FALSE;
1851 close(fd);
1852 *evtmask = eventmask;
1853 TRACE("%s%s%s%s%s%s%s%s%s\n",
1854 (eventmask&EV_BREAK)?"EV_BREAK":"",
1855 (eventmask&EV_CTS)?"EV_CTS":"",
1856 (eventmask&EV_DSR)?"EV_DSR":"",
1857 (eventmask&EV_ERR)?"EV_ERR":"",
1858 (eventmask&EV_RING)?"EV_RING":"",
1859 (eventmask&EV_RLSD)?"EV_RLSD":"",
1860 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1861 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1862 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1864 return TRUE;
1867 /*****************************************************************************
1868 * SetCommMask (KERNEL32.451)
1870 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1872 int fd;
1874 TRACE("handle %d, mask %lx\n", handle, evtmask);
1875 TRACE("%s%s%s%s%s%s%s%s%s\n",
1876 (evtmask&EV_BREAK)?"EV_BREAK":"",
1877 (evtmask&EV_CTS)?"EV_CTS":"",
1878 (evtmask&EV_DSR)?"EV_DSR":"",
1879 (evtmask&EV_ERR)?"EV_ERR":"",
1880 (evtmask&EV_RING)?"EV_RING":"",
1881 (evtmask&EV_RLSD)?"EV_RLSD":"",
1882 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1883 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1884 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1886 if(0>(fd=COMM_GetWriteFd(handle))) {
1887 FIXME("no handle %d found\n",handle);
1888 return FALSE;
1890 close(fd);
1891 eventmask = evtmask;
1892 return TRUE;
1895 /*****************************************************************************
1896 * SetCommState (KERNEL32.452)
1898 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1900 struct termios port;
1901 int fd;
1903 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1904 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1905 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1906 (lpdcb->StopBits == ONESTOPBIT)?1:
1907 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1908 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1909 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1911 if ((fd = COMM_GetWriteFd(handle)) < 0) {
1912 FIXME("no handle %d found\n",handle);
1913 return FALSE;
1916 if ((tcgetattr(fd,&port)) == -1) {
1917 int save_error = errno;
1918 commerror = WinError();
1919 close( fd );
1920 #ifdef HAVE_STRERROR
1921 ERR("tcgetattr error '%s'\n", strerror(save_error));
1922 #else
1923 ERR("tcgetattr error %d\n", save_error);
1924 #endif
1925 return FALSE;
1928 port.c_cc[VMIN] = 0;
1929 port.c_cc[VTIME] = 1;
1931 #ifdef IMAXBEL
1932 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1933 #else
1934 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1935 #endif
1936 port.c_iflag |= (IGNBRK);
1938 port.c_oflag &= ~(OPOST);
1940 port.c_cflag &= ~(HUPCL);
1941 port.c_cflag |= CLOCAL | CREAD;
1943 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1944 port.c_lflag |= NOFLSH;
1947 ** MJM - removed default baudrate settings
1948 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1950 #ifdef CBAUD
1951 port.c_cflag &= ~CBAUD;
1952 switch (lpdcb->BaudRate) {
1953 case 110:
1954 case CBR_110:
1955 port.c_cflag |= B110;
1956 break;
1957 case 300:
1958 case CBR_300:
1959 port.c_cflag |= B300;
1960 break;
1961 case 600:
1962 case CBR_600:
1963 port.c_cflag |= B600;
1964 break;
1965 case 1200:
1966 case CBR_1200:
1967 port.c_cflag |= B1200;
1968 break;
1969 case 2400:
1970 case CBR_2400:
1971 port.c_cflag |= B2400;
1972 break;
1973 case 4800:
1974 case CBR_4800:
1975 port.c_cflag |= B4800;
1976 break;
1977 case 9600:
1978 case CBR_9600:
1979 port.c_cflag |= B9600;
1980 break;
1981 case 19200:
1982 case CBR_19200:
1983 port.c_cflag |= B19200;
1984 break;
1985 case 38400:
1986 case CBR_38400:
1987 port.c_cflag |= B38400;
1988 break;
1989 #ifdef B57600
1990 case 57600:
1991 port.c_cflag |= B57600;
1992 break;
1993 #endif
1994 #ifdef B115200
1995 case 115200:
1996 port.c_cflag |= B115200;
1997 break;
1998 #endif
1999 #ifdef B230400
2000 case 230400:
2001 port.c_cflag |= B230400;
2002 break;
2003 #endif
2004 #ifdef B460800
2005 case 460600:
2006 port.c_cflag |= B460800;
2007 break;
2008 #endif
2009 default:
2010 commerror = IE_BAUDRATE;
2011 close( fd );
2012 ERR("baudrate %ld\n",lpdcb->BaudRate);
2013 return FALSE;
2015 #elif !defined(__EMX__)
2016 switch (lpdcb->BaudRate) {
2017 case 110:
2018 case CBR_110:
2019 port.c_ospeed = B110;
2020 break;
2021 case 300:
2022 case CBR_300:
2023 port.c_ospeed = B300;
2024 break;
2025 case 600:
2026 case CBR_600:
2027 port.c_ospeed = B600;
2028 break;
2029 case 1200:
2030 case CBR_1200:
2031 port.c_ospeed = B1200;
2032 break;
2033 case 2400:
2034 case CBR_2400:
2035 port.c_ospeed = B2400;
2036 break;
2037 case 4800:
2038 case CBR_4800:
2039 port.c_ospeed = B4800;
2040 break;
2041 case 9600:
2042 case CBR_9600:
2043 port.c_ospeed = B9600;
2044 break;
2045 case 19200:
2046 case CBR_19200:
2047 port.c_ospeed = B19200;
2048 break;
2049 case 38400:
2050 case CBR_38400:
2051 port.c_ospeed = B38400;
2052 break;
2053 default:
2054 commerror = IE_BAUDRATE;
2055 close( fd );
2056 ERR("baudrate %d \n",lpdcb->BaudRate);
2057 return FALSE;
2059 port.c_ispeed = port.c_ospeed;
2060 #endif
2061 port.c_cflag &= ~CSIZE;
2062 switch (lpdcb->ByteSize) {
2063 case 5:
2064 port.c_cflag |= CS5;
2065 break;
2066 case 6:
2067 port.c_cflag |= CS6;
2068 break;
2069 case 7:
2070 port.c_cflag |= CS7;
2071 break;
2072 case 8:
2073 port.c_cflag |= CS8;
2074 break;
2075 default:
2076 commerror = IE_BYTESIZE;
2077 close( fd );
2078 ERR("ByteSize\n");
2079 return FALSE;
2082 port.c_cflag &= ~(PARENB | PARODD);
2083 if (lpdcb->fParity)
2084 port.c_iflag |= INPCK;
2085 else
2086 port.c_iflag &= ~INPCK;
2087 switch (lpdcb->Parity) {
2088 case NOPARITY:
2089 break;
2090 case ODDPARITY:
2091 port.c_cflag |= (PARENB | PARODD);
2092 break;
2093 case EVENPARITY:
2094 port.c_cflag |= PARENB;
2095 break;
2096 default:
2097 commerror = IE_BYTESIZE;
2098 close( fd );
2099 ERR("Parity\n");
2100 return FALSE;
2104 switch (lpdcb->StopBits) {
2105 case ONESTOPBIT:
2106 port.c_cflag &= ~CSTOPB;
2107 break;
2108 case TWOSTOPBITS:
2109 port.c_cflag |= CSTOPB;
2110 break;
2111 default:
2112 commerror = IE_BYTESIZE;
2113 close( fd );
2114 ERR("StopBits\n");
2115 return FALSE;
2117 #ifdef CRTSCTS
2118 if ( lpdcb->fOutxCtsFlow ||
2119 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2120 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2123 port.c_cflag |= CRTSCTS;
2124 TRACE("CRTSCTS\n");
2127 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2129 port.c_cflag &= ~CRTSCTS;
2130 TRACE("~CRTSCTS\n");
2133 #endif
2134 if (lpdcb->fInX)
2135 port.c_iflag |= IXON;
2136 else
2137 port.c_iflag &= ~IXON;
2138 if (lpdcb->fOutX)
2139 port.c_iflag |= IXOFF;
2140 else
2141 port.c_iflag &= ~IXOFF;
2143 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2144 int save_error=errno;
2145 commerror = WinError();
2146 close( fd );
2147 #ifdef HAVE_STRERROR
2148 ERR("tcgetattr error '%s'\n", strerror(save_error));
2149 #else
2150 ERR("tcgetattr error %d\n", save_error);
2151 #endif
2152 return FALSE;
2153 } else {
2154 commerror = 0;
2155 close( fd );
2156 return TRUE;
2161 /*****************************************************************************
2162 * GetCommState (KERNEL32.159)
2164 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2166 struct termios port;
2167 int fd,speed;
2169 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2171 if ((fd = COMM_GetReadFd(handle)) < 0)
2173 ERR("can't get COMM_GetReadFd\n");
2174 return FALSE;
2176 if (tcgetattr(fd, &port) == -1) {
2177 int save_error=errno;
2178 #ifdef HAVE_STRERROR
2179 ERR("tcgetattr error '%s'\n", strerror(save_error));
2180 #else
2181 ERR("tcgetattr error %d\n", save_error);
2182 #endif
2183 commerror = WinError();
2184 close( fd );
2185 return FALSE;
2187 close( fd );
2188 #ifndef __EMX__
2189 #ifdef CBAUD
2190 speed= (port.c_cflag & CBAUD);
2191 #else
2192 speed= (cfgetospeed(&port));
2193 #endif
2194 switch (speed) {
2195 case B110:
2196 lpdcb->BaudRate = 110;
2197 break;
2198 case B300:
2199 lpdcb->BaudRate = 300;
2200 break;
2201 case B600:
2202 lpdcb->BaudRate = 600;
2203 break;
2204 case B1200:
2205 lpdcb->BaudRate = 1200;
2206 break;
2207 case B2400:
2208 lpdcb->BaudRate = 2400;
2209 break;
2210 case B4800:
2211 lpdcb->BaudRate = 4800;
2212 break;
2213 case B9600:
2214 lpdcb->BaudRate = 9600;
2215 break;
2216 case B19200:
2217 lpdcb->BaudRate = 19200;
2218 break;
2219 case B38400:
2220 lpdcb->BaudRate = 38400;
2221 break;
2222 #ifdef B57600
2223 case B57600:
2224 lpdcb->BaudRate = 57600;
2225 break;
2226 #endif
2227 #ifdef B115200
2228 case B115200:
2229 lpdcb->BaudRate = 115200;
2230 break;
2231 #endif
2232 #ifdef B230400
2233 case B230400:
2234 lpdcb->BaudRate = 230400;
2235 break;
2236 #endif
2237 #ifdef B460800
2238 case B460800:
2239 lpdcb->BaudRate = 460800;
2240 break;
2241 #endif
2242 default:
2243 ERR("unknown speed %x \n",speed);
2245 #endif
2246 switch (port.c_cflag & CSIZE) {
2247 case CS5:
2248 lpdcb->ByteSize = 5;
2249 break;
2250 case CS6:
2251 lpdcb->ByteSize = 6;
2252 break;
2253 case CS7:
2254 lpdcb->ByteSize = 7;
2255 break;
2256 case CS8:
2257 lpdcb->ByteSize = 8;
2258 break;
2259 default:
2260 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2263 if(port.c_iflag & INPCK)
2264 lpdcb->fParity = TRUE;
2265 else
2266 lpdcb->fParity = FALSE;
2267 switch (port.c_cflag & (PARENB | PARODD)) {
2268 case 0:
2269 lpdcb->Parity = NOPARITY;
2270 break;
2271 case PARENB:
2272 lpdcb->Parity = EVENPARITY;
2273 break;
2274 case (PARENB | PARODD):
2275 lpdcb->Parity = ODDPARITY;
2276 break;
2279 if (port.c_cflag & CSTOPB)
2280 lpdcb->StopBits = TWOSTOPBITS;
2281 else
2282 lpdcb->StopBits = ONESTOPBIT;
2284 lpdcb->fNull = 0;
2285 lpdcb->fBinary = 1;
2287 #ifdef CRTSCTS
2289 if (port.c_cflag & CRTSCTS) {
2290 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2291 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2292 lpdcb->fOutxCtsFlow = 1;
2293 lpdcb->fOutxDsrFlow = 1;
2294 } else
2295 #endif
2297 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2298 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2300 if (port.c_iflag & IXON)
2301 lpdcb->fInX = 1;
2302 else
2303 lpdcb->fInX = 0;
2305 if (port.c_iflag & IXOFF)
2306 lpdcb->fOutX = 1;
2307 else
2308 lpdcb->fOutX = 0;
2310 lpdcb->XonChar =
2311 lpdcb->XoffChar =
2313 lpdcb->XonLim = 10;
2314 lpdcb->XoffLim = 10;
2316 commerror = 0;
2318 TRACE("OK\n");
2320 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2321 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2322 (lpdcb->StopBits == ONESTOPBIT)?1:
2323 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2324 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2325 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2326 #ifdef CRTSCTS
2327 if ( lpdcb->fOutxCtsFlow ||
2328 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2329 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2331 TRACE("CRTSCTS\n");
2333 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2334 TRACE("~CRTSCTS\n");
2336 #endif
2337 return TRUE;
2340 /*****************************************************************************
2341 * TransmitCommChar (KERNEL32.535)
2343 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2345 struct DosDeviceStruct *ptr;
2347 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2348 if ((ptr = GetDeviceStruct(cid)) == NULL)
2349 FIXME("no handle for cid = %0x!.\n",cid);
2350 return FALSE;
2352 if (ptr->suspended) {
2353 ptr->commerror = IE_HARDWARE;
2354 return FALSE;
2356 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2357 ptr->commerror = WinError();
2358 return FALSE;
2359 } else {
2360 ptr->commerror = 0;
2361 return TRUE;
2365 /*****************************************************************************
2366 * GetCommTimeouts (KERNEL32.160)
2368 BOOL WINAPI GetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts)
2370 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2371 return TRUE;
2374 /*****************************************************************************
2375 * SetCommTimeouts (KERNEL32.453)
2377 BOOL WINAPI SetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts) {
2378 /* struct DosDeviceStruct *ptr; */
2379 struct termios tios;
2380 int fd;
2382 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2384 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2385 FIXME("no handle for cid = %0x!.\n",hcom);
2386 return FALSE;
2390 fd = COMM_GetWriteFd(hcom);
2391 if (fd < 0) {
2392 FIXME("no fd for cid = %0x!.\n",hcom);
2393 return FALSE;
2397 FIXME("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2398 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts->ReadTotalTimeoutMultiplier);
2399 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts->ReadTotalTimeoutConstant);
2400 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts->WriteTotalTimeoutMultiplier);
2401 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts->WriteTotalTimeoutConstant);
2404 if (-1==tcgetattr(fd,&tios)) {
2405 FIXME("tcgetattr on fd %d failed!\n",fd);
2406 return FALSE;
2408 /* VTIME is in 1/10 seconds */
2409 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2410 if (-1==tcsetattr(fd,0,&tios)) {
2411 FIXME("tcsetattr on fd %d failed!\n",fd);
2412 return FALSE;
2414 return TRUE;
2417 /***********************************************************************
2418 * GetCommModemStatus (KERNEL32.285)
2420 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2422 int fd,mstat, result=FALSE;
2424 *lpModemStat=0;
2425 #ifdef TIOCMGET
2426 fd = COMM_GetWriteFd(hFile);
2427 if(fd<0)
2428 return FALSE;
2429 result = ioctl(fd, TIOCMGET, &mstat);
2430 close(fd);
2431 if (result == -1)
2433 TRACE("ioctl failed\n");
2434 return FALSE;
2436 if (mstat & TIOCM_CTS)
2437 *lpModemStat |= MS_CTS_ON;
2438 if (mstat & TIOCM_DSR)
2439 *lpModemStat |= MS_DSR_ON;
2440 if (mstat & TIOCM_RNG)
2441 *lpModemStat |= MS_RING_ON;
2442 /*FIXME: Not really sure about RLSD UB 990810*/
2443 if (mstat & TIOCM_CAR)
2444 *lpModemStat |= MS_RLSD_ON;
2445 TRACE("%s%s%s%s\n",
2446 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2447 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2448 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2449 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2450 return TRUE;
2451 #else
2452 return FALSE;
2453 #endif
2455 /***********************************************************************
2456 * WaitCommEvent (KERNEL32.719)
2458 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2460 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2461 return TRUE;
2464 /***********************************************************************
2465 * GetCommProperties (KERNEL32.???)
2467 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2469 FIXME("(%d %p )\n",hFile,dcb);
2470 return TRUE;
2473 /***********************************************************************
2474 * SetCommProperties (KERNEL32.???)
2476 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2478 FIXME("(%d %p )\n",hFile,dcb);
2479 return TRUE;