Split off wingdi16.h from wingdi.h. Add many more #defines/typedefs
[wine.git] / misc / comm.c
blobb9ad9bebf9d5d7e0e2debce30ed8f7933585d9f5
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/request.h"
65 #include "server.h"
66 #include "process.h"
67 #include "winerror.h"
68 #include "async.h"
70 #include "debug.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(comm,"Can't use `%s' as %s !\n", temp, option);
113 else
114 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
115 WARN(comm,"Can't malloc for device info!\n");
116 else {
117 COM[x].fd = 0;
118 strcpy(COM[x].devicename, temp);
120 TRACE(comm, "%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(comm,"Can't use `%s' as %s !\n", temp, option);
135 else
136 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
137 WARN(comm,"Can't malloc for device info!\n");
138 else {
139 LPT[x].fd = 0;
140 strcpy(LPT[x].devicename, temp);
142 TRACE(comm, "%s = %s\n", option, LPT[x].devicename);
149 struct DosDeviceStruct *GetDeviceStruct_fd(int fd)
151 int x;
153 for (x=0; x!=MAX_PORTS; x++) {
154 if (COM[x].fd == fd)
155 return &COM[x];
156 if (LPT[x].fd == fd)
157 return &LPT[x];
160 return NULL;
163 struct DosDeviceStruct *GetDeviceStruct(int fd)
165 if ((fd&0x7F)<=MAX_PORTS) {
166 if (!(fd&FLAG_LPT)) {
167 if (COM[fd].fd)
168 return &COM[fd];
169 } else {
170 if (LPT[fd].fd)
171 return &LPT[fd];
175 return NULL;
178 int GetCommPort_fd(int fd)
180 int x;
182 for (x=0; x<MAX_PORTS; x++) {
183 if (COM[x].fd == fd)
184 return x;
187 return -1;
190 int ValidCOMPort(int x)
192 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
195 int ValidLPTPort(int x)
197 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
200 int WinError(void)
202 TRACE(comm, "errno = %d\n", errno);
203 switch (errno) {
204 default:
205 return CE_IOE;
209 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
211 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
212 + ptr->ibuf_head - ptr->ibuf_tail;
215 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
217 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
218 + ptr->obuf_head - ptr->obuf_tail;
221 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
223 unsigned int mstat, okay;
224 okay = ioctl(fd, TIOCMGET, &mstat);
225 if (okay) return okay;
226 if (andy) mstat &= andy;
227 mstat |= orrie;
228 return ioctl(fd, TIOCMSET, &mstat);
231 static void comm_notification(int fd,void*private)
233 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
234 int prev, bleft, len;
235 WORD mask = 0;
236 int cid = GetCommPort_fd(fd);
238 /* read data from comm port */
239 prev = comm_inbuf(ptr);
240 do {
241 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
242 - ptr->ibuf_head;
243 len = read(fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
244 if (len > 0) {
245 if (!bleft) {
246 ptr->commerror = CE_RXOVER;
247 } else {
248 ptr->ibuf_head += len;
249 if (ptr->ibuf_head >= ptr->ibuf_size)
250 ptr->ibuf_head = 0;
251 /* flag event */
252 if (ptr->eventmask & EV_RXCHAR)
253 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
254 /* FIXME: check for event character (EV_RXFLAG) */
257 } while (len > 0);
258 /* check for notification */
259 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
260 (comm_inbuf(ptr)>=ptr->n_read)) {
261 /* passed the receive notification threshold */
262 mask |= CN_RECEIVE;
265 /* write any TransmitCommChar character */
266 if (ptr->xmit>=0) {
267 len = write(fd, &(ptr->xmit), 1);
268 if (len > 0) ptr->xmit = -1;
270 /* write from output queue */
271 prev = comm_outbuf(ptr);
272 do {
273 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
274 - ptr->obuf_tail;
275 len = bleft ? write(fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
276 if (len > 0) {
277 ptr->obuf_tail += len;
278 if (ptr->obuf_tail >= ptr->obuf_size)
279 ptr->obuf_tail = 0;
280 /* flag event */
281 if ((ptr->obuf_tail == ptr->obuf_head) && (ptr->eventmask & EV_TXEMPTY))
282 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
284 } while (len > 0);
285 /* check for notification */
286 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
287 (comm_outbuf(ptr)<ptr->n_write)) {
288 /* passed the transmit notification threshold */
289 mask |= CN_TRANSMIT;
292 /* send notifications, if any */
293 if (ptr->wnd && mask) {
294 PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
298 /**************************************************************************
299 * BuildCommDCB (USER.213)
301 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
303 /* "COM1:9600,n,8,1" */
304 /* 012345 */
305 int port;
306 char *ptr, temp[256];
308 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
310 if (!lstrncmpiA(device,"COM",3)) {
311 port = device[3] - '0';
314 if (port-- == 0) {
315 ERR(comm, "BUG ! COM0 can't exist!.\n");
316 return -1;
319 if (!ValidCOMPort(port)) {
320 return -1;
323 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
325 lpdcb->Id = port;
327 if (!*(device+4))
328 return 0;
330 if (*(device+4) != ':')
331 return -1;
333 strcpy(temp,device+5);
334 ptr = strtok(temp, ", ");
336 if (COM[port].baudrate > 0)
337 lpdcb->BaudRate = COM[port].baudrate;
338 else
339 lpdcb->BaudRate = atoi(ptr);
340 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
342 ptr = strtok(NULL, ", ");
343 if (islower(*ptr))
344 *ptr = toupper(*ptr);
346 TRACE(comm,"parity (%c)\n", *ptr);
347 lpdcb->fParity = TRUE;
348 switch (*ptr) {
349 case 'N':
350 lpdcb->Parity = NOPARITY;
351 lpdcb->fParity = FALSE;
352 break;
353 case 'E':
354 lpdcb->Parity = EVENPARITY;
355 break;
356 case 'M':
357 lpdcb->Parity = MARKPARITY;
358 break;
359 case 'O':
360 lpdcb->Parity = ODDPARITY;
361 break;
362 default:
363 WARN(comm,"Unknown parity `%c'!\n", *ptr);
364 return -1;
367 ptr = strtok(NULL, ", ");
368 TRACE(comm, "charsize (%c)\n", *ptr);
369 lpdcb->ByteSize = *ptr - '0';
371 ptr = strtok(NULL, ", ");
372 TRACE(comm, "stopbits (%c)\n", *ptr);
373 switch (*ptr) {
374 case '1':
375 lpdcb->StopBits = ONESTOPBIT;
376 break;
377 case '2':
378 lpdcb->StopBits = TWOSTOPBITS;
379 break;
380 default:
381 WARN(comm,"Unknown # of stopbits `%c'!\n", *ptr);
382 return -1;
386 return 0;
389 /*****************************************************************************
390 * OpenComm (USER.200)
392 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
394 int port,fd;
396 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
398 port = device[3] - '0';
400 if (port-- == 0)
401 ERR(comm, "BUG ! COM0 or LPT0 don't exist !\n");
403 if (!lstrncmpiA(device,"COM",3)) {
405 TRACE(comm, "%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 return IE_HARDWARE;
416 } else {
417 unknown[port] = SEGPTR_ALLOC(40);
418 bzero(unknown[port],40);
419 COM[port].fd = fd;
420 COM[port].commerror = 0;
421 COM[port].eventmask = 0;
422 /* save terminal state */
423 tcgetattr(fd,&m_stat[port]);
424 /* set default parameters */
425 if(COM[port].baudrate>-1){
426 DCB16 dcb;
427 GetCommState16(port, &dcb);
428 dcb.BaudRate=COM[port].baudrate;
429 /* more defaults:
430 * databits, parity, stopbits
432 SetCommState16( &dcb);
434 /* init priority characters */
435 COM[port].unget = -1;
436 COM[port].xmit = -1;
437 /* allocate buffers */
438 COM[port].ibuf_size = cbInQueue;
439 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
440 COM[port].obuf_size = cbOutQueue;
441 COM[port].obuf_head = COM[port].obuf_tail = 0;
443 COM[port].inbuf = malloc(cbInQueue);
444 if (COM[port].inbuf) {
445 COM[port].outbuf = malloc(cbOutQueue);
446 if (!COM[port].outbuf)
447 free(COM[port].inbuf);
448 } else COM[port].outbuf = NULL;
449 if (!COM[port].outbuf) {
450 /* not enough memory */
451 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
452 close(COM[port].fd);
453 return IE_MEMORY;
456 /* enable async notifications */
457 ASYNC_RegisterFD(COM[port].fd,comm_notification,&COM[port]);
458 return port;
461 else
462 if (!lstrncmpiA(device,"LPT",3)) {
464 if (!ValidLPTPort(port))
465 return IE_BADID;
467 if (LPT[port].fd)
468 return IE_OPEN;
470 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
471 if (fd == -1) {
472 return IE_HARDWARE;
473 } else {
474 LPT[port].fd = fd;
475 LPT[port].commerror = 0;
476 LPT[port].eventmask = 0;
477 return port|FLAG_LPT;
480 return 0;
483 /*****************************************************************************
484 * CloseComm (USER.207)
486 INT16 WINAPI CloseComm16(INT16 cid)
488 struct DosDeviceStruct *ptr;
490 TRACE(comm,"cid=%d\n", cid);
491 if ((ptr = GetDeviceStruct(cid)) == NULL) {
492 return -1;
494 if (!(cid&FLAG_LPT)) {
495 /* COM port */
496 SEGPTR_FREE(unknown[cid]); /* [LW] */
498 /* disable async notifications */
499 ASYNC_UnregisterFD(COM[cid].fd,comm_notification);
500 /* free buffers */
501 free(ptr->outbuf);
502 free(ptr->inbuf);
504 /* reset modem lines */
505 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
508 if (close(ptr->fd) == -1) {
509 ptr->commerror = WinError();
510 /* FIXME: should we clear ptr->fd here? */
511 return -1;
512 } else {
513 ptr->commerror = 0;
514 ptr->fd = 0;
515 return 0;
519 /*****************************************************************************
520 * SetCommBreak (USER.210)
522 INT16 WINAPI SetCommBreak16(INT16 cid)
524 struct DosDeviceStruct *ptr;
526 TRACE(comm,"cid=%d\n", cid);
527 if ((ptr = GetDeviceStruct(cid)) == NULL) {
528 return -1;
531 ptr->suspended = 1;
532 ptr->commerror = 0;
533 return 0;
536 /*****************************************************************************
537 * ClearCommBreak (USER.211)
539 INT16 WINAPI ClearCommBreak16(INT16 cid)
541 struct DosDeviceStruct *ptr;
543 TRACE(comm,"cid=%d\n", cid);
544 if ((ptr = GetDeviceStruct(cid)) == NULL) {
545 return -1;
548 ptr->suspended = 0;
549 ptr->commerror = 0;
550 return 0;
553 /*****************************************************************************
554 * EscapeCommFunction (USER.214)
556 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
558 int max;
559 struct DosDeviceStruct *ptr;
560 struct termios port;
562 TRACE(comm,"cid=%d, function=%d\n", cid, nFunction);
563 if ((ptr = GetDeviceStruct(cid)) == NULL) {
564 return -1;
566 if (tcgetattr(ptr->fd,&port) == -1) {
567 ptr->commerror=WinError();
568 return -1;
571 switch (nFunction) {
572 case RESETDEV:
573 break;
575 case GETMAXCOM:
576 for (max = MAX_PORTS;!COM[max].devicename;max--)
578 return max;
579 break;
581 case GETMAXLPT:
582 for (max = MAX_PORTS;!LPT[max].devicename;max--)
584 return FLAG_LPT + max;
585 break;
587 #ifdef TIOCM_DTR
588 case CLRDTR:
589 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
590 #endif
591 #ifdef TIOCM_RTS
592 case CLRRTS:
593 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
594 #endif
596 #ifdef TIOCM_DTR
597 case SETDTR:
598 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
599 #endif
601 #ifdef TIOCM_RTS
602 case SETRTS:
603 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
604 #endif
606 case SETXOFF:
607 port.c_iflag |= IXOFF;
608 break;
610 case SETXON:
611 port.c_iflag |= IXON;
612 break;
614 default:
615 WARN(comm,"(cid=%d,nFunction=%d): Unknown function\n",
616 cid, nFunction);
617 break;
620 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
621 ptr->commerror = WinError();
622 return -1;
623 } else {
624 ptr->commerror = 0;
625 return 0;
629 /*****************************************************************************
630 * FlushComm (USER.215)
632 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
634 int queue;
635 struct DosDeviceStruct *ptr;
637 TRACE(comm,"cid=%d, queue=%d\n", cid, fnQueue);
638 if ((ptr = GetDeviceStruct(cid)) == NULL) {
639 return -1;
641 switch (fnQueue) {
642 case 0:
643 queue = TCOFLUSH;
644 ptr->obuf_tail = ptr->obuf_head;
645 break;
646 case 1:
647 queue = TCIFLUSH;
648 ptr->ibuf_head = ptr->ibuf_tail;
649 break;
650 default:
651 WARN(comm,"(cid=%d,fnQueue=%d):Unknown queue\n",
652 cid, fnQueue);
653 return -1;
655 if (tcflush(ptr->fd, queue)) {
656 ptr->commerror = WinError();
657 return -1;
658 } else {
659 ptr->commerror = 0;
660 return 0;
664 /********************************************************************
665 * GetCommError (USER.203)
667 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
669 int temperror;
670 struct DosDeviceStruct *ptr;
671 unsigned char *stol;
672 unsigned int mstat;
674 if ((ptr = GetDeviceStruct(cid)) == NULL) {
675 return -1;
677 if (cid&FLAG_LPT) {
678 WARN(comm," cid %d not comm port\n",cid);
679 return CE_MODE;
681 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
682 ioctl(ptr->fd,TIOCMGET,&mstat);
683 if( mstat&TIOCM_CAR )
684 *stol |= 0x80;
685 else
686 *stol &=0x7f;
688 if (lpStat) {
689 lpStat->status = 0;
691 lpStat->cbOutQue = comm_outbuf(ptr);
692 lpStat->cbInQue = comm_inbuf(ptr);
694 TRACE(comm, "cid %d, error %d, lpStat %d %d %d stol %x\n",
695 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
696 lpStat->cbOutQue, *stol);
698 else
699 TRACE(comm, "cid %d, error %d, lpStat NULL stol %x\n",
700 cid, ptr->commerror, *stol);
702 /* Return any errors and clear it */
703 temperror = ptr->commerror;
704 ptr->commerror = 0;
705 return(temperror);
708 /*****************************************************************************
709 * SetCommEventMask (USER.208)
711 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
713 struct DosDeviceStruct *ptr;
714 unsigned char *stol;
715 int repid;
716 unsigned int mstat;
718 TRACE(comm,"cid %d,mask %d\n",cid,fuEvtMask);
719 if ((ptr = GetDeviceStruct(cid)) == NULL)
720 return (SEGPTR)NULL;
722 ptr->eventmask = fuEvtMask;
724 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
725 WARN(comm," cid %d not comm port\n",cid);
726 return (SEGPTR)NULL;
728 /* it's a COM port ? -> modify flags */
729 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
730 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
731 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
732 if ((mstat&TIOCM_CAR))
733 *stol |= 0x80;
734 else
735 *stol &=0x7f;
737 TRACE(comm," modem dcd construct %x\n",*stol);
738 return SEGPTR_GET(unknown[cid]);
741 /*****************************************************************************
742 * GetCommEventMask (USER.209)
744 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
746 struct DosDeviceStruct *ptr;
747 WORD events;
749 TRACE(comm, "cid %d, mask %d\n", cid, fnEvtClear);
750 if ((ptr = GetDeviceStruct(cid)) == NULL)
751 return 0;
753 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
754 WARN(comm," cid %d not comm port\n",cid);
755 return 0;
758 events = *(WORD*)(unknown[cid]) & fnEvtClear;
759 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
760 return events;
763 /*****************************************************************************
764 * SetCommState16 (USER.201)
766 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
768 struct termios port;
769 struct DosDeviceStruct *ptr;
771 TRACE(comm, "cid %d, ptr %p\n", lpdcb->Id, lpdcb);
772 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
773 return -1;
775 if (tcgetattr(ptr->fd, &port) == -1) {
776 ptr->commerror = WinError();
777 return -1;
780 port.c_cc[VMIN] = 0;
781 port.c_cc[VTIME] = 1;
783 #ifdef IMAXBEL
784 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
785 #else
786 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
787 #endif
788 port.c_iflag |= (IGNBRK);
790 port.c_oflag &= ~(OPOST);
792 port.c_cflag &= ~(HUPCL);
793 port.c_cflag |= CLOCAL | CREAD;
795 port.c_lflag &= ~(ICANON|ECHO|ISIG);
796 port.c_lflag |= NOFLSH;
798 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
799 #ifdef CBAUD
800 port.c_cflag &= ~CBAUD;
801 switch (lpdcb->BaudRate) {
802 case 110:
803 case CBR_110:
804 port.c_cflag |= B110;
805 break;
806 case 300:
807 case CBR_300:
808 port.c_cflag |= B300;
809 break;
810 case 600:
811 case CBR_600:
812 port.c_cflag |= B600;
813 break;
814 case 1200:
815 case CBR_1200:
816 port.c_cflag |= B1200;
817 break;
818 case 2400:
819 case CBR_2400:
820 port.c_cflag |= B2400;
821 break;
822 case 4800:
823 case CBR_4800:
824 port.c_cflag |= B4800;
825 break;
826 case 9600:
827 case CBR_9600:
828 port.c_cflag |= B9600;
829 break;
830 case 19200:
831 case CBR_19200:
832 port.c_cflag |= B19200;
833 break;
834 case 38400:
835 case CBR_38400:
836 port.c_cflag |= B38400;
837 break;
838 #ifdef B57600
839 case 57600:
840 port.c_cflag |= B57600;
841 break;
842 #endif
843 #ifdef B115200
844 case 57601:
845 port.c_cflag |= B115200;
846 break;
847 #endif
848 default:
849 ptr->commerror = IE_BAUDRATE;
850 return -1;
852 #elif !defined(__EMX__)
853 switch (lpdcb->BaudRate) {
854 case 110:
855 case CBR_110:
856 port.c_ospeed = B110;
857 break;
858 case 300:
859 case CBR_300:
860 port.c_ospeed = B300;
861 break;
862 case 600:
863 case CBR_600:
864 port.c_ospeed = B600;
865 break;
866 case 1200:
867 case CBR_1200:
868 port.c_ospeed = B1200;
869 break;
870 case 2400:
871 case CBR_2400:
872 port.c_ospeed = B2400;
873 break;
874 case 4800:
875 case CBR_4800:
876 port.c_ospeed = B4800;
877 break;
878 case 9600:
879 case CBR_9600:
880 port.c_ospeed = B9600;
881 break;
882 case 19200:
883 case CBR_19200:
884 port.c_ospeed = B19200;
885 break;
886 case 38400:
887 case CBR_38400:
888 port.c_ospeed = B38400;
889 break;
890 default:
891 ptr->commerror = IE_BAUDRATE;
892 return -1;
894 port.c_ispeed = port.c_ospeed;
895 #endif
896 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
897 port.c_cflag &= ~CSIZE;
898 switch (lpdcb->ByteSize) {
899 case 5:
900 port.c_cflag |= CS5;
901 break;
902 case 6:
903 port.c_cflag |= CS6;
904 break;
905 case 7:
906 port.c_cflag |= CS7;
907 break;
908 case 8:
909 port.c_cflag |= CS8;
910 break;
911 default:
912 ptr->commerror = IE_BYTESIZE;
913 return -1;
916 TRACE(comm,"fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
917 port.c_cflag &= ~(PARENB | PARODD);
918 if (lpdcb->fParity)
919 port.c_iflag |= INPCK;
920 else
921 port.c_iflag &= ~INPCK;
922 switch (lpdcb->Parity) {
923 case NOPARITY:
924 break;
925 case ODDPARITY:
926 port.c_cflag |= (PARENB | PARODD);
927 break;
928 case EVENPARITY:
929 port.c_cflag |= PARENB;
930 break;
931 default:
932 ptr->commerror = IE_BYTESIZE;
933 return -1;
937 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
939 switch (lpdcb->StopBits) {
940 case ONESTOPBIT:
941 port.c_cflag &= ~CSTOPB;
942 break;
943 case TWOSTOPBITS:
944 port.c_cflag |= CSTOPB;
945 break;
946 default:
947 ptr->commerror = IE_BYTESIZE;
948 return -1;
950 #ifdef CRTSCTS
952 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
953 port.c_cflag |= CRTSCTS;
955 if (lpdcb->fDtrDisable)
956 port.c_cflag &= ~CRTSCTS;
957 #endif
958 if (lpdcb->fInX)
959 port.c_iflag |= IXON;
960 else
961 port.c_iflag &= ~IXON;
962 if (lpdcb->fOutX)
963 port.c_iflag |= IXOFF;
964 else
965 port.c_iflag &= ~IXOFF;
967 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
968 ptr->commerror = WinError();
969 return FALSE;
970 } else {
971 ptr->commerror = 0;
972 return 0;
976 /*****************************************************************************
977 * GetCommState (USER.202)
979 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
981 struct DosDeviceStruct *ptr;
982 struct termios port;
984 TRACE(comm,"cid %d, ptr %p\n", cid, lpdcb);
985 if ((ptr = GetDeviceStruct(cid)) == NULL) {
986 return -1;
988 if (tcgetattr(ptr->fd, &port) == -1) {
989 ptr->commerror = WinError();
990 return -1;
992 lpdcb->Id = cid;
993 #ifndef __EMX__
994 #ifdef CBAUD
995 switch (port.c_cflag & CBAUD) {
996 #else
997 switch (port.c_ospeed) {
998 #endif
999 case B110:
1000 lpdcb->BaudRate = 110;
1001 break;
1002 case B300:
1003 lpdcb->BaudRate = 300;
1004 break;
1005 case B600:
1006 lpdcb->BaudRate = 600;
1007 break;
1008 case B1200:
1009 lpdcb->BaudRate = 1200;
1010 break;
1011 case B2400:
1012 lpdcb->BaudRate = 2400;
1013 break;
1014 case B4800:
1015 lpdcb->BaudRate = 4800;
1016 break;
1017 case B9600:
1018 lpdcb->BaudRate = 9600;
1019 break;
1020 case B19200:
1021 lpdcb->BaudRate = 19200;
1022 break;
1023 case B38400:
1024 lpdcb->BaudRate = 38400;
1025 break;
1026 #ifdef B57600
1027 case B57600:
1028 lpdcb->BaudRate = 57600;
1029 break;
1030 #endif
1031 #ifdef B115200
1032 case B115200:
1033 lpdcb->BaudRate = 57601;
1034 break;
1035 #endif
1037 #endif
1038 switch (port.c_cflag & CSIZE) {
1039 case CS5:
1040 lpdcb->ByteSize = 5;
1041 break;
1042 case CS6:
1043 lpdcb->ByteSize = 6;
1044 break;
1045 case CS7:
1046 lpdcb->ByteSize = 7;
1047 break;
1048 case CS8:
1049 lpdcb->ByteSize = 8;
1050 break;
1053 if(port.c_iflag & INPCK)
1054 lpdcb->fParity = TRUE;
1055 else
1056 lpdcb->fParity = FALSE;
1057 switch (port.c_cflag & (PARENB | PARODD)) {
1058 case 0:
1059 lpdcb->Parity = NOPARITY;
1060 break;
1061 case PARENB:
1062 lpdcb->Parity = EVENPARITY;
1063 break;
1064 case (PARENB | PARODD):
1065 lpdcb->Parity = ODDPARITY;
1066 break;
1069 if (port.c_cflag & CSTOPB)
1070 lpdcb->StopBits = TWOSTOPBITS;
1071 else
1072 lpdcb->StopBits = ONESTOPBIT;
1074 lpdcb->RlsTimeout = 50;
1075 lpdcb->CtsTimeout = 50;
1076 lpdcb->DsrTimeout = 50;
1077 lpdcb->fNull = 0;
1078 lpdcb->fChEvt = 0;
1079 lpdcb->fBinary = 1;
1080 lpdcb->fDtrDisable = 0;
1082 #ifdef CRTSCTS
1084 if (port.c_cflag & CRTSCTS) {
1085 lpdcb->fDtrflow = 1;
1086 lpdcb->fRtsflow = 1;
1087 lpdcb->fOutxCtsFlow = 1;
1088 lpdcb->fOutxDsrFlow = 1;
1089 } else
1090 #endif
1091 lpdcb->fDtrDisable = 1;
1093 if (port.c_iflag & IXON)
1094 lpdcb->fInX = 1;
1095 else
1096 lpdcb->fInX = 0;
1098 if (port.c_iflag & IXOFF)
1099 lpdcb->fOutX = 1;
1100 else
1101 lpdcb->fOutX = 0;
1103 lpdcb->XonChar =
1104 lpdcb->XoffChar =
1106 lpdcb->XonLim = 10;
1107 lpdcb->XoffLim = 10;
1109 ptr->commerror = 0;
1110 return 0;
1113 /*****************************************************************************
1114 * TransmitCommChar (USER.206)
1116 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1118 struct DosDeviceStruct *ptr;
1120 TRACE(comm, "cid %d, data %d \n", cid, chTransmit);
1121 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1122 return -1;
1125 if (ptr->suspended) {
1126 ptr->commerror = IE_HARDWARE;
1127 return -1;
1130 if (ptr->xmit >= 0) {
1131 /* character already queued */
1132 /* FIXME: which error would Windows return? */
1133 ptr->commerror = CE_TXFULL;
1134 return -1;
1137 if (ptr->obuf_head == ptr->obuf_tail) {
1138 /* transmit queue empty, try to transmit directly */
1139 if (write(ptr->fd, &chTransmit, 1) == -1) {
1140 /* didn't work, queue it */
1141 ptr->xmit = chTransmit;
1143 } else {
1144 /* data in queue, let this char be transmitted next */
1145 ptr->xmit = chTransmit;
1148 ptr->commerror = 0;
1149 return 0;
1152 /*****************************************************************************
1153 * UngetCommChar (USER.212)
1155 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1157 struct DosDeviceStruct *ptr;
1159 TRACE(comm,"cid %d (char %d)\n", cid, chUnget);
1160 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1161 return -1;
1164 if (ptr->suspended) {
1165 ptr->commerror = IE_HARDWARE;
1166 return -1;
1169 if (ptr->unget>=0) {
1170 /* character already queued */
1171 /* FIXME: which error would Windows return? */
1172 ptr->commerror = CE_RXOVER;
1173 return -1;
1176 ptr->unget = chUnget;
1178 ptr->commerror = 0;
1179 return 0;
1182 /*****************************************************************************
1183 * ReadComm (USER.204)
1185 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1187 int status, length;
1188 struct DosDeviceStruct *ptr;
1189 LPSTR orgBuf = lpvBuf;
1191 TRACE(comm, "cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1192 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1193 return -1;
1196 if (ptr->suspended) {
1197 ptr->commerror = IE_HARDWARE;
1198 return -1;
1201 /* read unget character */
1202 if (ptr->unget>=0) {
1203 *lpvBuf++ = ptr->unget;
1204 ptr->unget = -1;
1206 length = 1;
1207 } else
1208 length = 0;
1210 /* read from receive buffer */
1211 while (length < cbRead) {
1212 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1213 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1214 if (!status) break;
1215 if ((cbRead - length) < status)
1216 status = cbRead - length;
1218 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1219 ptr->ibuf_tail += status;
1220 if (ptr->ibuf_tail >= ptr->ibuf_size)
1221 ptr->ibuf_tail = 0;
1222 lpvBuf += status;
1223 length += status;
1226 TRACE(comm,"%.*s\n", length, orgBuf);
1227 ptr->commerror = 0;
1228 return length;
1231 /*****************************************************************************
1232 * WriteComm (USER.205)
1234 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1236 int status, length;
1237 struct DosDeviceStruct *ptr;
1239 TRACE(comm,"cid %d, ptr %p, length %d\n",
1240 cid, lpvBuf, cbWrite);
1241 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1242 return -1;
1245 if (ptr->suspended) {
1246 ptr->commerror = IE_HARDWARE;
1247 return -1;
1250 TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
1252 length = 0;
1253 while (length < cbWrite) {
1254 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1255 /* no data queued, try to write directly */
1256 status = write(ptr->fd, lpvBuf, cbWrite - length);
1257 if (status > 0) {
1258 lpvBuf += status;
1259 length += status;
1260 continue;
1263 /* can't write directly, put into transmit buffer */
1264 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1265 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1266 if (!status) break;
1267 if ((cbWrite - length) < status)
1268 status = cbWrite - length;
1269 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1270 ptr->obuf_head += status;
1271 if (ptr->obuf_head >= ptr->obuf_size)
1272 ptr->obuf_head = 0;
1273 lpvBuf += status;
1274 length += status;
1277 ptr->commerror = 0;
1278 return length;
1281 /***********************************************************************
1282 * EnableCommNotification (USER.246)
1284 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1285 INT16 cbWriteNotify, INT16 cbOutQueue )
1287 struct DosDeviceStruct *ptr;
1289 TRACE(comm, "(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1290 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1291 ptr->commerror = IE_BADID;
1292 return -1;
1294 ptr->wnd = hwnd;
1295 ptr->n_read = cbWriteNotify;
1296 ptr->n_write = cbOutQueue;
1297 return TRUE;
1301 /**************************************************************************
1302 * BuildCommDCBA (KERNEL32.14)
1304 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1306 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1309 /**************************************************************************
1310 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1312 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1313 LPCOMMTIMEOUTS lptimeouts)
1315 int port;
1316 char *ptr,*temp;
1318 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1320 if (!lstrncmpiA(device,"COM",3)) {
1321 port=device[3]-'0';
1322 if (port--==0) {
1323 ERR(comm,"BUG! COM0 can't exists!.\n");
1324 return FALSE;
1326 if (!ValidCOMPort(port))
1327 return FALSE;
1328 if (*(device+4)!=':')
1329 return FALSE;
1330 temp=(LPSTR)(device+5);
1331 } else
1332 temp=(LPSTR)device;
1334 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1336 lpdcb->DCBlength = sizeof(DCB);
1337 if (strchr(temp,',')) { /* old style */
1338 DCB16 dcb16;
1339 BOOL16 ret;
1340 char last=temp[strlen(temp)-1];
1342 ret=BuildCommDCB16(device,&dcb16);
1343 if (!ret)
1344 return FALSE;
1345 lpdcb->BaudRate = dcb16.BaudRate;
1346 lpdcb->ByteSize = dcb16.ByteSize;
1347 lpdcb->fBinary = dcb16.fBinary;
1348 lpdcb->Parity = dcb16.Parity;
1349 lpdcb->fParity = dcb16.fParity;
1350 lpdcb->fNull = dcb16.fNull;
1351 lpdcb->StopBits = dcb16.StopBits;
1352 if (last == 'x') {
1353 lpdcb->fInX = TRUE;
1354 lpdcb->fOutX = TRUE;
1355 lpdcb->fOutxCtsFlow = FALSE;
1356 lpdcb->fOutxDsrFlow = FALSE;
1357 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1358 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1359 } else if (last=='p') {
1360 lpdcb->fInX = FALSE;
1361 lpdcb->fOutX = FALSE;
1362 lpdcb->fOutxCtsFlow = TRUE;
1363 lpdcb->fOutxDsrFlow = TRUE;
1364 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1365 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1366 } else {
1367 lpdcb->fInX = FALSE;
1368 lpdcb->fOutX = FALSE;
1369 lpdcb->fOutxCtsFlow = FALSE;
1370 lpdcb->fOutxDsrFlow = FALSE;
1371 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1372 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1374 lpdcb->XonChar = dcb16.XonChar;
1375 lpdcb->XoffChar = dcb16.XoffChar;
1376 lpdcb->ErrorChar= dcb16.PeChar;
1377 lpdcb->fErrorChar= dcb16.fPeChar;
1378 lpdcb->EofChar = dcb16.EofChar;
1379 lpdcb->EvtChar = dcb16.EvtChar;
1380 lpdcb->XonLim = dcb16.XonLim;
1381 lpdcb->XoffLim = dcb16.XoffLim;
1382 return TRUE;
1384 ptr=strtok(temp," ");
1385 while (ptr) {
1386 DWORD flag,x;
1388 flag=0;
1389 if (!strncmp("baud=",ptr,5)) {
1390 if (!sscanf(ptr+5,"%ld",&x))
1391 WARN(comm,"Couldn't parse %s\n",ptr);
1392 lpdcb->BaudRate = x;
1393 flag=1;
1395 if (!strncmp("stop=",ptr,5)) {
1396 if (!sscanf(ptr+5,"%ld",&x))
1397 WARN(comm,"Couldn't parse %s\n",ptr);
1398 lpdcb->StopBits = x;
1399 flag=1;
1401 if (!strncmp("data=",ptr,5)) {
1402 if (!sscanf(ptr+5,"%ld",&x))
1403 WARN(comm,"Couldn't parse %s\n",ptr);
1404 lpdcb->ByteSize = x;
1405 flag=1;
1407 if (!strncmp("parity=",ptr,7)) {
1408 lpdcb->fParity = TRUE;
1409 switch (ptr[8]) {
1410 case 'N':case 'n':
1411 lpdcb->fParity = FALSE;
1412 lpdcb->Parity = NOPARITY;
1413 break;
1414 case 'E':case 'e':
1415 lpdcb->Parity = EVENPARITY;
1416 break;
1417 case 'O':case 'o':
1418 lpdcb->Parity = ODDPARITY;
1419 break;
1420 case 'M':case 'm':
1421 lpdcb->Parity = MARKPARITY;
1422 break;
1424 flag=1;
1426 if (!flag)
1427 ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
1428 ptr=strtok(NULL," ");
1430 if (lpdcb->BaudRate==110)
1431 lpdcb->StopBits = 2;
1432 return TRUE;
1435 /**************************************************************************
1436 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1438 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1439 LPCOMMTIMEOUTS lptimeouts )
1441 LPSTR devidA;
1442 BOOL ret;
1444 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1445 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1446 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1447 HeapFree( GetProcessHeap(), 0, devidA );
1448 return ret;
1451 /**************************************************************************
1452 * BuildCommDCBW (KERNEL32.17)
1454 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1456 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1459 /*****************************************************************************
1460 * COMM_Handle2fd
1461 * returns a file descriptor for reading from or writing to
1462 * mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
1463 * the handle afterwards!
1465 int COMM_Handle2fd(HANDLE handle, int mode) {
1466 struct get_read_fd_request r_req;
1467 struct get_write_fd_request w_req;
1468 int fd;
1470 w_req.handle = r_req.handle = handle;
1472 switch(mode) {
1473 case GENERIC_WRITE:
1474 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &w_req, sizeof(w_req) );
1475 break;
1476 case GENERIC_READ:
1477 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &r_req, sizeof(r_req) );
1478 break;
1479 default:
1480 ERR(comm,"COMM_Handle2fd: Don't know what type of fd is required.\n");
1481 return -1;
1483 CLIENT_WaitReply( NULL, &fd, 0 );
1485 return fd;
1488 /* FIXME: having these global for win32 for now */
1489 int commerror=0,eventmask=0;
1491 /*****************************************************************************
1492 * SetCommBreak (KERNEL32.449)
1494 BOOL WINAPI SetCommBreak(HANDLE handle)
1496 FIXME(comm,"handle %d, stub!\n", handle);
1497 return TRUE;
1500 /*****************************************************************************
1501 * ClearCommBreak (KERNEL32.20)
1503 BOOL WINAPI ClearCommBreak(HANDLE handle)
1505 FIXME(comm,"handle %d, stub!\n", handle);
1506 return TRUE;
1509 /*****************************************************************************
1510 * EscapeCommFunction (KERNEL32.214)
1512 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1514 int fd;
1515 struct termios port;
1517 TRACE(comm,"handle %d, function=%d\n", handle, nFunction);
1518 fd = COMM_Handle2fd(handle, GENERIC_WRITE);
1519 if(fd<0)
1520 return FALSE;
1522 if (tcgetattr(fd,&port) == -1) {
1523 commerror=WinError();
1524 close(fd);
1525 return FALSE;
1528 switch (nFunction) {
1529 case RESETDEV:
1530 break;
1532 #ifdef TIOCM_DTR
1533 case CLRDTR:
1534 port.c_cflag &= TIOCM_DTR;
1535 break;
1536 #endif
1538 #ifdef TIOCM_RTS
1539 case CLRRTS:
1540 port.c_cflag &= TIOCM_RTS;
1541 break;
1542 #endif
1544 #ifdef CRTSCTS
1545 case SETDTR:
1546 port.c_cflag |= CRTSCTS;
1547 break;
1549 case SETRTS:
1550 port.c_cflag |= CRTSCTS;
1551 break;
1552 #endif
1554 case SETXOFF:
1555 port.c_iflag |= IXOFF;
1556 break;
1558 case SETXON:
1559 port.c_iflag |= IXON;
1560 break;
1561 case SETBREAK:
1562 FIXME(comm,"setbreak, stub\n");
1563 /* ptr->suspended = 1; */
1564 break;
1565 case CLRBREAK:
1566 FIXME(comm,"clrbreak, stub\n");
1567 /* ptr->suspended = 0; */
1568 break;
1569 default:
1570 WARN(comm,"(handle=%d,nFunction=%d): Unknown function\n",
1571 handle, nFunction);
1572 break;
1575 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1576 commerror = WinError();
1577 close(fd);
1578 return FALSE;
1579 } else {
1580 commerror = 0;
1581 close(fd);
1582 return TRUE;
1586 /********************************************************************
1587 * PurgeComm (KERNEL32.557)
1589 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1591 int fd;
1593 TRACE(comm,"handle %d, flags %lx\n", handle, flags);
1595 fd = COMM_Handle2fd(handle, GENERIC_WRITE);
1596 if(fd<0)
1597 return FALSE;
1600 ** not exactly sure how these are different
1601 ** Perhaps if we had our own internal queues, one flushes them
1602 ** and the other flushes the kernel's buffers.
1604 if(flags&PURGE_TXABORT)
1606 tcflush(fd,TCOFLUSH);
1608 if(flags&PURGE_RXABORT)
1610 tcflush(fd,TCIFLUSH);
1612 if(flags&PURGE_TXCLEAR)
1614 tcflush(fd,TCOFLUSH);
1616 if(flags&PURGE_RXCLEAR)
1618 tcflush(fd,TCIFLUSH);
1620 close(fd);
1622 return 1;
1625 /*****************************************************************************
1626 * ClearCommError (KERNEL32.21)
1628 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1630 int fd;
1632 fd=COMM_Handle2fd(handle,GENERIC_READ);
1633 if(0>fd)
1635 return FALSE;
1638 if (lpStat)
1640 lpStat->status = 0;
1642 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1643 WARN(comm, "ioctl returned error\n");
1645 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1646 WARN(comm, "ioctl returned error\n");
1649 close(fd);
1651 TRACE(comm,"handle %d cbInQue = %ld cbOutQue = %ld\n",
1652 handle,
1653 lpStat->cbInQue,
1654 lpStat->cbOutQue);
1656 if(errors)
1657 *errors = 0;
1660 ** After an asynchronous write opperation, the
1661 ** app will call ClearCommError to see if the
1662 ** results are ready yet. It waits for ERROR_IO_PENDING
1664 commerror = ERROR_IO_PENDING;
1666 return TRUE;
1669 /*****************************************************************************
1670 * SetupComm (KERNEL32.676)
1672 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1674 int fd;
1676 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1677 fd=COMM_Handle2fd(handle,GENERIC_WRITE);
1678 if(0>fd)
1680 return FALSE;
1682 close(fd);
1683 return TRUE;
1686 /*****************************************************************************
1687 * GetCommMask (KERNEL32.156)
1689 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1691 int fd;
1693 TRACE(comm, "handle %d, mask %p\n", handle, evtmask);
1694 if(0>(fd=COMM_Handle2fd(handle,GENERIC_READ)))
1696 return FALSE;
1698 close(fd);
1699 *evtmask = eventmask;
1700 return TRUE;
1703 /*****************************************************************************
1704 * SetCommMask (KERNEL32.451)
1706 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1708 int fd;
1710 TRACE(comm, "handle %d, mask %lx\n", handle, evtmask);
1711 if(0>(fd=COMM_Handle2fd(handle,GENERIC_WRITE))) {
1712 return FALSE;
1714 close(fd);
1715 eventmask = evtmask;
1716 return TRUE;
1719 /*****************************************************************************
1720 * SetCommState (KERNEL32.452)
1722 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1724 struct termios port;
1725 int fd;
1726 struct get_write_fd_request req;
1728 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1730 req.handle = handle;
1731 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
1732 CLIENT_WaitReply( NULL, &fd, 0 );
1734 if(fd<0)
1735 return FALSE;
1737 if (tcgetattr(fd,&port) == -1) {
1738 commerror = WinError();
1739 return FALSE;
1742 port.c_cc[VMIN] = 0;
1743 port.c_cc[VTIME] = 1;
1745 #ifdef IMAXBEL
1746 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1747 #else
1748 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1749 #endif
1750 port.c_iflag |= (IGNBRK);
1752 port.c_oflag &= ~(OPOST);
1754 port.c_cflag &= ~(HUPCL);
1755 port.c_cflag |= CLOCAL | CREAD;
1757 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1758 port.c_lflag |= NOFLSH;
1761 ** MJM - removed default baudrate settings
1762 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1764 #ifdef CBAUD
1765 port.c_cflag &= ~CBAUD;
1766 switch (lpdcb->BaudRate) {
1767 case 110:
1768 case CBR_110:
1769 port.c_cflag |= B110;
1770 break;
1771 case 300:
1772 case CBR_300:
1773 port.c_cflag |= B300;
1774 break;
1775 case 600:
1776 case CBR_600:
1777 port.c_cflag |= B600;
1778 break;
1779 case 1200:
1780 case CBR_1200:
1781 port.c_cflag |= B1200;
1782 break;
1783 case 2400:
1784 case CBR_2400:
1785 port.c_cflag |= B2400;
1786 break;
1787 case 4800:
1788 case CBR_4800:
1789 port.c_cflag |= B4800;
1790 break;
1791 case 9600:
1792 case CBR_9600:
1793 port.c_cflag |= B9600;
1794 break;
1795 case 19200:
1796 case CBR_19200:
1797 port.c_cflag |= B19200;
1798 break;
1799 case 38400:
1800 case CBR_38400:
1801 port.c_cflag |= B38400;
1802 break;
1803 default:
1804 commerror = IE_BAUDRATE;
1805 return FALSE;
1807 #elif !defined(__EMX__)
1808 switch (lpdcb->BaudRate) {
1809 case 110:
1810 case CBR_110:
1811 port.c_ospeed = B110;
1812 break;
1813 case 300:
1814 case CBR_300:
1815 port.c_ospeed = B300;
1816 break;
1817 case 600:
1818 case CBR_600:
1819 port.c_ospeed = B600;
1820 break;
1821 case 1200:
1822 case CBR_1200:
1823 port.c_ospeed = B1200;
1824 break;
1825 case 2400:
1826 case CBR_2400:
1827 port.c_ospeed = B2400;
1828 break;
1829 case 4800:
1830 case CBR_4800:
1831 port.c_ospeed = B4800;
1832 break;
1833 case 9600:
1834 case CBR_9600:
1835 port.c_ospeed = B9600;
1836 break;
1837 case 19200:
1838 case CBR_19200:
1839 port.c_ospeed = B19200;
1840 break;
1841 case 38400:
1842 case CBR_38400:
1843 port.c_ospeed = B38400;
1844 break;
1845 default:
1846 commerror = IE_BAUDRATE;
1847 return FALSE;
1849 port.c_ispeed = port.c_ospeed;
1850 #endif
1851 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1852 port.c_cflag &= ~CSIZE;
1853 switch (lpdcb->ByteSize) {
1854 case 5:
1855 port.c_cflag |= CS5;
1856 break;
1857 case 6:
1858 port.c_cflag |= CS6;
1859 break;
1860 case 7:
1861 port.c_cflag |= CS7;
1862 break;
1863 case 8:
1864 port.c_cflag |= CS8;
1865 break;
1866 default:
1867 commerror = IE_BYTESIZE;
1868 return FALSE;
1871 TRACE(comm,"fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
1872 port.c_cflag &= ~(PARENB | PARODD);
1873 if (lpdcb->fParity)
1874 port.c_iflag |= INPCK;
1875 else
1876 port.c_iflag &= ~INPCK;
1877 switch (lpdcb->Parity) {
1878 case NOPARITY:
1879 break;
1880 case ODDPARITY:
1881 port.c_cflag |= (PARENB | PARODD);
1882 break;
1883 case EVENPARITY:
1884 port.c_cflag |= PARENB;
1885 break;
1886 default:
1887 commerror = IE_BYTESIZE;
1888 return FALSE;
1892 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1893 switch (lpdcb->StopBits) {
1894 case ONESTOPBIT:
1895 port.c_cflag &= ~CSTOPB;
1896 break;
1897 case TWOSTOPBITS:
1898 port.c_cflag |= CSTOPB;
1899 break;
1900 default:
1901 commerror = IE_BYTESIZE;
1902 return FALSE;
1904 #ifdef CRTSCTS
1905 if ( lpdcb->fOutxCtsFlow ||
1906 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1907 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1909 port.c_cflag |= CRTSCTS;
1910 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1911 port.c_cflag &= ~CRTSCTS;
1913 #endif
1914 if (lpdcb->fInX)
1915 port.c_iflag |= IXON;
1916 else
1917 port.c_iflag &= ~IXON;
1918 if (lpdcb->fOutX)
1919 port.c_iflag |= IXOFF;
1920 else
1921 port.c_iflag &= ~IXOFF;
1923 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1924 commerror = WinError();
1925 return FALSE;
1926 } else {
1927 commerror = 0;
1928 return TRUE;
1933 /*****************************************************************************
1934 * GetCommState (KERNEL32.159)
1936 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
1938 struct termios port;
1939 int fd;
1940 struct get_read_fd_request req;
1942 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1943 req.handle = handle;
1944 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
1945 CLIENT_WaitReply( NULL, &fd, 0 );
1947 if(fd<0)
1948 return FALSE;
1950 if (tcgetattr(fd, &port) == -1) {
1951 TRACE(comm,"tcgetattr(%d, ...) returned -1",fd);
1952 commerror = WinError();
1953 return FALSE;
1955 #ifndef __EMX__
1956 #ifdef CBAUD
1957 switch (port.c_cflag & CBAUD) {
1958 #else
1959 switch (port.c_ospeed) {
1960 #endif
1961 case B110:
1962 lpdcb->BaudRate = 110;
1963 break;
1964 case B300:
1965 lpdcb->BaudRate = 300;
1966 break;
1967 case B600:
1968 lpdcb->BaudRate = 600;
1969 break;
1970 case B1200:
1971 lpdcb->BaudRate = 1200;
1972 break;
1973 case B2400:
1974 lpdcb->BaudRate = 2400;
1975 break;
1976 case B4800:
1977 lpdcb->BaudRate = 4800;
1978 break;
1979 case B9600:
1980 lpdcb->BaudRate = 9600;
1981 break;
1982 case B19200:
1983 lpdcb->BaudRate = 19200;
1984 break;
1985 case B38400:
1986 lpdcb->BaudRate = 38400;
1987 break;
1989 #endif
1990 switch (port.c_cflag & CSIZE) {
1991 case CS5:
1992 lpdcb->ByteSize = 5;
1993 break;
1994 case CS6:
1995 lpdcb->ByteSize = 6;
1996 break;
1997 case CS7:
1998 lpdcb->ByteSize = 7;
1999 break;
2000 case CS8:
2001 lpdcb->ByteSize = 8;
2002 break;
2005 if(port.c_iflag & INPCK)
2006 lpdcb->fParity = TRUE;
2007 else
2008 lpdcb->fParity = FALSE;
2009 switch (port.c_cflag & (PARENB | PARODD)) {
2010 case 0:
2011 lpdcb->Parity = NOPARITY;
2012 break;
2013 case PARENB:
2014 lpdcb->Parity = EVENPARITY;
2015 break;
2016 case (PARENB | PARODD):
2017 lpdcb->Parity = ODDPARITY;
2018 break;
2021 if (port.c_cflag & CSTOPB)
2022 lpdcb->StopBits = TWOSTOPBITS;
2023 else
2024 lpdcb->StopBits = ONESTOPBIT;
2026 lpdcb->fNull = 0;
2027 lpdcb->fBinary = 1;
2029 #ifdef CRTSCTS
2031 if (port.c_cflag & CRTSCTS) {
2032 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2033 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2034 lpdcb->fOutxCtsFlow = 1;
2035 lpdcb->fOutxDsrFlow = 1;
2036 } else
2037 #endif
2039 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2040 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2042 if (port.c_iflag & IXON)
2043 lpdcb->fInX = 1;
2044 else
2045 lpdcb->fInX = 0;
2047 if (port.c_iflag & IXOFF)
2048 lpdcb->fOutX = 1;
2049 else
2050 lpdcb->fOutX = 0;
2052 lpdcb->XonChar =
2053 lpdcb->XoffChar =
2055 lpdcb->XonLim = 10;
2056 lpdcb->XoffLim = 10;
2058 commerror = 0;
2060 TRACE(comm,"OK\n");
2062 return TRUE;
2065 /*****************************************************************************
2066 * TransmitCommChar (KERNEL32.535)
2068 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2070 struct DosDeviceStruct *ptr;
2072 FIXME(comm,"(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2073 if ((ptr = GetDeviceStruct(cid)) == NULL) {
2074 return FALSE;
2077 if (ptr->suspended) {
2078 ptr->commerror = IE_HARDWARE;
2079 return FALSE;
2081 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2082 ptr->commerror = WinError();
2083 return FALSE;
2084 } else {
2085 ptr->commerror = 0;
2086 return TRUE;
2090 /*****************************************************************************
2091 * GetCommTimeouts (KERNEL32.160)
2093 BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
2095 FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
2096 return TRUE;
2099 /*****************************************************************************
2100 * SetCommTimeouts (KERNEL32.453)
2102 BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
2103 FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
2104 return TRUE;
2107 /***********************************************************************
2108 * GetCommModemStatus (KERNEL32.285)
2110 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2112 FIXME(comm, "(%d %p)\n",hFile,lpModemStat );
2113 return TRUE;
2115 /***********************************************************************
2116 * WaitCommEvent (KERNEL32.719)
2118 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2120 FIXME(comm, "(%d %p %p )\n",hFile, eventmask,overlapped);
2121 return TRUE;
2124 /***********************************************************************
2125 * GetCommProperties (KERNEL32.???)
2127 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2129 FIXME(comm, "(%d %p )\n",hFile,dcb);
2130 return TRUE;
2133 /***********************************************************************
2134 * SetCommProperties (KERNEL32.???)
2136 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2138 FIXME(comm, "(%d %p )\n",hFile,dcb);
2139 return TRUE;