Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbeyj@wpi.edu>
[wine/multimedia.git] / misc / comm.c
blob4732f39885f0e37bb3735ffc36f163caa8ca61bf
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
9 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
12 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
13 * - Use port indices instead of unixfds for win16
14 * - Moved things around (separated win16 and win32 routines)
15 * - Added some hints on how to implement buffers and EnableCommNotification.
17 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
18 * - ptr->fd wasn't getting cleared on close.
19 * - GetCommEventMask() and GetCommError() didn't do much of anything.
20 * IMHO, they are still wrong, but they at least implement the RXCHAR
21 * event and return I/O queue sizes, which makes the app I'm interested
22 * in (analog devices EZKIT DSP development system) work.
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
26 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
28 * Oktober 98, Rein Klazes [RHK]
29 * A program that wants to monitor the modem status line (RLSD/DCD) may
30 * poll the modem status register in the commMask structure. I update the bit
31 * in GetCommError, waiting for an implementation of communication events.
35 #include "config.h"
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <termios.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #ifdef HAVE_STRINGS_H
43 # include <strings.h>
44 #endif
45 #include <errno.h>
46 #include <ctype.h>
47 #include <sys/stat.h>
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
50 #endif
51 #include <sys/ioctl.h>
52 #include <unistd.h>
54 #include "windef.h"
55 #include "wingdi.h"
56 #include "wine/winuser16.h"
57 #include "comm.h"
58 #ifdef HAVE_SYS_MODEM_H
59 # include <sys/modem.h>
60 #endif
61 #ifdef HAVE_SYS_STRTIO_H
62 # include <sys/strtio.h>
63 #endif
64 #include "heap.h"
65 #include "options.h"
67 #include "server.h"
68 #include "process.h"
69 #include "winerror.h"
70 #include "services.h"
71 #include "callback.h"
72 #include "file.h"
74 #include "debugtools.h"
76 DEFAULT_DEBUG_CHANNEL(comm);
78 #ifndef TIOCINQ
79 #define TIOCINQ FIONREAD
80 #endif
82 /* window's semi documented modem status register */
83 #define COMM_MSR_OFFSET 35
84 #define MSR_CTS 0x10
85 #define MSR_DSR 0x20
86 #define MSR_RI 0x40
87 #define MSR_RLSD 0x80
88 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
90 #define FLAG_LPT 0x80
92 #ifdef linux
93 #define CMSPAR 0x40000000 /* stick parity */
94 #endif
96 struct DosDeviceStruct COM[MAX_PORTS];
97 struct DosDeviceStruct LPT[MAX_PORTS];
98 /* pointers to unknown(==undocumented) comm structure */
99 LPCVOID *unknown[MAX_PORTS];
100 /* save terminal states */
101 static struct termios m_stat[MAX_PORTS];
103 /* update window's semi documented modem status register */
104 /* see knowledge base Q101417 */
105 static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
107 UCHAR tmpmsr=0;
108 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
109 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
110 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
111 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
112 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
115 void COMM_Init(void)
117 int x;
118 char option[10], temp[256], *btemp;
119 struct stat st;
121 for (x=0; x!=MAX_PORTS; x++) {
122 strcpy(option,"COMx");
123 option[3] = '1' + x;
124 option[4] = '\0';
126 PROFILE_GetWineIniString( "serialports", option, "*",
127 temp, sizeof(temp) );
128 if (!strcmp(temp, "*") || *temp == '\0')
129 COM[x].devicename = NULL;
130 else {
131 btemp = strchr(temp,',');
132 if (btemp != NULL) {
133 *btemp++ = '\0';
134 COM[x].baudrate = atoi(btemp);
135 } else {
136 COM[x].baudrate = -1;
138 stat(temp, &st);
139 if (!S_ISCHR(st.st_mode))
140 WARN("Can't use `%s' as %s !\n", temp, option);
141 else
142 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
143 WARN("Can't malloc for device info!\n");
144 else {
145 COM[x].fd = 0;
146 strcpy(COM[x].devicename, temp);
148 TRACE("%s = %s\n", option, COM[x].devicename);
151 strcpy(option, "LPTx");
152 option[3] = '1' + x;
153 option[4] = '\0';
155 PROFILE_GetWineIniString( "parallelports", option, "*",
156 temp, sizeof(temp) );
157 if (!strcmp(temp, "*") || *temp == '\0')
158 LPT[x].devicename = NULL;
159 else {
160 stat(temp, &st);
161 if (!S_ISCHR(st.st_mode))
162 WARN("Can't use `%s' as %s !\n", temp, option);
163 else
164 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
165 WARN("Can't malloc for device info!\n");
166 else {
167 LPT[x].fd = 0;
168 strcpy(LPT[x].devicename, temp);
170 TRACE("%s = %s\n", option, LPT[x].devicename);
177 static struct DosDeviceStruct *GetDeviceStruct(int fd)
179 if ((fd&0x7F)<=MAX_PORTS) {
180 if (!(fd&FLAG_LPT)) {
181 if (COM[fd].fd)
182 return &COM[fd];
183 } else {
184 fd &= 0x7f;
185 if (LPT[fd].fd)
186 return &LPT[fd];
190 return NULL;
193 static 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 static int ValidCOMPort(int x)
207 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
210 static int ValidLPTPort(int x)
212 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
215 static int WinError(void)
217 TRACE("errno = %d\n", errno);
218 switch (errno) {
219 default:
220 return CE_IOE;
224 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
226 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
227 + ptr->ibuf_head - ptr->ibuf_tail;
230 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
232 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
233 + ptr->obuf_head - ptr->obuf_tail;
236 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
238 unsigned int mstat, okay;
239 okay = ioctl(fd, TIOCMGET, &mstat);
240 if (okay) return okay;
241 if (andy) mstat &= andy;
242 mstat |= orrie;
243 return ioctl(fd, TIOCMSET, &mstat);
246 static void CALLBACK comm_notification( ULONG_PTR private )
248 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
249 int prev, bleft, len;
250 WORD mask = 0;
251 int cid = GetCommPort_fd(ptr->fd);
253 TRACE("async notification\n");
254 /* read data from comm port */
255 prev = comm_inbuf(ptr);
256 do {
257 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
258 - ptr->ibuf_head;
259 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
260 if (len > 0) {
261 if (!bleft) {
262 ptr->commerror = CE_RXOVER;
263 } else {
264 /* check for events */
265 if ((ptr->eventmask & EV_RXFLAG) &&
266 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
267 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
268 mask |= CN_EVENT;
270 if (ptr->eventmask & EV_RXCHAR) {
271 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
272 mask |= CN_EVENT;
274 /* advance buffer position */
275 ptr->ibuf_head += len;
276 if (ptr->ibuf_head >= ptr->ibuf_size)
277 ptr->ibuf_head = 0;
280 } while (len > 0);
281 /* check for notification */
282 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
283 (comm_inbuf(ptr)>=ptr->n_read)) {
284 /* passed the receive notification threshold */
285 mask |= CN_RECEIVE;
288 /* write any TransmitCommChar character */
289 if (ptr->xmit>=0) {
290 len = write(ptr->fd, &(ptr->xmit), 1);
291 if (len > 0) ptr->xmit = -1;
293 /* write from output queue */
294 prev = comm_outbuf(ptr);
295 do {
296 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
297 - ptr->obuf_tail;
298 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
299 if (len > 0) {
300 ptr->obuf_tail += len;
301 if (ptr->obuf_tail >= ptr->obuf_size)
302 ptr->obuf_tail = 0;
303 /* flag event */
304 if (ptr->obuf_tail == ptr->obuf_head) {
305 if (ptr->s_write) {
306 SERVICE_Delete( ptr->s_write );
307 ptr->s_write = INVALID_HANDLE_VALUE;
309 if (ptr->eventmask & EV_TXEMPTY) {
310 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
311 mask |= CN_EVENT;
315 } while (len > 0);
316 /* check for notification */
317 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
318 (comm_outbuf(ptr)<ptr->n_write)) {
319 /* passed the transmit notification threshold */
320 mask |= CN_TRANSMIT;
323 /* send notifications, if any */
324 if (ptr->wnd && mask) {
325 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
326 Callout.PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
330 static void comm_waitread(struct DosDeviceStruct *ptr)
332 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
333 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
334 GENERIC_READ | SYNCHRONIZE ),
335 comm_notification,
336 (ULONG_PTR)ptr );
339 static void comm_waitwrite(struct DosDeviceStruct *ptr)
341 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
342 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
343 GENERIC_WRITE | SYNCHRONIZE ),
344 comm_notification,
345 (ULONG_PTR)ptr );
348 /**************************************************************************
349 * BuildCommDCB (USER.213)
351 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
353 /* "COM1:9600,n,8,1" */
354 /* 012345 */
355 int port;
356 char *ptr, temp[256];
358 TRACE("(%s), ptr %p\n", device, lpdcb);
360 if (!lstrncmpiA(device,"COM",3)) {
361 port = device[3] - '0';
364 if (port-- == 0) {
365 ERR("BUG ! COM0 can't exist!.\n");
366 return -1;
369 if (!ValidCOMPort(port)) {
370 FIXME("invalid COM port %d?\n",port);
371 return -1;
374 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
376 lpdcb->Id = port;
378 if (!*(device+4))
379 return 0;
381 if (*(device+4) != ':')
382 return -1;
384 strcpy(temp,device+5);
385 ptr = strtok(temp, ", ");
387 if (COM[port].baudrate > 0)
388 lpdcb->BaudRate = COM[port].baudrate;
389 else
390 lpdcb->BaudRate = atoi(ptr);
391 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
393 ptr = strtok(NULL, ", ");
394 if (islower(*ptr))
395 *ptr = toupper(*ptr);
397 TRACE("parity (%c)\n", *ptr);
398 lpdcb->fParity = TRUE;
399 switch (*ptr) {
400 case 'N':
401 lpdcb->Parity = NOPARITY;
402 lpdcb->fParity = FALSE;
403 break;
404 case 'E':
405 lpdcb->Parity = EVENPARITY;
406 break;
407 case 'M':
408 lpdcb->Parity = MARKPARITY;
409 break;
410 case 'O':
411 lpdcb->Parity = ODDPARITY;
412 break;
413 default:
414 WARN("Unknown parity `%c'!\n", *ptr);
415 return -1;
418 ptr = strtok(NULL, ", ");
419 TRACE("charsize (%c)\n", *ptr);
420 lpdcb->ByteSize = *ptr - '0';
422 ptr = strtok(NULL, ", ");
423 TRACE("stopbits (%c)\n", *ptr);
424 switch (*ptr) {
425 case '1':
426 lpdcb->StopBits = ONESTOPBIT;
427 break;
428 case '2':
429 lpdcb->StopBits = TWOSTOPBITS;
430 break;
431 default:
432 WARN("Unknown # of stopbits `%c'!\n", *ptr);
433 return -1;
437 return 0;
440 /*****************************************************************************
441 * OpenComm (USER.200)
443 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
445 int port,fd;
447 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
449 if (strlen(device) < 4)
450 return IE_BADID;
452 port = device[3] - '0';
454 if (port-- == 0)
455 ERR("BUG ! COM0 or LPT0 don't exist !\n");
457 if (!lstrncmpiA(device,"COM",3)) {
459 TRACE("%s = %s\n", device, COM[port].devicename);
461 if (!ValidCOMPort(port))
462 return IE_BADID;
464 if (COM[port].fd)
465 return IE_OPEN;
467 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
468 if (fd == -1) {
469 ERR("error=%d\n", errno);
470 return IE_HARDWARE;
471 } else {
472 unknown[port] = SEGPTR_ALLOC(40);
473 bzero(unknown[port],40);
474 COM[port].fd = fd;
475 COM[port].commerror = 0;
476 COM[port].eventmask = 0;
477 COM[port].evtchar = 0; /* FIXME: default? */
478 /* save terminal state */
479 tcgetattr(fd,&m_stat[port]);
480 /* set default parameters */
481 if(COM[port].baudrate>-1){
482 DCB16 dcb;
483 GetCommState16(port, &dcb);
484 dcb.BaudRate=COM[port].baudrate;
485 /* more defaults:
486 * databits, parity, stopbits
488 SetCommState16( &dcb);
490 /* init priority characters */
491 COM[port].unget = -1;
492 COM[port].xmit = -1;
493 /* allocate buffers */
494 COM[port].ibuf_size = cbInQueue;
495 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
496 COM[port].obuf_size = cbOutQueue;
497 COM[port].obuf_head = COM[port].obuf_tail = 0;
499 COM[port].inbuf = malloc(cbInQueue);
500 if (COM[port].inbuf) {
501 COM[port].outbuf = malloc(cbOutQueue);
502 if (!COM[port].outbuf)
503 free(COM[port].inbuf);
504 } else COM[port].outbuf = NULL;
505 if (!COM[port].outbuf) {
506 /* not enough memory */
507 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
508 close(COM[port].fd);
509 ERR("out of memory");
510 return IE_MEMORY;
513 COM[port].s_read = INVALID_HANDLE_VALUE;
514 COM[port].s_write = INVALID_HANDLE_VALUE;
515 comm_waitread( &COM[port] );
516 return port;
519 else
520 if (!lstrncmpiA(device,"LPT",3)) {
522 if (!ValidLPTPort(port))
523 return IE_BADID;
525 if (LPT[port].fd)
526 return IE_OPEN;
528 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
529 if (fd == -1) {
530 return IE_HARDWARE;
531 } else {
532 LPT[port].fd = fd;
533 LPT[port].commerror = 0;
534 LPT[port].eventmask = 0;
535 return port|FLAG_LPT;
538 return 0;
541 /*****************************************************************************
542 * CloseComm (USER.207)
544 INT16 WINAPI CloseComm16(INT16 cid)
546 struct DosDeviceStruct *ptr;
548 TRACE("cid=%d\n", cid);
549 if ((ptr = GetDeviceStruct(cid)) == NULL) {
550 FIXME("no cid=%d found!\n", cid);
551 return -1;
553 if (!(cid&FLAG_LPT)) {
554 /* COM port */
555 SEGPTR_FREE(unknown[cid]); /* [LW] */
557 SERVICE_Delete( COM[cid].s_write );
558 SERVICE_Delete( COM[cid].s_read );
559 /* free buffers */
560 free(ptr->outbuf);
561 free(ptr->inbuf);
563 /* reset modem lines */
564 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
567 if (close(ptr->fd) == -1) {
568 ptr->commerror = WinError();
569 /* FIXME: should we clear ptr->fd here? */
570 return -1;
571 } else {
572 ptr->commerror = 0;
573 ptr->fd = 0;
574 return 0;
578 /*****************************************************************************
579 * SetCommBreak (USER.210)
581 INT16 WINAPI SetCommBreak16(INT16 cid)
583 struct DosDeviceStruct *ptr;
585 TRACE("cid=%d\n", cid);
586 if ((ptr = GetDeviceStruct(cid)) == NULL) {
587 FIXME("no cid=%d found!\n", cid);
588 return -1;
591 ptr->suspended = 1;
592 ptr->commerror = 0;
593 return 0;
596 /*****************************************************************************
597 * ClearCommBreak (USER.211)
599 INT16 WINAPI ClearCommBreak16(INT16 cid)
601 struct DosDeviceStruct *ptr;
603 TRACE("cid=%d\n", cid);
604 if (!(ptr = GetDeviceStruct(cid))) {
605 FIXME("no cid=%d found!\n", cid);
606 return -1;
608 ptr->suspended = 0;
609 ptr->commerror = 0;
610 return 0;
613 /*****************************************************************************
614 * EscapeCommFunction (USER.214)
616 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
618 int max;
619 struct DosDeviceStruct *ptr;
620 struct termios port;
622 TRACE("cid=%d, function=%d\n", cid, nFunction);
623 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
624 if ((ptr = GetDeviceStruct(cid)) == NULL) {
625 FIXME("no cid=%d found!\n", cid);
626 return -1;
628 if (tcgetattr(ptr->fd,&port) == -1) {
629 TRACE("tcgetattr failed\n");
630 ptr->commerror=WinError();
631 return -1;
633 } else ptr = NULL;
635 switch (nFunction) {
636 case RESETDEV:
637 TRACE("RESETDEV\n");
638 break;
640 case GETMAXCOM:
641 TRACE("GETMAXCOM\n");
642 for (max = MAX_PORTS;!COM[max].devicename;max--)
644 return max;
645 break;
647 case GETMAXLPT:
648 TRACE("GETMAXLPT\n");
649 for (max = MAX_PORTS;!LPT[max].devicename;max--)
651 return FLAG_LPT + max;
652 break;
654 case GETBASEIRQ:
655 TRACE("GETBASEIRQ\n");
656 /* FIXME: use tables */
657 /* just fake something for now */
658 if (cid & FLAG_LPT) {
659 /* LPT1: irq 7, LPT2: irq 5 */
660 return (cid & 0x7f) ? 5 : 7;
661 } else {
662 /* COM1: irq 4, COM2: irq 3,
663 COM3: irq 4, COM4: irq 3 */
664 return 4 - (cid & 1);
666 break;
668 case CLRDTR:
669 TRACE("CLRDTR\n");
670 #ifdef TIOCM_DTR
671 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
672 #endif
673 case CLRRTS:
674 TRACE("CLRRTS\n");
675 #ifdef TIOCM_RTS
676 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
677 #endif
679 case SETDTR:
680 TRACE("SETDTR\n");
681 #ifdef TIOCM_DTR
682 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
683 #endif
685 case SETRTS:
686 TRACE("SETRTS\n");
687 #ifdef TIOCM_RTS
688 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
689 #endif
691 case SETXOFF:
692 TRACE("SETXOFF\n");
693 port.c_iflag |= IXOFF;
694 break;
696 case SETXON:
697 TRACE("SETXON\n");
698 port.c_iflag |= IXON;
699 break;
701 default:
702 WARN("(cid=%d,nFunction=%d): Unknown function\n",
703 cid, nFunction);
704 break;
707 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
708 ptr->commerror = WinError();
709 return -1;
710 } else {
711 ptr->commerror = 0;
712 return 0;
716 /*****************************************************************************
717 * FlushComm (USER.215)
719 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
721 int queue;
722 struct DosDeviceStruct *ptr;
724 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
725 if ((ptr = GetDeviceStruct(cid)) == NULL) {
726 FIXME("no cid=%d found!\n", cid);
727 return -1;
729 switch (fnQueue) {
730 case 0:
731 queue = TCOFLUSH;
732 ptr->obuf_tail = ptr->obuf_head;
733 break;
734 case 1:
735 queue = TCIFLUSH;
736 ptr->ibuf_head = ptr->ibuf_tail;
737 break;
738 default:
739 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
740 cid, fnQueue);
741 return -1;
743 if (tcflush(ptr->fd, queue)) {
744 ptr->commerror = WinError();
745 return -1;
746 } else {
747 ptr->commerror = 0;
748 return 0;
752 /********************************************************************
753 * GetCommError (USER.203)
755 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
757 int temperror;
758 struct DosDeviceStruct *ptr;
759 unsigned char *stol;
760 unsigned int mstat;
762 if ((ptr = GetDeviceStruct(cid)) == NULL) {
763 FIXME("no handle for cid = %0x!.\n",cid);
764 return -1;
766 if (cid&FLAG_LPT) {
767 WARN(" cid %d not comm port\n",cid);
768 return CE_MODE;
770 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
771 ioctl(ptr->fd,TIOCMGET,&mstat);
772 COMM_MSRUpdate( stol, mstat);
774 if (lpStat) {
775 lpStat->status = 0;
777 lpStat->cbOutQue = comm_outbuf(ptr);
778 lpStat->cbInQue = comm_inbuf(ptr);
780 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
781 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
782 lpStat->cbOutQue, *stol);
784 else
785 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
786 cid, ptr->commerror, *stol);
788 /* Return any errors and clear it */
789 temperror = ptr->commerror;
790 ptr->commerror = 0;
791 return(temperror);
794 /*****************************************************************************
795 * SetCommEventMask (USER.208)
797 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
799 struct DosDeviceStruct *ptr;
800 unsigned char *stol;
801 int repid;
802 unsigned int mstat;
804 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
805 if ((ptr = GetDeviceStruct(cid)) == NULL) {
806 FIXME("no handle for cid = %0x!.\n",cid);
807 return (SEGPTR)NULL;
810 ptr->eventmask = fuEvtMask;
812 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
813 WARN(" cid %d not comm port\n",cid);
814 return (SEGPTR)NULL;
816 /* it's a COM port ? -> modify flags */
817 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
818 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
819 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
820 COMM_MSRUpdate( stol, mstat);
822 TRACE(" modem dcd construct %x\n",*stol);
823 return SEGPTR_GET(unknown[cid]);
826 /*****************************************************************************
827 * GetCommEventMask (USER.209)
829 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
831 struct DosDeviceStruct *ptr;
832 WORD events;
834 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
835 if ((ptr = GetDeviceStruct(cid)) == NULL) {
836 FIXME("no handle for cid = %0x!.\n",cid);
837 return 0;
840 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
841 WARN(" cid %d not comm port\n",cid);
842 return 0;
845 events = *(WORD*)(unknown[cid]) & fnEvtClear;
846 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
847 return events;
850 /*****************************************************************************
851 * SetCommState16 (USER.201)
853 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
855 struct termios port;
856 struct DosDeviceStruct *ptr;
857 int bytesize, stopbits;
858 int fail=0;
860 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
861 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
862 FIXME("no handle for cid = %0x!.\n",lpdcb->Id);
863 return -1;
865 if (tcgetattr(ptr->fd, &port) == -1) {
866 ptr->commerror = WinError();
867 return -1;
870 port.c_cc[VMIN] = 0;
871 port.c_cc[VTIME] = 1;
873 #ifdef IMAXBEL
874 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
875 #else
876 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
877 #endif
878 port.c_iflag |= (IGNBRK);
880 port.c_oflag &= ~(OPOST);
882 port.c_cflag &= ~(HUPCL);
883 port.c_cflag |= CLOCAL | CREAD;
885 port.c_lflag &= ~(ICANON|ECHO|ISIG);
886 port.c_lflag |= NOFLSH;
888 TRACE("baudrate %d\n",lpdcb->BaudRate);
889 #ifdef CBAUD
890 port.c_cflag &= ~CBAUD;
891 switch (lpdcb->BaudRate) {
892 case 110:
893 case CBR_110:
894 port.c_cflag |= B110;
895 break;
896 case 300:
897 case CBR_300:
898 port.c_cflag |= B300;
899 break;
900 case 600:
901 case CBR_600:
902 port.c_cflag |= B600;
903 break;
904 case 1200:
905 case CBR_1200:
906 port.c_cflag |= B1200;
907 break;
908 case 2400:
909 case CBR_2400:
910 port.c_cflag |= B2400;
911 break;
912 case 4800:
913 case CBR_4800:
914 port.c_cflag |= B4800;
915 break;
916 case 9600:
917 case CBR_9600:
918 port.c_cflag |= B9600;
919 break;
920 case 19200:
921 case CBR_19200:
922 port.c_cflag |= B19200;
923 break;
924 case 38400:
925 case CBR_38400:
926 port.c_cflag |= B38400;
927 break;
928 #ifdef B57600
929 case 57600:
930 port.c_cflag |= B57600;
931 break;
932 #endif
933 #ifdef B115200
934 case 57601:
935 port.c_cflag |= B115200;
936 break;
937 #endif
938 default:
939 ptr->commerror = IE_BAUDRATE;
940 fail=1;
942 #elif !defined(__EMX__)
943 switch (lpdcb->BaudRate) {
944 case 110:
945 case CBR_110:
946 port.c_ospeed = B110;
947 break;
948 case 300:
949 case CBR_300:
950 port.c_ospeed = B300;
951 break;
952 case 600:
953 case CBR_600:
954 port.c_ospeed = B600;
955 break;
956 case 1200:
957 case CBR_1200:
958 port.c_ospeed = B1200;
959 break;
960 case 2400:
961 case CBR_2400:
962 port.c_ospeed = B2400;
963 break;
964 case 4800:
965 case CBR_4800:
966 port.c_ospeed = B4800;
967 break;
968 case 9600:
969 case CBR_9600:
970 port.c_ospeed = B9600;
971 break;
972 case 19200:
973 case CBR_19200:
974 port.c_ospeed = B19200;
975 break;
976 case 38400:
977 case CBR_38400:
978 port.c_ospeed = B38400;
979 break;
980 default:
981 ptr->commerror = IE_BAUDRATE;
982 fail=1;
984 port.c_ispeed = port.c_ospeed;
985 #endif
986 bytesize=lpdcb->ByteSize;
987 stopbits=lpdcb->StopBits;
989 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
990 #ifdef CMSPAR
991 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
992 #else
993 port.c_cflag &= ~(PARENB | PARODD);
994 #endif
995 if (lpdcb->fParity)
996 port.c_iflag |= INPCK;
997 else
998 port.c_iflag &= ~INPCK;
999 switch (lpdcb->Parity) {
1000 case NOPARITY:
1001 break;
1002 case ODDPARITY:
1003 port.c_cflag |= (PARENB | PARODD);
1004 break;
1005 case EVENPARITY:
1006 port.c_cflag |= PARENB;
1007 break;
1008 #ifdef CMSPAR
1009 /* Linux defines mark/space (stick) parity */
1010 case MARKPARITY:
1011 port.c_cflag |= (PARENB | CMSPAR);
1012 break;
1013 case SPACEPARITY:
1014 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1015 break;
1016 #else
1017 /* try the POSIX way */
1018 case MARKPARITY:
1019 if( stopbits == ONESTOPBIT) {
1020 stopbits = TWOSTOPBITS;
1021 port.c_iflag &= ~INPCK;
1022 } else {
1023 ptr->commerror = IE_BYTESIZE;
1024 fail=1;
1026 break;
1027 case SPACEPARITY:
1028 if( bytesize < 8) {
1029 bytesize +=1;
1030 port.c_iflag &= ~INPCK;
1031 } else {
1032 ptr->commerror = IE_BYTESIZE;
1033 fail=1;
1035 break;
1036 #endif
1037 default:
1038 ptr->commerror = IE_BYTESIZE;
1039 fail=1;
1042 TRACE("bytesize %d\n",bytesize);
1043 port.c_cflag &= ~CSIZE;
1044 switch (bytesize) {
1045 case 5:
1046 port.c_cflag |= CS5;
1047 break;
1048 case 6:
1049 port.c_cflag |= CS6;
1050 break;
1051 case 7:
1052 port.c_cflag |= CS7;
1053 break;
1054 case 8:
1055 port.c_cflag |= CS8;
1056 break;
1057 default:
1058 ptr->commerror = IE_BYTESIZE;
1059 fail=1;
1062 TRACE("stopbits %d\n",stopbits);
1064 switch (stopbits) {
1065 case ONESTOPBIT:
1066 port.c_cflag &= ~CSTOPB;
1067 break;
1068 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1069 case TWOSTOPBITS:
1070 port.c_cflag |= CSTOPB;
1071 break;
1072 default:
1073 ptr->commerror = IE_BYTESIZE;
1074 fail=1;
1076 #ifdef CRTSCTS
1078 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1079 port.c_cflag |= CRTSCTS;
1081 if (lpdcb->fDtrDisable)
1082 port.c_cflag &= ~CRTSCTS;
1083 #endif
1084 if (lpdcb->fInX)
1085 port.c_iflag |= IXON;
1086 else
1087 port.c_iflag &= ~IXON;
1088 if (lpdcb->fOutX)
1089 port.c_iflag |= IXOFF;
1090 else
1091 port.c_iflag &= ~IXOFF;
1093 ptr->evtchar = lpdcb->EvtChar;
1095 if(fail)
1096 return -1;
1098 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1099 ptr->commerror = WinError();
1100 return -1;
1101 } else {
1102 ptr->commerror = 0;
1103 return 0;
1107 /*****************************************************************************
1108 * GetCommState (USER.202)
1110 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1112 int speed;
1113 struct DosDeviceStruct *ptr;
1114 struct termios port;
1116 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1117 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1118 FIXME("no handle for cid = %0x!.\n",cid);
1119 return -1;
1121 if (tcgetattr(ptr->fd, &port) == -1) {
1122 ptr->commerror = WinError();
1123 return -1;
1125 lpdcb->Id = cid;
1126 #ifndef __EMX__
1127 #ifdef CBAUD
1128 speed = port.c_cflag & CBAUD;
1129 #else
1130 speed = port.c_ospeed;
1131 #endif
1132 switch(speed) {
1133 case B110:
1134 lpdcb->BaudRate = 110;
1135 break;
1136 case B300:
1137 lpdcb->BaudRate = 300;
1138 break;
1139 case B600:
1140 lpdcb->BaudRate = 600;
1141 break;
1142 case B1200:
1143 lpdcb->BaudRate = 1200;
1144 break;
1145 case B2400:
1146 lpdcb->BaudRate = 2400;
1147 break;
1148 case B4800:
1149 lpdcb->BaudRate = 4800;
1150 break;
1151 case B9600:
1152 lpdcb->BaudRate = 9600;
1153 break;
1154 case B19200:
1155 lpdcb->BaudRate = 19200;
1156 break;
1157 case B38400:
1158 lpdcb->BaudRate = 38400;
1159 break;
1160 #ifdef B57600
1161 case B57600:
1162 lpdcb->BaudRate = 57600;
1163 break;
1164 #endif
1165 #ifdef B115200
1166 case B115200:
1167 lpdcb->BaudRate = 57601;
1168 break;
1169 #endif
1171 #endif
1172 switch (port.c_cflag & CSIZE) {
1173 case CS5:
1174 lpdcb->ByteSize = 5;
1175 break;
1176 case CS6:
1177 lpdcb->ByteSize = 6;
1178 break;
1179 case CS7:
1180 lpdcb->ByteSize = 7;
1181 break;
1182 case CS8:
1183 lpdcb->ByteSize = 8;
1184 break;
1187 if(port.c_iflag & INPCK)
1188 lpdcb->fParity = TRUE;
1189 else
1190 lpdcb->fParity = FALSE;
1191 #ifdef CMSPAR
1192 switch (port.c_cflag & (PARENB | PARODD | CMSPAR)) {
1193 #else
1194 switch (port.c_cflag & (PARENB | PARODD)) {
1195 #endif
1196 case 0:
1197 lpdcb->Parity = NOPARITY;
1198 break;
1199 case PARENB:
1200 lpdcb->Parity = EVENPARITY;
1201 break;
1202 case (PARENB | PARODD):
1203 lpdcb->Parity = ODDPARITY;
1204 break;
1205 #ifdef CMSPAR
1206 case (PARENB | CMSPAR):
1207 lpdcb->Parity = MARKPARITY;
1208 break;
1209 case (PARENB | PARODD | CMSPAR):
1210 lpdcb->Parity = SPACEPARITY;
1211 break;
1212 #endif
1215 if (port.c_cflag & CSTOPB)
1216 if(lpdcb->ByteSize == 5)
1217 lpdcb->StopBits = ONE5STOPBITS;
1218 else
1219 lpdcb->StopBits = TWOSTOPBITS;
1220 else
1221 lpdcb->StopBits = ONESTOPBIT;
1223 lpdcb->RlsTimeout = 50;
1224 lpdcb->CtsTimeout = 50;
1225 lpdcb->DsrTimeout = 50;
1226 lpdcb->fNull = 0;
1227 lpdcb->fChEvt = 0;
1228 lpdcb->fBinary = 1;
1229 lpdcb->fDtrDisable = 0;
1231 #ifdef CRTSCTS
1233 if (port.c_cflag & CRTSCTS) {
1234 lpdcb->fDtrflow = 1;
1235 lpdcb->fRtsflow = 1;
1236 lpdcb->fOutxCtsFlow = 1;
1237 lpdcb->fOutxDsrFlow = 1;
1238 } else
1239 #endif
1240 lpdcb->fDtrDisable = 1;
1242 if (port.c_iflag & IXON)
1243 lpdcb->fInX = 1;
1244 else
1245 lpdcb->fInX = 0;
1247 if (port.c_iflag & IXOFF)
1248 lpdcb->fOutX = 1;
1249 else
1250 lpdcb->fOutX = 0;
1252 lpdcb->XonChar =
1253 lpdcb->XoffChar =
1255 lpdcb->XonLim = 10;
1256 lpdcb->XoffLim = 10;
1258 lpdcb->EvtChar = ptr->evtchar;
1260 ptr->commerror = 0;
1261 return 0;
1264 /*****************************************************************************
1265 * TransmitCommChar (USER.206)
1267 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1269 struct DosDeviceStruct *ptr;
1271 TRACE("cid %d, data %d \n", cid, chTransmit);
1272 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1273 FIXME("no handle for cid = %0x!.\n",cid);
1274 return -1;
1277 if (ptr->suspended) {
1278 ptr->commerror = IE_HARDWARE;
1279 return -1;
1282 if (ptr->xmit >= 0) {
1283 /* character already queued */
1284 /* FIXME: which error would Windows return? */
1285 ptr->commerror = CE_TXFULL;
1286 return -1;
1289 if (ptr->obuf_head == ptr->obuf_tail) {
1290 /* transmit queue empty, try to transmit directly */
1291 if (write(ptr->fd, &chTransmit, 1) == -1) {
1292 /* didn't work, queue it */
1293 ptr->xmit = chTransmit;
1294 comm_waitwrite(ptr);
1296 } else {
1297 /* data in queue, let this char be transmitted next */
1298 ptr->xmit = chTransmit;
1299 comm_waitwrite(ptr);
1302 ptr->commerror = 0;
1303 return 0;
1306 /*****************************************************************************
1307 * UngetCommChar (USER.212)
1309 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1311 struct DosDeviceStruct *ptr;
1313 TRACE("cid %d (char %d)\n", cid, chUnget);
1314 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1315 FIXME("no handle for cid = %0x!.\n",cid);
1316 return -1;
1319 if (ptr->suspended) {
1320 ptr->commerror = IE_HARDWARE;
1321 return -1;
1324 if (ptr->unget>=0) {
1325 /* character already queued */
1326 /* FIXME: which error would Windows return? */
1327 ptr->commerror = CE_RXOVER;
1328 return -1;
1331 ptr->unget = chUnget;
1333 ptr->commerror = 0;
1334 return 0;
1337 /*****************************************************************************
1338 * ReadComm (USER.204)
1340 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1342 int status, length;
1343 struct DosDeviceStruct *ptr;
1344 LPSTR orgBuf = lpvBuf;
1346 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1347 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1348 FIXME("no handle for cid = %0x!.\n",cid);
1349 return -1;
1352 if (ptr->suspended) {
1353 ptr->commerror = IE_HARDWARE;
1354 return -1;
1357 /* read unget character */
1358 if (ptr->unget>=0) {
1359 *lpvBuf++ = ptr->unget;
1360 ptr->unget = -1;
1362 length = 1;
1363 } else
1364 length = 0;
1366 /* read from receive buffer */
1367 while (length < cbRead) {
1368 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1369 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1370 if (!status) break;
1371 if ((cbRead - length) < status)
1372 status = cbRead - length;
1374 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1375 ptr->ibuf_tail += status;
1376 if (ptr->ibuf_tail >= ptr->ibuf_size)
1377 ptr->ibuf_tail = 0;
1378 lpvBuf += status;
1379 length += status;
1382 TRACE("%.*s\n", length, orgBuf);
1383 ptr->commerror = 0;
1384 return length;
1387 /*****************************************************************************
1388 * WriteComm (USER.205)
1390 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1392 int status, length;
1393 struct DosDeviceStruct *ptr;
1395 TRACE("cid %d, ptr %p, length %d\n",
1396 cid, lpvBuf, cbWrite);
1397 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1398 FIXME("no handle for cid = %0x!.\n",cid);
1399 return -1;
1402 if (ptr->suspended) {
1403 ptr->commerror = IE_HARDWARE;
1404 return -1;
1407 TRACE("%.*s\n", cbWrite, lpvBuf );
1409 length = 0;
1410 while (length < cbWrite) {
1411 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1412 /* no data queued, try to write directly */
1413 status = write(ptr->fd, lpvBuf, cbWrite - length);
1414 if (status > 0) {
1415 lpvBuf += status;
1416 length += status;
1417 continue;
1420 /* can't write directly, put into transmit buffer */
1421 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1422 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1423 if (!status) break;
1424 if ((cbWrite - length) < status)
1425 status = cbWrite - length;
1426 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1427 ptr->obuf_head += status;
1428 if (ptr->obuf_head >= ptr->obuf_size)
1429 ptr->obuf_head = 0;
1430 lpvBuf += status;
1431 length += status;
1432 comm_waitwrite(ptr);
1435 ptr->commerror = 0;
1436 return length;
1439 /***********************************************************************
1440 * EnableCommNotification (USER.246)
1442 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1443 INT16 cbWriteNotify, INT16 cbOutQueue )
1445 struct DosDeviceStruct *ptr;
1447 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1448 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1449 FIXME("no handle for cid = %0x!.\n",cid);
1450 return -1;
1452 ptr->wnd = hwnd;
1453 ptr->n_read = cbWriteNotify;
1454 ptr->n_write = cbOutQueue;
1455 return TRUE;
1459 /**************************************************************************
1460 * BuildCommDCBA (KERNEL32.14)
1462 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1464 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1467 /**************************************************************************
1468 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1470 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1471 LPCOMMTIMEOUTS lptimeouts)
1473 int port;
1474 char *ptr,*temp;
1476 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1478 if (!lstrncmpiA(device,"COM",3)) {
1479 port=device[3]-'0';
1480 if (port--==0) {
1481 ERR("BUG! COM0 can't exists!.\n");
1482 return FALSE;
1484 if (!ValidCOMPort(port))
1485 return FALSE;
1486 if (*(device+4)!=':')
1487 return FALSE;
1488 temp=(LPSTR)(device+5);
1489 } else
1490 temp=(LPSTR)device;
1492 lpdcb->DCBlength = sizeof(DCB);
1493 if (strchr(temp,',')) { /* old style */
1494 DCB16 dcb16;
1495 BOOL16 ret;
1496 char last=temp[strlen(temp)-1];
1498 ret=BuildCommDCB16(device,&dcb16);
1499 if (!ret)
1500 return FALSE;
1501 lpdcb->BaudRate = dcb16.BaudRate;
1502 lpdcb->ByteSize = dcb16.ByteSize;
1503 lpdcb->fBinary = dcb16.fBinary;
1504 lpdcb->Parity = dcb16.Parity;
1505 lpdcb->fParity = dcb16.fParity;
1506 lpdcb->fNull = dcb16.fNull;
1507 lpdcb->StopBits = dcb16.StopBits;
1508 if (last == 'x') {
1509 lpdcb->fInX = TRUE;
1510 lpdcb->fOutX = TRUE;
1511 lpdcb->fOutxCtsFlow = FALSE;
1512 lpdcb->fOutxDsrFlow = FALSE;
1513 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1514 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1515 } else if (last=='p') {
1516 lpdcb->fInX = FALSE;
1517 lpdcb->fOutX = FALSE;
1518 lpdcb->fOutxCtsFlow = TRUE;
1519 lpdcb->fOutxDsrFlow = TRUE;
1520 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1521 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1522 } else {
1523 lpdcb->fInX = FALSE;
1524 lpdcb->fOutX = FALSE;
1525 lpdcb->fOutxCtsFlow = FALSE;
1526 lpdcb->fOutxDsrFlow = FALSE;
1527 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1528 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1530 lpdcb->XonChar = dcb16.XonChar;
1531 lpdcb->XoffChar = dcb16.XoffChar;
1532 lpdcb->ErrorChar= dcb16.PeChar;
1533 lpdcb->fErrorChar= dcb16.fPeChar;
1534 lpdcb->EofChar = dcb16.EofChar;
1535 lpdcb->EvtChar = dcb16.EvtChar;
1536 lpdcb->XonLim = dcb16.XonLim;
1537 lpdcb->XoffLim = dcb16.XoffLim;
1538 return TRUE;
1540 ptr=strtok(temp," ");
1541 while (ptr) {
1542 DWORD flag,x;
1544 flag=0;
1545 if (!strncmp("baud=",ptr,5)) {
1546 if (!sscanf(ptr+5,"%ld",&x))
1547 WARN("Couldn't parse %s\n",ptr);
1548 lpdcb->BaudRate = x;
1549 flag=1;
1551 if (!strncmp("stop=",ptr,5)) {
1552 if (!sscanf(ptr+5,"%ld",&x))
1553 WARN("Couldn't parse %s\n",ptr);
1554 lpdcb->StopBits = x;
1555 flag=1;
1557 if (!strncmp("data=",ptr,5)) {
1558 if (!sscanf(ptr+5,"%ld",&x))
1559 WARN("Couldn't parse %s\n",ptr);
1560 lpdcb->ByteSize = x;
1561 flag=1;
1563 if (!strncmp("parity=",ptr,7)) {
1564 lpdcb->fParity = TRUE;
1565 switch (ptr[8]) {
1566 case 'N':case 'n':
1567 lpdcb->fParity = FALSE;
1568 lpdcb->Parity = NOPARITY;
1569 break;
1570 case 'E':case 'e':
1571 lpdcb->Parity = EVENPARITY;
1572 break;
1573 case 'O':case 'o':
1574 lpdcb->Parity = ODDPARITY;
1575 break;
1576 case 'M':case 'm':
1577 lpdcb->Parity = MARKPARITY;
1578 break;
1580 flag=1;
1582 if (!flag)
1583 ERR("Unhandled specifier '%s', please report.\n",ptr);
1584 ptr=strtok(NULL," ");
1586 if (lpdcb->BaudRate==110)
1587 lpdcb->StopBits = 2;
1588 return TRUE;
1591 /**************************************************************************
1592 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1594 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1595 LPCOMMTIMEOUTS lptimeouts )
1597 LPSTR devidA;
1598 BOOL ret;
1600 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1601 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1602 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1603 HeapFree( GetProcessHeap(), 0, devidA );
1604 return ret;
1607 /**************************************************************************
1608 * BuildCommDCBW (KERNEL32.17)
1610 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1612 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1615 /*****************************************************************************
1616 * COMM_GetReadFd
1617 * Returns a file descriptor for reading.
1618 * Make sure to close the handle afterwards!
1620 static int COMM_GetReadFd( HANDLE handle)
1622 int fd;
1623 struct get_read_fd_request *req = get_req_buffer();
1624 req->handle = handle;
1625 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1626 return fd;
1629 /*****************************************************************************
1630 * COMM_GetWriteFd
1631 * Returns a file descriptor for writing.
1632 * Make sure to close the handle afterwards!
1634 static int COMM_GetWriteFd( HANDLE handle)
1636 int fd = -1;
1637 struct get_write_fd_request *req = get_req_buffer();
1638 req->handle = handle;
1639 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1640 return fd;
1643 /* FIXME: having these global for win32 for now */
1644 int commerror=0,eventmask=0;
1646 /*****************************************************************************
1647 * SetCommBreak (KERNEL32.449)
1649 BOOL WINAPI SetCommBreak(HANDLE handle)
1651 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1652 int fd,result;
1654 fd = COMM_GetWriteFd(handle);
1655 if(fd<0) {
1656 TRACE("COMM_GetWriteFd failed\n");
1657 return FALSE;
1659 result = ioctl(fd,TIOCSBRK,0);
1660 close(fd);
1661 if (result ==-1)
1663 TRACE("ioctl failed\n");
1664 SetLastError(ERROR_NOT_SUPPORTED);
1665 return FALSE;
1667 return TRUE;
1668 #else
1669 FIXME("ioctl not available\n");
1670 SetLastError(ERROR_NOT_SUPPORTED);
1671 return FALSE;
1672 #endif
1675 /*****************************************************************************
1676 * ClearCommBreak (KERNEL32.20)
1678 BOOL WINAPI ClearCommBreak(HANDLE handle)
1680 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1681 int fd,result;
1683 fd = COMM_GetWriteFd(handle);
1684 if(fd<0) {
1685 TRACE("COMM_GetWriteFd failed\n");
1686 return FALSE;
1688 result = ioctl(fd,TIOCCBRK,0);
1689 close(fd);
1690 if (result ==-1)
1692 TRACE("ioctl failed\n");
1693 SetLastError(ERROR_NOT_SUPPORTED);
1694 return FALSE;
1696 return TRUE;
1697 #else
1698 FIXME("ioctl not available\n");
1699 SetLastError(ERROR_NOT_SUPPORTED);
1700 return FALSE;
1701 #endif
1704 /*****************************************************************************
1705 * EscapeCommFunction (KERNEL32.214)
1707 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1709 int fd,direct=FALSE,result=FALSE;
1710 struct termios port;
1712 TRACE("handle %d, function=%d\n", handle, nFunction);
1713 fd = COMM_GetWriteFd(handle);
1714 if(fd<0) {
1715 FIXME("handle %d not found.\n",handle);
1716 return FALSE;
1719 if (tcgetattr(fd,&port) == -1) {
1720 commerror=WinError();
1721 close(fd);
1722 return FALSE;
1725 switch (nFunction) {
1726 case RESETDEV:
1727 TRACE("\n");
1728 break;
1730 case CLRDTR:
1731 TRACE("CLRDTR\n");
1732 #ifdef TIOCM_DTR
1733 direct=TRUE;
1734 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1735 break;
1736 #endif
1738 case CLRRTS:
1739 TRACE("CLRRTS\n");
1740 #ifdef TIOCM_RTS
1741 direct=TRUE;
1742 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1743 break;
1744 #endif
1746 case SETDTR:
1747 TRACE("SETDTR\n");
1748 #ifdef TIOCM_DTR
1749 direct=TRUE;
1750 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1751 break;
1752 #endif
1754 case SETRTS:
1755 TRACE("SETRTS\n");
1756 #ifdef TIOCM_DTR
1757 direct=TRUE;
1758 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1759 break;
1760 #endif
1762 case SETXOFF:
1763 TRACE("SETXOFF\n");
1764 port.c_iflag |= IXOFF;
1765 break;
1767 case SETXON:
1768 TRACE("SETXON\n");
1769 port.c_iflag |= IXON;
1770 break;
1771 case SETBREAK:
1772 TRACE("setbreak\n");
1773 #ifdef TIOCSBRK
1774 direct=TRUE;
1775 result = ioctl(fd,TIOCSBRK,0);
1776 break;
1777 #endif
1778 case CLRBREAK:
1779 TRACE("clrbreak\n");
1780 #ifdef TIOCSBRK
1781 direct=TRUE;
1782 result = ioctl(fd,TIOCCBRK,0);
1783 break;
1784 #endif
1785 default:
1786 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1787 handle, nFunction);
1788 break;
1791 if (!direct)
1792 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1793 commerror = WinError();
1794 close(fd);
1795 return FALSE;
1796 } else
1797 result= TRUE;
1798 else
1800 if (result == -1)
1802 result= FALSE;
1803 commerror=WinError();
1805 else
1806 result = TRUE;
1808 close(fd);
1809 return result;
1812 /********************************************************************
1813 * PurgeComm (KERNEL32.557)
1815 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1817 int fd;
1819 TRACE("handle %d, flags %lx\n", handle, flags);
1821 fd = COMM_GetWriteFd(handle);
1822 if(fd<0) {
1823 FIXME("no handle %d found\n",handle);
1824 return FALSE;
1828 ** not exactly sure how these are different
1829 ** Perhaps if we had our own internal queues, one flushes them
1830 ** and the other flushes the kernel's buffers.
1832 if(flags&PURGE_TXABORT)
1833 tcflush(fd,TCOFLUSH);
1834 if(flags&PURGE_RXABORT)
1835 tcflush(fd,TCIFLUSH);
1836 if(flags&PURGE_TXCLEAR)
1837 tcflush(fd,TCOFLUSH);
1838 if(flags&PURGE_RXCLEAR)
1839 tcflush(fd,TCIFLUSH);
1840 close(fd);
1842 return 1;
1845 /*****************************************************************************
1846 * ClearCommError (KERNEL32.21)
1848 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
1850 int fd;
1852 fd=COMM_GetReadFd(handle);
1853 if(0>fd)
1855 FIXME("no handle %d found\n",handle);
1856 return FALSE;
1859 if (lpStat)
1861 lpStat->status = 0;
1863 #ifdef TIOCOUTQ
1864 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1865 WARN("ioctl returned error\n");
1866 #else
1867 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1868 #endif
1870 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1871 WARN("ioctl returned error\n");
1873 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1874 handle, lpStat->cbInQue, lpStat->cbOutQue);
1877 close(fd);
1879 if(errors)
1880 *errors = 0;
1883 ** After an asynchronous write opperation, the
1884 ** app will call ClearCommError to see if the
1885 ** results are ready yet. It waits for ERROR_IO_PENDING
1887 commerror = ERROR_IO_PENDING;
1889 return TRUE;
1892 /*****************************************************************************
1893 * SetupComm (KERNEL32.676)
1895 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1897 int fd;
1899 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1900 fd=COMM_GetWriteFd(handle);
1901 if(0>fd) {
1902 FIXME("handle %d not found?\n",handle);
1903 return FALSE;
1905 close(fd);
1906 return TRUE;
1909 /*****************************************************************************
1910 * GetCommMask (KERNEL32.156)
1912 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1914 int fd;
1916 TRACE("handle %d, mask %p\n", handle, evtmask);
1917 if(0>(fd=COMM_GetReadFd(handle)))
1919 FIXME("no handle %d found\n",handle);
1920 return FALSE;
1922 close(fd);
1923 *evtmask = eventmask;
1924 TRACE("%s%s%s%s%s%s%s%s%s\n",
1925 (eventmask&EV_BREAK)?"EV_BREAK":"",
1926 (eventmask&EV_CTS)?"EV_CTS":"",
1927 (eventmask&EV_DSR)?"EV_DSR":"",
1928 (eventmask&EV_ERR)?"EV_ERR":"",
1929 (eventmask&EV_RING)?"EV_RING":"",
1930 (eventmask&EV_RLSD)?"EV_RLSD":"",
1931 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1932 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1933 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1935 return TRUE;
1938 /*****************************************************************************
1939 * SetCommMask (KERNEL32.451)
1941 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1943 int fd;
1945 TRACE("handle %d, mask %lx\n", handle, evtmask);
1946 TRACE("%s%s%s%s%s%s%s%s%s\n",
1947 (evtmask&EV_BREAK)?"EV_BREAK":"",
1948 (evtmask&EV_CTS)?"EV_CTS":"",
1949 (evtmask&EV_DSR)?"EV_DSR":"",
1950 (evtmask&EV_ERR)?"EV_ERR":"",
1951 (evtmask&EV_RING)?"EV_RING":"",
1952 (evtmask&EV_RLSD)?"EV_RLSD":"",
1953 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1954 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1955 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1957 if(0>(fd=COMM_GetWriteFd(handle))) {
1958 FIXME("no handle %d found\n",handle);
1959 return FALSE;
1961 close(fd);
1962 eventmask = evtmask;
1963 return TRUE;
1966 /*****************************************************************************
1967 * SetCommState (KERNEL32.452)
1969 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1971 struct termios port;
1972 int fd;
1973 int bytesize, stopbits;
1975 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1976 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1977 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1978 (lpdcb->StopBits == ONESTOPBIT)?1:
1979 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1980 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1981 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1983 if ((fd = COMM_GetWriteFd(handle)) < 0) {
1984 FIXME("no handle %d found\n",handle);
1985 return FALSE;
1988 if ((tcgetattr(fd,&port)) == -1) {
1989 int save_error = errno;
1990 commerror = WinError();
1991 close( fd );
1992 #ifdef HAVE_STRERROR
1993 ERR("tcgetattr error '%s'\n", strerror(save_error));
1994 #else
1995 ERR("tcgetattr error %d\n", save_error);
1996 #endif
1997 return FALSE;
2000 port.c_cc[VMIN] = 0;
2001 port.c_cc[VTIME] = 1;
2003 #ifdef IMAXBEL
2004 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
2005 #else
2006 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
2007 #endif
2008 port.c_iflag |= (IGNBRK);
2010 port.c_oflag &= ~(OPOST);
2012 port.c_cflag &= ~(HUPCL);
2013 port.c_cflag |= CLOCAL | CREAD;
2015 port.c_lflag &= ~(ICANON|ECHO|ISIG);
2016 port.c_lflag |= NOFLSH;
2019 ** MJM - removed default baudrate settings
2020 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2022 #ifdef CBAUD
2023 port.c_cflag &= ~CBAUD;
2024 switch (lpdcb->BaudRate) {
2025 case 110:
2026 case CBR_110:
2027 port.c_cflag |= B110;
2028 break;
2029 case 300:
2030 case CBR_300:
2031 port.c_cflag |= B300;
2032 break;
2033 case 600:
2034 case CBR_600:
2035 port.c_cflag |= B600;
2036 break;
2037 case 1200:
2038 case CBR_1200:
2039 port.c_cflag |= B1200;
2040 break;
2041 case 2400:
2042 case CBR_2400:
2043 port.c_cflag |= B2400;
2044 break;
2045 case 4800:
2046 case CBR_4800:
2047 port.c_cflag |= B4800;
2048 break;
2049 case 9600:
2050 case CBR_9600:
2051 port.c_cflag |= B9600;
2052 break;
2053 case 19200:
2054 case CBR_19200:
2055 port.c_cflag |= B19200;
2056 break;
2057 case 38400:
2058 case CBR_38400:
2059 port.c_cflag |= B38400;
2060 break;
2061 #ifdef B57600
2062 case 57600:
2063 port.c_cflag |= B57600;
2064 break;
2065 #endif
2066 #ifdef B115200
2067 case 115200:
2068 port.c_cflag |= B115200;
2069 break;
2070 #endif
2071 #ifdef B230400
2072 case 230400:
2073 port.c_cflag |= B230400;
2074 break;
2075 #endif
2076 #ifdef B460800
2077 case 460600:
2078 port.c_cflag |= B460800;
2079 break;
2080 #endif
2081 default:
2082 commerror = IE_BAUDRATE;
2083 close( fd );
2084 ERR("baudrate %ld\n",lpdcb->BaudRate);
2085 return FALSE;
2087 #elif !defined(__EMX__)
2088 switch (lpdcb->BaudRate) {
2089 case 110:
2090 case CBR_110:
2091 port.c_ospeed = B110;
2092 break;
2093 case 300:
2094 case CBR_300:
2095 port.c_ospeed = B300;
2096 break;
2097 case 600:
2098 case CBR_600:
2099 port.c_ospeed = B600;
2100 break;
2101 case 1200:
2102 case CBR_1200:
2103 port.c_ospeed = B1200;
2104 break;
2105 case 2400:
2106 case CBR_2400:
2107 port.c_ospeed = B2400;
2108 break;
2109 case 4800:
2110 case CBR_4800:
2111 port.c_ospeed = B4800;
2112 break;
2113 case 9600:
2114 case CBR_9600:
2115 port.c_ospeed = B9600;
2116 break;
2117 case 19200:
2118 case CBR_19200:
2119 port.c_ospeed = B19200;
2120 break;
2121 case 38400:
2122 case CBR_38400:
2123 port.c_ospeed = B38400;
2124 break;
2125 default:
2126 commerror = IE_BAUDRATE;
2127 close( fd );
2128 ERR("baudrate %d \n",lpdcb->BaudRate);
2129 return FALSE;
2131 port.c_ispeed = port.c_ospeed;
2132 #endif
2133 bytesize=lpdcb->ByteSize;
2134 stopbits=lpdcb->StopBits;
2136 #ifdef CMSPAR
2137 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
2138 #else
2139 port.c_cflag &= ~(PARENB | PARODD);
2140 #endif
2141 if (lpdcb->fParity)
2142 port.c_iflag |= INPCK;
2143 else
2144 port.c_iflag &= ~INPCK;
2145 switch (lpdcb->Parity) {
2146 case NOPARITY:
2147 break;
2148 case ODDPARITY:
2149 port.c_cflag |= (PARENB | PARODD);
2150 break;
2151 case EVENPARITY:
2152 port.c_cflag |= PARENB;
2153 break;
2154 #ifdef CMSPAR
2155 /* Linux defines mark/space (stick) parity */
2156 case MARKPARITY:
2157 port.c_cflag |= (PARENB | CMSPAR);
2158 break;
2159 case SPACEPARITY:
2160 port.c_cflag |= (PARENB | PARODD | CMSPAR);
2161 break;
2162 #else
2163 /* try the POSIX way */
2164 case MARKPARITY:
2165 if( stopbits == ONESTOPBIT) {
2166 stopbits = TWOSTOPBITS;
2167 port.c_iflag &= ~INPCK;
2168 } else {
2169 commerror = IE_BYTESIZE;
2170 close( fd );
2171 ERR("Cannot set MARK Parity\n");
2172 return FALSE;
2174 break;
2175 case SPACEPARITY:
2176 if( bytesize < 8) {
2177 bytesize +=1;
2178 port.c_iflag &= ~INPCK;
2179 } else {
2180 commerror = IE_BYTESIZE;
2181 close( fd );
2182 ERR("Cannot set SPACE Parity\n");
2183 return FALSE;
2185 break;
2186 #endif
2187 default:
2188 commerror = IE_BYTESIZE;
2189 close( fd );
2190 ERR("Parity\n");
2191 return FALSE;
2195 port.c_cflag &= ~CSIZE;
2196 switch (bytesize) {
2197 case 5:
2198 port.c_cflag |= CS5;
2199 break;
2200 case 6:
2201 port.c_cflag |= CS6;
2202 break;
2203 case 7:
2204 port.c_cflag |= CS7;
2205 break;
2206 case 8:
2207 port.c_cflag |= CS8;
2208 break;
2209 default:
2210 commerror = IE_BYTESIZE;
2211 close( fd );
2212 ERR("ByteSize\n");
2213 return FALSE;
2216 switch (stopbits) {
2217 case ONESTOPBIT:
2218 port.c_cflag &= ~CSTOPB;
2219 break;
2220 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
2221 case TWOSTOPBITS:
2222 port.c_cflag |= CSTOPB;
2223 break;
2224 default:
2225 commerror = IE_BYTESIZE;
2226 close( fd );
2227 ERR("StopBits\n");
2228 return FALSE;
2230 #ifdef CRTSCTS
2231 if ( lpdcb->fOutxCtsFlow ||
2232 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2233 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2236 port.c_cflag |= CRTSCTS;
2237 TRACE("CRTSCTS\n");
2240 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2242 port.c_cflag &= ~CRTSCTS;
2243 TRACE("~CRTSCTS\n");
2246 #endif
2247 if (lpdcb->fInX)
2248 port.c_iflag |= IXON;
2249 else
2250 port.c_iflag &= ~IXON;
2251 if (lpdcb->fOutX)
2252 port.c_iflag |= IXOFF;
2253 else
2254 port.c_iflag &= ~IXOFF;
2256 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2257 int save_error=errno;
2258 commerror = WinError();
2259 close( fd );
2260 #ifdef HAVE_STRERROR
2261 ERR("tcgetattr error '%s'\n", strerror(save_error));
2262 #else
2263 ERR("tcgetattr error %d\n", save_error);
2264 #endif
2265 return FALSE;
2266 } else {
2267 commerror = 0;
2268 close( fd );
2269 return TRUE;
2274 /*****************************************************************************
2275 * GetCommState (KERNEL32.159)
2277 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
2279 struct termios port;
2280 int fd,speed;
2282 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2284 if ((fd = COMM_GetReadFd(handle)) < 0)
2286 ERR("can't get COMM_GetReadFd\n");
2287 return FALSE;
2289 if (tcgetattr(fd, &port) == -1) {
2290 int save_error=errno;
2291 #ifdef HAVE_STRERROR
2292 ERR("tcgetattr error '%s'\n", strerror(save_error));
2293 #else
2294 ERR("tcgetattr error %d\n", save_error);
2295 #endif
2296 commerror = WinError();
2297 close( fd );
2298 return FALSE;
2300 close( fd );
2301 #ifndef __EMX__
2302 #ifdef CBAUD
2303 speed= (port.c_cflag & CBAUD);
2304 #else
2305 speed= (cfgetospeed(&port));
2306 #endif
2307 switch (speed) {
2308 case B110:
2309 lpdcb->BaudRate = 110;
2310 break;
2311 case B300:
2312 lpdcb->BaudRate = 300;
2313 break;
2314 case B600:
2315 lpdcb->BaudRate = 600;
2316 break;
2317 case B1200:
2318 lpdcb->BaudRate = 1200;
2319 break;
2320 case B2400:
2321 lpdcb->BaudRate = 2400;
2322 break;
2323 case B4800:
2324 lpdcb->BaudRate = 4800;
2325 break;
2326 case B9600:
2327 lpdcb->BaudRate = 9600;
2328 break;
2329 case B19200:
2330 lpdcb->BaudRate = 19200;
2331 break;
2332 case B38400:
2333 lpdcb->BaudRate = 38400;
2334 break;
2335 #ifdef B57600
2336 case B57600:
2337 lpdcb->BaudRate = 57600;
2338 break;
2339 #endif
2340 #ifdef B115200
2341 case B115200:
2342 lpdcb->BaudRate = 115200;
2343 break;
2344 #endif
2345 #ifdef B230400
2346 case B230400:
2347 lpdcb->BaudRate = 230400;
2348 break;
2349 #endif
2350 #ifdef B460800
2351 case B460800:
2352 lpdcb->BaudRate = 460800;
2353 break;
2354 #endif
2355 default:
2356 ERR("unknown speed %x \n",speed);
2358 #endif
2359 switch (port.c_cflag & CSIZE) {
2360 case CS5:
2361 lpdcb->ByteSize = 5;
2362 break;
2363 case CS6:
2364 lpdcb->ByteSize = 6;
2365 break;
2366 case CS7:
2367 lpdcb->ByteSize = 7;
2368 break;
2369 case CS8:
2370 lpdcb->ByteSize = 8;
2371 break;
2372 default:
2373 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2376 if(port.c_iflag & INPCK)
2377 lpdcb->fParity = TRUE;
2378 else
2379 lpdcb->fParity = FALSE;
2380 #ifdef CMSPAR
2381 switch (port.c_cflag & (PARENB | PARODD | CMSPAR)) {
2382 #else
2383 switch (port.c_cflag & (PARENB | PARODD)) {
2384 #endif
2385 case 0:
2386 lpdcb->Parity = NOPARITY;
2387 break;
2388 case PARENB:
2389 lpdcb->Parity = EVENPARITY;
2390 break;
2391 case (PARENB | PARODD):
2392 lpdcb->Parity = ODDPARITY;
2393 break;
2394 #ifdef CMSPAR
2395 case (PARENB | CMSPAR):
2396 lpdcb->Parity = MARKPARITY;
2397 break;
2398 case (PARENB | PARODD | CMSPAR):
2399 lpdcb->Parity = SPACEPARITY;
2400 break;
2401 #endif
2404 if (port.c_cflag & CSTOPB)
2405 if(lpdcb->ByteSize == 5)
2406 lpdcb->StopBits = ONE5STOPBITS;
2407 else
2408 lpdcb->StopBits = TWOSTOPBITS;
2409 else
2410 lpdcb->StopBits = ONESTOPBIT;
2412 lpdcb->fNull = 0;
2413 lpdcb->fBinary = 1;
2415 #ifdef CRTSCTS
2417 if (port.c_cflag & CRTSCTS) {
2418 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2419 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2420 lpdcb->fOutxCtsFlow = 1;
2421 lpdcb->fOutxDsrFlow = 1;
2422 } else
2423 #endif
2425 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2426 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2428 if (port.c_iflag & IXON)
2429 lpdcb->fInX = 1;
2430 else
2431 lpdcb->fInX = 0;
2433 if (port.c_iflag & IXOFF)
2434 lpdcb->fOutX = 1;
2435 else
2436 lpdcb->fOutX = 0;
2438 lpdcb->XonChar =
2439 lpdcb->XoffChar =
2441 lpdcb->XonLim = 10;
2442 lpdcb->XoffLim = 10;
2444 commerror = 0;
2446 TRACE("OK\n");
2448 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2449 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2450 (lpdcb->StopBits == ONESTOPBIT)?1:
2451 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2452 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2453 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2454 #ifdef CRTSCTS
2455 if ( lpdcb->fOutxCtsFlow ||
2456 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2457 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2459 TRACE("CRTSCTS\n");
2461 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2462 TRACE("~CRTSCTS\n");
2464 #endif
2465 return TRUE;
2468 /*****************************************************************************
2469 * TransmitCommChar (KERNEL32.535)
2471 BOOL WINAPI TransmitCommChar(INT cid,CHAR chTransmit)
2473 struct DosDeviceStruct *ptr;
2475 FIXME("(%d,'%c'), use win32 handle!\n",cid,chTransmit);
2476 if ((ptr = GetDeviceStruct(cid)) == NULL)
2477 FIXME("no handle for cid = %0x!.\n",cid);
2478 return FALSE;
2480 if (ptr->suspended) {
2481 ptr->commerror = IE_HARDWARE;
2482 return FALSE;
2484 if (write(ptr->fd, (void *) &chTransmit, 1) == -1) {
2485 ptr->commerror = WinError();
2486 return FALSE;
2487 } else {
2488 ptr->commerror = 0;
2489 return TRUE;
2493 /*****************************************************************************
2494 * GetCommTimeouts (KERNEL32.160)
2496 BOOL WINAPI GetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts)
2498 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2499 return TRUE;
2502 /*****************************************************************************
2503 * SetCommTimeouts (KERNEL32.453)
2505 BOOL WINAPI SetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts) {
2506 /* struct DosDeviceStruct *ptr; */
2507 struct termios tios;
2508 int fd;
2510 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2512 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2513 FIXME("no handle for cid = %0x!.\n",hcom);
2514 return FALSE;
2518 fd = COMM_GetWriteFd(hcom);
2519 if (fd < 0) {
2520 FIXME("no fd for cid = %0x!.\n",hcom);
2521 return FALSE;
2525 FIXME("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2526 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts->ReadTotalTimeoutMultiplier);
2527 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts->ReadTotalTimeoutConstant);
2528 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts->WriteTotalTimeoutMultiplier);
2529 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts->WriteTotalTimeoutConstant);
2532 if (-1==tcgetattr(fd,&tios)) {
2533 FIXME("tcgetattr on fd %d failed!\n",fd);
2534 return FALSE;
2536 /* VTIME is in 1/10 seconds */
2537 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2538 if (-1==tcsetattr(fd,0,&tios)) {
2539 FIXME("tcsetattr on fd %d failed!\n",fd);
2540 return FALSE;
2542 return TRUE;
2545 /***********************************************************************
2546 * GetCommModemStatus (KERNEL32.285)
2548 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2550 int fd,mstat, result=FALSE;
2552 *lpModemStat=0;
2553 #ifdef TIOCMGET
2554 fd = COMM_GetWriteFd(hFile);
2555 if(fd<0)
2556 return FALSE;
2557 result = ioctl(fd, TIOCMGET, &mstat);
2558 close(fd);
2559 if (result == -1)
2561 TRACE("ioctl failed\n");
2562 return FALSE;
2564 if (mstat & TIOCM_CTS)
2565 *lpModemStat |= MS_CTS_ON;
2566 if (mstat & TIOCM_DSR)
2567 *lpModemStat |= MS_DSR_ON;
2568 if (mstat & TIOCM_RNG)
2569 *lpModemStat |= MS_RING_ON;
2570 /*FIXME: Not really sure about RLSD UB 990810*/
2571 if (mstat & TIOCM_CAR)
2572 *lpModemStat |= MS_RLSD_ON;
2573 TRACE("%s%s%s%s\n",
2574 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2575 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2576 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2577 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2578 return TRUE;
2579 #else
2580 return FALSE;
2581 #endif
2583 /***********************************************************************
2584 * WaitCommEvent (KERNEL32.719)
2586 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2588 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2589 return TRUE;
2592 /***********************************************************************
2593 * GetCommProperties (KERNEL32.???)
2595 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
2597 FIXME("(%d %p )\n",hFile,dcb);
2598 return TRUE;
2601 /***********************************************************************
2602 * SetCommProperties (KERNEL32.???)
2604 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
2606 FIXME("(%d %p )\n",hFile,dcb);
2607 return TRUE;