Added support for icons in property sheet tabs.
[wine/testsucceed.git] / misc / comm.c
blobe0cedf3d99ab3a0aac6439c5d0a3d022f78f69a0
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
9 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
12 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
13 * - Use port indices instead of unixfds for win16
14 * - Moved things around (separated win16 and win32 routines)
15 * - Added some hints on how to implement buffers and EnableCommNotification.
17 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
18 * - ptr->fd wasn't getting cleared on close.
19 * - GetCommEventMask() and GetCommError() didn't do much of anything.
20 * IMHO, they are still wrong, but they at least implement the RXCHAR
21 * event and return I/O queue sizes, which makes the app I'm interested
22 * in (analog devices EZKIT DSP development system) work.
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
26 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
28 * Oktober 98, Rein Klazes [RHK]
29 * A program that wants to monitor the modem status line (RLSD/DCD) may
30 * poll the modem status register in the commMask structure. I update the bit
31 * in GetCommError, waiting for an implementation of communication events.
35 #include "config.h"
37 #include <stdlib.h>
38 #include <termios.h>
39 #include <fcntl.h>
40 #include <string.h>
41 #ifdef HAVE_STRINGS_H
42 # include <strings.h>
43 #endif
44 #include <errno.h>
45 #include <ctype.h>
46 #include <sys/stat.h>
47 #ifdef HAVE_SYS_FILIO_H
48 # include <sys/filio.h>
49 #endif
50 #include <sys/ioctl.h>
51 #include <unistd.h>
53 #include "wine/winuser16.h"
54 #include "comm.h"
55 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
57 #endif
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
60 #endif
61 #include "heap.h"
62 #include "options.h"
64 #include "server.h"
65 #include "process.h"
66 #include "winerror.h"
67 #include "services.h"
68 #include "file.h"
70 #include "debugtools.h"
72 DEFAULT_DEBUG_CHANNEL(comm)
74 #ifndef TIOCINQ
75 #define TIOCINQ FIONREAD
76 #endif
77 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
78 #define FLAG_LPT 0x80
80 struct DosDeviceStruct COM[MAX_PORTS];
81 struct DosDeviceStruct LPT[MAX_PORTS];
82 /* pointers to unknown(==undocumented) comm structure */
83 LPCVOID *unknown[MAX_PORTS];
84 /* save terminal states */
85 static struct termios m_stat[MAX_PORTS];
87 void COMM_Init(void)
89 int x;
90 char option[10], temp[256], *btemp;
91 struct stat st;
93 for (x=0; x!=MAX_PORTS; x++) {
94 strcpy(option,"COMx");
95 option[3] = '1' + x;
96 option[4] = '\0';
98 PROFILE_GetWineIniString( "serialports", option, "*",
99 temp, sizeof(temp) );
100 if (!strcmp(temp, "*") || *temp == '\0')
101 COM[x].devicename = NULL;
102 else {
103 btemp = strchr(temp,',');
104 if (btemp != NULL) {
105 *btemp++ = '\0';
106 COM[x].baudrate = atoi(btemp);
107 } else {
108 COM[x].baudrate = -1;
110 stat(temp, &st);
111 if (!S_ISCHR(st.st_mode))
112 WARN("Can't use `%s' as %s !\n", temp, option);
113 else
114 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
115 WARN("Can't malloc for device info!\n");
116 else {
117 COM[x].fd = 0;
118 strcpy(COM[x].devicename, temp);
120 TRACE("%s = %s\n", option, COM[x].devicename);
123 strcpy(option, "LPTx");
124 option[3] = '1' + x;
125 option[4] = '\0';
127 PROFILE_GetWineIniString( "parallelports", option, "*",
128 temp, sizeof(temp) );
129 if (!strcmp(temp, "*") || *temp == '\0')
130 LPT[x].devicename = NULL;
131 else {
132 stat(temp, &st);
133 if (!S_ISCHR(st.st_mode))
134 WARN("Can't use `%s' as %s !\n", temp, option);
135 else
136 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
137 WARN("Can't malloc for device info!\n");
138 else {
139 LPT[x].fd = 0;
140 strcpy(LPT[x].devicename, temp);
142 TRACE("%s = %s\n", option, LPT[x].devicename);
149 static struct DosDeviceStruct *GetDeviceStruct(int fd)
151 if ((fd&0x7F)<=MAX_PORTS) {
152 if (!(fd&FLAG_LPT)) {
153 if (COM[fd].fd)
154 return &COM[fd];
155 } else {
156 if (LPT[fd].fd)
157 return &LPT[fd];
161 return NULL;
164 static int GetCommPort_fd(int fd)
166 int x;
168 for (x=0; x<MAX_PORTS; x++) {
169 if (COM[x].fd == fd)
170 return x;
173 return -1;
176 static int ValidCOMPort(int x)
178 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
181 static int ValidLPTPort(int x)
183 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
186 static int WinError(void)
188 TRACE("errno = %d\n", errno);
189 switch (errno) {
190 default:
191 return CE_IOE;
195 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
197 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
198 + ptr->ibuf_head - ptr->ibuf_tail;
201 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
203 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
204 + ptr->obuf_head - ptr->obuf_tail;
207 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
209 unsigned int mstat, okay;
210 okay = ioctl(fd, TIOCMGET, &mstat);
211 if (okay) return okay;
212 if (andy) mstat &= andy;
213 mstat |= orrie;
214 return ioctl(fd, TIOCMSET, &mstat);
217 static void CALLBACK comm_notification( ULONG_PTR private )
219 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
220 int prev, bleft, len;
221 WORD mask = 0;
222 int cid = GetCommPort_fd(ptr->fd);
224 TRACE("async notification\n");
225 /* read data from comm port */
226 prev = comm_inbuf(ptr);
227 do {
228 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
229 - ptr->ibuf_head;
230 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
231 if (len > 0) {
232 if (!bleft) {
233 ptr->commerror = CE_RXOVER;
234 } else {
235 /* check for events */
236 if ((ptr->eventmask & EV_RXFLAG) &&
237 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
238 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
239 mask |= CN_EVENT;
241 if (ptr->eventmask & EV_RXCHAR) {
242 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
243 mask |= CN_EVENT;
245 /* advance buffer position */
246 ptr->ibuf_head += len;
247 if (ptr->ibuf_head >= ptr->ibuf_size)
248 ptr->ibuf_head = 0;
251 } while (len > 0);
252 /* check for notification */
253 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
254 (comm_inbuf(ptr)>=ptr->n_read)) {
255 /* passed the receive notification threshold */
256 mask |= CN_RECEIVE;
259 /* write any TransmitCommChar character */
260 if (ptr->xmit>=0) {
261 len = write(ptr->fd, &(ptr->xmit), 1);
262 if (len > 0) ptr->xmit = -1;
264 /* write from output queue */
265 prev = comm_outbuf(ptr);
266 do {
267 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
268 - ptr->obuf_tail;
269 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
270 if (len > 0) {
271 ptr->obuf_tail += len;
272 if (ptr->obuf_tail >= ptr->obuf_size)
273 ptr->obuf_tail = 0;
274 /* flag event */
275 if ((ptr->obuf_tail == ptr->obuf_head) && (ptr->eventmask & EV_TXEMPTY)) {
276 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
277 mask |= CN_EVENT;
280 } while (len > 0);
281 /* check for notification */
282 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
283 (comm_outbuf(ptr)<ptr->n_write)) {
284 /* passed the transmit notification threshold */
285 mask |= CN_TRANSMIT;
288 /* send notifications, if any */
289 if (ptr->wnd && mask) {
290 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
291 PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
295 /**************************************************************************
296 * BuildCommDCB (USER.213)
298 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
300 /* "COM1:9600,n,8,1" */
301 /* 012345 */
302 int port;
303 char *ptr, temp[256];
305 TRACE("(%s), ptr %p\n", device, lpdcb);
307 if (!lstrncmpiA(device,"COM",3)) {
308 port = device[3] - '0';
311 if (port-- == 0) {
312 ERR("BUG ! COM0 can't exist!.\n");
313 return -1;
316 if (!ValidCOMPort(port)) {
317 return -1;
320 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
322 lpdcb->Id = port;
324 if (!*(device+4))
325 return 0;
327 if (*(device+4) != ':')
328 return -1;
330 strcpy(temp,device+5);
331 ptr = strtok(temp, ", ");
333 if (COM[port].baudrate > 0)
334 lpdcb->BaudRate = COM[port].baudrate;
335 else
336 lpdcb->BaudRate = atoi(ptr);
337 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
339 ptr = strtok(NULL, ", ");
340 if (islower(*ptr))
341 *ptr = toupper(*ptr);
343 TRACE("parity (%c)\n", *ptr);
344 lpdcb->fParity = TRUE;
345 switch (*ptr) {
346 case 'N':
347 lpdcb->Parity = NOPARITY;
348 lpdcb->fParity = FALSE;
349 break;
350 case 'E':
351 lpdcb->Parity = EVENPARITY;
352 break;
353 case 'M':
354 lpdcb->Parity = MARKPARITY;
355 break;
356 case 'O':
357 lpdcb->Parity = ODDPARITY;
358 break;
359 default:
360 WARN("Unknown parity `%c'!\n", *ptr);
361 return -1;
364 ptr = strtok(NULL, ", ");
365 TRACE("charsize (%c)\n", *ptr);
366 lpdcb->ByteSize = *ptr - '0';
368 ptr = strtok(NULL, ", ");
369 TRACE("stopbits (%c)\n", *ptr);
370 switch (*ptr) {
371 case '1':
372 lpdcb->StopBits = ONESTOPBIT;
373 break;
374 case '2':
375 lpdcb->StopBits = TWOSTOPBITS;
376 break;
377 default:
378 WARN("Unknown # of stopbits `%c'!\n", *ptr);
379 return -1;
383 return 0;
386 /*****************************************************************************
387 * OpenComm (USER.200)
389 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
391 int port,fd;
393 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
395 if (strlen(device) < 4)
396 return IE_BADID;
398 port = device[3] - '0';
400 if (port-- == 0)
401 ERR("BUG ! COM0 or LPT0 don't exist !\n");
403 if (!lstrncmpiA(device,"COM",3)) {
405 TRACE("%s = %s\n", device, COM[port].devicename);
407 if (!ValidCOMPort(port))
408 return IE_BADID;
410 if (COM[port].fd)
411 return IE_OPEN;
413 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
414 if (fd == -1) {
415 ERR("error=%d\n", errno);
416 return IE_HARDWARE;
417 } else {
418 unknown[port] = SEGPTR_ALLOC(40);
419 bzero(unknown[port],40);
420 COM[port].fd = fd;
421 COM[port].commerror = 0;
422 COM[port].eventmask = 0;
423 COM[port].evtchar = 0; /* FIXME: default? */
424 /* save terminal state */
425 tcgetattr(fd,&m_stat[port]);
426 /* set default parameters */
427 if(COM[port].baudrate>-1){
428 DCB16 dcb;
429 GetCommState16(port, &dcb);
430 dcb.BaudRate=COM[port].baudrate;
431 /* more defaults:
432 * databits, parity, stopbits
434 SetCommState16( &dcb);
436 /* init priority characters */
437 COM[port].unget = -1;
438 COM[port].xmit = -1;
439 /* allocate buffers */
440 COM[port].ibuf_size = cbInQueue;
441 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
442 COM[port].obuf_size = cbOutQueue;
443 COM[port].obuf_head = COM[port].obuf_tail = 0;
445 COM[port].inbuf = malloc(cbInQueue);
446 if (COM[port].inbuf) {
447 COM[port].outbuf = malloc(cbOutQueue);
448 if (!COM[port].outbuf)
449 free(COM[port].inbuf);
450 } else COM[port].outbuf = NULL;
451 if (!COM[port].outbuf) {
452 /* not enough memory */
453 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
454 close(COM[port].fd);
455 ERR("out of memory");
456 return IE_MEMORY;
459 COM[port].service = SERVICE_AddObject( FILE_DupUnixHandle( COM[port].fd,
460 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE ),
461 comm_notification,
462 (ULONG_PTR)&COM[port] );
463 /* bootstrap notifications, just in case */
464 comm_notification( (ULONG_PTR)&COM[port] );
465 return port;
468 else
469 if (!lstrncmpiA(device,"LPT",3)) {
471 if (!ValidLPTPort(port))
472 return IE_BADID;
474 if (LPT[port].fd)
475 return IE_OPEN;
477 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
478 if (fd == -1) {
479 return IE_HARDWARE;
480 } else {
481 LPT[port].fd = fd;
482 LPT[port].commerror = 0;
483 LPT[port].eventmask = 0;
484 return port|FLAG_LPT;
487 return 0;
490 /*****************************************************************************
491 * CloseComm (USER.207)
493 INT16 WINAPI CloseComm16(INT16 cid)
495 struct DosDeviceStruct *ptr;
497 TRACE("cid=%d\n", cid);
498 if ((ptr = GetDeviceStruct(cid)) == NULL) {
499 return -1;
501 if (!(cid&FLAG_LPT)) {
502 /* COM port */
503 SEGPTR_FREE(unknown[cid]); /* [LW] */
505 SERVICE_Delete( COM[cid].service );
506 /* free buffers */
507 free(ptr->outbuf);
508 free(ptr->inbuf);
510 /* reset modem lines */
511 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
514 if (close(ptr->fd) == -1) {
515 ptr->commerror = WinError();
516 /* FIXME: should we clear ptr->fd here? */
517 return -1;
518 } else {
519 ptr->commerror = 0;
520 ptr->fd = 0;
521 return 0;
525 /*****************************************************************************
526 * SetCommBreak (USER.210)
528 INT16 WINAPI SetCommBreak16(INT16 cid)
530 struct DosDeviceStruct *ptr;
532 TRACE("cid=%d\n", cid);
533 if ((ptr = GetDeviceStruct(cid)) == NULL) {
534 return -1;
537 ptr->suspended = 1;
538 ptr->commerror = 0;
539 return 0;
542 /*****************************************************************************
543 * ClearCommBreak (USER.211)
545 INT16 WINAPI ClearCommBreak16(INT16 cid)
547 struct DosDeviceStruct *ptr;
549 TRACE("cid=%d\n", cid);
550 if ((ptr = GetDeviceStruct(cid)) == NULL) {
551 return -1;
554 ptr->suspended = 0;
555 ptr->commerror = 0;
556 return 0;
559 /*****************************************************************************
560 * EscapeCommFunction (USER.214)
562 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
564 int max;
565 struct DosDeviceStruct *ptr;
566 struct termios port;
568 TRACE("cid=%d, function=%d\n", cid, nFunction);
569 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
570 if ((ptr = GetDeviceStruct(cid)) == NULL) {
571 return -1;
573 if (tcgetattr(ptr->fd,&port) == -1) {
574 ptr->commerror=WinError();
575 return -1;
577 } else ptr = NULL;
579 switch (nFunction) {
580 case RESETDEV:
581 break;
583 case GETMAXCOM:
584 for (max = MAX_PORTS;!COM[max].devicename;max--)
586 return max;
587 break;
589 case GETMAXLPT:
590 for (max = MAX_PORTS;!LPT[max].devicename;max--)
592 return FLAG_LPT + max;
593 break;
595 case GETBASEIRQ:
596 /* FIXME: use tables */
597 /* just fake something for now */
598 if (cid & FLAG_LPT) {
599 /* LPT1: irq 7, LPT2: irq 5 */
600 return (cid & 0x7f) ? 5 : 7;
601 } else {
602 /* COM1: irq 4, COM2: irq 3,
603 COM3: irq 4, COM4: irq 3 */
604 return 4 - (cid & 1);
606 break;
608 #ifdef TIOCM_DTR
609 case CLRDTR:
610 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
611 #endif
612 #ifdef TIOCM_RTS
613 case CLRRTS:
614 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
615 #endif
617 #ifdef TIOCM_DTR
618 case SETDTR:
619 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
620 #endif
622 #ifdef TIOCM_RTS
623 case SETRTS:
624 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
625 #endif
627 case SETXOFF:
628 port.c_iflag |= IXOFF;
629 break;
631 case SETXON:
632 port.c_iflag |= IXON;
633 break;
635 default:
636 WARN("(cid=%d,nFunction=%d): Unknown function\n",
637 cid, nFunction);
638 break;
641 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
642 ptr->commerror = WinError();
643 return -1;
644 } else {
645 ptr->commerror = 0;
646 return 0;
650 /*****************************************************************************
651 * FlushComm (USER.215)
653 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
655 int queue;
656 struct DosDeviceStruct *ptr;
658 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
659 if ((ptr = GetDeviceStruct(cid)) == NULL) {
660 return -1;
662 switch (fnQueue) {
663 case 0:
664 queue = TCOFLUSH;
665 ptr->obuf_tail = ptr->obuf_head;
666 break;
667 case 1:
668 queue = TCIFLUSH;
669 ptr->ibuf_head = ptr->ibuf_tail;
670 break;
671 default:
672 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
673 cid, fnQueue);
674 return -1;
676 if (tcflush(ptr->fd, queue)) {
677 ptr->commerror = WinError();
678 return -1;
679 } else {
680 ptr->commerror = 0;
681 return 0;
685 /********************************************************************
686 * GetCommError (USER.203)
688 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
690 int temperror;
691 struct DosDeviceStruct *ptr;
692 unsigned char *stol;
693 unsigned int mstat;
695 if ((ptr = GetDeviceStruct(cid)) == NULL) {
696 return -1;
698 if (cid&FLAG_LPT) {
699 WARN(" cid %d not comm port\n",cid);
700 return CE_MODE;
702 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
703 ioctl(ptr->fd,TIOCMGET,&mstat);
704 if( mstat&TIOCM_CAR )
705 *stol |= 0x80;
706 else
707 *stol &=0x7f;
709 if (lpStat) {
710 lpStat->status = 0;
712 lpStat->cbOutQue = comm_outbuf(ptr);
713 lpStat->cbInQue = comm_inbuf(ptr);
715 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
716 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
717 lpStat->cbOutQue, *stol);
719 else
720 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
721 cid, ptr->commerror, *stol);
723 /* Return any errors and clear it */
724 temperror = ptr->commerror;
725 ptr->commerror = 0;
726 return(temperror);
729 /*****************************************************************************
730 * SetCommEventMask (USER.208)
732 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
734 struct DosDeviceStruct *ptr;
735 unsigned char *stol;
736 int repid;
737 unsigned int mstat;
739 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
740 if ((ptr = GetDeviceStruct(cid)) == NULL)
741 return (SEGPTR)NULL;
743 ptr->eventmask = fuEvtMask;
745 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
746 WARN(" cid %d not comm port\n",cid);
747 return (SEGPTR)NULL;
749 /* it's a COM port ? -> modify flags */
750 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
751 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
752 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
753 if ((mstat&TIOCM_CAR))
754 *stol |= 0x80;
755 else
756 *stol &=0x7f;
758 TRACE(" modem dcd construct %x\n",*stol);
759 return SEGPTR_GET(unknown[cid]);
762 /*****************************************************************************
763 * GetCommEventMask (USER.209)
765 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
767 struct DosDeviceStruct *ptr;
768 WORD events;
770 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
771 if ((ptr = GetDeviceStruct(cid)) == NULL)
772 return 0;
774 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
775 WARN(" cid %d not comm port\n",cid);
776 return 0;
779 events = *(WORD*)(unknown[cid]) & fnEvtClear;
780 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
781 return events;
784 /*****************************************************************************
785 * SetCommState16 (USER.201)
787 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
789 struct termios port;
790 struct DosDeviceStruct *ptr;
792 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
793 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
794 return -1;
796 if (tcgetattr(ptr->fd, &port) == -1) {
797 ptr->commerror = WinError();
798 return -1;
801 port.c_cc[VMIN] = 0;
802 port.c_cc[VTIME] = 1;
804 #ifdef IMAXBEL
805 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
806 #else
807 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
808 #endif
809 port.c_iflag |= (IGNBRK);
811 port.c_oflag &= ~(OPOST);
813 port.c_cflag &= ~(HUPCL);
814 port.c_cflag |= CLOCAL | CREAD;
816 port.c_lflag &= ~(ICANON|ECHO|ISIG);
817 port.c_lflag |= NOFLSH;
819 TRACE("baudrate %d\n",lpdcb->BaudRate);
820 #ifdef CBAUD
821 port.c_cflag &= ~CBAUD;
822 switch (lpdcb->BaudRate) {
823 case 110:
824 case CBR_110:
825 port.c_cflag |= B110;
826 break;
827 case 300:
828 case CBR_300:
829 port.c_cflag |= B300;
830 break;
831 case 600:
832 case CBR_600:
833 port.c_cflag |= B600;
834 break;
835 case 1200:
836 case CBR_1200:
837 port.c_cflag |= B1200;
838 break;
839 case 2400:
840 case CBR_2400:
841 port.c_cflag |= B2400;
842 break;
843 case 4800:
844 case CBR_4800:
845 port.c_cflag |= B4800;
846 break;
847 case 9600:
848 case CBR_9600:
849 port.c_cflag |= B9600;
850 break;
851 case 19200:
852 case CBR_19200:
853 port.c_cflag |= B19200;
854 break;
855 case 38400:
856 case CBR_38400:
857 port.c_cflag |= B38400;
858 break;
859 #ifdef B57600
860 case 57600:
861 port.c_cflag |= B57600;
862 break;
863 #endif
864 #ifdef B115200
865 case 57601:
866 port.c_cflag |= B115200;
867 break;
868 #endif
869 default:
870 ptr->commerror = IE_BAUDRATE;
871 return -1;
873 #elif !defined(__EMX__)
874 switch (lpdcb->BaudRate) {
875 case 110:
876 case CBR_110:
877 port.c_ospeed = B110;
878 break;
879 case 300:
880 case CBR_300:
881 port.c_ospeed = B300;
882 break;
883 case 600:
884 case CBR_600:
885 port.c_ospeed = B600;
886 break;
887 case 1200:
888 case CBR_1200:
889 port.c_ospeed = B1200;
890 break;
891 case 2400:
892 case CBR_2400:
893 port.c_ospeed = B2400;
894 break;
895 case 4800:
896 case CBR_4800:
897 port.c_ospeed = B4800;
898 break;
899 case 9600:
900 case CBR_9600:
901 port.c_ospeed = B9600;
902 break;
903 case 19200:
904 case CBR_19200:
905 port.c_ospeed = B19200;
906 break;
907 case 38400:
908 case CBR_38400:
909 port.c_ospeed = B38400;
910 break;
911 default:
912 ptr->commerror = IE_BAUDRATE;
913 return -1;
915 port.c_ispeed = port.c_ospeed;
916 #endif
917 TRACE("bytesize %d\n",lpdcb->ByteSize);
918 port.c_cflag &= ~CSIZE;
919 switch (lpdcb->ByteSize) {
920 case 5:
921 port.c_cflag |= CS5;
922 break;
923 case 6:
924 port.c_cflag |= CS6;
925 break;
926 case 7:
927 port.c_cflag |= CS7;
928 break;
929 case 8:
930 port.c_cflag |= CS8;
931 break;
932 default:
933 ptr->commerror = IE_BYTESIZE;
934 return -1;
937 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
938 port.c_cflag &= ~(PARENB | PARODD);
939 if (lpdcb->fParity)
940 port.c_iflag |= INPCK;
941 else
942 port.c_iflag &= ~INPCK;
943 switch (lpdcb->Parity) {
944 case NOPARITY:
945 break;
946 case ODDPARITY:
947 port.c_cflag |= (PARENB | PARODD);
948 break;
949 case EVENPARITY:
950 port.c_cflag |= PARENB;
951 break;
952 default:
953 ptr->commerror = IE_BYTESIZE;
954 return -1;
958 TRACE("stopbits %d\n",lpdcb->StopBits);
960 switch (lpdcb->StopBits) {
961 case ONESTOPBIT:
962 port.c_cflag &= ~CSTOPB;
963 break;
964 case TWOSTOPBITS:
965 port.c_cflag |= CSTOPB;
966 break;
967 default:
968 ptr->commerror = IE_BYTESIZE;
969 return -1;
971 #ifdef CRTSCTS
973 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
974 port.c_cflag |= CRTSCTS;
976 if (lpdcb->fDtrDisable)
977 port.c_cflag &= ~CRTSCTS;
978 #endif
979 if (lpdcb->fInX)
980 port.c_iflag |= IXON;
981 else
982 port.c_iflag &= ~IXON;
983 if (lpdcb->fOutX)
984 port.c_iflag |= IXOFF;
985 else
986 port.c_iflag &= ~IXOFF;
988 ptr->evtchar = lpdcb->EvtChar;
990 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
991 ptr->commerror = WinError();
992 return FALSE;
993 } else {
994 ptr->commerror = 0;
995 return 0;
999 /*****************************************************************************
1000 * GetCommState (USER.202)
1002 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1004 struct DosDeviceStruct *ptr;
1005 struct termios port;
1007 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1008 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1009 return -1;
1011 if (tcgetattr(ptr->fd, &port) == -1) {
1012 ptr->commerror = WinError();
1013 return -1;
1015 lpdcb->Id = cid;
1016 #ifndef __EMX__
1017 #ifdef CBAUD
1018 switch (port.c_cflag & CBAUD) {
1019 #else
1020 switch (port.c_ospeed) {
1021 #endif
1022 case B110:
1023 lpdcb->BaudRate = 110;
1024 break;
1025 case B300:
1026 lpdcb->BaudRate = 300;
1027 break;
1028 case B600:
1029 lpdcb->BaudRate = 600;
1030 break;
1031 case B1200:
1032 lpdcb->BaudRate = 1200;
1033 break;
1034 case B2400:
1035 lpdcb->BaudRate = 2400;
1036 break;
1037 case B4800:
1038 lpdcb->BaudRate = 4800;
1039 break;
1040 case B9600:
1041 lpdcb->BaudRate = 9600;
1042 break;
1043 case B19200:
1044 lpdcb->BaudRate = 19200;
1045 break;
1046 case B38400:
1047 lpdcb->BaudRate = 38400;
1048 break;
1049 #ifdef B57600
1050 case B57600:
1051 lpdcb->BaudRate = 57600;
1052 break;
1053 #endif
1054 #ifdef B115200
1055 case B115200:
1056 lpdcb->BaudRate = 57601;
1057 break;
1058 #endif
1060 #endif
1061 switch (port.c_cflag & CSIZE) {
1062 case CS5:
1063 lpdcb->ByteSize = 5;
1064 break;
1065 case CS6:
1066 lpdcb->ByteSize = 6;
1067 break;
1068 case CS7:
1069 lpdcb->ByteSize = 7;
1070 break;
1071 case CS8:
1072 lpdcb->ByteSize = 8;
1073 break;
1076 if(port.c_iflag & INPCK)
1077 lpdcb->fParity = TRUE;
1078 else
1079 lpdcb->fParity = FALSE;
1080 switch (port.c_cflag & (PARENB | PARODD)) {
1081 case 0:
1082 lpdcb->Parity = NOPARITY;
1083 break;
1084 case PARENB:
1085 lpdcb->Parity = EVENPARITY;
1086 break;
1087 case (PARENB | PARODD):
1088 lpdcb->Parity = ODDPARITY;
1089 break;
1092 if (port.c_cflag & CSTOPB)
1093 lpdcb->StopBits = TWOSTOPBITS;
1094 else
1095 lpdcb->StopBits = ONESTOPBIT;
1097 lpdcb->RlsTimeout = 50;
1098 lpdcb->CtsTimeout = 50;
1099 lpdcb->DsrTimeout = 50;
1100 lpdcb->fNull = 0;
1101 lpdcb->fChEvt = 0;
1102 lpdcb->fBinary = 1;
1103 lpdcb->fDtrDisable = 0;
1105 #ifdef CRTSCTS
1107 if (port.c_cflag & CRTSCTS) {
1108 lpdcb->fDtrflow = 1;
1109 lpdcb->fRtsflow = 1;
1110 lpdcb->fOutxCtsFlow = 1;
1111 lpdcb->fOutxDsrFlow = 1;
1112 } else
1113 #endif
1114 lpdcb->fDtrDisable = 1;
1116 if (port.c_iflag & IXON)
1117 lpdcb->fInX = 1;
1118 else
1119 lpdcb->fInX = 0;
1121 if (port.c_iflag & IXOFF)
1122 lpdcb->fOutX = 1;
1123 else
1124 lpdcb->fOutX = 0;
1126 lpdcb->XonChar =
1127 lpdcb->XoffChar =
1129 lpdcb->XonLim = 10;
1130 lpdcb->XoffLim = 10;
1132 lpdcb->EvtChar = ptr->evtchar;
1134 ptr->commerror = 0;
1135 return 0;
1138 /*****************************************************************************
1139 * TransmitCommChar (USER.206)
1141 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1143 struct DosDeviceStruct *ptr;
1145 TRACE("cid %d, data %d \n", cid, chTransmit);
1146 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1147 return -1;
1150 if (ptr->suspended) {
1151 ptr->commerror = IE_HARDWARE;
1152 return -1;
1155 if (ptr->xmit >= 0) {
1156 /* character already queued */
1157 /* FIXME: which error would Windows return? */
1158 ptr->commerror = CE_TXFULL;
1159 return -1;
1162 if (ptr->obuf_head == ptr->obuf_tail) {
1163 /* transmit queue empty, try to transmit directly */
1164 if (write(ptr->fd, &chTransmit, 1) == -1) {
1165 /* didn't work, queue it */
1166 ptr->xmit = chTransmit;
1168 } else {
1169 /* data in queue, let this char be transmitted next */
1170 ptr->xmit = chTransmit;
1173 ptr->commerror = 0;
1174 return 0;
1177 /*****************************************************************************
1178 * UngetCommChar (USER.212)
1180 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1182 struct DosDeviceStruct *ptr;
1184 TRACE("cid %d (char %d)\n", cid, chUnget);
1185 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1186 return -1;
1189 if (ptr->suspended) {
1190 ptr->commerror = IE_HARDWARE;
1191 return -1;
1194 if (ptr->unget>=0) {
1195 /* character already queued */
1196 /* FIXME: which error would Windows return? */
1197 ptr->commerror = CE_RXOVER;
1198 return -1;
1201 ptr->unget = chUnget;
1203 ptr->commerror = 0;
1204 return 0;
1207 /*****************************************************************************
1208 * ReadComm (USER.204)
1210 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1212 int status, length;
1213 struct DosDeviceStruct *ptr;
1214 LPSTR orgBuf = lpvBuf;
1216 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1217 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1218 return -1;
1221 if (ptr->suspended) {
1222 ptr->commerror = IE_HARDWARE;
1223 return -1;
1226 /* read unget character */
1227 if (ptr->unget>=0) {
1228 *lpvBuf++ = ptr->unget;
1229 ptr->unget = -1;
1231 length = 1;
1232 } else
1233 length = 0;
1235 /* read from receive buffer */
1236 while (length < cbRead) {
1237 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1238 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1239 if (!status) break;
1240 if ((cbRead - length) < status)
1241 status = cbRead - length;
1243 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1244 ptr->ibuf_tail += status;
1245 if (ptr->ibuf_tail >= ptr->ibuf_size)
1246 ptr->ibuf_tail = 0;
1247 lpvBuf += status;
1248 length += status;
1251 TRACE("%.*s\n", length, orgBuf);
1252 ptr->commerror = 0;
1253 return length;
1256 /*****************************************************************************
1257 * WriteComm (USER.205)
1259 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1261 int status, length;
1262 struct DosDeviceStruct *ptr;
1264 TRACE("cid %d, ptr %p, length %d\n",
1265 cid, lpvBuf, cbWrite);
1266 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1267 return -1;
1270 if (ptr->suspended) {
1271 ptr->commerror = IE_HARDWARE;
1272 return -1;
1275 TRACE("%.*s\n", cbWrite, lpvBuf );
1277 length = 0;
1278 while (length < cbWrite) {
1279 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1280 /* no data queued, try to write directly */
1281 status = write(ptr->fd, lpvBuf, cbWrite - length);
1282 if (status > 0) {
1283 lpvBuf += status;
1284 length += status;
1285 continue;
1288 /* can't write directly, put into transmit buffer */
1289 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1290 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1291 if (!status) break;
1292 if ((cbWrite - length) < status)
1293 status = cbWrite - length;
1294 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1295 ptr->obuf_head += status;
1296 if (ptr->obuf_head >= ptr->obuf_size)
1297 ptr->obuf_head = 0;
1298 lpvBuf += status;
1299 length += status;
1302 ptr->commerror = 0;
1303 return length;
1306 /***********************************************************************
1307 * EnableCommNotification (USER.246)
1309 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1310 INT16 cbWriteNotify, INT16 cbOutQueue )
1312 struct DosDeviceStruct *ptr;
1314 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1315 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1316 ptr->commerror = IE_BADID;
1317 return -1;
1319 ptr->wnd = hwnd;
1320 ptr->n_read = cbWriteNotify;
1321 ptr->n_write = cbOutQueue;
1322 return TRUE;
1326 /**************************************************************************
1327 * BuildCommDCBA (KERNEL32.14)
1329 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1331 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1334 /**************************************************************************
1335 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1337 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1338 LPCOMMTIMEOUTS lptimeouts)
1340 int port;
1341 char *ptr,*temp;
1343 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1345 if (!lstrncmpiA(device,"COM",3)) {
1346 port=device[3]-'0';
1347 if (port--==0) {
1348 ERR("BUG! COM0 can't exists!.\n");
1349 return FALSE;
1351 if (!ValidCOMPort(port))
1352 return FALSE;
1353 if (*(device+4)!=':')
1354 return FALSE;
1355 temp=(LPSTR)(device+5);
1356 } else
1357 temp=(LPSTR)device;
1359 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1361 lpdcb->DCBlength = sizeof(DCB);
1362 if (strchr(temp,',')) { /* old style */
1363 DCB16 dcb16;
1364 BOOL16 ret;
1365 char last=temp[strlen(temp)-1];
1367 ret=BuildCommDCB16(device,&dcb16);
1368 if (!ret)
1369 return FALSE;
1370 lpdcb->BaudRate = dcb16.BaudRate;
1371 lpdcb->ByteSize = dcb16.ByteSize;
1372 lpdcb->fBinary = dcb16.fBinary;
1373 lpdcb->Parity = dcb16.Parity;
1374 lpdcb->fParity = dcb16.fParity;
1375 lpdcb->fNull = dcb16.fNull;
1376 lpdcb->StopBits = dcb16.StopBits;
1377 if (last == 'x') {
1378 lpdcb->fInX = TRUE;
1379 lpdcb->fOutX = TRUE;
1380 lpdcb->fOutxCtsFlow = FALSE;
1381 lpdcb->fOutxDsrFlow = FALSE;
1382 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1383 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1384 } else if (last=='p') {
1385 lpdcb->fInX = FALSE;
1386 lpdcb->fOutX = FALSE;
1387 lpdcb->fOutxCtsFlow = TRUE;
1388 lpdcb->fOutxDsrFlow = TRUE;
1389 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1390 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1391 } else {
1392 lpdcb->fInX = FALSE;
1393 lpdcb->fOutX = FALSE;
1394 lpdcb->fOutxCtsFlow = FALSE;
1395 lpdcb->fOutxDsrFlow = FALSE;
1396 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1397 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1399 lpdcb->XonChar = dcb16.XonChar;
1400 lpdcb->XoffChar = dcb16.XoffChar;
1401 lpdcb->ErrorChar= dcb16.PeChar;
1402 lpdcb->fErrorChar= dcb16.fPeChar;
1403 lpdcb->EofChar = dcb16.EofChar;
1404 lpdcb->EvtChar = dcb16.EvtChar;
1405 lpdcb->XonLim = dcb16.XonLim;
1406 lpdcb->XoffLim = dcb16.XoffLim;
1407 return TRUE;
1409 ptr=strtok(temp," ");
1410 while (ptr) {
1411 DWORD flag,x;
1413 flag=0;
1414 if (!strncmp("baud=",ptr,5)) {
1415 if (!sscanf(ptr+5,"%ld",&x))
1416 WARN("Couldn't parse %s\n",ptr);
1417 lpdcb->BaudRate = x;
1418 flag=1;
1420 if (!strncmp("stop=",ptr,5)) {
1421 if (!sscanf(ptr+5,"%ld",&x))
1422 WARN("Couldn't parse %s\n",ptr);
1423 lpdcb->StopBits = x;
1424 flag=1;
1426 if (!strncmp("data=",ptr,5)) {
1427 if (!sscanf(ptr+5,"%ld",&x))
1428 WARN("Couldn't parse %s\n",ptr);
1429 lpdcb->ByteSize = x;
1430 flag=1;
1432 if (!strncmp("parity=",ptr,7)) {
1433 lpdcb->fParity = TRUE;
1434 switch (ptr[8]) {
1435 case 'N':case 'n':
1436 lpdcb->fParity = FALSE;
1437 lpdcb->Parity = NOPARITY;
1438 break;
1439 case 'E':case 'e':
1440 lpdcb->Parity = EVENPARITY;
1441 break;
1442 case 'O':case 'o':
1443 lpdcb->Parity = ODDPARITY;
1444 break;
1445 case 'M':case 'm':
1446 lpdcb->Parity = MARKPARITY;
1447 break;
1449 flag=1;
1451 if (!flag)
1452 ERR("Unhandled specifier '%s', please report.\n",ptr);
1453 ptr=strtok(NULL," ");
1455 if (lpdcb->BaudRate==110)
1456 lpdcb->StopBits = 2;
1457 return TRUE;
1460 /**************************************************************************
1461 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1463 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1464 LPCOMMTIMEOUTS lptimeouts )
1466 LPSTR devidA;
1467 BOOL ret;
1469 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1470 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1471 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1472 HeapFree( GetProcessHeap(), 0, devidA );
1473 return ret;
1476 /**************************************************************************
1477 * BuildCommDCBW (KERNEL32.17)
1479 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1481 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1484 /*****************************************************************************
1485 * COMM_GetReadFd
1486 * Returns a file descriptor for reading.
1487 * Make sure to close the handle afterwards!
1489 static int COMM_GetReadFd( HANDLE handle)
1491 int fd;
1492 struct get_read_fd_request *req = get_req_buffer();
1493 req->handle = handle;
1494 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1495 return fd;
1498 /*****************************************************************************
1499 * COMM_GetWriteFd
1500 * Returns a file descriptor for writing.
1501 * Make sure to close the handle afterwards!
1503 static int COMM_GetWriteFd( HANDLE handle)
1505 int fd;
1506 struct get_write_fd_request *req = get_req_buffer();
1507 req->handle = handle;
1508 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1509 return fd;
1512 /* FIXME: having these global for win32 for now */
1513 int commerror=0,eventmask=0;
1515 /*****************************************************************************
1516 * SetCommBreak (KERNEL32.449)
1518 BOOL WINAPI SetCommBreak(HANDLE handle)
1520 FIXME("handle %d, stub!\n", handle);
1521 return TRUE;
1524 /*****************************************************************************
1525 * ClearCommBreak (KERNEL32.20)
1527 BOOL WINAPI ClearCommBreak(HANDLE handle)
1529 FIXME("handle %d, stub!\n", handle);
1530 return TRUE;
1533 /*****************************************************************************
1534 * EscapeCommFunction (KERNEL32.214)
1536 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1538 int fd;
1539 struct termios port;
1541 TRACE("handle %d, function=%d\n", handle, nFunction);
1542 fd = COMM_GetWriteFd(handle);
1543 if(fd<0)
1544 return FALSE;
1546 if (tcgetattr(fd,&port) == -1) {
1547 commerror=WinError();
1548 close(fd);
1549 return FALSE;
1552 switch (nFunction) {
1553 case RESETDEV:
1554 break;
1556 #ifdef TIOCM_DTR
1557 case CLRDTR:
1558 port.c_cflag &= TIOCM_DTR;
1559 break;
1560 #endif
1562 #ifdef TIOCM_RTS
1563 case CLRRTS:
1564 port.c_cflag &= TIOCM_RTS;
1565 break;
1566 #endif
1568 #ifdef CRTSCTS
1569 case SETDTR:
1570 port.c_cflag |= CRTSCTS;
1571 break;
1573 case SETRTS:
1574 port.c_cflag |= CRTSCTS;
1575 break;
1576 #endif
1578 case SETXOFF:
1579 port.c_iflag |= IXOFF;
1580 break;
1582 case SETXON:
1583 port.c_iflag |= IXON;
1584 break;
1585 case SETBREAK:
1586 FIXME("setbreak, stub\n");
1587 /* ptr->suspended = 1; */
1588 break;
1589 case CLRBREAK:
1590 FIXME("clrbreak, stub\n");
1591 /* ptr->suspended = 0; */
1592 break;
1593 default:
1594 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1595 handle, nFunction);
1596 break;
1599 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1600 commerror = WinError();
1601 close(fd);
1602 return FALSE;
1603 } else {
1604 commerror = 0;
1605 close(fd);
1606 return TRUE;
1610 /********************************************************************
1611 * PurgeComm (KERNEL32.557)
1613 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1615 int fd;
1617 TRACE("handle %d, flags %lx\n", handle, flags);
1619 fd = COMM_GetWriteFd(handle);
1620 if(fd<0)
1621 return FALSE;
1624 ** not exactly sure how these are different
1625 ** Perhaps if we had our own internal queues, one flushes them
1626 ** and the other flushes the kernel's buffers.
1628 if(flags&PURGE_TXABORT)
1630 tcflush(fd,TCOFLUSH);
1632 if(flags&PURGE_RXABORT)
1634 tcflush(fd,TCIFLUSH);
1636 if(flags&PURGE_TXCLEAR)
1638 tcflush(fd,TCOFLUSH);
1640 if(flags&PURGE_RXCLEAR)
1642 tcflush(fd,TCIFLUSH);
1644 close(fd);
1646 return 1;
1649 /*****************************************************************************
1650 * ClearCommError (KERNEL32.21)
1652 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1654 int fd;
1656 fd=COMM_GetReadFd(handle);
1657 if(0>fd)
1659 return FALSE;
1662 if (lpStat)
1664 lpStat->status = 0;
1666 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1667 WARN("ioctl returned error\n");
1669 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1670 WARN("ioctl returned error\n");
1672 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1673 handle, lpStat->cbInQue, lpStat->cbOutQue);
1676 close(fd);
1678 if(errors)
1679 *errors = 0;
1682 ** After an asynchronous write opperation, the
1683 ** app will call ClearCommError to see if the
1684 ** results are ready yet. It waits for ERROR_IO_PENDING
1686 commerror = ERROR_IO_PENDING;
1688 return TRUE;
1691 /*****************************************************************************
1692 * SetupComm (KERNEL32.676)
1694 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1696 int fd;
1698 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1699 fd=COMM_GetWriteFd(handle);
1700 if(0>fd)
1702 return FALSE;
1704 close(fd);
1705 return TRUE;
1708 /*****************************************************************************
1709 * GetCommMask (KERNEL32.156)
1711 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1713 int fd;
1715 TRACE("handle %d, mask %p\n", handle, evtmask);
1716 if(0>(fd=COMM_GetReadFd(handle)))
1718 return FALSE;
1720 close(fd);
1721 *evtmask = eventmask;
1722 TRACE("%s%s%s%s%s%s%s%s%s\n",
1723 (eventmask&EV_BREAK)?"EV_BREAK":"",
1724 (eventmask&EV_CTS)?"EV_CTS":"",
1725 (eventmask&EV_DSR)?"EV_DSR":"",
1726 (eventmask&EV_ERR)?"EV_ERR":"",
1727 (eventmask&EV_RING)?"EV_RING":"",
1728 (eventmask&EV_RLSD)?"EV_RLSD":"",
1729 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1730 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1731 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1733 return TRUE;
1736 /*****************************************************************************
1737 * SetCommMask (KERNEL32.451)
1739 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1741 int fd;
1743 TRACE("handle %d, mask %lx\n", handle, evtmask);
1744 TRACE("%s%s%s%s%s%s%s%s%s\n",
1745 (evtmask&EV_BREAK)?"EV_BREAK":"",
1746 (evtmask&EV_CTS)?"EV_CTS":"",
1747 (evtmask&EV_DSR)?"EV_DSR":"",
1748 (evtmask&EV_ERR)?"EV_ERR":"",
1749 (evtmask&EV_RING)?"EV_RING":"",
1750 (evtmask&EV_RLSD)?"EV_RLSD":"",
1751 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1752 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1753 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1755 if(0>(fd=COMM_GetWriteFd(handle))) {
1756 return FALSE;
1758 close(fd);
1759 eventmask = evtmask;
1760 return TRUE;
1763 /*****************************************************************************
1764 * SetCommState (KERNEL32.452)
1766 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1768 struct termios port;
1769 int fd;
1771 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1772 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1773 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1774 (lpdcb->StopBits == ONESTOPBIT)?1:
1775 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1776 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1777 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1779 if ((fd = COMM_GetWriteFd(handle)) < 0) return FALSE;
1781 if ((tcgetattr(fd,&port)) == -1) {
1782 int save_error = errno;
1783 commerror = WinError();
1784 close( fd );
1785 #ifdef HAVE_STRERROR
1786 ERR("tcgetattr error '%s'\n", strerror(save_error));
1787 #else
1788 ERR("tcgetattr error %d\n", save_error);
1789 #endif
1790 return FALSE;
1793 port.c_cc[VMIN] = 0;
1794 port.c_cc[VTIME] = 1;
1796 #ifdef IMAXBEL
1797 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1798 #else
1799 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1800 #endif
1801 port.c_iflag |= (IGNBRK);
1803 port.c_oflag &= ~(OPOST);
1805 port.c_cflag &= ~(HUPCL);
1806 port.c_cflag |= CLOCAL | CREAD;
1808 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1809 port.c_lflag |= NOFLSH;
1812 ** MJM - removed default baudrate settings
1813 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1815 #ifdef CBAUD
1816 port.c_cflag &= ~CBAUD;
1817 switch (lpdcb->BaudRate) {
1818 case 110:
1819 case CBR_110:
1820 port.c_cflag |= B110;
1821 break;
1822 case 300:
1823 case CBR_300:
1824 port.c_cflag |= B300;
1825 break;
1826 case 600:
1827 case CBR_600:
1828 port.c_cflag |= B600;
1829 break;
1830 case 1200:
1831 case CBR_1200:
1832 port.c_cflag |= B1200;
1833 break;
1834 case 2400:
1835 case CBR_2400:
1836 port.c_cflag |= B2400;
1837 break;
1838 case 4800:
1839 case CBR_4800:
1840 port.c_cflag |= B4800;
1841 break;
1842 case 9600:
1843 case CBR_9600:
1844 port.c_cflag |= B9600;
1845 break;
1846 case 19200:
1847 case CBR_19200:
1848 port.c_cflag |= B19200;
1849 break;
1850 case 38400:
1851 case CBR_38400:
1852 port.c_cflag |= B38400;
1853 break;
1854 #ifdef B57600
1855 case 57600:
1856 port.c_cflag |= B57600;
1857 break;
1858 #endif
1859 #ifdef B115200
1860 case 115200:
1861 port.c_cflag |= B115200;
1862 break;
1863 #endif
1864 #ifdef B230400
1865 case 230400:
1866 port.c_cflag |= B230400;
1867 break;
1868 #endif
1869 #ifdef B460800
1870 case 460600:
1871 port.c_cflag |= B460800;
1872 break;
1873 #endif
1874 default:
1875 commerror = IE_BAUDRATE;
1876 close( fd );
1877 ERR("baudrate %ld\n",lpdcb->BaudRate);
1878 return FALSE;
1880 #elif !defined(__EMX__)
1881 switch (lpdcb->BaudRate) {
1882 case 110:
1883 case CBR_110:
1884 port.c_ospeed = B110;
1885 break;
1886 case 300:
1887 case CBR_300:
1888 port.c_ospeed = B300;
1889 break;
1890 case 600:
1891 case CBR_600:
1892 port.c_ospeed = B600;
1893 break;
1894 case 1200:
1895 case CBR_1200:
1896 port.c_ospeed = B1200;
1897 break;
1898 case 2400:
1899 case CBR_2400:
1900 port.c_ospeed = B2400;
1901 break;
1902 case 4800:
1903 case CBR_4800:
1904 port.c_ospeed = B4800;
1905 break;
1906 case 9600:
1907 case CBR_9600:
1908 port.c_ospeed = B9600;
1909 break;
1910 case 19200:
1911 case CBR_19200:
1912 port.c_ospeed = B19200;
1913 break;
1914 case 38400:
1915 case CBR_38400:
1916 port.c_ospeed = B38400;
1917 break;
1918 default:
1919 commerror = IE_BAUDRATE;
1920 close( fd );
1921 ERR("baudrate %d \n",lpdcb->BaudRate);
1922 return FALSE;
1924 port.c_ispeed = port.c_ospeed;
1925 #endif
1926 port.c_cflag &= ~CSIZE;
1927 switch (lpdcb->ByteSize) {
1928 case 5:
1929 port.c_cflag |= CS5;
1930 break;
1931 case 6:
1932 port.c_cflag |= CS6;
1933 break;
1934 case 7:
1935 port.c_cflag |= CS7;
1936 break;
1937 case 8:
1938 port.c_cflag |= CS8;
1939 break;
1940 default:
1941 commerror = IE_BYTESIZE;
1942 close( fd );
1943 ERR("ByteSize\n");
1944 return FALSE;
1947 port.c_cflag &= ~(PARENB | PARODD);
1948 if (lpdcb->fParity)
1949 port.c_iflag |= INPCK;
1950 else
1951 port.c_iflag &= ~INPCK;
1952 switch (lpdcb->Parity) {
1953 case NOPARITY:
1954 break;
1955 case ODDPARITY:
1956 port.c_cflag |= (PARENB | PARODD);
1957 break;
1958 case EVENPARITY:
1959 port.c_cflag |= PARENB;
1960 break;
1961 default:
1962 commerror = IE_BYTESIZE;
1963 close( fd );
1964 ERR("Parity\n");
1965 return FALSE;
1969 switch (lpdcb->StopBits) {
1970 case ONESTOPBIT:
1971 port.c_cflag &= ~CSTOPB;
1972 break;
1973 case TWOSTOPBITS:
1974 port.c_cflag |= CSTOPB;
1975 break;
1976 default:
1977 commerror = IE_BYTESIZE;
1978 close( fd );
1979 ERR("StopBits\n");
1980 return FALSE;
1982 #ifdef CRTSCTS
1983 if ( lpdcb->fOutxCtsFlow ||
1984 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1985 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1988 port.c_cflag |= CRTSCTS;
1989 TRACE("CRTSCTS\n");
1992 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1994 port.c_cflag &= ~CRTSCTS;
1995 TRACE("~CRTSCTS\n");
1998 #endif
1999 if (lpdcb->fInX)
2000 port.c_iflag |= IXON;
2001 else
2002 port.c_iflag &= ~IXON;
2003 if (lpdcb->fOutX)
2004 port.c_iflag |= IXOFF;
2005 else
2006 port.c_iflag &= ~IXOFF;
2008 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2009 int save_error=errno;
2010 commerror = WinError();
2011 close( fd );
2012 #ifdef HAVE_STRERROR
2013 ERR("tcgetattr error '%s'\n", strerror(save_error));
2014 #else
2015 ERR("tcgetattr error %d\n", save_error);
2016 #endif
2017 return FALSE;
2018 } else {
2019 commerror = 0;
2020 close( fd );
2021 return TRUE;
2026 /*****************************************************************************
2027 * GetCommState (KERNEL32.159)
2029 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2031 struct termios port;
2032 int fd,speed;
2034 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2036 if ((fd = COMM_GetReadFd(handle)) < 0)
2038 ERR("can't get COMM_GetReadFd\n");
2039 return FALSE;
2041 if (tcgetattr(fd, &port) == -1) {
2042 int save_error=errno;
2043 #ifdef HAVE_STRERROR
2044 ERR("tcgetattr error '%s'\n", strerror(save_error));
2045 #else
2046 ERR("tcgetattr error %d\n", save_error);
2047 #endif
2048 commerror = WinError();
2049 close( fd );
2050 return FALSE;
2052 close( fd );
2053 #ifndef __EMX__
2054 #ifdef CBAUD
2055 speed= (port.c_cflag & CBAUD);
2056 #else
2057 speed= (cfgetospeed(&port));
2058 #endif
2059 switch (speed) {
2060 case B110:
2061 lpdcb->BaudRate = 110;
2062 break;
2063 case B300:
2064 lpdcb->BaudRate = 300;
2065 break;
2066 case B600:
2067 lpdcb->BaudRate = 600;
2068 break;
2069 case B1200:
2070 lpdcb->BaudRate = 1200;
2071 break;
2072 case B2400:
2073 lpdcb->BaudRate = 2400;
2074 break;
2075 case B4800:
2076 lpdcb->BaudRate = 4800;
2077 break;
2078 case B9600:
2079 lpdcb->BaudRate = 9600;
2080 break;
2081 case B19200:
2082 lpdcb->BaudRate = 19200;
2083 break;
2084 case B38400:
2085 lpdcb->BaudRate = 38400;
2086 break;
2087 #ifdef B57600
2088 case B57600:
2089 lpdcb->BaudRate = 57600;
2090 break;
2091 #endif
2092 #ifdef B115200
2093 case B115200:
2094 lpdcb->BaudRate = 115200;
2095 break;
2096 #endif
2097 #ifdef B230400
2098 case B230400:
2099 lpdcb->BaudRate = 230400;
2100 break;
2101 #endif
2102 #ifdef B460800
2103 case B460800:
2104 lpdcb->BaudRate = 460800;
2105 break;
2106 #endif
2107 default:
2108 ERR("unknown speed %x \n",speed);
2110 #endif
2111 switch (port.c_cflag & CSIZE) {
2112 case CS5:
2113 lpdcb->ByteSize = 5;
2114 break;
2115 case CS6:
2116 lpdcb->ByteSize = 6;
2117 break;
2118 case CS7:
2119 lpdcb->ByteSize = 7;
2120 break;
2121 case CS8:
2122 lpdcb->ByteSize = 8;
2123 break;
2124 default:
2125 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2128 if(port.c_iflag & INPCK)
2129 lpdcb->fParity = TRUE;
2130 else
2131 lpdcb->fParity = FALSE;
2132 switch (port.c_cflag & (PARENB | PARODD)) {
2133 case 0:
2134 lpdcb->Parity = NOPARITY;
2135 break;
2136 case PARENB:
2137 lpdcb->Parity = EVENPARITY;
2138 break;
2139 case (PARENB | PARODD):
2140 lpdcb->Parity = ODDPARITY;
2141 break;
2144 if (port.c_cflag & CSTOPB)
2145 lpdcb->StopBits = TWOSTOPBITS;
2146 else
2147 lpdcb->StopBits = ONESTOPBIT;
2149 lpdcb->fNull = 0;
2150 lpdcb->fBinary = 1;
2152 #ifdef CRTSCTS
2154 if (port.c_cflag & CRTSCTS) {
2155 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2156 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2157 lpdcb->fOutxCtsFlow = 1;
2158 lpdcb->fOutxDsrFlow = 1;
2159 } else
2160 #endif
2162 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2163 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2165 if (port.c_iflag & IXON)
2166 lpdcb->fInX = 1;
2167 else
2168 lpdcb->fInX = 0;
2170 if (port.c_iflag & IXOFF)
2171 lpdcb->fOutX = 1;
2172 else
2173 lpdcb->fOutX = 0;
2175 lpdcb->XonChar =
2176 lpdcb->XoffChar =
2178 lpdcb->XonLim = 10;
2179 lpdcb->XoffLim = 10;
2181 commerror = 0;
2183 TRACE("OK\n");
2185 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2186 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2187 (lpdcb->StopBits == ONESTOPBIT)?1:
2188 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2189 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2190 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2191 #ifdef CRTSCTS
2192 if ( lpdcb->fOutxCtsFlow ||
2193 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2194 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2196 TRACE("CRTSCTS\n");
2198 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2199 TRACE("~CRTSCTS\n");
2201 #endif
2202 return TRUE;
2205 /*****************************************************************************
2206 * TransmitCommChar (KERNEL32.535)
2208 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2210 struct DosDeviceStruct *ptr;
2212 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2213 if ((ptr = GetDeviceStruct(cid)) == NULL) {
2214 return FALSE;
2217 if (ptr->suspended) {
2218 ptr->commerror = IE_HARDWARE;
2219 return FALSE;
2221 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2222 ptr->commerror = WinError();
2223 return FALSE;
2224 } else {
2225 ptr->commerror = 0;
2226 return TRUE;
2230 /*****************************************************************************
2231 * GetCommTimeouts (KERNEL32.160)
2233 BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
2235 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2236 return TRUE;
2239 /*****************************************************************************
2240 * SetCommTimeouts (KERNEL32.453)
2242 BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
2243 FIXME("(%x,%p):stub.\n",cid,lptimeouts);
2244 TRACE("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2245 TRACE("ReadTotalTimeoutMultiplier %ld\n",
2246 lptimeouts->ReadTotalTimeoutMultiplier);
2247 TRACE("ReadTotalTimeoutConstant %ld\n",
2248 lptimeouts->ReadTotalTimeoutConstant);
2249 TRACE("WriteTotalTimeoutMultiplier %ld\n",
2250 lptimeouts->WriteTotalTimeoutMultiplier);
2251 TRACE("WriteTotalTimeoutConstant %ld\n",
2252 lptimeouts->WriteTotalTimeoutConstant);
2253 return TRUE;
2256 /***********************************************************************
2257 * GetCommModemStatus (KERNEL32.285)
2259 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2261 FIXME("(%d %p)\n",hFile,lpModemStat );
2262 return TRUE;
2264 /***********************************************************************
2265 * WaitCommEvent (KERNEL32.719)
2267 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2269 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2270 return TRUE;
2273 /***********************************************************************
2274 * GetCommProperties (KERNEL32.???)
2276 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2278 FIXME("(%d %p )\n",hFile,dcb);
2279 return TRUE;
2282 /***********************************************************************
2283 * SetCommProperties (KERNEL32.???)
2285 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2287 FIXME("(%d %p )\n",hFile,dcb);
2288 return TRUE;