lstrcpyA can't use strcpy.
[wine/dcerpc.git] / misc / comm.c
blobc101d7e1a71b9a7da0a3594ba427d17d12f729dc
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Use port indices instead of unixfds for win16
8 * - Moved things around (separated win16 and win32 routines)
9 * - Added some hints on how to implement buffers and EnableCommNotification.
11 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
12 * - ptr->fd wasn't getting cleared on close.
13 * - GetCommEventMask() and GetCommError() didn't do much of anything.
14 * IMHO, they are still wrong, but they at least implement the RXCHAR
15 * event and return I/O queue sizes, which makes the app I'm interested
16 * in (analog devices EZKIT DSP development system) work.
18 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
19 * <lawson_whitney@juno.com>
20 * July 6, 1998. Fixes and comments by Valentijn Sessink
21 * <vsessink@ic.uva.nl> [V]
22 * I only quick-fixed an error for the output buffers. The thing is this: if a
23 * WinApp starts using serial ports, it calls OpenComm, asking it to open two
24 * buffers, cbInQueue and cbOutQueue size, to hold data to/from the serial
25 * ports. Wine OpenComm only returns "OK". Now the kernel buffer size for
26 * serial communication is only 4096 bytes large. Error: (App asks for
27 * a 104,000 bytes size buffer, Wine returns "OK", App asks "How many char's
28 * are in the buffer", Wine returns "4000" and App thinks "OK, another
29 * 100,000 chars left, good!")
30 * The solution below is a bad but working quickfix for the transmit buffer:
31 * the cbInQueue is saved in a variable; when the program asks how many chars
32 * there are in the buffer, GetCommError returns # in buffer PLUS
33 * the additional (cbOutQeueu - 4096), which leaves the application thinking
34 * "wow, almost full".
35 * Sorry for the rather chatty explanation - but I think comm.c needs to be
36 * redefined with real working buffers make it work; maybe these comments are
37 * of help.
38 * Oktober 98, Rein Klazes [RHK]
39 * A program that wants to monitor the modem status line (RLSD/DCD) may
40 * poll the modem status register in the commMask structure. I update the bit
41 * in GetCommError, waiting for an implementation of communication events.
45 #include "config.h"
47 #include <stdlib.h>
48 #include <termios.h>
49 #include <fcntl.h>
50 #include <string.h>
51 #ifdef HAVE_STRINGS_H
52 # include <strings.h>
53 #endif
54 #include <errno.h>
55 #include <ctype.h>
56 #include <sys/stat.h>
57 #ifdef HAVE_SYS_FILIO_H
58 # include <sys/filio.h>
59 #endif
60 #include <sys/ioctl.h>
61 #include <unistd.h>
63 #include "wine/winuser16.h"
64 #include "comm.h"
65 #ifdef HAVE_SYS_MODEM_H
66 # include <sys/modem.h>
67 #endif
68 #ifdef HAVE_SYS_STRTIO_H
69 # include <sys/strtio.h>
70 #endif
71 #include "heap.h"
72 #include "options.h"
74 #include "server/request.h"
75 #include "server.h"
76 #include "process.h"
77 #include "winerror.h"
78 #include "async.h"
80 #include "debug.h"
82 #ifndef TIOCINQ
83 #define TIOCINQ FIONREAD
84 #endif
85 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
88 * [V] If above globals are wrong, the one below will be wrong as well. It
89 * should probably be in the DosDeviceStruct on per port basis too.
91 int iGlobalOutQueueFiller;
93 #define SERIAL_XMIT_SIZE 4096
95 struct DosDeviceStruct COM[MAX_PORTS];
96 struct DosDeviceStruct LPT[MAX_PORTS];
97 /* pointers to unknown(==undocumented) comm structure */
98 LPCVOID *unknown[MAX_PORTS];
99 /* save terminal states */
100 static struct termios m_stat[MAX_PORTS];
102 void COMM_Init(void)
104 int x;
105 char option[10], temp[256], *btemp;
106 struct stat st;
108 for (x=0; x!=MAX_PORTS; x++) {
109 strcpy(option,"COMx");
110 option[3] = '1' + x;
111 option[4] = '\0';
113 PROFILE_GetWineIniString( "serialports", option, "*",
114 temp, sizeof(temp) );
115 if (!strcmp(temp, "*") || *temp == '\0')
116 COM[x].devicename = NULL;
117 else {
118 btemp = strchr(temp,',');
119 if (btemp != NULL) {
120 *btemp++ = '\0';
121 COM[x].baudrate = atoi(btemp);
122 } else {
123 COM[x].baudrate = -1;
125 stat(temp, &st);
126 if (!S_ISCHR(st.st_mode))
127 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
128 else
129 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
130 WARN(comm,"Can't malloc for device info!\n");
131 else {
132 COM[x].fd = 0;
133 strcpy(COM[x].devicename, temp);
135 TRACE(comm, "%s = %s\n", option, COM[x].devicename);
138 strcpy(option, "LPTx");
139 option[3] = '1' + x;
140 option[4] = '\0';
142 PROFILE_GetWineIniString( "parallelports", option, "*",
143 temp, sizeof(temp) );
144 if (!strcmp(temp, "*") || *temp == '\0')
145 LPT[x].devicename = NULL;
146 else {
147 stat(temp, &st);
148 if (!S_ISCHR(st.st_mode))
149 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
150 else
151 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
152 WARN(comm,"Can't malloc for device info!\n");
153 else {
154 LPT[x].fd = 0;
155 strcpy(LPT[x].devicename, temp);
157 TRACE(comm, "%s = %s\n", option, LPT[x].devicename);
164 struct DosDeviceStruct *GetDeviceStruct_fd(int fd)
166 int x;
168 for (x=0; x!=MAX_PORTS; x++) {
169 if (COM[x].fd == fd)
170 return &COM[x];
171 if (LPT[x].fd == fd)
172 return &LPT[x];
175 return NULL;
178 struct DosDeviceStruct *GetDeviceStruct(int fd)
180 if ((fd&0x7F)<=MAX_PORTS) {
181 if (!(fd&0x80)) {
182 if (COM[fd].fd)
183 return &COM[fd];
184 } else {
185 if (LPT[fd].fd)
186 return &LPT[fd];
190 return NULL;
193 int GetCommPort_fd(int fd)
195 int x;
197 for (x=0; x<MAX_PORTS; x++) {
198 if (COM[x].fd == fd)
199 return x;
202 return -1;
205 int ValidCOMPort(int x)
207 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
210 int ValidLPTPort(int x)
212 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
215 int WinError(void)
217 TRACE(comm, "errno = %d\n", errno);
218 switch (errno) {
219 default:
220 return CE_IOE;
224 static void WINE_UNUSED comm_notification(int fd,void*private)
226 /* in here, we need to:
227 1. read any data from the comm port
228 2. save it into our own internal buffers
229 (we need our own buffers to implement notifications properly!)
230 3. write data from our own internal buffers to the comm port
231 4. if wnd is set, send WM_COMMNOTIFY (using PostMessage) when
232 thresholds set by EnableCommNotification are passed */
236 /**************************************************************************
237 * BuildCommDCB (USER.213)
239 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
241 /* "COM1:9600,n,8,1" */
242 /* 012345 */
243 int port;
244 char *ptr, temp[256];
246 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
248 if (!lstrncmpiA(device,"COM",3)) {
249 port = device[3] - '0';
252 if (port-- == 0) {
253 ERR(comm, "BUG ! COM0 can't exist!.\n");
254 return -1;
257 if (!ValidCOMPort(port)) {
258 return -1;
261 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
263 lpdcb->Id = port;
265 if (!*(device+4))
266 return 0;
268 if (*(device+4) != ':')
269 return -1;
271 strcpy(temp,device+5);
272 ptr = strtok(temp, ", ");
274 if (COM[port].baudrate > 0)
275 lpdcb->BaudRate = COM[port].baudrate;
276 else
277 lpdcb->BaudRate = atoi(ptr);
278 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
280 ptr = strtok(NULL, ", ");
281 if (islower(*ptr))
282 *ptr = toupper(*ptr);
284 TRACE(comm,"parity (%c)\n", *ptr);
285 lpdcb->fParity = TRUE;
286 switch (*ptr) {
287 case 'N':
288 lpdcb->Parity = NOPARITY;
289 lpdcb->fParity = FALSE;
290 break;
291 case 'E':
292 lpdcb->Parity = EVENPARITY;
293 break;
294 case 'M':
295 lpdcb->Parity = MARKPARITY;
296 break;
297 case 'O':
298 lpdcb->Parity = ODDPARITY;
299 break;
300 default:
301 WARN(comm,"Unknown parity `%c'!\n", *ptr);
302 return -1;
305 ptr = strtok(NULL, ", ");
306 TRACE(comm, "charsize (%c)\n", *ptr);
307 lpdcb->ByteSize = *ptr - '0';
309 ptr = strtok(NULL, ", ");
310 TRACE(comm, "stopbits (%c)\n", *ptr);
311 switch (*ptr) {
312 case '1':
313 lpdcb->StopBits = ONESTOPBIT;
314 break;
315 case '2':
316 lpdcb->StopBits = TWOSTOPBITS;
317 break;
318 default:
319 WARN(comm,"Unknown # of stopbits `%c'!\n", *ptr);
320 return -1;
324 return 0;
327 /*****************************************************************************
328 * OpenComm (USER.200)
330 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
332 int port,fd;
334 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
336 if (!lstrncmpiA(device,"COM",3)) {
337 port = device[3] - '0';
339 if (port-- == 0) {
340 ERR(comm, "BUG ! COM0 doesn't exist !\n");
343 /* to help GetCommError return left buffsize [V] */
344 iGlobalOutQueueFiller = (cbOutQueue - SERIAL_XMIT_SIZE);
345 if (iGlobalOutQueueFiller < 0) iGlobalOutQueueFiller = 0;
347 TRACE(comm, "%s = %s\n", device, COM[port].devicename);
349 if (!ValidCOMPort(port)) {
350 return IE_BADID;
352 if (COM[port].fd) {
353 return IE_OPEN;
356 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
357 if (fd == -1) {
358 return WinError();
359 } else {
360 unknown[port] = SEGPTR_ALLOC(40);
361 bzero(unknown[port],40);
362 COM[port].fd = fd;
363 COM[port].commerror = 0;
364 COM[port].eventmask = 0;
365 /* save terminal state */
366 tcgetattr(fd,&m_stat[port]);
367 #if 0
368 /* allocate buffers */
369 /* ... */
370 /* enable async notifications */
371 ASYNC_RegisterFD(COM[port].fd,comm_notification,&COM[port]);
372 #endif
373 return port;
376 else
377 if (!lstrncmpiA(device,"LPT",3)) {
378 port = device[3] - '0';
380 if (port-- == 0) {
381 ERR(comm, "BUG ! LPT0 doesn't exist !\n");
384 if (!ValidLPTPort(port)) {
385 return IE_BADID;
387 if (LPT[port].fd) {
388 return IE_OPEN;
391 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
392 if (fd == -1) {
393 return WinError();
394 } else {
395 LPT[port].fd = fd;
396 LPT[port].commerror = 0;
397 LPT[port].eventmask = 0;
398 return port|0x80;
401 return 0;
404 /*****************************************************************************
405 * CloseComm (USER.207)
407 INT16 WINAPI CloseComm16(INT16 cid)
409 struct DosDeviceStruct *ptr;
411 TRACE(comm,"cid=%d\n", cid);
412 if ((ptr = GetDeviceStruct(cid)) == NULL) {
413 return -1;
415 if (!(cid&0x80)) {
416 /* COM port */
417 SEGPTR_FREE(unknown[cid]); /* [LW] */
418 #if 0
419 /* disable async notifications */
420 ASYNC_UnregisterFD(COM[cid].fd,comm_notification);
421 /* free buffers */
422 /* ... */
423 #endif
424 /* reset modem lines */
425 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
428 if (close(ptr->fd) == -1) {
429 ptr->commerror = WinError();
430 /* FIXME: should we clear ptr->fd here? */
431 return -1;
432 } else {
433 ptr->commerror = 0;
434 ptr->fd = 0;
435 return 0;
439 /*****************************************************************************
440 * SetCommBreak (USER.210)
442 INT16 WINAPI SetCommBreak16(INT16 cid)
444 struct DosDeviceStruct *ptr;
446 TRACE(comm,"cid=%d\n", cid);
447 if ((ptr = GetDeviceStruct(cid)) == NULL) {
448 return -1;
451 ptr->suspended = 1;
452 ptr->commerror = 0;
453 return 0;
456 /*****************************************************************************
457 * ClearCommBreak (USER.211)
459 INT16 WINAPI ClearCommBreak16(INT16 cid)
461 struct DosDeviceStruct *ptr;
463 TRACE(comm,"cid=%d\n", cid);
464 if ((ptr = GetDeviceStruct(cid)) == NULL) {
465 return -1;
468 ptr->suspended = 0;
469 ptr->commerror = 0;
470 return 0;
473 /*****************************************************************************
474 * EscapeCommFunction (USER.214)
476 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
478 int max;
479 struct DosDeviceStruct *ptr;
480 struct termios port;
482 TRACE(comm,"cid=%d, function=%d\n", cid, nFunction);
483 if ((ptr = GetDeviceStruct(cid)) == NULL) {
484 return -1;
486 if (tcgetattr(ptr->fd,&port) == -1) {
487 ptr->commerror=WinError();
488 return -1;
491 switch (nFunction) {
492 case RESETDEV:
493 break;
495 case GETMAXCOM:
496 for (max = MAX_PORTS;!COM[max].devicename;max--)
498 return max;
499 break;
501 case GETMAXLPT:
502 for (max = MAX_PORTS;!LPT[max].devicename;max--)
504 return 0x80 + max;
505 break;
507 #ifdef TIOCM_DTR
508 case CLRDTR:
509 port.c_cflag &= TIOCM_DTR;
510 break;
511 #endif
513 #ifdef TIOCM_RTS
514 case CLRRTS:
515 port.c_cflag &= TIOCM_RTS;
516 break;
517 #endif
519 #ifdef CRTSCTS
520 case SETDTR:
521 port.c_cflag |= CRTSCTS;
522 break;
524 case SETRTS:
525 port.c_cflag |= CRTSCTS;
526 break;
527 #endif
529 case SETXOFF:
530 port.c_iflag |= IXOFF;
531 break;
533 case SETXON:
534 port.c_iflag |= IXON;
535 break;
537 default:
538 WARN(comm,"(cid=%d,nFunction=%d): Unknown function\n",
539 cid, nFunction);
540 break;
543 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
544 ptr->commerror = WinError();
545 return -1;
546 } else {
547 ptr->commerror = 0;
548 return 0;
552 /*****************************************************************************
553 * FlushComm (USER.215)
555 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
557 int queue;
558 struct DosDeviceStruct *ptr;
560 TRACE(comm,"cid=%d, queue=%d\n", cid, fnQueue);
561 if ((ptr = GetDeviceStruct(cid)) == NULL) {
562 return -1;
564 switch (fnQueue) {
565 case 0: queue = TCOFLUSH;
566 break;
567 case 1: queue = TCIFLUSH;
568 break;
569 default:WARN(comm,"(cid=%d,fnQueue=%d):Unknown queue\n",
570 cid, fnQueue);
571 return -1;
573 if (tcflush(ptr->fd, queue)) {
574 ptr->commerror = WinError();
575 return -1;
576 } else {
577 ptr->commerror = 0;
578 return 0;
582 /********************************************************************
583 * GetCommError (USER.203)
585 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
587 int temperror;
588 unsigned long cnt;
589 int rc;
590 struct DosDeviceStruct *ptr;
591 unsigned char *stol;
592 unsigned int mstat;
594 if ((ptr = GetDeviceStruct(cid)) == NULL) {
595 return -1;
597 if (cid&0x80) {
598 WARN(comm," cid %d not comm port\n",cid);
599 return CE_MODE;
601 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
602 ioctl(ptr->fd,TIOCMGET,&mstat);
603 if( mstat&TIOCM_CAR )
604 *stol |= 0x80;
605 else
606 *stol &=0x7f;
608 if (lpStat) {
609 lpStat->status = 0;
611 rc = ioctl(ptr->fd, TIOCOUTQ, &cnt);
612 if (rc) WARN(comm, "Error !\n");
613 lpStat->cbOutQue = cnt + iGlobalOutQueueFiller;
615 rc = ioctl(ptr->fd, TIOCINQ, &cnt);
616 if (rc) WARN(comm, "Error !\n");
617 lpStat->cbInQue = cnt;
619 TRACE(comm, "cid %d, error %d, lpStat %d %d %d stol %x\n",
620 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
621 lpStat->cbOutQue, *stol);
623 else
624 TRACE(comm, "cid %d, error %d, lpStat NULL stol %x\n",
625 cid, ptr->commerror, *stol);
627 /* Return any errors and clear it */
628 temperror = ptr->commerror;
629 ptr->commerror = 0;
630 return(temperror);
633 /*****************************************************************************
634 * SetCommEventMask (USER.208)
636 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
638 struct DosDeviceStruct *ptr;
639 unsigned char *stol;
640 int repid;
641 unsigned int mstat;
643 TRACE(comm,"cid %d,mask %d\n",cid,fuEvtMask);
644 if ((ptr = GetDeviceStruct(cid)) == NULL) {
645 return -1;
647 ptr->eventmask |= fuEvtMask;
648 if (cid&0x80) {
649 WARN(comm," cid %d not comm port\n",cid);
650 return SEGPTR_GET(NULL);
652 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
653 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
654 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
655 if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
656 else {*stol &=0x7f;}
657 TRACE(comm," modem dcd construct %x\n",*stol);
658 return SEGPTR_GET(unknown[cid]);
661 /*****************************************************************************
662 * GetCommEventMask (USER.209)
664 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
666 int events = 0;
667 struct DosDeviceStruct *ptr;
669 TRACE(comm, "cid %d, mask %d\n", cid, fnEvtClear);
670 if ((ptr = GetDeviceStruct(cid)) == NULL) {
671 return -1;
675 * Determine if any characters are available
677 if (fnEvtClear & EV_RXCHAR)
679 int rc;
680 unsigned long cnt;
682 rc = ioctl(ptr->fd, TIOCINQ, &cnt);
683 if (cnt) events |= EV_RXCHAR;
685 TRACE(comm, "rxchar %ld\n", cnt);
689 * There are other events that need to be checked for
691 /* TODO */
693 TRACE(comm, "return events %d\n", events);
694 return events;
697 * [RER] The following was gibberish
699 #if 0
700 tempmask = ptr->eventmask;
701 ptr->eventmask &= ~fnEvtClear;
702 return ptr->eventmask;
703 #endif
706 /*****************************************************************************
707 * SetCommState16 (USER.201)
709 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
711 struct termios port;
712 struct DosDeviceStruct *ptr;
714 TRACE(comm, "cid %d, ptr %p\n", lpdcb->Id, lpdcb);
715 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
716 return -1;
718 if (tcgetattr(ptr->fd, &port) == -1) {
719 ptr->commerror = WinError();
720 return -1;
723 port.c_cc[VMIN] = 0;
724 port.c_cc[VTIME] = 1;
726 #ifdef IMAXBEL
727 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
728 #else
729 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
730 #endif
731 port.c_iflag |= (IGNBRK);
733 port.c_oflag &= ~(OPOST);
735 port.c_cflag &= ~(HUPCL);
736 port.c_cflag |= CLOCAL | CREAD;
738 port.c_lflag &= ~(ICANON|ECHO|ISIG);
739 port.c_lflag |= NOFLSH;
741 if (ptr->baudrate > 0)
742 lpdcb->BaudRate = ptr->baudrate;
743 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
744 #ifdef CBAUD
745 port.c_cflag &= ~CBAUD;
746 switch (lpdcb->BaudRate) {
747 case 110:
748 case CBR_110:
749 port.c_cflag |= B110;
750 break;
751 case 300:
752 case CBR_300:
753 port.c_cflag |= B300;
754 break;
755 case 600:
756 case CBR_600:
757 port.c_cflag |= B600;
758 break;
759 case 1200:
760 case CBR_1200:
761 port.c_cflag |= B1200;
762 break;
763 case 2400:
764 case CBR_2400:
765 port.c_cflag |= B2400;
766 break;
767 case 4800:
768 case CBR_4800:
769 port.c_cflag |= B4800;
770 break;
771 case 9600:
772 case CBR_9600:
773 port.c_cflag |= B9600;
774 break;
775 case 19200:
776 case CBR_19200:
777 port.c_cflag |= B19200;
778 break;
779 case 38400:
780 case CBR_38400:
781 port.c_cflag |= B38400;
782 break;
783 #ifdef B57600
784 case 57600:
785 port.c_cflag |= B57600;
786 break;
787 #endif
788 #ifdef B115200
789 case 57601:
790 port.c_cflag |= B115200;
791 break;
792 #endif
793 default:
794 ptr->commerror = IE_BAUDRATE;
795 return -1;
797 #elif !defined(__EMX__)
798 switch (lpdcb->BaudRate) {
799 case 110:
800 case CBR_110:
801 port.c_ospeed = B110;
802 break;
803 case 300:
804 case CBR_300:
805 port.c_ospeed = B300;
806 break;
807 case 600:
808 case CBR_600:
809 port.c_ospeed = B600;
810 break;
811 case 1200:
812 case CBR_1200:
813 port.c_ospeed = B1200;
814 break;
815 case 2400:
816 case CBR_2400:
817 port.c_ospeed = B2400;
818 break;
819 case 4800:
820 case CBR_4800:
821 port.c_ospeed = B4800;
822 break;
823 case 9600:
824 case CBR_9600:
825 port.c_ospeed = B9600;
826 break;
827 case 19200:
828 case CBR_19200:
829 port.c_ospeed = B19200;
830 break;
831 case 38400:
832 case CBR_38400:
833 port.c_ospeed = B38400;
834 break;
835 default:
836 ptr->commerror = IE_BAUDRATE;
837 return -1;
839 port.c_ispeed = port.c_ospeed;
840 #endif
841 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
842 port.c_cflag &= ~CSIZE;
843 switch (lpdcb->ByteSize) {
844 case 5:
845 port.c_cflag |= CS5;
846 break;
847 case 6:
848 port.c_cflag |= CS6;
849 break;
850 case 7:
851 port.c_cflag |= CS7;
852 break;
853 case 8:
854 port.c_cflag |= CS8;
855 break;
856 default:
857 ptr->commerror = IE_BYTESIZE;
858 return -1;
861 TRACE(comm,"parity %d\n",lpdcb->Parity);
862 port.c_cflag &= ~(PARENB | PARODD);
863 if (lpdcb->fParity)
864 switch (lpdcb->Parity) {
865 case NOPARITY:
866 port.c_iflag &= ~INPCK;
867 break;
868 case ODDPARITY:
869 port.c_cflag |= (PARENB | PARODD);
870 port.c_iflag |= INPCK;
871 break;
872 case EVENPARITY:
873 port.c_cflag |= PARENB;
874 port.c_iflag |= INPCK;
875 break;
876 default:
877 ptr->commerror = IE_BYTESIZE;
878 return -1;
882 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
884 switch (lpdcb->StopBits) {
885 case ONESTOPBIT:
886 port.c_cflag &= ~CSTOPB;
887 break;
888 case TWOSTOPBITS:
889 port.c_cflag |= CSTOPB;
890 break;
891 default:
892 ptr->commerror = IE_BYTESIZE;
893 return -1;
895 #ifdef CRTSCTS
897 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
898 port.c_cflag |= CRTSCTS;
900 if (lpdcb->fDtrDisable)
901 port.c_cflag &= ~CRTSCTS;
902 #endif
903 if (lpdcb->fInX)
904 port.c_iflag |= IXON;
905 else
906 port.c_iflag &= ~IXON;
907 if (lpdcb->fOutX)
908 port.c_iflag |= IXOFF;
909 else
910 port.c_iflag &= ~IXOFF;
912 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
913 ptr->commerror = WinError();
914 return FALSE;
915 } else {
916 ptr->commerror = 0;
917 return 0;
921 /*****************************************************************************
922 * GetCommState (USER.202)
924 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
926 struct DosDeviceStruct *ptr;
927 struct termios port;
929 TRACE(comm,"cid %d, ptr %p\n", cid, lpdcb);
930 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
931 return -1;
933 if (tcgetattr(ptr->fd, &port) == -1) {
934 ptr->commerror = WinError();
935 return -1;
937 lpdcb->Id = cid;
938 #ifndef __EMX__
939 #ifdef CBAUD
940 switch (port.c_cflag & CBAUD) {
941 #else
942 switch (port.c_ospeed) {
943 #endif
944 case B110:
945 lpdcb->BaudRate = 110;
946 break;
947 case B300:
948 lpdcb->BaudRate = 300;
949 break;
950 case B600:
951 lpdcb->BaudRate = 600;
952 break;
953 case B1200:
954 lpdcb->BaudRate = 1200;
955 break;
956 case B2400:
957 lpdcb->BaudRate = 2400;
958 break;
959 case B4800:
960 lpdcb->BaudRate = 4800;
961 break;
962 case B9600:
963 lpdcb->BaudRate = 9600;
964 break;
965 case B19200:
966 lpdcb->BaudRate = 19200;
967 break;
968 case B38400:
969 lpdcb->BaudRate = 38400;
970 break;
971 #ifdef B57600
972 case B57600:
973 lpdcb->BaudRate = 57600;
974 break;
975 #endif
976 #ifdef B115200
977 case B115200:
978 lpdcb->BaudRate = 57601;
979 break;
980 #endif
982 #endif
983 switch (port.c_cflag & CSIZE) {
984 case CS5:
985 lpdcb->ByteSize = 5;
986 break;
987 case CS6:
988 lpdcb->ByteSize = 6;
989 break;
990 case CS7:
991 lpdcb->ByteSize = 7;
992 break;
993 case CS8:
994 lpdcb->ByteSize = 8;
995 break;
998 switch (port.c_cflag & (PARENB | PARODD)) {
999 case 0:
1000 lpdcb->fParity = FALSE;
1001 lpdcb->Parity = NOPARITY;
1002 break;
1003 case PARENB:
1004 lpdcb->fParity = TRUE;
1005 lpdcb->Parity = EVENPARITY;
1006 break;
1007 case (PARENB | PARODD):
1008 lpdcb->fParity = TRUE;
1009 lpdcb->Parity = ODDPARITY;
1010 break;
1013 if (port.c_cflag & CSTOPB)
1014 lpdcb->StopBits = TWOSTOPBITS;
1015 else
1016 lpdcb->StopBits = ONESTOPBIT;
1018 lpdcb->RlsTimeout = 50;
1019 lpdcb->CtsTimeout = 50;
1020 lpdcb->DsrTimeout = 50;
1021 lpdcb->fNull = 0;
1022 lpdcb->fChEvt = 0;
1023 lpdcb->fBinary = 1;
1024 lpdcb->fDtrDisable = 0;
1026 #ifdef CRTSCTS
1028 if (port.c_cflag & CRTSCTS) {
1029 lpdcb->fDtrflow = 1;
1030 lpdcb->fRtsflow = 1;
1031 lpdcb->fOutxCtsFlow = 1;
1032 lpdcb->fOutxDsrFlow = 1;
1033 } else
1034 #endif
1035 lpdcb->fDtrDisable = 1;
1037 if (port.c_iflag & IXON)
1038 lpdcb->fInX = 1;
1039 else
1040 lpdcb->fInX = 0;
1042 if (port.c_iflag & IXOFF)
1043 lpdcb->fOutX = 1;
1044 else
1045 lpdcb->fOutX = 0;
1047 lpdcb->XonChar =
1048 lpdcb->XoffChar =
1050 lpdcb->XonLim = 10;
1051 lpdcb->XoffLim = 10;
1053 ptr->commerror = 0;
1054 return 0;
1057 /*****************************************************************************
1058 * TransmitCommChar (USER.206)
1060 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1062 struct DosDeviceStruct *ptr;
1064 TRACE(comm, "cid %d, data %d \n", cid, chTransmit);
1065 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1066 return -1;
1069 if (ptr->suspended) {
1070 ptr->commerror = IE_HARDWARE;
1071 return -1;
1074 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
1075 ptr->commerror = WinError();
1076 return -1;
1077 } else {
1078 ptr->commerror = 0;
1079 return 0;
1083 /*****************************************************************************
1084 * UngetCommChar (USER.212)
1086 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1088 struct DosDeviceStruct *ptr;
1090 TRACE(comm,"cid %d (char %d)\n", cid, chUnget);
1091 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1092 return -1;
1095 if (ptr->suspended) {
1096 ptr->commerror = IE_HARDWARE;
1097 return -1;
1100 ptr->unget = 1;
1101 ptr->unget_byte = chUnget;
1102 ptr->commerror = 0;
1103 return 0;
1106 /*****************************************************************************
1107 * ReadComm (USER.204)
1109 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1111 int status, length;
1112 struct DosDeviceStruct *ptr;
1114 TRACE(comm, "cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1115 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1116 return -1;
1119 if (ptr->suspended) {
1120 ptr->commerror = IE_HARDWARE;
1121 return -1;
1124 if (ptr->unget) {
1125 *lpvBuf = ptr->unget_byte;
1126 lpvBuf++;
1127 ptr->unget = 0;
1129 length = 1;
1130 } else
1131 length = 0;
1133 status = read(ptr->fd, (void *) lpvBuf, cbRead);
1135 if (status == -1) {
1136 if (errno != EAGAIN) {
1137 ptr->commerror = WinError();
1138 return -1 - length;
1139 } else {
1140 ptr->commerror = 0;
1141 return length;
1143 } else {
1144 TRACE(comm,"%.*s\n", length+status, lpvBuf);
1145 ptr->commerror = 0;
1146 return length + status;
1150 /*****************************************************************************
1151 * WriteComm (USER.205)
1153 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1155 int length;
1156 struct DosDeviceStruct *ptr;
1158 TRACE(comm,"cid %d, ptr %p, length %d\n",
1159 cid, lpvBuf, cbWrite);
1160 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1161 return -1;
1164 if (ptr->suspended) {
1165 ptr->commerror = IE_HARDWARE;
1166 return -1;
1169 TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
1170 length = write(ptr->fd, (void *) lpvBuf, cbWrite);
1172 if (length == -1) {
1173 ptr->commerror = WinError();
1174 return -1;
1175 } else {
1176 ptr->commerror = 0;
1177 return length;
1181 /***********************************************************************
1182 * EnableCommNotification (USER.246)
1184 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1185 INT16 cbWriteNotify, INT16 cbOutQueue )
1187 struct DosDeviceStruct *ptr;
1189 FIXME(comm, "(%d, %x, %d, %d):stub.\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1190 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1191 ptr->commerror = IE_BADID;
1192 return -1;
1194 ptr->wnd = hwnd;
1195 ptr->n_read = cbWriteNotify;
1196 ptr->n_write = cbOutQueue;
1197 return TRUE;
1201 /**************************************************************************
1202 * BuildCommDCBA (KERNEL32.14)
1204 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1206 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1209 /**************************************************************************
1210 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1212 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1213 LPCOMMTIMEOUTS lptimeouts)
1215 int port;
1216 char *ptr,*temp;
1218 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1220 if (!lstrncmpiA(device,"COM",3)) {
1221 port=device[3]-'0';
1222 if (port--==0) {
1223 ERR(comm,"BUG! COM0 can't exists!.\n");
1224 return FALSE;
1226 if (!ValidCOMPort(port))
1227 return FALSE;
1228 if (*(device+4)!=':')
1229 return FALSE;
1230 temp=(LPSTR)(device+5);
1231 } else
1232 temp=(LPSTR)device;
1234 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
1236 lpdcb->DCBlength = sizeof(DCB);
1237 if (strchr(temp,',')) { /* old style */
1238 DCB16 dcb16;
1239 BOOL16 ret;
1240 char last=temp[strlen(temp)-1];
1242 ret=BuildCommDCB16(device,&dcb16);
1243 if (!ret)
1244 return FALSE;
1245 lpdcb->BaudRate = dcb16.BaudRate;
1246 lpdcb->ByteSize = dcb16.ByteSize;
1247 lpdcb->fBinary = dcb16.fBinary;
1248 lpdcb->Parity = dcb16.Parity;
1249 lpdcb->fParity = dcb16.fParity;
1250 lpdcb->fNull = dcb16.fNull;
1251 lpdcb->StopBits = dcb16.StopBits;
1252 if (last == 'x') {
1253 lpdcb->fInX = TRUE;
1254 lpdcb->fOutX = TRUE;
1255 lpdcb->fOutxCtsFlow = FALSE;
1256 lpdcb->fOutxDsrFlow = FALSE;
1257 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1258 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1259 } else if (last=='p') {
1260 lpdcb->fInX = FALSE;
1261 lpdcb->fOutX = FALSE;
1262 lpdcb->fOutxCtsFlow = TRUE;
1263 lpdcb->fOutxDsrFlow = TRUE;
1264 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1265 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1266 } else {
1267 lpdcb->fInX = FALSE;
1268 lpdcb->fOutX = FALSE;
1269 lpdcb->fOutxCtsFlow = FALSE;
1270 lpdcb->fOutxDsrFlow = FALSE;
1271 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1272 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1274 lpdcb->XonChar = dcb16.XonChar;
1275 lpdcb->XoffChar = dcb16.XoffChar;
1276 lpdcb->ErrorChar= dcb16.PeChar;
1277 lpdcb->fErrorChar= dcb16.fPeChar;
1278 lpdcb->EofChar = dcb16.EofChar;
1279 lpdcb->EvtChar = dcb16.EvtChar;
1280 lpdcb->XonLim = dcb16.XonLim;
1281 lpdcb->XoffLim = dcb16.XoffLim;
1282 return TRUE;
1284 ptr=strtok(temp," ");
1285 while (ptr) {
1286 DWORD flag,x;
1288 flag=0;
1289 if (!strncmp("baud=",ptr,5)) {
1290 if (!sscanf(ptr+5,"%ld",&x))
1291 WARN(comm,"Couldn't parse %s\n",ptr);
1292 lpdcb->BaudRate = x;
1293 flag=1;
1295 if (!strncmp("stop=",ptr,5)) {
1296 if (!sscanf(ptr+5,"%ld",&x))
1297 WARN(comm,"Couldn't parse %s\n",ptr);
1298 lpdcb->StopBits = x;
1299 flag=1;
1301 if (!strncmp("data=",ptr,5)) {
1302 if (!sscanf(ptr+5,"%ld",&x))
1303 WARN(comm,"Couldn't parse %s\n",ptr);
1304 lpdcb->ByteSize = x;
1305 flag=1;
1307 if (!strncmp("parity=",ptr,7)) {
1308 lpdcb->fParity = TRUE;
1309 switch (ptr[8]) {
1310 case 'N':case 'n':
1311 lpdcb->fParity = FALSE;
1312 lpdcb->Parity = NOPARITY;
1313 break;
1314 case 'E':case 'e':
1315 lpdcb->Parity = EVENPARITY;
1316 break;
1317 case 'O':case 'o':
1318 lpdcb->Parity = ODDPARITY;
1319 break;
1320 case 'M':case 'm':
1321 lpdcb->Parity = MARKPARITY;
1322 break;
1324 flag=1;
1326 if (!flag)
1327 ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
1328 ptr=strtok(NULL," ");
1330 if (lpdcb->BaudRate==110)
1331 lpdcb->StopBits = 2;
1332 return TRUE;
1335 /**************************************************************************
1336 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1338 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1339 LPCOMMTIMEOUTS lptimeouts )
1341 LPSTR devidA;
1342 BOOL ret;
1344 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1345 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1346 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1347 HeapFree( GetProcessHeap(), 0, devidA );
1348 return ret;
1351 /**************************************************************************
1352 * BuildCommDCBW (KERNEL32.17)
1354 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1356 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1359 /*****************************************************************************
1360 * COMM_Handle2fd
1361 * returns a file descriptor for reading from or writing to
1362 * mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
1363 * the handle afterwards!
1365 int COMM_Handle2fd(HANDLE handle, int mode) {
1366 struct get_read_fd_request r_req;
1367 struct get_write_fd_request w_req;
1368 int fd;
1370 w_req.handle = r_req.handle = handle;
1372 switch(mode) {
1373 case GENERIC_WRITE:
1374 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &w_req, sizeof(w_req) );
1375 break;
1376 case GENERIC_READ:
1377 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &r_req, sizeof(r_req) );
1378 break;
1379 default:
1380 ERR(comm,"COMM_Handle2fd: Don't know what type of fd is required.\n");
1381 return -1;
1383 CLIENT_WaitReply( NULL, &fd, 0 );
1385 return fd;
1388 /* FIXME: having these global for win32 for now */
1389 int commerror=0,eventmask=0;
1391 /*****************************************************************************
1392 * SetCommBreak (KERNEL32.449)
1394 BOOL WINAPI SetCommBreak(HANDLE handle)
1396 FIXME(comm,"handle %d, stub!\n", handle);
1397 return TRUE;
1400 /*****************************************************************************
1401 * ClearCommBreak (KERNEL32.20)
1403 BOOL WINAPI ClearCommBreak(HANDLE handle)
1405 FIXME(comm,"handle %d, stub!\n", handle);
1406 return TRUE;
1409 /*****************************************************************************
1410 * EscapeCommFunction (KERNEL32.214)
1412 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1414 int fd;
1415 struct termios port;
1417 TRACE(comm,"handle %d, function=%d\n", handle, nFunction);
1418 fd = COMM_Handle2fd(handle, GENERIC_WRITE);
1419 if(fd<0)
1420 return FALSE;
1422 if (tcgetattr(fd,&port) == -1) {
1423 commerror=WinError();
1424 close(fd);
1425 return FALSE;
1428 switch (nFunction) {
1429 case RESETDEV:
1430 break;
1432 #ifdef TIOCM_DTR
1433 case CLRDTR:
1434 port.c_cflag &= TIOCM_DTR;
1435 break;
1436 #endif
1438 #ifdef TIOCM_RTS
1439 case CLRRTS:
1440 port.c_cflag &= TIOCM_RTS;
1441 break;
1442 #endif
1444 #ifdef CRTSCTS
1445 case SETDTR:
1446 port.c_cflag |= CRTSCTS;
1447 break;
1449 case SETRTS:
1450 port.c_cflag |= CRTSCTS;
1451 break;
1452 #endif
1454 case SETXOFF:
1455 port.c_iflag |= IXOFF;
1456 break;
1458 case SETXON:
1459 port.c_iflag |= IXON;
1460 break;
1461 case SETBREAK:
1462 FIXME(comm,"setbreak, stub\n");
1463 /* ptr->suspended = 1; */
1464 break;
1465 case CLRBREAK:
1466 FIXME(comm,"clrbreak, stub\n");
1467 /* ptr->suspended = 0; */
1468 break;
1469 default:
1470 WARN(comm,"(handle=%d,nFunction=%d): Unknown function\n",
1471 handle, nFunction);
1472 break;
1475 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1476 commerror = WinError();
1477 close(fd);
1478 return FALSE;
1479 } else {
1480 commerror = 0;
1481 close(fd);
1482 return TRUE;
1486 /********************************************************************
1487 * PurgeComm (KERNEL32.557)
1489 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1491 int fd;
1493 TRACE(comm,"handle %d, flags %lx\n", handle, flags);
1495 fd = COMM_Handle2fd(handle, GENERIC_WRITE);
1496 if(fd<0)
1497 return FALSE;
1500 ** not exactly sure how these are different
1501 ** Perhaps if we had our own internal queues, one flushes them
1502 ** and the other flushes the kernel's buffers.
1504 if(flags&PURGE_TXABORT)
1506 tcflush(fd,TCOFLUSH);
1508 if(flags&PURGE_RXABORT)
1510 tcflush(fd,TCIFLUSH);
1512 if(flags&PURGE_TXCLEAR)
1514 tcflush(fd,TCOFLUSH);
1516 if(flags&PURGE_RXCLEAR)
1518 tcflush(fd,TCIFLUSH);
1520 close(fd);
1522 return 1;
1525 /*****************************************************************************
1526 * ClearCommError (KERNEL32.21)
1528 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1530 int fd;
1532 fd=COMM_Handle2fd(handle,GENERIC_READ);
1533 if(0>fd)
1535 return FALSE;
1538 if (lpStat)
1540 lpStat->status = 0;
1542 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1543 WARN(comm, "ioctl returned error\n");
1545 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1546 WARN(comm, "ioctl returned error\n");
1549 close(fd);
1551 TRACE(comm,"handle %d cbInQue = %ld cbOutQue = %ld\n",
1552 handle,
1553 lpStat->cbInQue,
1554 lpStat->cbOutQue);
1556 if(errors)
1557 *errors = 0;
1560 ** After an asynchronous write opperation, the
1561 ** app will call ClearCommError to see if the
1562 ** results are ready yet. It waits for ERROR_IO_PENDING
1564 commerror = ERROR_IO_PENDING;
1566 return TRUE;
1569 /*****************************************************************************
1570 * SetupComm (KERNEL32.676)
1572 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1574 int fd;
1576 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1577 fd=COMM_Handle2fd(handle,GENERIC_WRITE);
1578 if(0>fd)
1580 return FALSE;
1582 close(fd);
1583 return TRUE;
1586 /*****************************************************************************
1587 * GetCommMask (KERNEL32.156)
1589 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1591 int fd;
1593 TRACE(comm, "handle %d, mask %p\n", handle, evtmask);
1594 if(0>(fd=COMM_Handle2fd(handle,GENERIC_READ)))
1596 return FALSE;
1598 close(fd);
1599 *evtmask = eventmask;
1600 return TRUE;
1603 /*****************************************************************************
1604 * SetCommMask (KERNEL32.451)
1606 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1608 int fd;
1610 TRACE(comm, "handle %d, mask %lx\n", handle, evtmask);
1611 if(0>(fd=COMM_Handle2fd(handle,GENERIC_WRITE))) {
1612 return FALSE;
1614 close(fd);
1615 eventmask = evtmask;
1616 return TRUE;
1619 /*****************************************************************************
1620 * SetCommState (KERNEL32.452)
1622 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1624 struct termios port;
1625 int fd;
1626 struct get_write_fd_request req;
1628 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1630 req.handle = handle;
1631 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
1632 CLIENT_WaitReply( NULL, &fd, 0 );
1634 if(fd<0)
1635 return FALSE;
1637 if (tcgetattr(fd,&port) == -1) {
1638 commerror = WinError();
1639 return FALSE;
1642 port.c_cc[VMIN] = 0;
1643 port.c_cc[VTIME] = 1;
1645 #ifdef IMAXBEL
1646 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1647 #else
1648 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1649 #endif
1650 port.c_iflag |= (IGNBRK);
1652 port.c_oflag &= ~(OPOST);
1654 port.c_cflag &= ~(HUPCL);
1655 port.c_cflag |= CLOCAL | CREAD;
1657 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1658 port.c_lflag |= NOFLSH;
1661 ** MJM - removed default baudrate settings
1662 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1664 #ifdef CBAUD
1665 port.c_cflag &= ~CBAUD;
1666 switch (lpdcb->BaudRate) {
1667 case 110:
1668 case CBR_110:
1669 port.c_cflag |= B110;
1670 break;
1671 case 300:
1672 case CBR_300:
1673 port.c_cflag |= B300;
1674 break;
1675 case 600:
1676 case CBR_600:
1677 port.c_cflag |= B600;
1678 break;
1679 case 1200:
1680 case CBR_1200:
1681 port.c_cflag |= B1200;
1682 break;
1683 case 2400:
1684 case CBR_2400:
1685 port.c_cflag |= B2400;
1686 break;
1687 case 4800:
1688 case CBR_4800:
1689 port.c_cflag |= B4800;
1690 break;
1691 case 9600:
1692 case CBR_9600:
1693 port.c_cflag |= B9600;
1694 break;
1695 case 19200:
1696 case CBR_19200:
1697 port.c_cflag |= B19200;
1698 break;
1699 case 38400:
1700 case CBR_38400:
1701 port.c_cflag |= B38400;
1702 break;
1703 default:
1704 commerror = IE_BAUDRATE;
1705 return FALSE;
1707 #elif !defined(__EMX__)
1708 switch (lpdcb->BaudRate) {
1709 case 110:
1710 case CBR_110:
1711 port.c_ospeed = B110;
1712 break;
1713 case 300:
1714 case CBR_300:
1715 port.c_ospeed = B300;
1716 break;
1717 case 600:
1718 case CBR_600:
1719 port.c_ospeed = B600;
1720 break;
1721 case 1200:
1722 case CBR_1200:
1723 port.c_ospeed = B1200;
1724 break;
1725 case 2400:
1726 case CBR_2400:
1727 port.c_ospeed = B2400;
1728 break;
1729 case 4800:
1730 case CBR_4800:
1731 port.c_ospeed = B4800;
1732 break;
1733 case 9600:
1734 case CBR_9600:
1735 port.c_ospeed = B9600;
1736 break;
1737 case 19200:
1738 case CBR_19200:
1739 port.c_ospeed = B19200;
1740 break;
1741 case 38400:
1742 case CBR_38400:
1743 port.c_ospeed = B38400;
1744 break;
1745 default:
1746 commerror = IE_BAUDRATE;
1747 return FALSE;
1749 port.c_ispeed = port.c_ospeed;
1750 #endif
1751 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1752 port.c_cflag &= ~CSIZE;
1753 switch (lpdcb->ByteSize) {
1754 case 5:
1755 port.c_cflag |= CS5;
1756 break;
1757 case 6:
1758 port.c_cflag |= CS6;
1759 break;
1760 case 7:
1761 port.c_cflag |= CS7;
1762 break;
1763 case 8:
1764 port.c_cflag |= CS8;
1765 break;
1766 default:
1767 commerror = IE_BYTESIZE;
1768 return FALSE;
1771 TRACE(comm,"parity %d\n",lpdcb->Parity);
1772 port.c_cflag &= ~(PARENB | PARODD);
1773 if (lpdcb->fParity)
1774 switch (lpdcb->Parity) {
1775 case NOPARITY:
1776 port.c_iflag &= ~INPCK;
1777 break;
1778 case ODDPARITY:
1779 port.c_cflag |= (PARENB | PARODD);
1780 port.c_iflag |= INPCK;
1781 break;
1782 case EVENPARITY:
1783 port.c_cflag |= PARENB;
1784 port.c_iflag |= INPCK;
1785 break;
1786 default:
1787 commerror = IE_BYTESIZE;
1788 return FALSE;
1792 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1793 switch (lpdcb->StopBits) {
1794 case ONESTOPBIT:
1795 port.c_cflag &= ~CSTOPB;
1796 break;
1797 case TWOSTOPBITS:
1798 port.c_cflag |= CSTOPB;
1799 break;
1800 default:
1801 commerror = IE_BYTESIZE;
1802 return FALSE;
1804 #ifdef CRTSCTS
1805 if ( lpdcb->fOutxCtsFlow ||
1806 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1807 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1809 port.c_cflag |= CRTSCTS;
1810 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1811 port.c_cflag &= ~CRTSCTS;
1813 #endif
1814 if (lpdcb->fInX)
1815 port.c_iflag |= IXON;
1816 else
1817 port.c_iflag &= ~IXON;
1818 if (lpdcb->fOutX)
1819 port.c_iflag |= IXOFF;
1820 else
1821 port.c_iflag &= ~IXOFF;
1823 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1824 commerror = WinError();
1825 return FALSE;
1826 } else {
1827 commerror = 0;
1828 return TRUE;
1833 /*****************************************************************************
1834 * GetCommState (KERNEL32.159)
1836 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
1838 struct termios port;
1839 int fd;
1840 struct get_read_fd_request req;
1842 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1843 req.handle = handle;
1844 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
1845 CLIENT_WaitReply( NULL, &fd, 0 );
1847 if(fd<0)
1848 return FALSE;
1850 if (tcgetattr(fd, &port) == -1) {
1851 TRACE(comm,"tcgetattr(%d, ...) returned -1",fd);
1852 commerror = WinError();
1853 return FALSE;
1855 #ifndef __EMX__
1856 #ifdef CBAUD
1857 switch (port.c_cflag & CBAUD) {
1858 #else
1859 switch (port.c_ospeed) {
1860 #endif
1861 case B110:
1862 lpdcb->BaudRate = 110;
1863 break;
1864 case B300:
1865 lpdcb->BaudRate = 300;
1866 break;
1867 case B600:
1868 lpdcb->BaudRate = 600;
1869 break;
1870 case B1200:
1871 lpdcb->BaudRate = 1200;
1872 break;
1873 case B2400:
1874 lpdcb->BaudRate = 2400;
1875 break;
1876 case B4800:
1877 lpdcb->BaudRate = 4800;
1878 break;
1879 case B9600:
1880 lpdcb->BaudRate = 9600;
1881 break;
1882 case B19200:
1883 lpdcb->BaudRate = 19200;
1884 break;
1885 case B38400:
1886 lpdcb->BaudRate = 38400;
1887 break;
1889 #endif
1890 switch (port.c_cflag & CSIZE) {
1891 case CS5:
1892 lpdcb->ByteSize = 5;
1893 break;
1894 case CS6:
1895 lpdcb->ByteSize = 6;
1896 break;
1897 case CS7:
1898 lpdcb->ByteSize = 7;
1899 break;
1900 case CS8:
1901 lpdcb->ByteSize = 8;
1902 break;
1905 switch (port.c_cflag & (PARENB | PARODD)) {
1906 case 0:
1907 lpdcb->fParity = FALSE;
1908 lpdcb->Parity = NOPARITY;
1909 break;
1910 case PARENB:
1911 lpdcb->fParity = TRUE;
1912 lpdcb->Parity = EVENPARITY;
1913 break;
1914 case (PARENB | PARODD):
1915 lpdcb->fParity = TRUE;
1916 lpdcb->Parity = ODDPARITY;
1917 break;
1920 if (port.c_cflag & CSTOPB)
1921 lpdcb->StopBits = TWOSTOPBITS;
1922 else
1923 lpdcb->StopBits = ONESTOPBIT;
1925 lpdcb->fNull = 0;
1926 lpdcb->fBinary = 1;
1928 #ifdef CRTSCTS
1930 if (port.c_cflag & CRTSCTS) {
1931 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1932 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1933 lpdcb->fOutxCtsFlow = 1;
1934 lpdcb->fOutxDsrFlow = 1;
1935 } else
1936 #endif
1938 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1939 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1941 if (port.c_iflag & IXON)
1942 lpdcb->fInX = 1;
1943 else
1944 lpdcb->fInX = 0;
1946 if (port.c_iflag & IXOFF)
1947 lpdcb->fOutX = 1;
1948 else
1949 lpdcb->fOutX = 0;
1951 lpdcb->XonChar =
1952 lpdcb->XoffChar =
1954 lpdcb->XonLim = 10;
1955 lpdcb->XoffLim = 10;
1957 commerror = 0;
1959 TRACE(comm,"OK\n");
1961 return TRUE;
1964 /*****************************************************************************
1965 * TransmitCommChar (KERNEL32.535)
1967 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
1969 struct DosDeviceStruct *ptr;
1971 FIXME(comm,"(%d,'%c'), use win32 handle!\n",cid,chTransmit);
1972 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1973 return FALSE;
1976 if (ptr->suspended) {
1977 ptr->commerror = IE_HARDWARE;
1978 return FALSE;
1980 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
1981 ptr->commerror = WinError();
1982 return FALSE;
1983 } else {
1984 ptr->commerror = 0;
1985 return TRUE;
1989 /*****************************************************************************
1990 * GetCommTimeouts (KERNEL32.160)
1992 BOOL WINAPI GetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts)
1994 FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
1995 return TRUE;
1998 /*****************************************************************************
1999 * SetCommTimeouts (KERNEL32.453)
2001 BOOL WINAPI SetCommTimeouts(INT cid,LPCOMMTIMEOUTS lptimeouts) {
2002 FIXME(comm,"(%x,%p):stub.\n",cid,lptimeouts);
2003 return TRUE;
2006 /***********************************************************************
2007 * GetCommModemStatus (KERNEL32.285)
2009 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2011 FIXME(comm, "(%d %p)\n",hFile,lpModemStat );
2012 return TRUE;
2014 /***********************************************************************
2015 * WaitCommEvent (KERNEL32.719)
2017 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2019 FIXME(comm, "(%d %p %p )\n",hFile, eventmask,overlapped);
2020 return TRUE;
2023 /***********************************************************************
2024 * GetCommProperties (KERNEL32.???)
2026 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2028 FIXME(comm, "(%d %p )\n",hFile,dcb);
2029 return TRUE;
2032 /***********************************************************************
2033 * SetCommProperties (KERNEL32.???)
2035 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2037 FIXME(comm, "(%d %p )\n",hFile,dcb);
2038 return TRUE;