This patch initializes the return buffer used in GetPrinterDriverA to
[wine.git] / misc / comm.c
blob0f9bf1ee1fc75a1da491feed454cfe20a78fe5c0
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 "file.h"
73 #include "debugtools.h"
75 DEFAULT_DEBUG_CHANNEL(comm);
77 #ifndef TIOCINQ
78 #define TIOCINQ FIONREAD
79 #endif
80 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
81 #define FLAG_LPT 0x80
83 struct DosDeviceStruct COM[MAX_PORTS];
84 struct DosDeviceStruct LPT[MAX_PORTS];
85 /* pointers to unknown(==undocumented) comm structure */
86 LPCVOID *unknown[MAX_PORTS];
87 /* save terminal states */
88 static struct termios m_stat[MAX_PORTS];
90 void COMM_Init(void)
92 int x;
93 char option[10], temp[256], *btemp;
94 struct stat st;
96 for (x=0; x!=MAX_PORTS; x++) {
97 strcpy(option,"COMx");
98 option[3] = '1' + x;
99 option[4] = '\0';
101 PROFILE_GetWineIniString( "serialports", option, "*",
102 temp, sizeof(temp) );
103 if (!strcmp(temp, "*") || *temp == '\0')
104 COM[x].devicename = NULL;
105 else {
106 btemp = strchr(temp,',');
107 if (btemp != NULL) {
108 *btemp++ = '\0';
109 COM[x].baudrate = atoi(btemp);
110 } else {
111 COM[x].baudrate = -1;
113 stat(temp, &st);
114 if (!S_ISCHR(st.st_mode))
115 WARN("Can't use `%s' as %s !\n", temp, option);
116 else
117 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
118 WARN("Can't malloc for device info!\n");
119 else {
120 COM[x].fd = 0;
121 strcpy(COM[x].devicename, temp);
123 TRACE("%s = %s\n", option, COM[x].devicename);
126 strcpy(option, "LPTx");
127 option[3] = '1' + x;
128 option[4] = '\0';
130 PROFILE_GetWineIniString( "parallelports", option, "*",
131 temp, sizeof(temp) );
132 if (!strcmp(temp, "*") || *temp == '\0')
133 LPT[x].devicename = NULL;
134 else {
135 stat(temp, &st);
136 if (!S_ISCHR(st.st_mode))
137 WARN("Can't use `%s' as %s !\n", temp, option);
138 else
139 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
140 WARN("Can't malloc for device info!\n");
141 else {
142 LPT[x].fd = 0;
143 strcpy(LPT[x].devicename, temp);
145 TRACE("%s = %s\n", option, LPT[x].devicename);
152 static struct DosDeviceStruct *GetDeviceStruct(int fd)
154 if ((fd&0x7F)<=MAX_PORTS) {
155 if (!(fd&FLAG_LPT)) {
156 if (COM[fd].fd)
157 return &COM[fd];
158 } else {
159 fd &= 0x7f;
160 if (LPT[fd].fd)
161 return &LPT[fd];
165 return NULL;
168 static int GetCommPort_fd(int fd)
170 int x;
172 for (x=0; x<MAX_PORTS; x++) {
173 if (COM[x].fd == fd)
174 return x;
177 return -1;
180 static int ValidCOMPort(int x)
182 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
185 static int ValidLPTPort(int x)
187 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
190 static int WinError(void)
192 TRACE("errno = %d\n", errno);
193 switch (errno) {
194 default:
195 return CE_IOE;
199 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
201 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
202 + ptr->ibuf_head - ptr->ibuf_tail;
205 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
207 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
208 + ptr->obuf_head - ptr->obuf_tail;
211 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
213 unsigned int mstat, okay;
214 okay = ioctl(fd, TIOCMGET, &mstat);
215 if (okay) return okay;
216 if (andy) mstat &= andy;
217 mstat |= orrie;
218 return ioctl(fd, TIOCMSET, &mstat);
221 static void CALLBACK comm_notification( ULONG_PTR private )
223 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
224 int prev, bleft, len;
225 WORD mask = 0;
226 int cid = GetCommPort_fd(ptr->fd);
228 TRACE("async notification\n");
229 /* read data from comm port */
230 prev = comm_inbuf(ptr);
231 do {
232 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
233 - ptr->ibuf_head;
234 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
235 if (len > 0) {
236 if (!bleft) {
237 ptr->commerror = CE_RXOVER;
238 } else {
239 /* check for events */
240 if ((ptr->eventmask & EV_RXFLAG) &&
241 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
242 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
243 mask |= CN_EVENT;
245 if (ptr->eventmask & EV_RXCHAR) {
246 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
247 mask |= CN_EVENT;
249 /* advance buffer position */
250 ptr->ibuf_head += len;
251 if (ptr->ibuf_head >= ptr->ibuf_size)
252 ptr->ibuf_head = 0;
255 } while (len > 0);
256 /* check for notification */
257 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
258 (comm_inbuf(ptr)>=ptr->n_read)) {
259 /* passed the receive notification threshold */
260 mask |= CN_RECEIVE;
263 /* write any TransmitCommChar character */
264 if (ptr->xmit>=0) {
265 len = write(ptr->fd, &(ptr->xmit), 1);
266 if (len > 0) ptr->xmit = -1;
268 /* write from output queue */
269 prev = comm_outbuf(ptr);
270 do {
271 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
272 - ptr->obuf_tail;
273 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
274 if (len > 0) {
275 ptr->obuf_tail += len;
276 if (ptr->obuf_tail >= ptr->obuf_size)
277 ptr->obuf_tail = 0;
278 /* flag event */
279 if (ptr->obuf_tail == ptr->obuf_head) {
280 if (ptr->s_write) {
281 SERVICE_Delete( ptr->s_write );
282 ptr->s_write = INVALID_HANDLE_VALUE;
284 if (ptr->eventmask & EV_TXEMPTY) {
285 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
286 mask |= CN_EVENT;
290 } while (len > 0);
291 /* check for notification */
292 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
293 (comm_outbuf(ptr)<ptr->n_write)) {
294 /* passed the transmit notification threshold */
295 mask |= CN_TRANSMIT;
298 /* send notifications, if any */
299 if (ptr->wnd && mask) {
300 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
301 PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
305 static void comm_waitread(struct DosDeviceStruct *ptr)
307 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
308 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
309 GENERIC_READ | SYNCHRONIZE ),
310 comm_notification,
311 (ULONG_PTR)ptr );
314 static void comm_waitwrite(struct DosDeviceStruct *ptr)
316 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
317 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
318 GENERIC_WRITE | SYNCHRONIZE ),
319 comm_notification,
320 (ULONG_PTR)ptr );
323 /**************************************************************************
324 * BuildCommDCB (USER.213)
326 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
328 /* "COM1:9600,n,8,1" */
329 /* 012345 */
330 int port;
331 char *ptr, temp[256];
333 TRACE("(%s), ptr %p\n", device, lpdcb);
335 if (!lstrncmpiA(device,"COM",3)) {
336 port = device[3] - '0';
339 if (port-- == 0) {
340 ERR("BUG ! COM0 can't exist!.\n");
341 return -1;
344 if (!ValidCOMPort(port)) {
345 FIXME("invalid COM port %d?\n",port);
346 return -1;
349 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
351 lpdcb->Id = port;
353 if (!*(device+4))
354 return 0;
356 if (*(device+4) != ':')
357 return -1;
359 strcpy(temp,device+5);
360 ptr = strtok(temp, ", ");
362 if (COM[port].baudrate > 0)
363 lpdcb->BaudRate = COM[port].baudrate;
364 else
365 lpdcb->BaudRate = atoi(ptr);
366 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
368 ptr = strtok(NULL, ", ");
369 if (islower(*ptr))
370 *ptr = toupper(*ptr);
372 TRACE("parity (%c)\n", *ptr);
373 lpdcb->fParity = TRUE;
374 switch (*ptr) {
375 case 'N':
376 lpdcb->Parity = NOPARITY;
377 lpdcb->fParity = FALSE;
378 break;
379 case 'E':
380 lpdcb->Parity = EVENPARITY;
381 break;
382 case 'M':
383 lpdcb->Parity = MARKPARITY;
384 break;
385 case 'O':
386 lpdcb->Parity = ODDPARITY;
387 break;
388 default:
389 WARN("Unknown parity `%c'!\n", *ptr);
390 return -1;
393 ptr = strtok(NULL, ", ");
394 TRACE("charsize (%c)\n", *ptr);
395 lpdcb->ByteSize = *ptr - '0';
397 ptr = strtok(NULL, ", ");
398 TRACE("stopbits (%c)\n", *ptr);
399 switch (*ptr) {
400 case '1':
401 lpdcb->StopBits = ONESTOPBIT;
402 break;
403 case '2':
404 lpdcb->StopBits = TWOSTOPBITS;
405 break;
406 default:
407 WARN("Unknown # of stopbits `%c'!\n", *ptr);
408 return -1;
412 return 0;
415 /*****************************************************************************
416 * OpenComm (USER.200)
418 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
420 int port,fd;
422 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
424 if (strlen(device) < 4)
425 return IE_BADID;
427 port = device[3] - '0';
429 if (port-- == 0)
430 ERR("BUG ! COM0 or LPT0 don't exist !\n");
432 if (!lstrncmpiA(device,"COM",3)) {
434 TRACE("%s = %s\n", device, COM[port].devicename);
436 if (!ValidCOMPort(port))
437 return IE_BADID;
439 if (COM[port].fd)
440 return IE_OPEN;
442 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
443 if (fd == -1) {
444 ERR("error=%d\n", errno);
445 return IE_HARDWARE;
446 } else {
447 unknown[port] = SEGPTR_ALLOC(40);
448 bzero(unknown[port],40);
449 COM[port].fd = fd;
450 COM[port].commerror = 0;
451 COM[port].eventmask = 0;
452 COM[port].evtchar = 0; /* FIXME: default? */
453 /* save terminal state */
454 tcgetattr(fd,&m_stat[port]);
455 /* set default parameters */
456 if(COM[port].baudrate>-1){
457 DCB16 dcb;
458 GetCommState16(port, &dcb);
459 dcb.BaudRate=COM[port].baudrate;
460 /* more defaults:
461 * databits, parity, stopbits
463 SetCommState16( &dcb);
465 /* init priority characters */
466 COM[port].unget = -1;
467 COM[port].xmit = -1;
468 /* allocate buffers */
469 COM[port].ibuf_size = cbInQueue;
470 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
471 COM[port].obuf_size = cbOutQueue;
472 COM[port].obuf_head = COM[port].obuf_tail = 0;
474 COM[port].inbuf = malloc(cbInQueue);
475 if (COM[port].inbuf) {
476 COM[port].outbuf = malloc(cbOutQueue);
477 if (!COM[port].outbuf)
478 free(COM[port].inbuf);
479 } else COM[port].outbuf = NULL;
480 if (!COM[port].outbuf) {
481 /* not enough memory */
482 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
483 close(COM[port].fd);
484 ERR("out of memory");
485 return IE_MEMORY;
488 COM[port].s_read = INVALID_HANDLE_VALUE;
489 COM[port].s_write = INVALID_HANDLE_VALUE;
490 comm_waitread( &COM[port] );
491 return port;
494 else
495 if (!lstrncmpiA(device,"LPT",3)) {
497 if (!ValidLPTPort(port))
498 return IE_BADID;
500 if (LPT[port].fd)
501 return IE_OPEN;
503 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
504 if (fd == -1) {
505 return IE_HARDWARE;
506 } else {
507 LPT[port].fd = fd;
508 LPT[port].commerror = 0;
509 LPT[port].eventmask = 0;
510 return port|FLAG_LPT;
513 return 0;
516 /*****************************************************************************
517 * CloseComm (USER.207)
519 INT16 WINAPI CloseComm16(INT16 cid)
521 struct DosDeviceStruct *ptr;
523 TRACE("cid=%d\n", cid);
524 if ((ptr = GetDeviceStruct(cid)) == NULL) {
525 FIXME("no cid=%d found!\n", cid);
526 return -1;
528 if (!(cid&FLAG_LPT)) {
529 /* COM port */
530 SEGPTR_FREE(unknown[cid]); /* [LW] */
532 SERVICE_Delete( COM[cid].s_write );
533 SERVICE_Delete( COM[cid].s_read );
534 /* free buffers */
535 free(ptr->outbuf);
536 free(ptr->inbuf);
538 /* reset modem lines */
539 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
542 if (close(ptr->fd) == -1) {
543 ptr->commerror = WinError();
544 /* FIXME: should we clear ptr->fd here? */
545 return -1;
546 } else {
547 ptr->commerror = 0;
548 ptr->fd = 0;
549 return 0;
553 /*****************************************************************************
554 * SetCommBreak (USER.210)
556 INT16 WINAPI SetCommBreak16(INT16 cid)
558 struct DosDeviceStruct *ptr;
560 TRACE("cid=%d\n", cid);
561 if ((ptr = GetDeviceStruct(cid)) == NULL) {
562 FIXME("no cid=%d found!\n", cid);
563 return -1;
566 ptr->suspended = 1;
567 ptr->commerror = 0;
568 return 0;
571 /*****************************************************************************
572 * ClearCommBreak (USER.211)
574 INT16 WINAPI ClearCommBreak16(INT16 cid)
576 struct DosDeviceStruct *ptr;
578 TRACE("cid=%d\n", cid);
579 if (!(ptr = GetDeviceStruct(cid))) {
580 FIXME("no cid=%d found!\n", cid);
581 return -1;
583 ptr->suspended = 0;
584 ptr->commerror = 0;
585 return 0;
588 /*****************************************************************************
589 * EscapeCommFunction (USER.214)
591 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
593 int max;
594 struct DosDeviceStruct *ptr;
595 struct termios port;
597 TRACE("cid=%d, function=%d\n", cid, nFunction);
598 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
599 if ((ptr = GetDeviceStruct(cid)) == NULL) {
600 FIXME("no cid=%d found!\n", cid);
601 return -1;
603 if (tcgetattr(ptr->fd,&port) == -1) {
604 TRACE("tcgetattr failed\n");
605 ptr->commerror=WinError();
606 return -1;
608 } else ptr = NULL;
610 switch (nFunction) {
611 case RESETDEV:
612 TRACE("RESETDEV\n");
613 break;
615 case GETMAXCOM:
616 TRACE("GETMAXCOM\n");
617 for (max = MAX_PORTS;!COM[max].devicename;max--)
619 return max;
620 break;
622 case GETMAXLPT:
623 TRACE("GETMAXLPT\n");
624 for (max = MAX_PORTS;!LPT[max].devicename;max--)
626 return FLAG_LPT + max;
627 break;
629 case GETBASEIRQ:
630 TRACE("GETBASEIRQ\n");
631 /* FIXME: use tables */
632 /* just fake something for now */
633 if (cid & FLAG_LPT) {
634 /* LPT1: irq 7, LPT2: irq 5 */
635 return (cid & 0x7f) ? 5 : 7;
636 } else {
637 /* COM1: irq 4, COM2: irq 3,
638 COM3: irq 4, COM4: irq 3 */
639 return 4 - (cid & 1);
641 break;
643 case CLRDTR:
644 TRACE("CLRDTR\n");
645 #ifdef TIOCM_DTR
646 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
647 #endif
648 case CLRRTS:
649 TRACE("CLRRTS\n");
650 #ifdef TIOCM_RTS
651 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
652 #endif
654 case SETDTR:
655 TRACE("SETDTR\n");
656 #ifdef TIOCM_DTR
657 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
658 #endif
660 case SETRTS:
661 TRACE("SETRTS\n");
662 #ifdef TIOCM_RTS
663 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
664 #endif
666 case SETXOFF:
667 TRACE("SETXOFF\n");
668 port.c_iflag |= IXOFF;
669 break;
671 case SETXON:
672 TRACE("SETXON\n");
673 port.c_iflag |= IXON;
674 break;
676 default:
677 WARN("(cid=%d,nFunction=%d): Unknown function\n",
678 cid, nFunction);
679 break;
682 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
683 ptr->commerror = WinError();
684 return -1;
685 } else {
686 ptr->commerror = 0;
687 return 0;
691 /*****************************************************************************
692 * FlushComm (USER.215)
694 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
696 int queue;
697 struct DosDeviceStruct *ptr;
699 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
700 if ((ptr = GetDeviceStruct(cid)) == NULL) {
701 FIXME("no cid=%d found!\n", cid);
702 return -1;
704 switch (fnQueue) {
705 case 0:
706 queue = TCOFLUSH;
707 ptr->obuf_tail = ptr->obuf_head;
708 break;
709 case 1:
710 queue = TCIFLUSH;
711 ptr->ibuf_head = ptr->ibuf_tail;
712 break;
713 default:
714 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
715 cid, fnQueue);
716 return -1;
718 if (tcflush(ptr->fd, queue)) {
719 ptr->commerror = WinError();
720 return -1;
721 } else {
722 ptr->commerror = 0;
723 return 0;
727 /********************************************************************
728 * GetCommError (USER.203)
730 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
732 int temperror;
733 struct DosDeviceStruct *ptr;
734 unsigned char *stol;
735 unsigned int mstat;
737 if ((ptr = GetDeviceStruct(cid)) == NULL) {
738 FIXME("no handle for cid = %0x!.\n",cid);
739 return -1;
741 if (cid&FLAG_LPT) {
742 WARN(" cid %d not comm port\n",cid);
743 return CE_MODE;
745 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
746 ioctl(ptr->fd,TIOCMGET,&mstat);
747 if( mstat&TIOCM_CAR )
748 *stol |= 0x80;
749 else
750 *stol &=0x7f;
752 if (lpStat) {
753 lpStat->status = 0;
755 lpStat->cbOutQue = comm_outbuf(ptr);
756 lpStat->cbInQue = comm_inbuf(ptr);
758 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
759 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
760 lpStat->cbOutQue, *stol);
762 else
763 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
764 cid, ptr->commerror, *stol);
766 /* Return any errors and clear it */
767 temperror = ptr->commerror;
768 ptr->commerror = 0;
769 return(temperror);
772 /*****************************************************************************
773 * SetCommEventMask (USER.208)
775 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
777 struct DosDeviceStruct *ptr;
778 unsigned char *stol;
779 int repid;
780 unsigned int mstat;
782 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
783 if ((ptr = GetDeviceStruct(cid)) == NULL) {
784 FIXME("no handle for cid = %0x!.\n",cid);
785 return (SEGPTR)NULL;
788 ptr->eventmask = fuEvtMask;
790 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
791 WARN(" cid %d not comm port\n",cid);
792 return (SEGPTR)NULL;
794 /* it's a COM port ? -> modify flags */
795 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
796 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
797 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
798 if ((mstat&TIOCM_CAR))
799 *stol |= 0x80;
800 else
801 *stol &=0x7f;
803 TRACE(" modem dcd construct %x\n",*stol);
804 return SEGPTR_GET(unknown[cid]);
807 /*****************************************************************************
808 * GetCommEventMask (USER.209)
810 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
812 struct DosDeviceStruct *ptr;
813 WORD events;
815 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
816 if ((ptr = GetDeviceStruct(cid)) == NULL) {
817 FIXME("no handle for cid = %0x!.\n",cid);
818 return 0;
821 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
822 WARN(" cid %d not comm port\n",cid);
823 return 0;
826 events = *(WORD*)(unknown[cid]) & fnEvtClear;
827 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
828 return events;
831 /*****************************************************************************
832 * SetCommState16 (USER.201)
834 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
836 struct termios port;
837 struct DosDeviceStruct *ptr;
839 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
840 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
841 FIXME("no handle for cid = %0x!.\n",lpdcb->Id);
842 return -1;
844 if (tcgetattr(ptr->fd, &port) == -1) {
845 ptr->commerror = WinError();
846 return -1;
849 port.c_cc[VMIN] = 0;
850 port.c_cc[VTIME] = 1;
852 #ifdef IMAXBEL
853 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
854 #else
855 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
856 #endif
857 port.c_iflag |= (IGNBRK);
859 port.c_oflag &= ~(OPOST);
861 port.c_cflag &= ~(HUPCL);
862 port.c_cflag |= CLOCAL | CREAD;
864 port.c_lflag &= ~(ICANON|ECHO|ISIG);
865 port.c_lflag |= NOFLSH;
867 TRACE("baudrate %d\n",lpdcb->BaudRate);
868 #ifdef CBAUD
869 port.c_cflag &= ~CBAUD;
870 switch (lpdcb->BaudRate) {
871 case 110:
872 case CBR_110:
873 port.c_cflag |= B110;
874 break;
875 case 300:
876 case CBR_300:
877 port.c_cflag |= B300;
878 break;
879 case 600:
880 case CBR_600:
881 port.c_cflag |= B600;
882 break;
883 case 1200:
884 case CBR_1200:
885 port.c_cflag |= B1200;
886 break;
887 case 2400:
888 case CBR_2400:
889 port.c_cflag |= B2400;
890 break;
891 case 4800:
892 case CBR_4800:
893 port.c_cflag |= B4800;
894 break;
895 case 9600:
896 case CBR_9600:
897 port.c_cflag |= B9600;
898 break;
899 case 19200:
900 case CBR_19200:
901 port.c_cflag |= B19200;
902 break;
903 case 38400:
904 case CBR_38400:
905 port.c_cflag |= B38400;
906 break;
907 #ifdef B57600
908 case 57600:
909 port.c_cflag |= B57600;
910 break;
911 #endif
912 #ifdef B115200
913 case 57601:
914 port.c_cflag |= B115200;
915 break;
916 #endif
917 default:
918 ptr->commerror = IE_BAUDRATE;
919 return -1;
921 #elif !defined(__EMX__)
922 switch (lpdcb->BaudRate) {
923 case 110:
924 case CBR_110:
925 port.c_ospeed = B110;
926 break;
927 case 300:
928 case CBR_300:
929 port.c_ospeed = B300;
930 break;
931 case 600:
932 case CBR_600:
933 port.c_ospeed = B600;
934 break;
935 case 1200:
936 case CBR_1200:
937 port.c_ospeed = B1200;
938 break;
939 case 2400:
940 case CBR_2400:
941 port.c_ospeed = B2400;
942 break;
943 case 4800:
944 case CBR_4800:
945 port.c_ospeed = B4800;
946 break;
947 case 9600:
948 case CBR_9600:
949 port.c_ospeed = B9600;
950 break;
951 case 19200:
952 case CBR_19200:
953 port.c_ospeed = B19200;
954 break;
955 case 38400:
956 case CBR_38400:
957 port.c_ospeed = B38400;
958 break;
959 default:
960 ptr->commerror = IE_BAUDRATE;
961 return -1;
963 port.c_ispeed = port.c_ospeed;
964 #endif
965 TRACE("bytesize %d\n",lpdcb->ByteSize);
966 port.c_cflag &= ~CSIZE;
967 switch (lpdcb->ByteSize) {
968 case 5:
969 port.c_cflag |= CS5;
970 break;
971 case 6:
972 port.c_cflag |= CS6;
973 break;
974 case 7:
975 port.c_cflag |= CS7;
976 break;
977 case 8:
978 port.c_cflag |= CS8;
979 break;
980 default:
981 ptr->commerror = IE_BYTESIZE;
982 return -1;
985 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
986 port.c_cflag &= ~(PARENB | PARODD);
987 if (lpdcb->fParity)
988 port.c_iflag |= INPCK;
989 else
990 port.c_iflag &= ~INPCK;
991 switch (lpdcb->Parity) {
992 case NOPARITY:
993 break;
994 case ODDPARITY:
995 port.c_cflag |= (PARENB | PARODD);
996 break;
997 case EVENPARITY:
998 port.c_cflag |= PARENB;
999 break;
1000 default:
1001 ptr->commerror = IE_BYTESIZE;
1002 return -1;
1006 TRACE("stopbits %d\n",lpdcb->StopBits);
1008 switch (lpdcb->StopBits) {
1009 case ONESTOPBIT:
1010 port.c_cflag &= ~CSTOPB;
1011 break;
1012 case TWOSTOPBITS:
1013 port.c_cflag |= CSTOPB;
1014 break;
1015 default:
1016 ptr->commerror = IE_BYTESIZE;
1017 return -1;
1019 #ifdef CRTSCTS
1021 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1022 port.c_cflag |= CRTSCTS;
1024 if (lpdcb->fDtrDisable)
1025 port.c_cflag &= ~CRTSCTS;
1026 #endif
1027 if (lpdcb->fInX)
1028 port.c_iflag |= IXON;
1029 else
1030 port.c_iflag &= ~IXON;
1031 if (lpdcb->fOutX)
1032 port.c_iflag |= IXOFF;
1033 else
1034 port.c_iflag &= ~IXOFF;
1036 ptr->evtchar = lpdcb->EvtChar;
1038 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1039 ptr->commerror = WinError();
1040 return FALSE;
1041 } else {
1042 ptr->commerror = 0;
1043 return 0;
1047 /*****************************************************************************
1048 * GetCommState (USER.202)
1050 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1052 int speed;
1053 struct DosDeviceStruct *ptr;
1054 struct termios port;
1056 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1057 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1058 FIXME("no handle for cid = %0x!.\n",cid);
1059 return -1;
1061 if (tcgetattr(ptr->fd, &port) == -1) {
1062 ptr->commerror = WinError();
1063 return -1;
1065 lpdcb->Id = cid;
1066 #ifndef __EMX__
1067 #ifdef CBAUD
1068 speed = port.c_cflag & CBAUD;
1069 #else
1070 speed = port.c_ospeed;
1071 #endif
1072 switch(speed) {
1073 case B110:
1074 lpdcb->BaudRate = 110;
1075 break;
1076 case B300:
1077 lpdcb->BaudRate = 300;
1078 break;
1079 case B600:
1080 lpdcb->BaudRate = 600;
1081 break;
1082 case B1200:
1083 lpdcb->BaudRate = 1200;
1084 break;
1085 case B2400:
1086 lpdcb->BaudRate = 2400;
1087 break;
1088 case B4800:
1089 lpdcb->BaudRate = 4800;
1090 break;
1091 case B9600:
1092 lpdcb->BaudRate = 9600;
1093 break;
1094 case B19200:
1095 lpdcb->BaudRate = 19200;
1096 break;
1097 case B38400:
1098 lpdcb->BaudRate = 38400;
1099 break;
1100 #ifdef B57600
1101 case B57600:
1102 lpdcb->BaudRate = 57600;
1103 break;
1104 #endif
1105 #ifdef B115200
1106 case B115200:
1107 lpdcb->BaudRate = 57601;
1108 break;
1109 #endif
1111 #endif
1112 switch (port.c_cflag & CSIZE) {
1113 case CS5:
1114 lpdcb->ByteSize = 5;
1115 break;
1116 case CS6:
1117 lpdcb->ByteSize = 6;
1118 break;
1119 case CS7:
1120 lpdcb->ByteSize = 7;
1121 break;
1122 case CS8:
1123 lpdcb->ByteSize = 8;
1124 break;
1127 if(port.c_iflag & INPCK)
1128 lpdcb->fParity = TRUE;
1129 else
1130 lpdcb->fParity = FALSE;
1131 switch (port.c_cflag & (PARENB | PARODD)) {
1132 case 0:
1133 lpdcb->Parity = NOPARITY;
1134 break;
1135 case PARENB:
1136 lpdcb->Parity = EVENPARITY;
1137 break;
1138 case (PARENB | PARODD):
1139 lpdcb->Parity = ODDPARITY;
1140 break;
1143 if (port.c_cflag & CSTOPB)
1144 lpdcb->StopBits = TWOSTOPBITS;
1145 else
1146 lpdcb->StopBits = ONESTOPBIT;
1148 lpdcb->RlsTimeout = 50;
1149 lpdcb->CtsTimeout = 50;
1150 lpdcb->DsrTimeout = 50;
1151 lpdcb->fNull = 0;
1152 lpdcb->fChEvt = 0;
1153 lpdcb->fBinary = 1;
1154 lpdcb->fDtrDisable = 0;
1156 #ifdef CRTSCTS
1158 if (port.c_cflag & CRTSCTS) {
1159 lpdcb->fDtrflow = 1;
1160 lpdcb->fRtsflow = 1;
1161 lpdcb->fOutxCtsFlow = 1;
1162 lpdcb->fOutxDsrFlow = 1;
1163 } else
1164 #endif
1165 lpdcb->fDtrDisable = 1;
1167 if (port.c_iflag & IXON)
1168 lpdcb->fInX = 1;
1169 else
1170 lpdcb->fInX = 0;
1172 if (port.c_iflag & IXOFF)
1173 lpdcb->fOutX = 1;
1174 else
1175 lpdcb->fOutX = 0;
1177 lpdcb->XonChar =
1178 lpdcb->XoffChar =
1180 lpdcb->XonLim = 10;
1181 lpdcb->XoffLim = 10;
1183 lpdcb->EvtChar = ptr->evtchar;
1185 ptr->commerror = 0;
1186 return 0;
1189 /*****************************************************************************
1190 * TransmitCommChar (USER.206)
1192 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1194 struct DosDeviceStruct *ptr;
1196 TRACE("cid %d, data %d \n", cid, chTransmit);
1197 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1198 FIXME("no handle for cid = %0x!.\n",cid);
1199 return -1;
1202 if (ptr->suspended) {
1203 ptr->commerror = IE_HARDWARE;
1204 return -1;
1207 if (ptr->xmit >= 0) {
1208 /* character already queued */
1209 /* FIXME: which error would Windows return? */
1210 ptr->commerror = CE_TXFULL;
1211 return -1;
1214 if (ptr->obuf_head == ptr->obuf_tail) {
1215 /* transmit queue empty, try to transmit directly */
1216 if (write(ptr->fd, &chTransmit, 1) == -1) {
1217 /* didn't work, queue it */
1218 ptr->xmit = chTransmit;
1219 comm_waitwrite(ptr);
1221 } else {
1222 /* data in queue, let this char be transmitted next */
1223 ptr->xmit = chTransmit;
1224 comm_waitwrite(ptr);
1227 ptr->commerror = 0;
1228 return 0;
1231 /*****************************************************************************
1232 * UngetCommChar (USER.212)
1234 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1236 struct DosDeviceStruct *ptr;
1238 TRACE("cid %d (char %d)\n", cid, chUnget);
1239 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1240 FIXME("no handle for cid = %0x!.\n",cid);
1241 return -1;
1244 if (ptr->suspended) {
1245 ptr->commerror = IE_HARDWARE;
1246 return -1;
1249 if (ptr->unget>=0) {
1250 /* character already queued */
1251 /* FIXME: which error would Windows return? */
1252 ptr->commerror = CE_RXOVER;
1253 return -1;
1256 ptr->unget = chUnget;
1258 ptr->commerror = 0;
1259 return 0;
1262 /*****************************************************************************
1263 * ReadComm (USER.204)
1265 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1267 int status, length;
1268 struct DosDeviceStruct *ptr;
1269 LPSTR orgBuf = lpvBuf;
1271 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1272 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1273 FIXME("no handle for cid = %0x!.\n",cid);
1274 return -1;
1277 if (ptr->suspended) {
1278 ptr->commerror = IE_HARDWARE;
1279 return -1;
1282 /* read unget character */
1283 if (ptr->unget>=0) {
1284 *lpvBuf++ = ptr->unget;
1285 ptr->unget = -1;
1287 length = 1;
1288 } else
1289 length = 0;
1291 /* read from receive buffer */
1292 while (length < cbRead) {
1293 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1294 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1295 if (!status) break;
1296 if ((cbRead - length) < status)
1297 status = cbRead - length;
1299 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1300 ptr->ibuf_tail += status;
1301 if (ptr->ibuf_tail >= ptr->ibuf_size)
1302 ptr->ibuf_tail = 0;
1303 lpvBuf += status;
1304 length += status;
1307 TRACE("%.*s\n", length, orgBuf);
1308 ptr->commerror = 0;
1309 return length;
1312 /*****************************************************************************
1313 * WriteComm (USER.205)
1315 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1317 int status, length;
1318 struct DosDeviceStruct *ptr;
1320 TRACE("cid %d, ptr %p, length %d\n",
1321 cid, lpvBuf, cbWrite);
1322 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1323 FIXME("no handle for cid = %0x!.\n",cid);
1324 return -1;
1327 if (ptr->suspended) {
1328 ptr->commerror = IE_HARDWARE;
1329 return -1;
1332 TRACE("%.*s\n", cbWrite, lpvBuf );
1334 length = 0;
1335 while (length < cbWrite) {
1336 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1337 /* no data queued, try to write directly */
1338 status = write(ptr->fd, lpvBuf, cbWrite - length);
1339 if (status > 0) {
1340 lpvBuf += status;
1341 length += status;
1342 continue;
1345 /* can't write directly, put into transmit buffer */
1346 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1347 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1348 if (!status) break;
1349 if ((cbWrite - length) < status)
1350 status = cbWrite - length;
1351 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1352 ptr->obuf_head += status;
1353 if (ptr->obuf_head >= ptr->obuf_size)
1354 ptr->obuf_head = 0;
1355 lpvBuf += status;
1356 length += status;
1357 comm_waitwrite(ptr);
1360 ptr->commerror = 0;
1361 return length;
1364 /***********************************************************************
1365 * EnableCommNotification (USER.246)
1367 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1368 INT16 cbWriteNotify, INT16 cbOutQueue )
1370 struct DosDeviceStruct *ptr;
1372 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1373 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1374 FIXME("no handle for cid = %0x!.\n",cid);
1375 ptr->commerror = IE_BADID;
1376 return -1;
1378 ptr->wnd = hwnd;
1379 ptr->n_read = cbWriteNotify;
1380 ptr->n_write = cbOutQueue;
1381 return TRUE;
1385 /**************************************************************************
1386 * BuildCommDCBA (KERNEL32.14)
1388 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1390 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1393 /**************************************************************************
1394 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1396 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1397 LPCOMMTIMEOUTS lptimeouts)
1399 int port;
1400 char *ptr,*temp;
1402 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1404 if (!lstrncmpiA(device,"COM",3)) {
1405 port=device[3]-'0';
1406 if (port--==0) {
1407 ERR("BUG! COM0 can't exists!.\n");
1408 return FALSE;
1410 if (!ValidCOMPort(port))
1411 return FALSE;
1412 if (*(device+4)!=':')
1413 return FALSE;
1414 temp=(LPSTR)(device+5);
1415 } else
1416 temp=(LPSTR)device;
1418 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1420 lpdcb->DCBlength = sizeof(DCB);
1421 if (strchr(temp,',')) { /* old style */
1422 DCB16 dcb16;
1423 BOOL16 ret;
1424 char last=temp[strlen(temp)-1];
1426 ret=BuildCommDCB16(device,&dcb16);
1427 if (!ret)
1428 return FALSE;
1429 lpdcb->BaudRate = dcb16.BaudRate;
1430 lpdcb->ByteSize = dcb16.ByteSize;
1431 lpdcb->fBinary = dcb16.fBinary;
1432 lpdcb->Parity = dcb16.Parity;
1433 lpdcb->fParity = dcb16.fParity;
1434 lpdcb->fNull = dcb16.fNull;
1435 lpdcb->StopBits = dcb16.StopBits;
1436 if (last == 'x') {
1437 lpdcb->fInX = TRUE;
1438 lpdcb->fOutX = TRUE;
1439 lpdcb->fOutxCtsFlow = FALSE;
1440 lpdcb->fOutxDsrFlow = FALSE;
1441 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1442 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1443 } else if (last=='p') {
1444 lpdcb->fInX = FALSE;
1445 lpdcb->fOutX = FALSE;
1446 lpdcb->fOutxCtsFlow = TRUE;
1447 lpdcb->fOutxDsrFlow = TRUE;
1448 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1449 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1450 } else {
1451 lpdcb->fInX = FALSE;
1452 lpdcb->fOutX = FALSE;
1453 lpdcb->fOutxCtsFlow = FALSE;
1454 lpdcb->fOutxDsrFlow = FALSE;
1455 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1456 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1458 lpdcb->XonChar = dcb16.XonChar;
1459 lpdcb->XoffChar = dcb16.XoffChar;
1460 lpdcb->ErrorChar= dcb16.PeChar;
1461 lpdcb->fErrorChar= dcb16.fPeChar;
1462 lpdcb->EofChar = dcb16.EofChar;
1463 lpdcb->EvtChar = dcb16.EvtChar;
1464 lpdcb->XonLim = dcb16.XonLim;
1465 lpdcb->XoffLim = dcb16.XoffLim;
1466 return TRUE;
1468 ptr=strtok(temp," ");
1469 while (ptr) {
1470 DWORD flag,x;
1472 flag=0;
1473 if (!strncmp("baud=",ptr,5)) {
1474 if (!sscanf(ptr+5,"%ld",&x))
1475 WARN("Couldn't parse %s\n",ptr);
1476 lpdcb->BaudRate = x;
1477 flag=1;
1479 if (!strncmp("stop=",ptr,5)) {
1480 if (!sscanf(ptr+5,"%ld",&x))
1481 WARN("Couldn't parse %s\n",ptr);
1482 lpdcb->StopBits = x;
1483 flag=1;
1485 if (!strncmp("data=",ptr,5)) {
1486 if (!sscanf(ptr+5,"%ld",&x))
1487 WARN("Couldn't parse %s\n",ptr);
1488 lpdcb->ByteSize = x;
1489 flag=1;
1491 if (!strncmp("parity=",ptr,7)) {
1492 lpdcb->fParity = TRUE;
1493 switch (ptr[8]) {
1494 case 'N':case 'n':
1495 lpdcb->fParity = FALSE;
1496 lpdcb->Parity = NOPARITY;
1497 break;
1498 case 'E':case 'e':
1499 lpdcb->Parity = EVENPARITY;
1500 break;
1501 case 'O':case 'o':
1502 lpdcb->Parity = ODDPARITY;
1503 break;
1504 case 'M':case 'm':
1505 lpdcb->Parity = MARKPARITY;
1506 break;
1508 flag=1;
1510 if (!flag)
1511 ERR("Unhandled specifier '%s', please report.\n",ptr);
1512 ptr=strtok(NULL," ");
1514 if (lpdcb->BaudRate==110)
1515 lpdcb->StopBits = 2;
1516 return TRUE;
1519 /**************************************************************************
1520 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1522 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1523 LPCOMMTIMEOUTS lptimeouts )
1525 LPSTR devidA;
1526 BOOL ret;
1528 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1529 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1530 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1531 HeapFree( GetProcessHeap(), 0, devidA );
1532 return ret;
1535 /**************************************************************************
1536 * BuildCommDCBW (KERNEL32.17)
1538 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1540 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1543 /*****************************************************************************
1544 * COMM_GetReadFd
1545 * Returns a file descriptor for reading.
1546 * Make sure to close the handle afterwards!
1548 static int COMM_GetReadFd( HANDLE handle)
1550 int fd;
1551 struct get_read_fd_request *req = get_req_buffer();
1552 req->handle = handle;
1553 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1554 return fd;
1557 /*****************************************************************************
1558 * COMM_GetWriteFd
1559 * Returns a file descriptor for writing.
1560 * Make sure to close the handle afterwards!
1562 static int COMM_GetWriteFd( HANDLE handle)
1564 int fd = -1;
1565 struct get_write_fd_request *req = get_req_buffer();
1566 req->handle = handle;
1567 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1568 return fd;
1571 /* FIXME: having these global for win32 for now */
1572 int commerror=0,eventmask=0;
1574 /*****************************************************************************
1575 * SetCommBreak (KERNEL32.449)
1577 BOOL WINAPI SetCommBreak(HANDLE handle)
1579 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1580 int fd,result;
1582 fd = COMM_GetWriteFd(handle);
1583 if(fd<0) {
1584 TRACE("COMM_GetWriteFd failed\n");
1585 return FALSE;
1587 result = ioctl(fd,TIOCSBRK,0);
1588 close(fd);
1589 if (result ==-1)
1591 TRACE("ioctl failed\n");
1592 SetLastError(ERROR_NOT_SUPPORTED);
1593 return FALSE;
1595 return TRUE;
1596 #else
1597 FIXME("ioctl not available\n");
1598 SetLastError(ERROR_NOT_SUPPORTED);
1599 return FALSE;
1600 #endif
1603 /*****************************************************************************
1604 * ClearCommBreak (KERNEL32.20)
1606 BOOL WINAPI ClearCommBreak(HANDLE handle)
1608 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1609 int fd,result;
1611 fd = COMM_GetWriteFd(handle);
1612 if(fd<0) {
1613 TRACE("COMM_GetWriteFd failed\n");
1614 return FALSE;
1616 result = ioctl(fd,TIOCCBRK,0);
1617 close(fd);
1618 if (result ==-1)
1620 TRACE("ioctl failed\n");
1621 SetLastError(ERROR_NOT_SUPPORTED);
1622 return FALSE;
1624 return TRUE;
1625 #else
1626 FIXME("ioctl not available\n");
1627 SetLastError(ERROR_NOT_SUPPORTED);
1628 return FALSE;
1629 #endif
1632 /*****************************************************************************
1633 * EscapeCommFunction (KERNEL32.214)
1635 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1637 int fd,direct=FALSE,result=FALSE;
1638 struct termios port;
1640 TRACE("handle %d, function=%d\n", handle, nFunction);
1641 fd = COMM_GetWriteFd(handle);
1642 if(fd<0) {
1643 FIXME("handle %d not found.\n",handle);
1644 return FALSE;
1647 if (tcgetattr(fd,&port) == -1) {
1648 commerror=WinError();
1649 close(fd);
1650 return FALSE;
1653 switch (nFunction) {
1654 case RESETDEV:
1655 TRACE("\n");
1656 break;
1658 case CLRDTR:
1659 TRACE("CLRDTR\n");
1660 #ifdef TIOCM_DTR
1661 direct=TRUE;
1662 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1663 break;
1664 #endif
1666 case CLRRTS:
1667 TRACE("CLRRTS\n");
1668 #ifdef TIOCM_RTS
1669 direct=TRUE;
1670 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1671 break;
1672 #endif
1674 case SETDTR:
1675 TRACE("SETDTR\n");
1676 #ifdef TIOCM_DTR
1677 direct=TRUE;
1678 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1679 break;
1680 #endif
1682 case SETRTS:
1683 TRACE("SETRTS\n");
1684 #ifdef TIOCM_DTR
1685 direct=TRUE;
1686 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1687 break;
1688 #endif
1690 case SETXOFF:
1691 TRACE("SETXOFF\n");
1692 port.c_iflag |= IXOFF;
1693 break;
1695 case SETXON:
1696 TRACE("SETXON\n");
1697 port.c_iflag |= IXON;
1698 break;
1699 case SETBREAK:
1700 TRACE("setbreak\n");
1701 #ifdef TIOCSBRK
1702 direct=TRUE;
1703 result = ioctl(fd,TIOCSBRK,0);
1704 break;
1705 #endif
1706 case CLRBREAK:
1707 TRACE("clrbreak\n");
1708 #ifdef TIOCSBRK
1709 direct=TRUE;
1710 result = ioctl(fd,TIOCCBRK,0);
1711 break;
1712 #endif
1713 default:
1714 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1715 handle, nFunction);
1716 break;
1719 if (!direct)
1720 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1721 commerror = WinError();
1722 close(fd);
1723 return FALSE;
1724 } else
1725 result= TRUE;
1726 else
1728 if (result == -1)
1730 result= FALSE;
1731 commerror=WinError();
1733 else
1734 result = TRUE;
1736 close(fd);
1737 return result;
1740 /********************************************************************
1741 * PurgeComm (KERNEL32.557)
1743 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1745 int fd;
1747 TRACE("handle %d, flags %lx\n", handle, flags);
1749 fd = COMM_GetWriteFd(handle);
1750 if(fd<0) {
1751 FIXME("no handle %d found\n",handle);
1752 return FALSE;
1756 ** not exactly sure how these are different
1757 ** Perhaps if we had our own internal queues, one flushes them
1758 ** and the other flushes the kernel's buffers.
1760 if(flags&PURGE_TXABORT)
1761 tcflush(fd,TCOFLUSH);
1762 if(flags&PURGE_RXABORT)
1763 tcflush(fd,TCIFLUSH);
1764 if(flags&PURGE_TXCLEAR)
1765 tcflush(fd,TCOFLUSH);
1766 if(flags&PURGE_RXCLEAR)
1767 tcflush(fd,TCIFLUSH);
1768 close(fd);
1770 return 1;
1773 /*****************************************************************************
1774 * ClearCommError (KERNEL32.21)
1776 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1778 int fd;
1780 fd=COMM_GetReadFd(handle);
1781 if(0>fd)
1783 FIXME("no handle %d found\n",handle);
1784 return FALSE;
1787 if (lpStat)
1789 lpStat->status = 0;
1791 #ifdef TIOCOUTQ
1792 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1793 WARN("ioctl returned error\n");
1794 #else
1795 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1796 #endif
1798 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1799 WARN("ioctl returned error\n");
1801 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1802 handle, lpStat->cbInQue, lpStat->cbOutQue);
1805 close(fd);
1807 if(errors)
1808 *errors = 0;
1811 ** After an asynchronous write opperation, the
1812 ** app will call ClearCommError to see if the
1813 ** results are ready yet. It waits for ERROR_IO_PENDING
1815 commerror = ERROR_IO_PENDING;
1817 return TRUE;
1820 /*****************************************************************************
1821 * SetupComm (KERNEL32.676)
1823 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1825 int fd;
1827 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1828 fd=COMM_GetWriteFd(handle);
1829 if(0>fd) {
1830 FIXME("handle %d not found?\n",handle);
1831 return FALSE;
1833 close(fd);
1834 return TRUE;
1837 /*****************************************************************************
1838 * GetCommMask (KERNEL32.156)
1840 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1842 int fd;
1844 TRACE("handle %d, mask %p\n", handle, evtmask);
1845 if(0>(fd=COMM_GetReadFd(handle)))
1847 FIXME("no handle %d found\n",handle);
1848 return FALSE;
1850 close(fd);
1851 *evtmask = eventmask;
1852 TRACE("%s%s%s%s%s%s%s%s%s\n",
1853 (eventmask&EV_BREAK)?"EV_BREAK":"",
1854 (eventmask&EV_CTS)?"EV_CTS":"",
1855 (eventmask&EV_DSR)?"EV_DSR":"",
1856 (eventmask&EV_ERR)?"EV_ERR":"",
1857 (eventmask&EV_RING)?"EV_RING":"",
1858 (eventmask&EV_RLSD)?"EV_RLSD":"",
1859 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1860 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1861 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1863 return TRUE;
1866 /*****************************************************************************
1867 * SetCommMask (KERNEL32.451)
1869 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1871 int fd;
1873 TRACE("handle %d, mask %lx\n", handle, evtmask);
1874 TRACE("%s%s%s%s%s%s%s%s%s\n",
1875 (evtmask&EV_BREAK)?"EV_BREAK":"",
1876 (evtmask&EV_CTS)?"EV_CTS":"",
1877 (evtmask&EV_DSR)?"EV_DSR":"",
1878 (evtmask&EV_ERR)?"EV_ERR":"",
1879 (evtmask&EV_RING)?"EV_RING":"",
1880 (evtmask&EV_RLSD)?"EV_RLSD":"",
1881 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1882 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1883 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1885 if(0>(fd=COMM_GetWriteFd(handle))) {
1886 FIXME("no handle %d found\n",handle);
1887 return FALSE;
1889 close(fd);
1890 eventmask = evtmask;
1891 return TRUE;
1894 /*****************************************************************************
1895 * SetCommState (KERNEL32.452)
1897 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1899 struct termios port;
1900 int fd;
1902 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1903 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1904 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1905 (lpdcb->StopBits == ONESTOPBIT)?1:
1906 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1907 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1908 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1910 if ((fd = COMM_GetWriteFd(handle)) < 0) {
1911 FIXME("no handle %d found\n",handle);
1912 return FALSE;
1915 if ((tcgetattr(fd,&port)) == -1) {
1916 int save_error = errno;
1917 commerror = WinError();
1918 close( fd );
1919 #ifdef HAVE_STRERROR
1920 ERR("tcgetattr error '%s'\n", strerror(save_error));
1921 #else
1922 ERR("tcgetattr error %d\n", save_error);
1923 #endif
1924 return FALSE;
1927 port.c_cc[VMIN] = 0;
1928 port.c_cc[VTIME] = 1;
1930 #ifdef IMAXBEL
1931 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1932 #else
1933 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1934 #endif
1935 port.c_iflag |= (IGNBRK);
1937 port.c_oflag &= ~(OPOST);
1939 port.c_cflag &= ~(HUPCL);
1940 port.c_cflag |= CLOCAL | CREAD;
1942 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1943 port.c_lflag |= NOFLSH;
1946 ** MJM - removed default baudrate settings
1947 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1949 #ifdef CBAUD
1950 port.c_cflag &= ~CBAUD;
1951 switch (lpdcb->BaudRate) {
1952 case 110:
1953 case CBR_110:
1954 port.c_cflag |= B110;
1955 break;
1956 case 300:
1957 case CBR_300:
1958 port.c_cflag |= B300;
1959 break;
1960 case 600:
1961 case CBR_600:
1962 port.c_cflag |= B600;
1963 break;
1964 case 1200:
1965 case CBR_1200:
1966 port.c_cflag |= B1200;
1967 break;
1968 case 2400:
1969 case CBR_2400:
1970 port.c_cflag |= B2400;
1971 break;
1972 case 4800:
1973 case CBR_4800:
1974 port.c_cflag |= B4800;
1975 break;
1976 case 9600:
1977 case CBR_9600:
1978 port.c_cflag |= B9600;
1979 break;
1980 case 19200:
1981 case CBR_19200:
1982 port.c_cflag |= B19200;
1983 break;
1984 case 38400:
1985 case CBR_38400:
1986 port.c_cflag |= B38400;
1987 break;
1988 #ifdef B57600
1989 case 57600:
1990 port.c_cflag |= B57600;
1991 break;
1992 #endif
1993 #ifdef B115200
1994 case 115200:
1995 port.c_cflag |= B115200;
1996 break;
1997 #endif
1998 #ifdef B230400
1999 case 230400:
2000 port.c_cflag |= B230400;
2001 break;
2002 #endif
2003 #ifdef B460800
2004 case 460600:
2005 port.c_cflag |= B460800;
2006 break;
2007 #endif
2008 default:
2009 commerror = IE_BAUDRATE;
2010 close( fd );
2011 ERR("baudrate %ld\n",lpdcb->BaudRate);
2012 return FALSE;
2014 #elif !defined(__EMX__)
2015 switch (lpdcb->BaudRate) {
2016 case 110:
2017 case CBR_110:
2018 port.c_ospeed = B110;
2019 break;
2020 case 300:
2021 case CBR_300:
2022 port.c_ospeed = B300;
2023 break;
2024 case 600:
2025 case CBR_600:
2026 port.c_ospeed = B600;
2027 break;
2028 case 1200:
2029 case CBR_1200:
2030 port.c_ospeed = B1200;
2031 break;
2032 case 2400:
2033 case CBR_2400:
2034 port.c_ospeed = B2400;
2035 break;
2036 case 4800:
2037 case CBR_4800:
2038 port.c_ospeed = B4800;
2039 break;
2040 case 9600:
2041 case CBR_9600:
2042 port.c_ospeed = B9600;
2043 break;
2044 case 19200:
2045 case CBR_19200:
2046 port.c_ospeed = B19200;
2047 break;
2048 case 38400:
2049 case CBR_38400:
2050 port.c_ospeed = B38400;
2051 break;
2052 default:
2053 commerror = IE_BAUDRATE;
2054 close( fd );
2055 ERR("baudrate %d \n",lpdcb->BaudRate);
2056 return FALSE;
2058 port.c_ispeed = port.c_ospeed;
2059 #endif
2060 port.c_cflag &= ~CSIZE;
2061 switch (lpdcb->ByteSize) {
2062 case 5:
2063 port.c_cflag |= CS5;
2064 break;
2065 case 6:
2066 port.c_cflag |= CS6;
2067 break;
2068 case 7:
2069 port.c_cflag |= CS7;
2070 break;
2071 case 8:
2072 port.c_cflag |= CS8;
2073 break;
2074 default:
2075 commerror = IE_BYTESIZE;
2076 close( fd );
2077 ERR("ByteSize\n");
2078 return FALSE;
2081 port.c_cflag &= ~(PARENB | PARODD);
2082 if (lpdcb->fParity)
2083 port.c_iflag |= INPCK;
2084 else
2085 port.c_iflag &= ~INPCK;
2086 switch (lpdcb->Parity) {
2087 case NOPARITY:
2088 break;
2089 case ODDPARITY:
2090 port.c_cflag |= (PARENB | PARODD);
2091 break;
2092 case EVENPARITY:
2093 port.c_cflag |= PARENB;
2094 break;
2095 default:
2096 commerror = IE_BYTESIZE;
2097 close( fd );
2098 ERR("Parity\n");
2099 return FALSE;
2103 switch (lpdcb->StopBits) {
2104 case ONESTOPBIT:
2105 port.c_cflag &= ~CSTOPB;
2106 break;
2107 case TWOSTOPBITS:
2108 port.c_cflag |= CSTOPB;
2109 break;
2110 default:
2111 commerror = IE_BYTESIZE;
2112 close( fd );
2113 ERR("StopBits\n");
2114 return FALSE;
2116 #ifdef CRTSCTS
2117 if ( lpdcb->fOutxCtsFlow ||
2118 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2119 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2122 port.c_cflag |= CRTSCTS;
2123 TRACE("CRTSCTS\n");
2126 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2128 port.c_cflag &= ~CRTSCTS;
2129 TRACE("~CRTSCTS\n");
2132 #endif
2133 if (lpdcb->fInX)
2134 port.c_iflag |= IXON;
2135 else
2136 port.c_iflag &= ~IXON;
2137 if (lpdcb->fOutX)
2138 port.c_iflag |= IXOFF;
2139 else
2140 port.c_iflag &= ~IXOFF;
2142 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2143 int save_error=errno;
2144 commerror = WinError();
2145 close( fd );
2146 #ifdef HAVE_STRERROR
2147 ERR("tcgetattr error '%s'\n", strerror(save_error));
2148 #else
2149 ERR("tcgetattr error %d\n", save_error);
2150 #endif
2151 return FALSE;
2152 } else {
2153 commerror = 0;
2154 close( fd );
2155 return TRUE;
2160 /*****************************************************************************
2161 * GetCommState (KERNEL32.159)
2163 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2165 struct termios port;
2166 int fd,speed;
2168 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2170 if ((fd = COMM_GetReadFd(handle)) < 0)
2172 ERR("can't get COMM_GetReadFd\n");
2173 return FALSE;
2175 if (tcgetattr(fd, &port) == -1) {
2176 int save_error=errno;
2177 #ifdef HAVE_STRERROR
2178 ERR("tcgetattr error '%s'\n", strerror(save_error));
2179 #else
2180 ERR("tcgetattr error %d\n", save_error);
2181 #endif
2182 commerror = WinError();
2183 close( fd );
2184 return FALSE;
2186 close( fd );
2187 #ifndef __EMX__
2188 #ifdef CBAUD
2189 speed= (port.c_cflag & CBAUD);
2190 #else
2191 speed= (cfgetospeed(&port));
2192 #endif
2193 switch (speed) {
2194 case B110:
2195 lpdcb->BaudRate = 110;
2196 break;
2197 case B300:
2198 lpdcb->BaudRate = 300;
2199 break;
2200 case B600:
2201 lpdcb->BaudRate = 600;
2202 break;
2203 case B1200:
2204 lpdcb->BaudRate = 1200;
2205 break;
2206 case B2400:
2207 lpdcb->BaudRate = 2400;
2208 break;
2209 case B4800:
2210 lpdcb->BaudRate = 4800;
2211 break;
2212 case B9600:
2213 lpdcb->BaudRate = 9600;
2214 break;
2215 case B19200:
2216 lpdcb->BaudRate = 19200;
2217 break;
2218 case B38400:
2219 lpdcb->BaudRate = 38400;
2220 break;
2221 #ifdef B57600
2222 case B57600:
2223 lpdcb->BaudRate = 57600;
2224 break;
2225 #endif
2226 #ifdef B115200
2227 case B115200:
2228 lpdcb->BaudRate = 115200;
2229 break;
2230 #endif
2231 #ifdef B230400
2232 case B230400:
2233 lpdcb->BaudRate = 230400;
2234 break;
2235 #endif
2236 #ifdef B460800
2237 case B460800:
2238 lpdcb->BaudRate = 460800;
2239 break;
2240 #endif
2241 default:
2242 ERR("unknown speed %x \n",speed);
2244 #endif
2245 switch (port.c_cflag & CSIZE) {
2246 case CS5:
2247 lpdcb->ByteSize = 5;
2248 break;
2249 case CS6:
2250 lpdcb->ByteSize = 6;
2251 break;
2252 case CS7:
2253 lpdcb->ByteSize = 7;
2254 break;
2255 case CS8:
2256 lpdcb->ByteSize = 8;
2257 break;
2258 default:
2259 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2262 if(port.c_iflag & INPCK)
2263 lpdcb->fParity = TRUE;
2264 else
2265 lpdcb->fParity = FALSE;
2266 switch (port.c_cflag & (PARENB | PARODD)) {
2267 case 0:
2268 lpdcb->Parity = NOPARITY;
2269 break;
2270 case PARENB:
2271 lpdcb->Parity = EVENPARITY;
2272 break;
2273 case (PARENB | PARODD):
2274 lpdcb->Parity = ODDPARITY;
2275 break;
2278 if (port.c_cflag & CSTOPB)
2279 lpdcb->StopBits = TWOSTOPBITS;
2280 else
2281 lpdcb->StopBits = ONESTOPBIT;
2283 lpdcb->fNull = 0;
2284 lpdcb->fBinary = 1;
2286 #ifdef CRTSCTS
2288 if (port.c_cflag & CRTSCTS) {
2289 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2290 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2291 lpdcb->fOutxCtsFlow = 1;
2292 lpdcb->fOutxDsrFlow = 1;
2293 } else
2294 #endif
2296 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2297 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2299 if (port.c_iflag & IXON)
2300 lpdcb->fInX = 1;
2301 else
2302 lpdcb->fInX = 0;
2304 if (port.c_iflag & IXOFF)
2305 lpdcb->fOutX = 1;
2306 else
2307 lpdcb->fOutX = 0;
2309 lpdcb->XonChar =
2310 lpdcb->XoffChar =
2312 lpdcb->XonLim = 10;
2313 lpdcb->XoffLim = 10;
2315 commerror = 0;
2317 TRACE("OK\n");
2319 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2320 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2321 (lpdcb->StopBits == ONESTOPBIT)?1:
2322 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2323 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2324 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2325 #ifdef CRTSCTS
2326 if ( lpdcb->fOutxCtsFlow ||
2327 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2328 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2330 TRACE("CRTSCTS\n");
2332 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2333 TRACE("~CRTSCTS\n");
2335 #endif
2336 return TRUE;
2339 /*****************************************************************************
2340 * TransmitCommChar (KERNEL32.535)
2342 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2344 struct DosDeviceStruct *ptr;
2346 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2347 if ((ptr = GetDeviceStruct(cid)) == NULL)
2348 FIXME("no handle for cid = %0x!.\n",cid);
2349 return FALSE;
2351 if (ptr->suspended) {
2352 ptr->commerror = IE_HARDWARE;
2353 return FALSE;
2355 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2356 ptr->commerror = WinError();
2357 return FALSE;
2358 } else {
2359 ptr->commerror = 0;
2360 return TRUE;
2364 /*****************************************************************************
2365 * GetCommTimeouts (KERNEL32.160)
2367 BOOL WINAPI GetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts)
2369 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2370 return TRUE;
2373 /*****************************************************************************
2374 * SetCommTimeouts (KERNEL32.453)
2376 BOOL WINAPI SetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts) {
2377 /* struct DosDeviceStruct *ptr; */
2378 struct termios tios;
2379 int fd;
2381 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2383 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2384 FIXME("no handle for cid = %0x!.\n",hcom);
2385 return FALSE;
2389 fd = COMM_GetWriteFd(hcom);
2390 if (fd < 0) {
2391 FIXME("no fd for cid = %0x!.\n",hcom);
2392 return FALSE;
2396 FIXME("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2397 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts->ReadTotalTimeoutMultiplier);
2398 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts->ReadTotalTimeoutConstant);
2399 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts->WriteTotalTimeoutMultiplier);
2400 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts->WriteTotalTimeoutConstant);
2403 if (-1==tcgetattr(fd,&tios)) {
2404 FIXME("tcgetattr on fd %d failed!\n",fd);
2405 return FALSE;
2407 /* VTIME is in 1/10 seconds */
2408 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2409 if (-1==tcsetattr(fd,0,&tios)) {
2410 FIXME("tcsetattr on fd %d failed!\n",fd);
2411 return FALSE;
2413 return TRUE;
2416 /***********************************************************************
2417 * GetCommModemStatus (KERNEL32.285)
2419 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2421 int fd,mstat, result=FALSE;
2423 *lpModemStat=0;
2424 #ifdef TIOCMGET
2425 fd = COMM_GetWriteFd(hFile);
2426 if(fd<0)
2427 return FALSE;
2428 result = ioctl(fd, TIOCMGET, &mstat);
2429 close(fd);
2430 if (result == -1)
2432 TRACE("ioctl failed\n");
2433 return FALSE;
2435 if (mstat & TIOCM_CTS)
2436 *lpModemStat |= MS_CTS_ON;
2437 if (mstat & TIOCM_DSR)
2438 *lpModemStat |= MS_DSR_ON;
2439 if (mstat & TIOCM_RNG)
2440 *lpModemStat |= MS_RING_ON;
2441 /*FIXME: Not really sure about RLSD UB 990810*/
2442 if (mstat & TIOCM_CAR)
2443 *lpModemStat |= MS_RLSD_ON;
2444 TRACE("%s%s%s%s\n",
2445 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2446 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2447 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2448 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2449 return TRUE;
2450 #else
2451 return FALSE;
2452 #endif
2454 /***********************************************************************
2455 * WaitCommEvent (KERNEL32.719)
2457 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2459 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2460 return TRUE;
2463 /***********************************************************************
2464 * GetCommProperties (KERNEL32.???)
2466 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2468 FIXME("(%d %p )\n",hFile,dcb);
2469 return TRUE;
2472 /***********************************************************************
2473 * SetCommProperties (KERNEL32.???)
2475 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2477 FIXME("(%d %p )\n",hFile,dcb);
2478 return TRUE;