Fixed file descriptor leaks.
[wine/multimedia.git] / misc / comm.c
blobc5f5eb522567337f2c231fe532802c43ac301642
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
82 /* window's semi documented modem status register */
83 #define COMM_MSR_OFFSET 35
84 #define MSR_CTS 0x10
85 #define MSR_DSR 0x20
86 #define MSR_RI 0x40
87 #define MSR_RLSD 0x80
88 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
90 #define FLAG_LPT 0x80
92 struct DosDeviceStruct COM[MAX_PORTS];
93 struct DosDeviceStruct LPT[MAX_PORTS];
94 /* pointers to unknown(==undocumented) comm structure */
95 LPCVOID *unknown[MAX_PORTS];
96 /* save terminal states */
97 static struct termios m_stat[MAX_PORTS];
99 /* update window's semi documented modem status register */
100 /* see knowledge base Q101417 */
101 static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
103 UCHAR tmpmsr=0;
104 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
105 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
106 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
107 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
108 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
111 void COMM_Init(void)
113 int x;
114 char option[10], temp[256], *btemp;
115 struct stat st;
117 for (x=0; x!=MAX_PORTS; x++) {
118 strcpy(option,"COMx");
119 option[3] = '1' + x;
120 option[4] = '\0';
122 PROFILE_GetWineIniString( "serialports", option, "*",
123 temp, sizeof(temp) );
124 if (!strcmp(temp, "*") || *temp == '\0')
125 COM[x].devicename = NULL;
126 else {
127 btemp = strchr(temp,',');
128 if (btemp != NULL) {
129 *btemp++ = '\0';
130 COM[x].baudrate = atoi(btemp);
131 } else {
132 COM[x].baudrate = -1;
134 stat(temp, &st);
135 if (!S_ISCHR(st.st_mode))
136 WARN("Can't use `%s' as %s !\n", temp, option);
137 else
138 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
139 WARN("Can't malloc for device info!\n");
140 else {
141 COM[x].fd = 0;
142 strcpy(COM[x].devicename, temp);
144 TRACE("%s = %s\n", option, COM[x].devicename);
147 strcpy(option, "LPTx");
148 option[3] = '1' + x;
149 option[4] = '\0';
151 PROFILE_GetWineIniString( "parallelports", option, "*",
152 temp, sizeof(temp) );
153 if (!strcmp(temp, "*") || *temp == '\0')
154 LPT[x].devicename = NULL;
155 else {
156 stat(temp, &st);
157 if (!S_ISCHR(st.st_mode))
158 WARN("Can't use `%s' as %s !\n", temp, option);
159 else
160 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
161 WARN("Can't malloc for device info!\n");
162 else {
163 LPT[x].fd = 0;
164 strcpy(LPT[x].devicename, temp);
166 TRACE("%s = %s\n", option, LPT[x].devicename);
173 static struct DosDeviceStruct *GetDeviceStruct(int fd)
175 if ((fd&0x7F)<=MAX_PORTS) {
176 if (!(fd&FLAG_LPT)) {
177 if (COM[fd].fd)
178 return &COM[fd];
179 } else {
180 fd &= 0x7f;
181 if (LPT[fd].fd)
182 return &LPT[fd];
186 return NULL;
189 static int GetCommPort_fd(int fd)
191 int x;
193 for (x=0; x<MAX_PORTS; x++) {
194 if (COM[x].fd == fd)
195 return x;
198 return -1;
201 static int ValidCOMPort(int x)
203 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
206 static int ValidLPTPort(int x)
208 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
211 static int WinError(void)
213 TRACE("errno = %d\n", errno);
214 switch (errno) {
215 default:
216 return CE_IOE;
220 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
222 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
223 + ptr->ibuf_head - ptr->ibuf_tail;
226 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
228 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
229 + ptr->obuf_head - ptr->obuf_tail;
232 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
234 unsigned int mstat, okay;
235 okay = ioctl(fd, TIOCMGET, &mstat);
236 if (okay) return okay;
237 if (andy) mstat &= andy;
238 mstat |= orrie;
239 return ioctl(fd, TIOCMSET, &mstat);
242 static void CALLBACK comm_notification( ULONG_PTR private )
244 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
245 int prev, bleft, len;
246 WORD mask = 0;
247 int cid = GetCommPort_fd(ptr->fd);
249 TRACE("async notification\n");
250 /* read data from comm port */
251 prev = comm_inbuf(ptr);
252 do {
253 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
254 - ptr->ibuf_head;
255 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
256 if (len > 0) {
257 if (!bleft) {
258 ptr->commerror = CE_RXOVER;
259 } else {
260 /* check for events */
261 if ((ptr->eventmask & EV_RXFLAG) &&
262 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
263 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
264 mask |= CN_EVENT;
266 if (ptr->eventmask & EV_RXCHAR) {
267 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
268 mask |= CN_EVENT;
270 /* advance buffer position */
271 ptr->ibuf_head += len;
272 if (ptr->ibuf_head >= ptr->ibuf_size)
273 ptr->ibuf_head = 0;
276 } while (len > 0);
277 /* check for notification */
278 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
279 (comm_inbuf(ptr)>=ptr->n_read)) {
280 /* passed the receive notification threshold */
281 mask |= CN_RECEIVE;
284 /* write any TransmitCommChar character */
285 if (ptr->xmit>=0) {
286 len = write(ptr->fd, &(ptr->xmit), 1);
287 if (len > 0) ptr->xmit = -1;
289 /* write from output queue */
290 prev = comm_outbuf(ptr);
291 do {
292 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
293 - ptr->obuf_tail;
294 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
295 if (len > 0) {
296 ptr->obuf_tail += len;
297 if (ptr->obuf_tail >= ptr->obuf_size)
298 ptr->obuf_tail = 0;
299 /* flag event */
300 if (ptr->obuf_tail == ptr->obuf_head) {
301 if (ptr->s_write) {
302 SERVICE_Delete( ptr->s_write );
303 ptr->s_write = INVALID_HANDLE_VALUE;
305 if (ptr->eventmask & EV_TXEMPTY) {
306 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
307 mask |= CN_EVENT;
311 } while (len > 0);
312 /* check for notification */
313 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
314 (comm_outbuf(ptr)<ptr->n_write)) {
315 /* passed the transmit notification threshold */
316 mask |= CN_TRANSMIT;
319 /* send notifications, if any */
320 if (ptr->wnd && mask) {
321 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
322 Callout.PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
326 static void comm_waitread(struct DosDeviceStruct *ptr)
328 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
329 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
330 GENERIC_READ | SYNCHRONIZE ),
331 comm_notification,
332 (ULONG_PTR)ptr );
335 static void comm_waitwrite(struct DosDeviceStruct *ptr)
337 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
338 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
339 GENERIC_WRITE | SYNCHRONIZE ),
340 comm_notification,
341 (ULONG_PTR)ptr );
344 /**************************************************************************
345 * BuildCommDCB (USER.213)
347 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
349 /* "COM1:9600,n,8,1" */
350 /* 012345 */
351 int port;
352 char *ptr, temp[256];
354 TRACE("(%s), ptr %p\n", device, lpdcb);
356 if (!lstrncmpiA(device,"COM",3)) {
357 port = device[3] - '0';
360 if (port-- == 0) {
361 ERR("BUG ! COM0 can't exist!.\n");
362 return -1;
365 if (!ValidCOMPort(port)) {
366 FIXME("invalid COM port %d?\n",port);
367 return -1;
370 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
372 lpdcb->Id = port;
374 if (!*(device+4))
375 return 0;
377 if (*(device+4) != ':')
378 return -1;
380 strcpy(temp,device+5);
381 ptr = strtok(temp, ", ");
383 if (COM[port].baudrate > 0)
384 lpdcb->BaudRate = COM[port].baudrate;
385 else
386 lpdcb->BaudRate = atoi(ptr);
387 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
389 ptr = strtok(NULL, ", ");
390 if (islower(*ptr))
391 *ptr = toupper(*ptr);
393 TRACE("parity (%c)\n", *ptr);
394 lpdcb->fParity = TRUE;
395 switch (*ptr) {
396 case 'N':
397 lpdcb->Parity = NOPARITY;
398 lpdcb->fParity = FALSE;
399 break;
400 case 'E':
401 lpdcb->Parity = EVENPARITY;
402 break;
403 case 'M':
404 lpdcb->Parity = MARKPARITY;
405 break;
406 case 'O':
407 lpdcb->Parity = ODDPARITY;
408 break;
409 default:
410 WARN("Unknown parity `%c'!\n", *ptr);
411 return -1;
414 ptr = strtok(NULL, ", ");
415 TRACE("charsize (%c)\n", *ptr);
416 lpdcb->ByteSize = *ptr - '0';
418 ptr = strtok(NULL, ", ");
419 TRACE("stopbits (%c)\n", *ptr);
420 switch (*ptr) {
421 case '1':
422 lpdcb->StopBits = ONESTOPBIT;
423 break;
424 case '2':
425 lpdcb->StopBits = TWOSTOPBITS;
426 break;
427 default:
428 WARN("Unknown # of stopbits `%c'!\n", *ptr);
429 return -1;
433 return 0;
436 /*****************************************************************************
437 * OpenComm (USER.200)
439 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
441 int port,fd;
443 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
445 if (strlen(device) < 4)
446 return IE_BADID;
448 port = device[3] - '0';
450 if (port-- == 0)
451 ERR("BUG ! COM0 or LPT0 don't exist !\n");
453 if (!lstrncmpiA(device,"COM",3)) {
455 TRACE("%s = %s\n", device, COM[port].devicename);
457 if (!ValidCOMPort(port))
458 return IE_BADID;
460 if (COM[port].fd)
461 return IE_OPEN;
463 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
464 if (fd == -1) {
465 ERR("error=%d\n", errno);
466 return IE_HARDWARE;
467 } else {
468 unknown[port] = SEGPTR_ALLOC(40);
469 bzero(unknown[port],40);
470 COM[port].fd = fd;
471 COM[port].commerror = 0;
472 COM[port].eventmask = 0;
473 COM[port].evtchar = 0; /* FIXME: default? */
474 /* save terminal state */
475 tcgetattr(fd,&m_stat[port]);
476 /* set default parameters */
477 if(COM[port].baudrate>-1){
478 DCB16 dcb;
479 GetCommState16(port, &dcb);
480 dcb.BaudRate=COM[port].baudrate;
481 /* more defaults:
482 * databits, parity, stopbits
484 SetCommState16( &dcb);
486 /* init priority characters */
487 COM[port].unget = -1;
488 COM[port].xmit = -1;
489 /* allocate buffers */
490 COM[port].ibuf_size = cbInQueue;
491 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
492 COM[port].obuf_size = cbOutQueue;
493 COM[port].obuf_head = COM[port].obuf_tail = 0;
495 COM[port].inbuf = malloc(cbInQueue);
496 if (COM[port].inbuf) {
497 COM[port].outbuf = malloc(cbOutQueue);
498 if (!COM[port].outbuf)
499 free(COM[port].inbuf);
500 } else COM[port].outbuf = NULL;
501 if (!COM[port].outbuf) {
502 /* not enough memory */
503 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
504 close(COM[port].fd);
505 ERR("out of memory");
506 return IE_MEMORY;
509 COM[port].s_read = INVALID_HANDLE_VALUE;
510 COM[port].s_write = INVALID_HANDLE_VALUE;
511 comm_waitread( &COM[port] );
512 return port;
515 else
516 if (!lstrncmpiA(device,"LPT",3)) {
518 if (!ValidLPTPort(port))
519 return IE_BADID;
521 if (LPT[port].fd)
522 return IE_OPEN;
524 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
525 if (fd == -1) {
526 return IE_HARDWARE;
527 } else {
528 LPT[port].fd = fd;
529 LPT[port].commerror = 0;
530 LPT[port].eventmask = 0;
531 return port|FLAG_LPT;
534 return 0;
537 /*****************************************************************************
538 * CloseComm (USER.207)
540 INT16 WINAPI CloseComm16(INT16 cid)
542 struct DosDeviceStruct *ptr;
544 TRACE("cid=%d\n", cid);
545 if ((ptr = GetDeviceStruct(cid)) == NULL) {
546 FIXME("no cid=%d found!\n", cid);
547 return -1;
549 if (!(cid&FLAG_LPT)) {
550 /* COM port */
551 SEGPTR_FREE(unknown[cid]); /* [LW] */
553 SERVICE_Delete( COM[cid].s_write );
554 SERVICE_Delete( COM[cid].s_read );
555 /* free buffers */
556 free(ptr->outbuf);
557 free(ptr->inbuf);
559 /* reset modem lines */
560 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
563 if (close(ptr->fd) == -1) {
564 ptr->commerror = WinError();
565 /* FIXME: should we clear ptr->fd here? */
566 return -1;
567 } else {
568 ptr->commerror = 0;
569 ptr->fd = 0;
570 return 0;
574 /*****************************************************************************
575 * SetCommBreak (USER.210)
577 INT16 WINAPI SetCommBreak16(INT16 cid)
579 struct DosDeviceStruct *ptr;
581 TRACE("cid=%d\n", cid);
582 if ((ptr = GetDeviceStruct(cid)) == NULL) {
583 FIXME("no cid=%d found!\n", cid);
584 return -1;
587 ptr->suspended = 1;
588 ptr->commerror = 0;
589 return 0;
592 /*****************************************************************************
593 * ClearCommBreak (USER.211)
595 INT16 WINAPI ClearCommBreak16(INT16 cid)
597 struct DosDeviceStruct *ptr;
599 TRACE("cid=%d\n", cid);
600 if (!(ptr = GetDeviceStruct(cid))) {
601 FIXME("no cid=%d found!\n", cid);
602 return -1;
604 ptr->suspended = 0;
605 ptr->commerror = 0;
606 return 0;
609 /*****************************************************************************
610 * EscapeCommFunction (USER.214)
612 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
614 int max;
615 struct DosDeviceStruct *ptr;
616 struct termios port;
618 TRACE("cid=%d, function=%d\n", cid, nFunction);
619 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
620 if ((ptr = GetDeviceStruct(cid)) == NULL) {
621 FIXME("no cid=%d found!\n", cid);
622 return -1;
624 if (tcgetattr(ptr->fd,&port) == -1) {
625 TRACE("tcgetattr failed\n");
626 ptr->commerror=WinError();
627 return -1;
629 } else ptr = NULL;
631 switch (nFunction) {
632 case RESETDEV:
633 TRACE("RESETDEV\n");
634 break;
636 case GETMAXCOM:
637 TRACE("GETMAXCOM\n");
638 for (max = MAX_PORTS;!COM[max].devicename;max--)
640 return max;
641 break;
643 case GETMAXLPT:
644 TRACE("GETMAXLPT\n");
645 for (max = MAX_PORTS;!LPT[max].devicename;max--)
647 return FLAG_LPT + max;
648 break;
650 case GETBASEIRQ:
651 TRACE("GETBASEIRQ\n");
652 /* FIXME: use tables */
653 /* just fake something for now */
654 if (cid & FLAG_LPT) {
655 /* LPT1: irq 7, LPT2: irq 5 */
656 return (cid & 0x7f) ? 5 : 7;
657 } else {
658 /* COM1: irq 4, COM2: irq 3,
659 COM3: irq 4, COM4: irq 3 */
660 return 4 - (cid & 1);
662 break;
664 case CLRDTR:
665 TRACE("CLRDTR\n");
666 #ifdef TIOCM_DTR
667 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
668 #endif
669 case CLRRTS:
670 TRACE("CLRRTS\n");
671 #ifdef TIOCM_RTS
672 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
673 #endif
675 case SETDTR:
676 TRACE("SETDTR\n");
677 #ifdef TIOCM_DTR
678 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
679 #endif
681 case SETRTS:
682 TRACE("SETRTS\n");
683 #ifdef TIOCM_RTS
684 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
685 #endif
687 case SETXOFF:
688 TRACE("SETXOFF\n");
689 port.c_iflag |= IXOFF;
690 break;
692 case SETXON:
693 TRACE("SETXON\n");
694 port.c_iflag |= IXON;
695 break;
697 default:
698 WARN("(cid=%d,nFunction=%d): Unknown function\n",
699 cid, nFunction);
700 break;
703 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
704 ptr->commerror = WinError();
705 return -1;
706 } else {
707 ptr->commerror = 0;
708 return 0;
712 /*****************************************************************************
713 * FlushComm (USER.215)
715 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
717 int queue;
718 struct DosDeviceStruct *ptr;
720 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
721 if ((ptr = GetDeviceStruct(cid)) == NULL) {
722 FIXME("no cid=%d found!\n", cid);
723 return -1;
725 switch (fnQueue) {
726 case 0:
727 queue = TCOFLUSH;
728 ptr->obuf_tail = ptr->obuf_head;
729 break;
730 case 1:
731 queue = TCIFLUSH;
732 ptr->ibuf_head = ptr->ibuf_tail;
733 break;
734 default:
735 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
736 cid, fnQueue);
737 return -1;
739 if (tcflush(ptr->fd, queue)) {
740 ptr->commerror = WinError();
741 return -1;
742 } else {
743 ptr->commerror = 0;
744 return 0;
748 /********************************************************************
749 * GetCommError (USER.203)
751 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
753 int temperror;
754 struct DosDeviceStruct *ptr;
755 unsigned char *stol;
756 unsigned int mstat;
758 if ((ptr = GetDeviceStruct(cid)) == NULL) {
759 FIXME("no handle for cid = %0x!.\n",cid);
760 return -1;
762 if (cid&FLAG_LPT) {
763 WARN(" cid %d not comm port\n",cid);
764 return CE_MODE;
766 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
767 ioctl(ptr->fd,TIOCMGET,&mstat);
768 COMM_MSRUpdate( stol, mstat);
770 if (lpStat) {
771 lpStat->status = 0;
773 lpStat->cbOutQue = comm_outbuf(ptr);
774 lpStat->cbInQue = comm_inbuf(ptr);
776 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
777 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
778 lpStat->cbOutQue, *stol);
780 else
781 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
782 cid, ptr->commerror, *stol);
784 /* Return any errors and clear it */
785 temperror = ptr->commerror;
786 ptr->commerror = 0;
787 return(temperror);
790 /*****************************************************************************
791 * SetCommEventMask (USER.208)
793 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
795 struct DosDeviceStruct *ptr;
796 unsigned char *stol;
797 int repid;
798 unsigned int mstat;
800 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
801 if ((ptr = GetDeviceStruct(cid)) == NULL) {
802 FIXME("no handle for cid = %0x!.\n",cid);
803 return (SEGPTR)NULL;
806 ptr->eventmask = fuEvtMask;
808 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
809 WARN(" cid %d not comm port\n",cid);
810 return (SEGPTR)NULL;
812 /* it's a COM port ? -> modify flags */
813 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
814 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
815 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
816 COMM_MSRUpdate( stol, mstat);
818 TRACE(" modem dcd construct %x\n",*stol);
819 return SEGPTR_GET(unknown[cid]);
822 /*****************************************************************************
823 * GetCommEventMask (USER.209)
825 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
827 struct DosDeviceStruct *ptr;
828 WORD events;
830 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
831 if ((ptr = GetDeviceStruct(cid)) == NULL) {
832 FIXME("no handle for cid = %0x!.\n",cid);
833 return 0;
836 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
837 WARN(" cid %d not comm port\n",cid);
838 return 0;
841 events = *(WORD*)(unknown[cid]) & fnEvtClear;
842 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
843 return events;
846 /*****************************************************************************
847 * SetCommState16 (USER.201)
849 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
851 struct termios port;
852 struct DosDeviceStruct *ptr;
854 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
855 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
856 FIXME("no handle for cid = %0x!.\n",lpdcb->Id);
857 return -1;
859 if (tcgetattr(ptr->fd, &port) == -1) {
860 ptr->commerror = WinError();
861 return -1;
864 port.c_cc[VMIN] = 0;
865 port.c_cc[VTIME] = 1;
867 #ifdef IMAXBEL
868 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
869 #else
870 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
871 #endif
872 port.c_iflag |= (IGNBRK);
874 port.c_oflag &= ~(OPOST);
876 port.c_cflag &= ~(HUPCL);
877 port.c_cflag |= CLOCAL | CREAD;
879 port.c_lflag &= ~(ICANON|ECHO|ISIG);
880 port.c_lflag |= NOFLSH;
882 TRACE("baudrate %d\n",lpdcb->BaudRate);
883 #ifdef CBAUD
884 port.c_cflag &= ~CBAUD;
885 switch (lpdcb->BaudRate) {
886 case 110:
887 case CBR_110:
888 port.c_cflag |= B110;
889 break;
890 case 300:
891 case CBR_300:
892 port.c_cflag |= B300;
893 break;
894 case 600:
895 case CBR_600:
896 port.c_cflag |= B600;
897 break;
898 case 1200:
899 case CBR_1200:
900 port.c_cflag |= B1200;
901 break;
902 case 2400:
903 case CBR_2400:
904 port.c_cflag |= B2400;
905 break;
906 case 4800:
907 case CBR_4800:
908 port.c_cflag |= B4800;
909 break;
910 case 9600:
911 case CBR_9600:
912 port.c_cflag |= B9600;
913 break;
914 case 19200:
915 case CBR_19200:
916 port.c_cflag |= B19200;
917 break;
918 case 38400:
919 case CBR_38400:
920 port.c_cflag |= B38400;
921 break;
922 #ifdef B57600
923 case 57600:
924 port.c_cflag |= B57600;
925 break;
926 #endif
927 #ifdef B115200
928 case 57601:
929 port.c_cflag |= B115200;
930 break;
931 #endif
932 default:
933 ptr->commerror = IE_BAUDRATE;
934 return -1;
936 #elif !defined(__EMX__)
937 switch (lpdcb->BaudRate) {
938 case 110:
939 case CBR_110:
940 port.c_ospeed = B110;
941 break;
942 case 300:
943 case CBR_300:
944 port.c_ospeed = B300;
945 break;
946 case 600:
947 case CBR_600:
948 port.c_ospeed = B600;
949 break;
950 case 1200:
951 case CBR_1200:
952 port.c_ospeed = B1200;
953 break;
954 case 2400:
955 case CBR_2400:
956 port.c_ospeed = B2400;
957 break;
958 case 4800:
959 case CBR_4800:
960 port.c_ospeed = B4800;
961 break;
962 case 9600:
963 case CBR_9600:
964 port.c_ospeed = B9600;
965 break;
966 case 19200:
967 case CBR_19200:
968 port.c_ospeed = B19200;
969 break;
970 case 38400:
971 case CBR_38400:
972 port.c_ospeed = B38400;
973 break;
974 default:
975 ptr->commerror = IE_BAUDRATE;
976 return -1;
978 port.c_ispeed = port.c_ospeed;
979 #endif
980 TRACE("bytesize %d\n",lpdcb->ByteSize);
981 port.c_cflag &= ~CSIZE;
982 switch (lpdcb->ByteSize) {
983 case 5:
984 port.c_cflag |= CS5;
985 break;
986 case 6:
987 port.c_cflag |= CS6;
988 break;
989 case 7:
990 port.c_cflag |= CS7;
991 break;
992 case 8:
993 port.c_cflag |= CS8;
994 break;
995 default:
996 ptr->commerror = IE_BYTESIZE;
997 return -1;
1000 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
1001 port.c_cflag &= ~(PARENB | PARODD);
1002 if (lpdcb->fParity)
1003 port.c_iflag |= INPCK;
1004 else
1005 port.c_iflag &= ~INPCK;
1006 switch (lpdcb->Parity) {
1007 case NOPARITY:
1008 break;
1009 case ODDPARITY:
1010 port.c_cflag |= (PARENB | PARODD);
1011 break;
1012 case EVENPARITY:
1013 port.c_cflag |= PARENB;
1014 break;
1015 default:
1016 ptr->commerror = IE_BYTESIZE;
1017 return -1;
1021 TRACE("stopbits %d\n",lpdcb->StopBits);
1023 switch (lpdcb->StopBits) {
1024 case ONESTOPBIT:
1025 port.c_cflag &= ~CSTOPB;
1026 break;
1027 case TWOSTOPBITS:
1028 port.c_cflag |= CSTOPB;
1029 break;
1030 default:
1031 ptr->commerror = IE_BYTESIZE;
1032 return -1;
1034 #ifdef CRTSCTS
1036 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1037 port.c_cflag |= CRTSCTS;
1039 if (lpdcb->fDtrDisable)
1040 port.c_cflag &= ~CRTSCTS;
1041 #endif
1042 if (lpdcb->fInX)
1043 port.c_iflag |= IXON;
1044 else
1045 port.c_iflag &= ~IXON;
1046 if (lpdcb->fOutX)
1047 port.c_iflag |= IXOFF;
1048 else
1049 port.c_iflag &= ~IXOFF;
1051 ptr->evtchar = lpdcb->EvtChar;
1053 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1054 ptr->commerror = WinError();
1055 return FALSE;
1056 } else {
1057 ptr->commerror = 0;
1058 return 0;
1062 /*****************************************************************************
1063 * GetCommState (USER.202)
1065 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1067 int speed;
1068 struct DosDeviceStruct *ptr;
1069 struct termios port;
1071 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1072 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1073 FIXME("no handle for cid = %0x!.\n",cid);
1074 return -1;
1076 if (tcgetattr(ptr->fd, &port) == -1) {
1077 ptr->commerror = WinError();
1078 return -1;
1080 lpdcb->Id = cid;
1081 #ifndef __EMX__
1082 #ifdef CBAUD
1083 speed = port.c_cflag & CBAUD;
1084 #else
1085 speed = port.c_ospeed;
1086 #endif
1087 switch(speed) {
1088 case B110:
1089 lpdcb->BaudRate = 110;
1090 break;
1091 case B300:
1092 lpdcb->BaudRate = 300;
1093 break;
1094 case B600:
1095 lpdcb->BaudRate = 600;
1096 break;
1097 case B1200:
1098 lpdcb->BaudRate = 1200;
1099 break;
1100 case B2400:
1101 lpdcb->BaudRate = 2400;
1102 break;
1103 case B4800:
1104 lpdcb->BaudRate = 4800;
1105 break;
1106 case B9600:
1107 lpdcb->BaudRate = 9600;
1108 break;
1109 case B19200:
1110 lpdcb->BaudRate = 19200;
1111 break;
1112 case B38400:
1113 lpdcb->BaudRate = 38400;
1114 break;
1115 #ifdef B57600
1116 case B57600:
1117 lpdcb->BaudRate = 57600;
1118 break;
1119 #endif
1120 #ifdef B115200
1121 case B115200:
1122 lpdcb->BaudRate = 57601;
1123 break;
1124 #endif
1126 #endif
1127 switch (port.c_cflag & CSIZE) {
1128 case CS5:
1129 lpdcb->ByteSize = 5;
1130 break;
1131 case CS6:
1132 lpdcb->ByteSize = 6;
1133 break;
1134 case CS7:
1135 lpdcb->ByteSize = 7;
1136 break;
1137 case CS8:
1138 lpdcb->ByteSize = 8;
1139 break;
1142 if(port.c_iflag & INPCK)
1143 lpdcb->fParity = TRUE;
1144 else
1145 lpdcb->fParity = FALSE;
1146 switch (port.c_cflag & (PARENB | PARODD)) {
1147 case 0:
1148 lpdcb->Parity = NOPARITY;
1149 break;
1150 case PARENB:
1151 lpdcb->Parity = EVENPARITY;
1152 break;
1153 case (PARENB | PARODD):
1154 lpdcb->Parity = ODDPARITY;
1155 break;
1158 if (port.c_cflag & CSTOPB)
1159 lpdcb->StopBits = TWOSTOPBITS;
1160 else
1161 lpdcb->StopBits = ONESTOPBIT;
1163 lpdcb->RlsTimeout = 50;
1164 lpdcb->CtsTimeout = 50;
1165 lpdcb->DsrTimeout = 50;
1166 lpdcb->fNull = 0;
1167 lpdcb->fChEvt = 0;
1168 lpdcb->fBinary = 1;
1169 lpdcb->fDtrDisable = 0;
1171 #ifdef CRTSCTS
1173 if (port.c_cflag & CRTSCTS) {
1174 lpdcb->fDtrflow = 1;
1175 lpdcb->fRtsflow = 1;
1176 lpdcb->fOutxCtsFlow = 1;
1177 lpdcb->fOutxDsrFlow = 1;
1178 } else
1179 #endif
1180 lpdcb->fDtrDisable = 1;
1182 if (port.c_iflag & IXON)
1183 lpdcb->fInX = 1;
1184 else
1185 lpdcb->fInX = 0;
1187 if (port.c_iflag & IXOFF)
1188 lpdcb->fOutX = 1;
1189 else
1190 lpdcb->fOutX = 0;
1192 lpdcb->XonChar =
1193 lpdcb->XoffChar =
1195 lpdcb->XonLim = 10;
1196 lpdcb->XoffLim = 10;
1198 lpdcb->EvtChar = ptr->evtchar;
1200 ptr->commerror = 0;
1201 return 0;
1204 /*****************************************************************************
1205 * TransmitCommChar (USER.206)
1207 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1209 struct DosDeviceStruct *ptr;
1211 TRACE("cid %d, data %d \n", cid, chTransmit);
1212 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1213 FIXME("no handle for cid = %0x!.\n",cid);
1214 return -1;
1217 if (ptr->suspended) {
1218 ptr->commerror = IE_HARDWARE;
1219 return -1;
1222 if (ptr->xmit >= 0) {
1223 /* character already queued */
1224 /* FIXME: which error would Windows return? */
1225 ptr->commerror = CE_TXFULL;
1226 return -1;
1229 if (ptr->obuf_head == ptr->obuf_tail) {
1230 /* transmit queue empty, try to transmit directly */
1231 if (write(ptr->fd, &chTransmit, 1) == -1) {
1232 /* didn't work, queue it */
1233 ptr->xmit = chTransmit;
1234 comm_waitwrite(ptr);
1236 } else {
1237 /* data in queue, let this char be transmitted next */
1238 ptr->xmit = chTransmit;
1239 comm_waitwrite(ptr);
1242 ptr->commerror = 0;
1243 return 0;
1246 /*****************************************************************************
1247 * UngetCommChar (USER.212)
1249 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1251 struct DosDeviceStruct *ptr;
1253 TRACE("cid %d (char %d)\n", cid, chUnget);
1254 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1255 FIXME("no handle for cid = %0x!.\n",cid);
1256 return -1;
1259 if (ptr->suspended) {
1260 ptr->commerror = IE_HARDWARE;
1261 return -1;
1264 if (ptr->unget>=0) {
1265 /* character already queued */
1266 /* FIXME: which error would Windows return? */
1267 ptr->commerror = CE_RXOVER;
1268 return -1;
1271 ptr->unget = chUnget;
1273 ptr->commerror = 0;
1274 return 0;
1277 /*****************************************************************************
1278 * ReadComm (USER.204)
1280 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1282 int status, length;
1283 struct DosDeviceStruct *ptr;
1284 LPSTR orgBuf = lpvBuf;
1286 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1287 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1288 FIXME("no handle for cid = %0x!.\n",cid);
1289 return -1;
1292 if (ptr->suspended) {
1293 ptr->commerror = IE_HARDWARE;
1294 return -1;
1297 /* read unget character */
1298 if (ptr->unget>=0) {
1299 *lpvBuf++ = ptr->unget;
1300 ptr->unget = -1;
1302 length = 1;
1303 } else
1304 length = 0;
1306 /* read from receive buffer */
1307 while (length < cbRead) {
1308 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1309 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1310 if (!status) break;
1311 if ((cbRead - length) < status)
1312 status = cbRead - length;
1314 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1315 ptr->ibuf_tail += status;
1316 if (ptr->ibuf_tail >= ptr->ibuf_size)
1317 ptr->ibuf_tail = 0;
1318 lpvBuf += status;
1319 length += status;
1322 TRACE("%.*s\n", length, orgBuf);
1323 ptr->commerror = 0;
1324 return length;
1327 /*****************************************************************************
1328 * WriteComm (USER.205)
1330 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1332 int status, length;
1333 struct DosDeviceStruct *ptr;
1335 TRACE("cid %d, ptr %p, length %d\n",
1336 cid, lpvBuf, cbWrite);
1337 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1338 FIXME("no handle for cid = %0x!.\n",cid);
1339 return -1;
1342 if (ptr->suspended) {
1343 ptr->commerror = IE_HARDWARE;
1344 return -1;
1347 TRACE("%.*s\n", cbWrite, lpvBuf );
1349 length = 0;
1350 while (length < cbWrite) {
1351 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1352 /* no data queued, try to write directly */
1353 status = write(ptr->fd, lpvBuf, cbWrite - length);
1354 if (status > 0) {
1355 lpvBuf += status;
1356 length += status;
1357 continue;
1360 /* can't write directly, put into transmit buffer */
1361 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1362 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1363 if (!status) break;
1364 if ((cbWrite - length) < status)
1365 status = cbWrite - length;
1366 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1367 ptr->obuf_head += status;
1368 if (ptr->obuf_head >= ptr->obuf_size)
1369 ptr->obuf_head = 0;
1370 lpvBuf += status;
1371 length += status;
1372 comm_waitwrite(ptr);
1375 ptr->commerror = 0;
1376 return length;
1379 /***********************************************************************
1380 * EnableCommNotification (USER.246)
1382 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1383 INT16 cbWriteNotify, INT16 cbOutQueue )
1385 struct DosDeviceStruct *ptr;
1387 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1388 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1389 FIXME("no handle for cid = %0x!.\n",cid);
1390 ptr->commerror = IE_BADID;
1391 return -1;
1393 ptr->wnd = hwnd;
1394 ptr->n_read = cbWriteNotify;
1395 ptr->n_write = cbOutQueue;
1396 return TRUE;
1400 /**************************************************************************
1401 * BuildCommDCBA (KERNEL32.14)
1403 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1405 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1408 /**************************************************************************
1409 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1411 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1412 LPCOMMTIMEOUTS lptimeouts)
1414 int port;
1415 char *ptr,*temp;
1417 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1419 if (!lstrncmpiA(device,"COM",3)) {
1420 port=device[3]-'0';
1421 if (port--==0) {
1422 ERR("BUG! COM0 can't exists!.\n");
1423 return FALSE;
1425 if (!ValidCOMPort(port))
1426 return FALSE;
1427 if (*(device+4)!=':')
1428 return FALSE;
1429 temp=(LPSTR)(device+5);
1430 } else
1431 temp=(LPSTR)device;
1433 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1435 lpdcb->DCBlength = sizeof(DCB);
1436 if (strchr(temp,',')) { /* old style */
1437 DCB16 dcb16;
1438 BOOL16 ret;
1439 char last=temp[strlen(temp)-1];
1441 ret=BuildCommDCB16(device,&dcb16);
1442 if (!ret)
1443 return FALSE;
1444 lpdcb->BaudRate = dcb16.BaudRate;
1445 lpdcb->ByteSize = dcb16.ByteSize;
1446 lpdcb->fBinary = dcb16.fBinary;
1447 lpdcb->Parity = dcb16.Parity;
1448 lpdcb->fParity = dcb16.fParity;
1449 lpdcb->fNull = dcb16.fNull;
1450 lpdcb->StopBits = dcb16.StopBits;
1451 if (last == 'x') {
1452 lpdcb->fInX = TRUE;
1453 lpdcb->fOutX = TRUE;
1454 lpdcb->fOutxCtsFlow = FALSE;
1455 lpdcb->fOutxDsrFlow = FALSE;
1456 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1457 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1458 } else if (last=='p') {
1459 lpdcb->fInX = FALSE;
1460 lpdcb->fOutX = FALSE;
1461 lpdcb->fOutxCtsFlow = TRUE;
1462 lpdcb->fOutxDsrFlow = TRUE;
1463 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1464 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1465 } else {
1466 lpdcb->fInX = FALSE;
1467 lpdcb->fOutX = FALSE;
1468 lpdcb->fOutxCtsFlow = FALSE;
1469 lpdcb->fOutxDsrFlow = FALSE;
1470 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1471 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1473 lpdcb->XonChar = dcb16.XonChar;
1474 lpdcb->XoffChar = dcb16.XoffChar;
1475 lpdcb->ErrorChar= dcb16.PeChar;
1476 lpdcb->fErrorChar= dcb16.fPeChar;
1477 lpdcb->EofChar = dcb16.EofChar;
1478 lpdcb->EvtChar = dcb16.EvtChar;
1479 lpdcb->XonLim = dcb16.XonLim;
1480 lpdcb->XoffLim = dcb16.XoffLim;
1481 return TRUE;
1483 ptr=strtok(temp," ");
1484 while (ptr) {
1485 DWORD flag,x;
1487 flag=0;
1488 if (!strncmp("baud=",ptr,5)) {
1489 if (!sscanf(ptr+5,"%ld",&x))
1490 WARN("Couldn't parse %s\n",ptr);
1491 lpdcb->BaudRate = x;
1492 flag=1;
1494 if (!strncmp("stop=",ptr,5)) {
1495 if (!sscanf(ptr+5,"%ld",&x))
1496 WARN("Couldn't parse %s\n",ptr);
1497 lpdcb->StopBits = x;
1498 flag=1;
1500 if (!strncmp("data=",ptr,5)) {
1501 if (!sscanf(ptr+5,"%ld",&x))
1502 WARN("Couldn't parse %s\n",ptr);
1503 lpdcb->ByteSize = x;
1504 flag=1;
1506 if (!strncmp("parity=",ptr,7)) {
1507 lpdcb->fParity = TRUE;
1508 switch (ptr[8]) {
1509 case 'N':case 'n':
1510 lpdcb->fParity = FALSE;
1511 lpdcb->Parity = NOPARITY;
1512 break;
1513 case 'E':case 'e':
1514 lpdcb->Parity = EVENPARITY;
1515 break;
1516 case 'O':case 'o':
1517 lpdcb->Parity = ODDPARITY;
1518 break;
1519 case 'M':case 'm':
1520 lpdcb->Parity = MARKPARITY;
1521 break;
1523 flag=1;
1525 if (!flag)
1526 ERR("Unhandled specifier '%s', please report.\n",ptr);
1527 ptr=strtok(NULL," ");
1529 if (lpdcb->BaudRate==110)
1530 lpdcb->StopBits = 2;
1531 return TRUE;
1534 /**************************************************************************
1535 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1537 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1538 LPCOMMTIMEOUTS lptimeouts )
1540 LPSTR devidA;
1541 BOOL ret;
1543 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1544 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1545 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1546 HeapFree( GetProcessHeap(), 0, devidA );
1547 return ret;
1550 /**************************************************************************
1551 * BuildCommDCBW (KERNEL32.17)
1553 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1555 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1558 /*****************************************************************************
1559 * COMM_GetReadFd
1560 * Returns a file descriptor for reading.
1561 * Make sure to close the handle afterwards!
1563 static int COMM_GetReadFd( HANDLE handle)
1565 int fd;
1566 struct get_read_fd_request *req = get_req_buffer();
1567 req->handle = handle;
1568 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1569 return fd;
1572 /*****************************************************************************
1573 * COMM_GetWriteFd
1574 * Returns a file descriptor for writing.
1575 * Make sure to close the handle afterwards!
1577 static int COMM_GetWriteFd( HANDLE handle)
1579 int fd = -1;
1580 struct get_write_fd_request *req = get_req_buffer();
1581 req->handle = handle;
1582 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1583 return fd;
1586 /* FIXME: having these global for win32 for now */
1587 int commerror=0,eventmask=0;
1589 /*****************************************************************************
1590 * SetCommBreak (KERNEL32.449)
1592 BOOL WINAPI SetCommBreak(HANDLE handle)
1594 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1595 int fd,result;
1597 fd = COMM_GetWriteFd(handle);
1598 if(fd<0) {
1599 TRACE("COMM_GetWriteFd failed\n");
1600 return FALSE;
1602 result = ioctl(fd,TIOCSBRK,0);
1603 close(fd);
1604 if (result ==-1)
1606 TRACE("ioctl failed\n");
1607 SetLastError(ERROR_NOT_SUPPORTED);
1608 return FALSE;
1610 return TRUE;
1611 #else
1612 FIXME("ioctl not available\n");
1613 SetLastError(ERROR_NOT_SUPPORTED);
1614 return FALSE;
1615 #endif
1618 /*****************************************************************************
1619 * ClearCommBreak (KERNEL32.20)
1621 BOOL WINAPI ClearCommBreak(HANDLE handle)
1623 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1624 int fd,result;
1626 fd = COMM_GetWriteFd(handle);
1627 if(fd<0) {
1628 TRACE("COMM_GetWriteFd failed\n");
1629 return FALSE;
1631 result = ioctl(fd,TIOCCBRK,0);
1632 close(fd);
1633 if (result ==-1)
1635 TRACE("ioctl failed\n");
1636 SetLastError(ERROR_NOT_SUPPORTED);
1637 return FALSE;
1639 return TRUE;
1640 #else
1641 FIXME("ioctl not available\n");
1642 SetLastError(ERROR_NOT_SUPPORTED);
1643 return FALSE;
1644 #endif
1647 /*****************************************************************************
1648 * EscapeCommFunction (KERNEL32.214)
1650 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1652 int fd,direct=FALSE,result=FALSE;
1653 struct termios port;
1655 TRACE("handle %d, function=%d\n", handle, nFunction);
1656 fd = COMM_GetWriteFd(handle);
1657 if(fd<0) {
1658 FIXME("handle %d not found.\n",handle);
1659 return FALSE;
1662 if (tcgetattr(fd,&port) == -1) {
1663 commerror=WinError();
1664 close(fd);
1665 return FALSE;
1668 switch (nFunction) {
1669 case RESETDEV:
1670 TRACE("\n");
1671 break;
1673 case CLRDTR:
1674 TRACE("CLRDTR\n");
1675 #ifdef TIOCM_DTR
1676 direct=TRUE;
1677 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1678 break;
1679 #endif
1681 case CLRRTS:
1682 TRACE("CLRRTS\n");
1683 #ifdef TIOCM_RTS
1684 direct=TRUE;
1685 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1686 break;
1687 #endif
1689 case SETDTR:
1690 TRACE("SETDTR\n");
1691 #ifdef TIOCM_DTR
1692 direct=TRUE;
1693 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1694 break;
1695 #endif
1697 case SETRTS:
1698 TRACE("SETRTS\n");
1699 #ifdef TIOCM_DTR
1700 direct=TRUE;
1701 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1702 break;
1703 #endif
1705 case SETXOFF:
1706 TRACE("SETXOFF\n");
1707 port.c_iflag |= IXOFF;
1708 break;
1710 case SETXON:
1711 TRACE("SETXON\n");
1712 port.c_iflag |= IXON;
1713 break;
1714 case SETBREAK:
1715 TRACE("setbreak\n");
1716 #ifdef TIOCSBRK
1717 direct=TRUE;
1718 result = ioctl(fd,TIOCSBRK,0);
1719 break;
1720 #endif
1721 case CLRBREAK:
1722 TRACE("clrbreak\n");
1723 #ifdef TIOCSBRK
1724 direct=TRUE;
1725 result = ioctl(fd,TIOCCBRK,0);
1726 break;
1727 #endif
1728 default:
1729 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1730 handle, nFunction);
1731 break;
1734 if (!direct)
1735 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1736 commerror = WinError();
1737 close(fd);
1738 return FALSE;
1739 } else
1740 result= TRUE;
1741 else
1743 if (result == -1)
1745 result= FALSE;
1746 commerror=WinError();
1748 else
1749 result = TRUE;
1751 close(fd);
1752 return result;
1755 /********************************************************************
1756 * PurgeComm (KERNEL32.557)
1758 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1760 int fd;
1762 TRACE("handle %d, flags %lx\n", handle, flags);
1764 fd = COMM_GetWriteFd(handle);
1765 if(fd<0) {
1766 FIXME("no handle %d found\n",handle);
1767 return FALSE;
1771 ** not exactly sure how these are different
1772 ** Perhaps if we had our own internal queues, one flushes them
1773 ** and the other flushes the kernel's buffers.
1775 if(flags&PURGE_TXABORT)
1776 tcflush(fd,TCOFLUSH);
1777 if(flags&PURGE_RXABORT)
1778 tcflush(fd,TCIFLUSH);
1779 if(flags&PURGE_TXCLEAR)
1780 tcflush(fd,TCOFLUSH);
1781 if(flags&PURGE_RXCLEAR)
1782 tcflush(fd,TCIFLUSH);
1783 close(fd);
1785 return 1;
1788 /*****************************************************************************
1789 * ClearCommError (KERNEL32.21)
1791 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1793 int fd;
1795 fd=COMM_GetReadFd(handle);
1796 if(0>fd)
1798 FIXME("no handle %d found\n",handle);
1799 return FALSE;
1802 if (lpStat)
1804 lpStat->status = 0;
1806 #ifdef TIOCOUTQ
1807 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1808 WARN("ioctl returned error\n");
1809 #else
1810 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1811 #endif
1813 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1814 WARN("ioctl returned error\n");
1816 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1817 handle, lpStat->cbInQue, lpStat->cbOutQue);
1820 close(fd);
1822 if(errors)
1823 *errors = 0;
1826 ** After an asynchronous write opperation, the
1827 ** app will call ClearCommError to see if the
1828 ** results are ready yet. It waits for ERROR_IO_PENDING
1830 commerror = ERROR_IO_PENDING;
1832 return TRUE;
1835 /*****************************************************************************
1836 * SetupComm (KERNEL32.676)
1838 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1840 int fd;
1842 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1843 fd=COMM_GetWriteFd(handle);
1844 if(0>fd) {
1845 FIXME("handle %d not found?\n",handle);
1846 return FALSE;
1848 close(fd);
1849 return TRUE;
1852 /*****************************************************************************
1853 * GetCommMask (KERNEL32.156)
1855 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1857 int fd;
1859 TRACE("handle %d, mask %p\n", handle, evtmask);
1860 if(0>(fd=COMM_GetReadFd(handle)))
1862 FIXME("no handle %d found\n",handle);
1863 return FALSE;
1865 close(fd);
1866 *evtmask = eventmask;
1867 TRACE("%s%s%s%s%s%s%s%s%s\n",
1868 (eventmask&EV_BREAK)?"EV_BREAK":"",
1869 (eventmask&EV_CTS)?"EV_CTS":"",
1870 (eventmask&EV_DSR)?"EV_DSR":"",
1871 (eventmask&EV_ERR)?"EV_ERR":"",
1872 (eventmask&EV_RING)?"EV_RING":"",
1873 (eventmask&EV_RLSD)?"EV_RLSD":"",
1874 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1875 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1876 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1878 return TRUE;
1881 /*****************************************************************************
1882 * SetCommMask (KERNEL32.451)
1884 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1886 int fd;
1888 TRACE("handle %d, mask %lx\n", handle, evtmask);
1889 TRACE("%s%s%s%s%s%s%s%s%s\n",
1890 (evtmask&EV_BREAK)?"EV_BREAK":"",
1891 (evtmask&EV_CTS)?"EV_CTS":"",
1892 (evtmask&EV_DSR)?"EV_DSR":"",
1893 (evtmask&EV_ERR)?"EV_ERR":"",
1894 (evtmask&EV_RING)?"EV_RING":"",
1895 (evtmask&EV_RLSD)?"EV_RLSD":"",
1896 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1897 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1898 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1900 if(0>(fd=COMM_GetWriteFd(handle))) {
1901 FIXME("no handle %d found\n",handle);
1902 return FALSE;
1904 close(fd);
1905 eventmask = evtmask;
1906 return TRUE;
1909 /*****************************************************************************
1910 * SetCommState (KERNEL32.452)
1912 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1914 struct termios port;
1915 int fd;
1917 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1918 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1919 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1920 (lpdcb->StopBits == ONESTOPBIT)?1:
1921 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1922 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1923 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1925 if ((fd = COMM_GetWriteFd(handle)) < 0) {
1926 FIXME("no handle %d found\n",handle);
1927 return FALSE;
1930 if ((tcgetattr(fd,&port)) == -1) {
1931 int save_error = errno;
1932 commerror = WinError();
1933 close( fd );
1934 #ifdef HAVE_STRERROR
1935 ERR("tcgetattr error '%s'\n", strerror(save_error));
1936 #else
1937 ERR("tcgetattr error %d\n", save_error);
1938 #endif
1939 return FALSE;
1942 port.c_cc[VMIN] = 0;
1943 port.c_cc[VTIME] = 1;
1945 #ifdef IMAXBEL
1946 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1947 #else
1948 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1949 #endif
1950 port.c_iflag |= (IGNBRK);
1952 port.c_oflag &= ~(OPOST);
1954 port.c_cflag &= ~(HUPCL);
1955 port.c_cflag |= CLOCAL | CREAD;
1957 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1958 port.c_lflag |= NOFLSH;
1961 ** MJM - removed default baudrate settings
1962 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1964 #ifdef CBAUD
1965 port.c_cflag &= ~CBAUD;
1966 switch (lpdcb->BaudRate) {
1967 case 110:
1968 case CBR_110:
1969 port.c_cflag |= B110;
1970 break;
1971 case 300:
1972 case CBR_300:
1973 port.c_cflag |= B300;
1974 break;
1975 case 600:
1976 case CBR_600:
1977 port.c_cflag |= B600;
1978 break;
1979 case 1200:
1980 case CBR_1200:
1981 port.c_cflag |= B1200;
1982 break;
1983 case 2400:
1984 case CBR_2400:
1985 port.c_cflag |= B2400;
1986 break;
1987 case 4800:
1988 case CBR_4800:
1989 port.c_cflag |= B4800;
1990 break;
1991 case 9600:
1992 case CBR_9600:
1993 port.c_cflag |= B9600;
1994 break;
1995 case 19200:
1996 case CBR_19200:
1997 port.c_cflag |= B19200;
1998 break;
1999 case 38400:
2000 case CBR_38400:
2001 port.c_cflag |= B38400;
2002 break;
2003 #ifdef B57600
2004 case 57600:
2005 port.c_cflag |= B57600;
2006 break;
2007 #endif
2008 #ifdef B115200
2009 case 115200:
2010 port.c_cflag |= B115200;
2011 break;
2012 #endif
2013 #ifdef B230400
2014 case 230400:
2015 port.c_cflag |= B230400;
2016 break;
2017 #endif
2018 #ifdef B460800
2019 case 460600:
2020 port.c_cflag |= B460800;
2021 break;
2022 #endif
2023 default:
2024 commerror = IE_BAUDRATE;
2025 close( fd );
2026 ERR("baudrate %ld\n",lpdcb->BaudRate);
2027 return FALSE;
2029 #elif !defined(__EMX__)
2030 switch (lpdcb->BaudRate) {
2031 case 110:
2032 case CBR_110:
2033 port.c_ospeed = B110;
2034 break;
2035 case 300:
2036 case CBR_300:
2037 port.c_ospeed = B300;
2038 break;
2039 case 600:
2040 case CBR_600:
2041 port.c_ospeed = B600;
2042 break;
2043 case 1200:
2044 case CBR_1200:
2045 port.c_ospeed = B1200;
2046 break;
2047 case 2400:
2048 case CBR_2400:
2049 port.c_ospeed = B2400;
2050 break;
2051 case 4800:
2052 case CBR_4800:
2053 port.c_ospeed = B4800;
2054 break;
2055 case 9600:
2056 case CBR_9600:
2057 port.c_ospeed = B9600;
2058 break;
2059 case 19200:
2060 case CBR_19200:
2061 port.c_ospeed = B19200;
2062 break;
2063 case 38400:
2064 case CBR_38400:
2065 port.c_ospeed = B38400;
2066 break;
2067 default:
2068 commerror = IE_BAUDRATE;
2069 close( fd );
2070 ERR("baudrate %d \n",lpdcb->BaudRate);
2071 return FALSE;
2073 port.c_ispeed = port.c_ospeed;
2074 #endif
2075 port.c_cflag &= ~CSIZE;
2076 switch (lpdcb->ByteSize) {
2077 case 5:
2078 port.c_cflag |= CS5;
2079 break;
2080 case 6:
2081 port.c_cflag |= CS6;
2082 break;
2083 case 7:
2084 port.c_cflag |= CS7;
2085 break;
2086 case 8:
2087 port.c_cflag |= CS8;
2088 break;
2089 default:
2090 commerror = IE_BYTESIZE;
2091 close( fd );
2092 ERR("ByteSize\n");
2093 return FALSE;
2096 port.c_cflag &= ~(PARENB | PARODD);
2097 if (lpdcb->fParity)
2098 port.c_iflag |= INPCK;
2099 else
2100 port.c_iflag &= ~INPCK;
2101 switch (lpdcb->Parity) {
2102 case NOPARITY:
2103 break;
2104 case ODDPARITY:
2105 port.c_cflag |= (PARENB | PARODD);
2106 break;
2107 case EVENPARITY:
2108 port.c_cflag |= PARENB;
2109 break;
2110 default:
2111 commerror = IE_BYTESIZE;
2112 close( fd );
2113 ERR("Parity\n");
2114 return FALSE;
2118 switch (lpdcb->StopBits) {
2119 case ONESTOPBIT:
2120 port.c_cflag &= ~CSTOPB;
2121 break;
2122 case TWOSTOPBITS:
2123 port.c_cflag |= CSTOPB;
2124 break;
2125 default:
2126 commerror = IE_BYTESIZE;
2127 close( fd );
2128 ERR("StopBits\n");
2129 return FALSE;
2131 #ifdef CRTSCTS
2132 if ( lpdcb->fOutxCtsFlow ||
2133 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2134 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2137 port.c_cflag |= CRTSCTS;
2138 TRACE("CRTSCTS\n");
2141 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2143 port.c_cflag &= ~CRTSCTS;
2144 TRACE("~CRTSCTS\n");
2147 #endif
2148 if (lpdcb->fInX)
2149 port.c_iflag |= IXON;
2150 else
2151 port.c_iflag &= ~IXON;
2152 if (lpdcb->fOutX)
2153 port.c_iflag |= IXOFF;
2154 else
2155 port.c_iflag &= ~IXOFF;
2157 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2158 int save_error=errno;
2159 commerror = WinError();
2160 close( fd );
2161 #ifdef HAVE_STRERROR
2162 ERR("tcgetattr error '%s'\n", strerror(save_error));
2163 #else
2164 ERR("tcgetattr error %d\n", save_error);
2165 #endif
2166 return FALSE;
2167 } else {
2168 commerror = 0;
2169 close( fd );
2170 return TRUE;
2175 /*****************************************************************************
2176 * GetCommState (KERNEL32.159)
2178 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2180 struct termios port;
2181 int fd,speed;
2183 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2185 if ((fd = COMM_GetReadFd(handle)) < 0)
2187 ERR("can't get COMM_GetReadFd\n");
2188 return FALSE;
2190 if (tcgetattr(fd, &port) == -1) {
2191 int save_error=errno;
2192 #ifdef HAVE_STRERROR
2193 ERR("tcgetattr error '%s'\n", strerror(save_error));
2194 #else
2195 ERR("tcgetattr error %d\n", save_error);
2196 #endif
2197 commerror = WinError();
2198 close( fd );
2199 return FALSE;
2201 close( fd );
2202 #ifndef __EMX__
2203 #ifdef CBAUD
2204 speed= (port.c_cflag & CBAUD);
2205 #else
2206 speed= (cfgetospeed(&port));
2207 #endif
2208 switch (speed) {
2209 case B110:
2210 lpdcb->BaudRate = 110;
2211 break;
2212 case B300:
2213 lpdcb->BaudRate = 300;
2214 break;
2215 case B600:
2216 lpdcb->BaudRate = 600;
2217 break;
2218 case B1200:
2219 lpdcb->BaudRate = 1200;
2220 break;
2221 case B2400:
2222 lpdcb->BaudRate = 2400;
2223 break;
2224 case B4800:
2225 lpdcb->BaudRate = 4800;
2226 break;
2227 case B9600:
2228 lpdcb->BaudRate = 9600;
2229 break;
2230 case B19200:
2231 lpdcb->BaudRate = 19200;
2232 break;
2233 case B38400:
2234 lpdcb->BaudRate = 38400;
2235 break;
2236 #ifdef B57600
2237 case B57600:
2238 lpdcb->BaudRate = 57600;
2239 break;
2240 #endif
2241 #ifdef B115200
2242 case B115200:
2243 lpdcb->BaudRate = 115200;
2244 break;
2245 #endif
2246 #ifdef B230400
2247 case B230400:
2248 lpdcb->BaudRate = 230400;
2249 break;
2250 #endif
2251 #ifdef B460800
2252 case B460800:
2253 lpdcb->BaudRate = 460800;
2254 break;
2255 #endif
2256 default:
2257 ERR("unknown speed %x \n",speed);
2259 #endif
2260 switch (port.c_cflag & CSIZE) {
2261 case CS5:
2262 lpdcb->ByteSize = 5;
2263 break;
2264 case CS6:
2265 lpdcb->ByteSize = 6;
2266 break;
2267 case CS7:
2268 lpdcb->ByteSize = 7;
2269 break;
2270 case CS8:
2271 lpdcb->ByteSize = 8;
2272 break;
2273 default:
2274 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2277 if(port.c_iflag & INPCK)
2278 lpdcb->fParity = TRUE;
2279 else
2280 lpdcb->fParity = FALSE;
2281 switch (port.c_cflag & (PARENB | PARODD)) {
2282 case 0:
2283 lpdcb->Parity = NOPARITY;
2284 break;
2285 case PARENB:
2286 lpdcb->Parity = EVENPARITY;
2287 break;
2288 case (PARENB | PARODD):
2289 lpdcb->Parity = ODDPARITY;
2290 break;
2293 if (port.c_cflag & CSTOPB)
2294 lpdcb->StopBits = TWOSTOPBITS;
2295 else
2296 lpdcb->StopBits = ONESTOPBIT;
2298 lpdcb->fNull = 0;
2299 lpdcb->fBinary = 1;
2301 #ifdef CRTSCTS
2303 if (port.c_cflag & CRTSCTS) {
2304 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2305 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2306 lpdcb->fOutxCtsFlow = 1;
2307 lpdcb->fOutxDsrFlow = 1;
2308 } else
2309 #endif
2311 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2312 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2314 if (port.c_iflag & IXON)
2315 lpdcb->fInX = 1;
2316 else
2317 lpdcb->fInX = 0;
2319 if (port.c_iflag & IXOFF)
2320 lpdcb->fOutX = 1;
2321 else
2322 lpdcb->fOutX = 0;
2324 lpdcb->XonChar =
2325 lpdcb->XoffChar =
2327 lpdcb->XonLim = 10;
2328 lpdcb->XoffLim = 10;
2330 commerror = 0;
2332 TRACE("OK\n");
2334 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2335 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2336 (lpdcb->StopBits == ONESTOPBIT)?1:
2337 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2338 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2339 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2340 #ifdef CRTSCTS
2341 if ( lpdcb->fOutxCtsFlow ||
2342 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2343 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2345 TRACE("CRTSCTS\n");
2347 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2348 TRACE("~CRTSCTS\n");
2350 #endif
2351 return TRUE;
2354 /*****************************************************************************
2355 * TransmitCommChar (KERNEL32.535)
2357 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2359 struct DosDeviceStruct *ptr;
2361 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2362 if ((ptr = GetDeviceStruct(cid)) == NULL)
2363 FIXME("no handle for cid = %0x!.\n",cid);
2364 return FALSE;
2366 if (ptr->suspended) {
2367 ptr->commerror = IE_HARDWARE;
2368 return FALSE;
2370 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2371 ptr->commerror = WinError();
2372 return FALSE;
2373 } else {
2374 ptr->commerror = 0;
2375 return TRUE;
2379 /*****************************************************************************
2380 * GetCommTimeouts (KERNEL32.160)
2382 BOOL WINAPI GetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts)
2384 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2385 return TRUE;
2388 /*****************************************************************************
2389 * SetCommTimeouts (KERNEL32.453)
2391 BOOL WINAPI SetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts) {
2392 /* struct DosDeviceStruct *ptr; */
2393 struct termios tios;
2394 int fd;
2396 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2398 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2399 FIXME("no handle for cid = %0x!.\n",hcom);
2400 return FALSE;
2404 fd = COMM_GetWriteFd(hcom);
2405 if (fd < 0) {
2406 FIXME("no fd for cid = %0x!.\n",hcom);
2407 return FALSE;
2411 FIXME("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2412 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts->ReadTotalTimeoutMultiplier);
2413 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts->ReadTotalTimeoutConstant);
2414 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts->WriteTotalTimeoutMultiplier);
2415 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts->WriteTotalTimeoutConstant);
2418 if (-1==tcgetattr(fd,&tios)) {
2419 FIXME("tcgetattr on fd %d failed!\n",fd);
2420 return FALSE;
2422 /* VTIME is in 1/10 seconds */
2423 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2424 if (-1==tcsetattr(fd,0,&tios)) {
2425 FIXME("tcsetattr on fd %d failed!\n",fd);
2426 return FALSE;
2428 return TRUE;
2431 /***********************************************************************
2432 * GetCommModemStatus (KERNEL32.285)
2434 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2436 int fd,mstat, result=FALSE;
2438 *lpModemStat=0;
2439 #ifdef TIOCMGET
2440 fd = COMM_GetWriteFd(hFile);
2441 if(fd<0)
2442 return FALSE;
2443 result = ioctl(fd, TIOCMGET, &mstat);
2444 close(fd);
2445 if (result == -1)
2447 TRACE("ioctl failed\n");
2448 return FALSE;
2450 if (mstat & TIOCM_CTS)
2451 *lpModemStat |= MS_CTS_ON;
2452 if (mstat & TIOCM_DSR)
2453 *lpModemStat |= MS_DSR_ON;
2454 if (mstat & TIOCM_RNG)
2455 *lpModemStat |= MS_RING_ON;
2456 /*FIXME: Not really sure about RLSD UB 990810*/
2457 if (mstat & TIOCM_CAR)
2458 *lpModemStat |= MS_RLSD_ON;
2459 TRACE("%s%s%s%s\n",
2460 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2461 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2462 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2463 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2464 return TRUE;
2465 #else
2466 return FALSE;
2467 #endif
2469 /***********************************************************************
2470 * WaitCommEvent (KERNEL32.719)
2472 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2474 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2475 return TRUE;
2478 /***********************************************************************
2479 * GetCommProperties (KERNEL32.???)
2481 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2483 FIXME("(%d %p )\n",hFile,dcb);
2484 return TRUE;
2487 /***********************************************************************
2488 * SetCommProperties (KERNEL32.???)
2490 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2492 FIXME("(%d %p )\n",hFile,dcb);
2493 return TRUE;