Fixed typo in wine_get_unix_file_name().
[wine/multimedia.git] / dlls / kernel / comm.c
blob745ebb5abcc3090fd5ae5f68c13989ff436ceab8
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 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
57 #endif
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
60 #endif
61 #include "heap.h"
62 #include "options.h"
63 #include "wine/port.h"
64 #include "server.h"
65 #include "winerror.h"
66 #include "services.h"
67 #include "callback.h"
68 #include "file.h"
70 #include "debugtools.h"
72 DEFAULT_DEBUG_CHANNEL(comm);
74 #if !defined(TIOCINQ) && defined(FIONREAD)
75 #define TIOCINQ FIONREAD
76 #endif
78 /* window's semi documented modem status register */
79 #define COMM_MSR_OFFSET 35
80 #define MSR_CTS 0x10
81 #define MSR_DSR 0x20
82 #define MSR_RI 0x40
83 #define MSR_RLSD 0x80
84 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
86 #define FLAG_LPT 0x80
88 #ifdef linux
89 #define CMSPAR 0x40000000 /* stick parity */
90 #endif
92 #define MAX_PORTS 9
94 struct DosDeviceStruct {
95 char *devicename; /* /dev/ttyS0 */
96 int fd;
97 int suspended;
98 int unget,xmit;
99 int baudrate;
100 int evtchar;
101 /* events */
102 int commerror, eventmask;
103 /* buffers */
104 char *inbuf,*outbuf;
105 unsigned ibuf_size,ibuf_head,ibuf_tail;
106 unsigned obuf_size,obuf_head,obuf_tail;
107 /* notifications */
108 int wnd, n_read, n_write;
109 HANDLE s_read, s_write;
113 static struct DosDeviceStruct COM[MAX_PORTS];
114 static struct DosDeviceStruct LPT[MAX_PORTS];
115 /* pointers to unknown(==undocumented) comm structure */
116 static LPCVOID *unknown[MAX_PORTS];
117 /* save terminal states */
118 static struct termios m_stat[MAX_PORTS];
120 /* update window's semi documented modem status register */
121 /* see knowledge base Q101417 */
122 static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
124 UCHAR tmpmsr=0;
125 #ifdef TIOCM_CTS
126 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
127 #endif
128 #ifdef TIOCM_DSR
129 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
130 #endif
131 #ifdef TIOCM_RI
132 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
133 #endif
134 #ifdef TIOCM_CAR
135 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
136 #endif
137 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
140 void COMM_Init(void)
142 int x;
143 char option[10], temp[256], *btemp;
144 struct stat st;
146 for (x=0; x!=MAX_PORTS; x++) {
147 strcpy(option,"COMx");
148 option[3] = '1' + x;
149 option[4] = '\0';
151 PROFILE_GetWineIniString( "serialports", option, "*",
152 temp, sizeof(temp) );
153 if (!strcmp(temp, "*") || *temp == '\0')
154 COM[x].devicename = NULL;
155 else {
156 btemp = strchr(temp,',');
157 if (btemp != NULL) {
158 *btemp++ = '\0';
159 COM[x].baudrate = atoi(btemp);
160 } else {
161 COM[x].baudrate = -1;
163 stat(temp, &st);
164 if (!S_ISCHR(st.st_mode))
165 WARN("Can't use `%s' as %s !\n", temp, option);
166 else
167 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
168 WARN("Can't malloc for device info!\n");
169 else {
170 COM[x].fd = 0;
171 strcpy(COM[x].devicename, temp);
173 TRACE("%s = %s\n", option, COM[x].devicename);
176 strcpy(option, "LPTx");
177 option[3] = '1' + x;
178 option[4] = '\0';
180 PROFILE_GetWineIniString( "parallelports", option, "*",
181 temp, sizeof(temp) );
182 if (!strcmp(temp, "*") || *temp == '\0')
183 LPT[x].devicename = NULL;
184 else {
185 stat(temp, &st);
186 if (!S_ISCHR(st.st_mode))
187 WARN("Can't use `%s' as %s !\n", temp, option);
188 else
189 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
190 WARN("Can't malloc for device info!\n");
191 else {
192 LPT[x].fd = 0;
193 strcpy(LPT[x].devicename, temp);
195 TRACE("%s = %s\n", option, LPT[x].devicename);
202 static struct DosDeviceStruct *GetDeviceStruct(int fd)
204 if ((fd&0x7F)<=MAX_PORTS) {
205 if (!(fd&FLAG_LPT)) {
206 if (COM[fd].fd)
207 return &COM[fd];
208 } else {
209 fd &= 0x7f;
210 if (LPT[fd].fd)
211 return &LPT[fd];
215 return NULL;
218 static int GetCommPort_fd(int fd)
220 int x;
222 for (x=0; x<MAX_PORTS; x++) {
223 if (COM[x].fd == fd)
224 return x;
227 return -1;
230 static int ValidCOMPort(int x)
232 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
235 static int ValidLPTPort(int x)
237 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
240 static int WinError(void)
242 TRACE("errno = %d\n", errno);
243 switch (errno) {
244 default:
245 return CE_IOE;
249 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
251 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
252 + ptr->ibuf_head - ptr->ibuf_tail;
255 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
257 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
258 + ptr->obuf_head - ptr->obuf_tail;
261 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
263 unsigned int mstat, okay;
264 okay = ioctl(fd, TIOCMGET, &mstat);
265 if (okay) return okay;
266 if (andy) mstat &= andy;
267 mstat |= orrie;
268 return ioctl(fd, TIOCMSET, &mstat);
271 static void CALLBACK comm_notification( ULONG_PTR private )
273 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
274 int prev, bleft, len;
275 WORD mask = 0;
276 int cid = GetCommPort_fd(ptr->fd);
278 TRACE("async notification\n");
279 /* read data from comm port */
280 prev = comm_inbuf(ptr);
281 do {
282 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
283 - ptr->ibuf_head;
284 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
285 if (len > 0) {
286 if (!bleft) {
287 ptr->commerror = CE_RXOVER;
288 } else {
289 /* check for events */
290 if ((ptr->eventmask & EV_RXFLAG) &&
291 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
292 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
293 mask |= CN_EVENT;
295 if (ptr->eventmask & EV_RXCHAR) {
296 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
297 mask |= CN_EVENT;
299 /* advance buffer position */
300 ptr->ibuf_head += len;
301 if (ptr->ibuf_head >= ptr->ibuf_size)
302 ptr->ibuf_head = 0;
305 } while (len > 0);
306 /* check for notification */
307 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
308 (comm_inbuf(ptr)>=ptr->n_read)) {
309 /* passed the receive notification threshold */
310 mask |= CN_RECEIVE;
313 /* write any TransmitCommChar character */
314 if (ptr->xmit>=0) {
315 len = write(ptr->fd, &(ptr->xmit), 1);
316 if (len > 0) ptr->xmit = -1;
318 /* write from output queue */
319 prev = comm_outbuf(ptr);
320 do {
321 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
322 - ptr->obuf_tail;
323 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
324 if (len > 0) {
325 ptr->obuf_tail += len;
326 if (ptr->obuf_tail >= ptr->obuf_size)
327 ptr->obuf_tail = 0;
328 /* flag event */
329 if (ptr->obuf_tail == ptr->obuf_head) {
330 if (ptr->s_write) {
331 SERVICE_Delete( ptr->s_write );
332 ptr->s_write = INVALID_HANDLE_VALUE;
334 if (ptr->eventmask & EV_TXEMPTY) {
335 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
336 mask |= CN_EVENT;
340 } while (len > 0);
341 /* check for notification */
342 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
343 (comm_outbuf(ptr)<ptr->n_write)) {
344 /* passed the transmit notification threshold */
345 mask |= CN_TRANSMIT;
348 /* send notifications, if any */
349 if (ptr->wnd && mask) {
350 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
351 if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
355 static void comm_waitread(struct DosDeviceStruct *ptr)
357 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
358 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
359 GENERIC_READ | SYNCHRONIZE ),
360 comm_notification,
361 (ULONG_PTR)ptr );
364 static void comm_waitwrite(struct DosDeviceStruct *ptr)
366 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
367 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
368 GENERIC_WRITE | SYNCHRONIZE ),
369 comm_notification,
370 (ULONG_PTR)ptr );
373 /**************************************************************************
374 * BuildCommDCB16 (USER.213)
376 * According to the ECMA-234 (368.3) the function will return FALSE on
377 * success, otherwise it will return -1.
378 * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA
379 * NEEDS TO BE FIXED
381 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
383 /* "COM1:9600,n,8,1" */
384 /* 012345 */
385 int port;
386 char *ptr, temp[256];
388 TRACE("(%s), ptr %p\n", device, lpdcb);
390 if (!strncasecmp(device,"COM",3)) {
391 port = device[3] - '0';
394 if (port-- == 0) {
395 ERR("BUG ! COM0 can't exist!\n");
396 return -1;
399 if (!ValidCOMPort(port)) {
400 FIXME("invalid COM port %d?\n",port);
401 return -1;
404 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
406 lpdcb->Id = port;
408 if (!*(device+4))
409 return 0;
411 if (*(device+4) != ':')
412 return -1;
414 strcpy(temp,device+5);
415 ptr = strtok(temp, ", ");
417 if (COM[port].baudrate > 0)
418 lpdcb->BaudRate = COM[port].baudrate;
419 else
420 lpdcb->BaudRate = atoi(ptr);
421 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
423 ptr = strtok(NULL, ", ");
424 if (islower(*ptr))
425 *ptr = toupper(*ptr);
427 TRACE("parity (%c)\n", *ptr);
428 lpdcb->fParity = TRUE;
429 switch (*ptr) {
430 case 'N':
431 lpdcb->Parity = NOPARITY;
432 lpdcb->fParity = FALSE;
433 break;
434 case 'E':
435 lpdcb->Parity = EVENPARITY;
436 break;
437 case 'M':
438 lpdcb->Parity = MARKPARITY;
439 break;
440 case 'O':
441 lpdcb->Parity = ODDPARITY;
442 break;
443 default:
444 WARN("Unknown parity `%c'!\n", *ptr);
445 return -1;
448 ptr = strtok(NULL, ", ");
449 TRACE("charsize (%c)\n", *ptr);
450 lpdcb->ByteSize = *ptr - '0';
452 ptr = strtok(NULL, ", ");
453 TRACE("stopbits (%c)\n", *ptr);
454 switch (*ptr) {
455 case '1':
456 lpdcb->StopBits = ONESTOPBIT;
457 break;
458 case '2':
459 lpdcb->StopBits = TWOSTOPBITS;
460 break;
461 default:
462 WARN("Unknown # of stopbits `%c'!\n", *ptr);
463 return -1;
467 return 0;
470 /*****************************************************************************
471 * OpenComm16 (USER.200)
473 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
475 int port,fd;
477 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
479 if (strlen(device) < 4)
480 return IE_BADID;
482 port = device[3] - '0';
484 if (port-- == 0)
485 ERR("BUG ! COM0 or LPT0 don't exist !\n");
487 if (!strncasecmp(device,"COM",3)) {
489 TRACE("%s = %s\n", device, COM[port].devicename);
491 if (!ValidCOMPort(port))
492 return IE_BADID;
494 if (COM[port].fd)
495 return IE_OPEN;
497 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
498 if (fd == -1) {
499 ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno));
500 return IE_HARDWARE;
501 } else {
502 unknown[port] = SEGPTR_ALLOC(40);
503 bzero(unknown[port],40);
504 COM[port].fd = fd;
505 COM[port].commerror = 0;
506 COM[port].eventmask = 0;
507 COM[port].evtchar = 0; /* FIXME: default? */
508 /* save terminal state */
509 tcgetattr(fd,&m_stat[port]);
510 /* set default parameters */
511 if(COM[port].baudrate>-1){
512 DCB16 dcb;
513 GetCommState16(port, &dcb);
514 dcb.BaudRate=COM[port].baudrate;
515 /* more defaults:
516 * databits, parity, stopbits
518 SetCommState16( &dcb);
520 /* init priority characters */
521 COM[port].unget = -1;
522 COM[port].xmit = -1;
523 /* allocate buffers */
524 COM[port].ibuf_size = cbInQueue;
525 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
526 COM[port].obuf_size = cbOutQueue;
527 COM[port].obuf_head = COM[port].obuf_tail = 0;
529 COM[port].inbuf = malloc(cbInQueue);
530 if (COM[port].inbuf) {
531 COM[port].outbuf = malloc(cbOutQueue);
532 if (!COM[port].outbuf)
533 free(COM[port].inbuf);
534 } else COM[port].outbuf = NULL;
535 if (!COM[port].outbuf) {
536 /* not enough memory */
537 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
538 close(COM[port].fd);
539 ERR("out of memory\n");
540 return IE_MEMORY;
543 COM[port].s_read = INVALID_HANDLE_VALUE;
544 COM[port].s_write = INVALID_HANDLE_VALUE;
545 comm_waitread( &COM[port] );
546 return port;
549 else
550 if (!strncasecmp(device,"LPT",3)) {
552 if (!ValidLPTPort(port))
553 return IE_BADID;
555 if (LPT[port].fd)
556 return IE_OPEN;
558 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
559 if (fd == -1) {
560 return IE_HARDWARE;
561 } else {
562 LPT[port].fd = fd;
563 LPT[port].commerror = 0;
564 LPT[port].eventmask = 0;
565 return port|FLAG_LPT;
568 return 0;
571 /*****************************************************************************
572 * CloseComm16 (USER.207)
574 INT16 WINAPI CloseComm16(INT16 cid)
576 struct DosDeviceStruct *ptr;
578 TRACE("cid=%d\n", cid);
579 if ((ptr = GetDeviceStruct(cid)) == NULL) {
580 FIXME("no cid=%d found!\n", cid);
581 return -1;
583 if (!(cid&FLAG_LPT)) {
584 /* COM port */
585 SEGPTR_FREE(unknown[cid]); /* [LW] */
587 SERVICE_Delete( COM[cid].s_write );
588 SERVICE_Delete( COM[cid].s_read );
589 /* free buffers */
590 free(ptr->outbuf);
591 free(ptr->inbuf);
593 /* reset modem lines */
594 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
597 if (close(ptr->fd) == -1) {
598 ptr->commerror = WinError();
599 /* FIXME: should we clear ptr->fd here? */
600 return -1;
601 } else {
602 ptr->commerror = 0;
603 ptr->fd = 0;
604 return 0;
608 /*****************************************************************************
609 * SetCommBreak16 (USER.210)
611 INT16 WINAPI SetCommBreak16(INT16 cid)
613 struct DosDeviceStruct *ptr;
615 TRACE("cid=%d\n", cid);
616 if ((ptr = GetDeviceStruct(cid)) == NULL) {
617 FIXME("no cid=%d found!\n", cid);
618 return -1;
621 ptr->suspended = 1;
622 ptr->commerror = 0;
623 return 0;
626 /*****************************************************************************
627 * ClearCommBreak16 (USER.211)
629 INT16 WINAPI ClearCommBreak16(INT16 cid)
631 struct DosDeviceStruct *ptr;
633 TRACE("cid=%d\n", cid);
634 if (!(ptr = GetDeviceStruct(cid))) {
635 FIXME("no cid=%d found!\n", cid);
636 return -1;
638 ptr->suspended = 0;
639 ptr->commerror = 0;
640 return 0;
643 /*****************************************************************************
644 * EscapeCommFunction16 (USER.214)
646 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
648 int max;
649 struct DosDeviceStruct *ptr;
650 struct termios port;
652 TRACE("cid=%d, function=%d\n", cid, nFunction);
653 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
654 if ((ptr = GetDeviceStruct(cid)) == NULL) {
655 FIXME("no cid=%d found!\n", cid);
656 return -1;
658 if (tcgetattr(ptr->fd,&port) == -1) {
659 TRACE("tcgetattr failed\n");
660 ptr->commerror=WinError();
661 return -1;
663 } else ptr = NULL;
665 switch (nFunction) {
666 case RESETDEV:
667 TRACE("RESETDEV\n");
668 break;
670 case GETMAXCOM:
671 TRACE("GETMAXCOM\n");
672 for (max = MAX_PORTS;!COM[max].devicename;max--)
674 return max;
675 break;
677 case GETMAXLPT:
678 TRACE("GETMAXLPT\n");
679 for (max = MAX_PORTS;!LPT[max].devicename;max--)
681 return FLAG_LPT + max;
682 break;
684 case GETBASEIRQ:
685 TRACE("GETBASEIRQ\n");
686 /* FIXME: use tables */
687 /* just fake something for now */
688 if (cid & FLAG_LPT) {
689 /* LPT1: irq 7, LPT2: irq 5 */
690 return (cid & 0x7f) ? 5 : 7;
691 } else {
692 /* COM1: irq 4, COM2: irq 3,
693 COM3: irq 4, COM4: irq 3 */
694 return 4 - (cid & 1);
696 break;
698 case CLRDTR:
699 TRACE("CLRDTR\n");
700 #ifdef TIOCM_DTR
701 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
702 #endif
703 case CLRRTS:
704 TRACE("CLRRTS\n");
705 #ifdef TIOCM_RTS
706 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
707 #endif
709 case SETDTR:
710 TRACE("SETDTR\n");
711 #ifdef TIOCM_DTR
712 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
713 #endif
715 case SETRTS:
716 TRACE("SETRTS\n");
717 #ifdef TIOCM_RTS
718 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
719 #endif
721 case SETXOFF:
722 TRACE("SETXOFF\n");
723 port.c_iflag |= IXOFF;
724 break;
726 case SETXON:
727 TRACE("SETXON\n");
728 port.c_iflag |= IXON;
729 break;
731 default:
732 WARN("(cid=%d,nFunction=%d): Unknown function\n",
733 cid, nFunction);
734 break;
737 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
738 ptr->commerror = WinError();
739 return -1;
740 } else {
741 ptr->commerror = 0;
742 return 0;
746 /*****************************************************************************
747 * FlushComm16 (USER.215)
749 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
751 int queue;
752 struct DosDeviceStruct *ptr;
754 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
755 if ((ptr = GetDeviceStruct(cid)) == NULL) {
756 FIXME("no cid=%d found!\n", cid);
757 return -1;
759 switch (fnQueue) {
760 case 0:
761 queue = TCOFLUSH;
762 ptr->obuf_tail = ptr->obuf_head;
763 break;
764 case 1:
765 queue = TCIFLUSH;
766 ptr->ibuf_head = ptr->ibuf_tail;
767 break;
768 default:
769 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
770 cid, fnQueue);
771 return -1;
773 if (tcflush(ptr->fd, queue)) {
774 ptr->commerror = WinError();
775 return -1;
776 } else {
777 ptr->commerror = 0;
778 return 0;
782 /********************************************************************
783 * GetCommError16 (USER.203)
785 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
787 int temperror;
788 struct DosDeviceStruct *ptr;
789 unsigned char *stol;
790 unsigned int mstat;
792 if ((ptr = GetDeviceStruct(cid)) == NULL) {
793 FIXME("no handle for cid = %0x!\n",cid);
794 return -1;
796 if (cid&FLAG_LPT) {
797 WARN(" cid %d not comm port\n",cid);
798 return CE_MODE;
800 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
801 ioctl(ptr->fd,TIOCMGET,&mstat);
802 COMM_MSRUpdate( stol, mstat);
804 if (lpStat) {
805 lpStat->status = 0;
807 lpStat->cbOutQue = comm_outbuf(ptr);
808 lpStat->cbInQue = comm_inbuf(ptr);
810 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
811 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
812 lpStat->cbOutQue, *stol);
814 else
815 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
816 cid, ptr->commerror, *stol);
818 /* Return any errors and clear it */
819 temperror = ptr->commerror;
820 ptr->commerror = 0;
821 return(temperror);
824 /*****************************************************************************
825 * SetCommEventMask16 (USER.208)
827 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
829 struct DosDeviceStruct *ptr;
830 unsigned char *stol;
831 int repid;
832 unsigned int mstat;
834 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
835 if ((ptr = GetDeviceStruct(cid)) == NULL) {
836 FIXME("no handle for cid = %0x!\n",cid);
837 return (SEGPTR)NULL;
840 ptr->eventmask = fuEvtMask;
842 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
843 WARN(" cid %d not comm port\n",cid);
844 return (SEGPTR)NULL;
846 /* it's a COM port ? -> modify flags */
847 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
848 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
849 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
850 COMM_MSRUpdate( stol, mstat);
852 TRACE(" modem dcd construct %x\n",*stol);
853 return SEGPTR_GET(unknown[cid]);
856 /*****************************************************************************
857 * GetCommEventMask16 (USER.209)
859 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
861 struct DosDeviceStruct *ptr;
862 WORD events;
864 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
865 if ((ptr = GetDeviceStruct(cid)) == NULL) {
866 FIXME("no handle for cid = %0x!\n",cid);
867 return 0;
870 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
871 WARN(" cid %d not comm port\n",cid);
872 return 0;
875 events = *(WORD*)(unknown[cid]) & fnEvtClear;
876 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
877 return events;
880 /*****************************************************************************
881 * SetCommState16 (USER.201)
883 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
885 struct termios port;
886 struct DosDeviceStruct *ptr;
887 int bytesize, stopbits;
888 int fail=0;
890 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
891 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
892 FIXME("no handle for cid = %0x!\n",lpdcb->Id);
893 return -1;
895 if (tcgetattr(ptr->fd, &port) == -1) {
896 ptr->commerror = WinError();
897 return -1;
900 port.c_cc[VMIN] = 0;
901 port.c_cc[VTIME] = 1;
903 #ifdef IMAXBEL
904 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
905 #else
906 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
907 #endif
908 port.c_iflag |= (IGNBRK);
910 port.c_oflag &= ~(OPOST);
912 port.c_cflag &= ~(HUPCL);
913 port.c_cflag |= CLOCAL | CREAD;
915 port.c_lflag &= ~(ICANON|ECHO|ISIG);
916 port.c_lflag |= NOFLSH;
918 TRACE("baudrate %d\n",lpdcb->BaudRate);
919 #ifdef CBAUD
920 port.c_cflag &= ~CBAUD;
921 switch (lpdcb->BaudRate) {
922 case 110:
923 case CBR_110:
924 port.c_cflag |= B110;
925 break;
926 case 300:
927 case CBR_300:
928 port.c_cflag |= B300;
929 break;
930 case 600:
931 case CBR_600:
932 port.c_cflag |= B600;
933 break;
934 case 1200:
935 case CBR_1200:
936 port.c_cflag |= B1200;
937 break;
938 case 2400:
939 case CBR_2400:
940 port.c_cflag |= B2400;
941 break;
942 case 4800:
943 case CBR_4800:
944 port.c_cflag |= B4800;
945 break;
946 case 9600:
947 case CBR_9600:
948 port.c_cflag |= B9600;
949 break;
950 case 19200:
951 case CBR_19200:
952 port.c_cflag |= B19200;
953 break;
954 case 38400:
955 case CBR_38400:
956 port.c_cflag |= B38400;
957 break;
958 #ifdef B57600
959 case 57600:
960 port.c_cflag |= B57600;
961 break;
962 #endif
963 #ifdef B115200
964 case 57601:
965 port.c_cflag |= B115200;
966 break;
967 #endif
968 default:
969 ptr->commerror = IE_BAUDRATE;
970 fail=1;
972 #elif !defined(__EMX__)
973 switch (lpdcb->BaudRate) {
974 case 110:
975 case CBR_110:
976 port.c_ospeed = B110;
977 break;
978 case 300:
979 case CBR_300:
980 port.c_ospeed = B300;
981 break;
982 case 600:
983 case CBR_600:
984 port.c_ospeed = B600;
985 break;
986 case 1200:
987 case CBR_1200:
988 port.c_ospeed = B1200;
989 break;
990 case 2400:
991 case CBR_2400:
992 port.c_ospeed = B2400;
993 break;
994 case 4800:
995 case CBR_4800:
996 port.c_ospeed = B4800;
997 break;
998 case 9600:
999 case CBR_9600:
1000 port.c_ospeed = B9600;
1001 break;
1002 case 19200:
1003 case CBR_19200:
1004 port.c_ospeed = B19200;
1005 break;
1006 case 38400:
1007 case CBR_38400:
1008 port.c_ospeed = B38400;
1009 break;
1010 default:
1011 ptr->commerror = IE_BAUDRATE;
1012 fail=1;
1014 port.c_ispeed = port.c_ospeed;
1015 #endif
1016 bytesize=lpdcb->ByteSize;
1017 stopbits=lpdcb->StopBits;
1019 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
1020 #ifdef CMSPAR
1021 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1022 #else
1023 port.c_cflag &= ~(PARENB | PARODD);
1024 #endif
1025 if (lpdcb->fParity)
1026 port.c_iflag |= INPCK;
1027 else
1028 port.c_iflag &= ~INPCK;
1029 switch (lpdcb->Parity) {
1030 case NOPARITY:
1031 break;
1032 case ODDPARITY:
1033 port.c_cflag |= (PARENB | PARODD);
1034 break;
1035 case EVENPARITY:
1036 port.c_cflag |= PARENB;
1037 break;
1038 #ifdef CMSPAR
1039 /* Linux defines mark/space (stick) parity */
1040 case MARKPARITY:
1041 port.c_cflag |= (PARENB | CMSPAR);
1042 break;
1043 case SPACEPARITY:
1044 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1045 break;
1046 #else
1047 /* try the POSIX way */
1048 case MARKPARITY:
1049 if( stopbits == ONESTOPBIT) {
1050 stopbits = TWOSTOPBITS;
1051 port.c_iflag &= ~INPCK;
1052 } else {
1053 ptr->commerror = IE_BYTESIZE;
1054 fail=1;
1056 break;
1057 case SPACEPARITY:
1058 if( bytesize < 8) {
1059 bytesize +=1;
1060 port.c_iflag &= ~INPCK;
1061 } else {
1062 ptr->commerror = IE_BYTESIZE;
1063 fail=1;
1065 break;
1066 #endif
1067 default:
1068 ptr->commerror = IE_BYTESIZE;
1069 fail=1;
1072 TRACE("bytesize %d\n",bytesize);
1073 port.c_cflag &= ~CSIZE;
1074 switch (bytesize) {
1075 case 5:
1076 port.c_cflag |= CS5;
1077 break;
1078 case 6:
1079 port.c_cflag |= CS6;
1080 break;
1081 case 7:
1082 port.c_cflag |= CS7;
1083 break;
1084 case 8:
1085 port.c_cflag |= CS8;
1086 break;
1087 default:
1088 ptr->commerror = IE_BYTESIZE;
1089 fail=1;
1092 TRACE("stopbits %d\n",stopbits);
1094 switch (stopbits) {
1095 case ONESTOPBIT:
1096 port.c_cflag &= ~CSTOPB;
1097 break;
1098 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1099 case TWOSTOPBITS:
1100 port.c_cflag |= CSTOPB;
1101 break;
1102 default:
1103 ptr->commerror = IE_BYTESIZE;
1104 fail=1;
1106 #ifdef CRTSCTS
1108 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1109 port.c_cflag |= CRTSCTS;
1111 if (lpdcb->fDtrDisable)
1112 port.c_cflag &= ~CRTSCTS;
1113 #endif
1114 if (lpdcb->fInX)
1115 port.c_iflag |= IXON;
1116 else
1117 port.c_iflag &= ~IXON;
1118 if (lpdcb->fOutX)
1119 port.c_iflag |= IXOFF;
1120 else
1121 port.c_iflag &= ~IXOFF;
1123 ptr->evtchar = lpdcb->EvtChar;
1125 if(fail)
1126 return -1;
1128 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1129 ptr->commerror = WinError();
1130 return -1;
1131 } else {
1132 ptr->commerror = 0;
1133 return 0;
1137 /*****************************************************************************
1138 * GetCommState16 (USER.202)
1140 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1142 int speed;
1143 struct DosDeviceStruct *ptr;
1144 struct termios port;
1146 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1147 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1148 FIXME("no handle for cid = %0x!\n",cid);
1149 return -1;
1151 if (tcgetattr(ptr->fd, &port) == -1) {
1152 ptr->commerror = WinError();
1153 return -1;
1155 lpdcb->Id = cid;
1156 #ifndef __EMX__
1157 #ifdef CBAUD
1158 speed = port.c_cflag & CBAUD;
1159 #else
1160 speed = port.c_ospeed;
1161 #endif
1162 switch(speed) {
1163 case B110:
1164 lpdcb->BaudRate = 110;
1165 break;
1166 case B300:
1167 lpdcb->BaudRate = 300;
1168 break;
1169 case B600:
1170 lpdcb->BaudRate = 600;
1171 break;
1172 case B1200:
1173 lpdcb->BaudRate = 1200;
1174 break;
1175 case B2400:
1176 lpdcb->BaudRate = 2400;
1177 break;
1178 case B4800:
1179 lpdcb->BaudRate = 4800;
1180 break;
1181 case B9600:
1182 lpdcb->BaudRate = 9600;
1183 break;
1184 case B19200:
1185 lpdcb->BaudRate = 19200;
1186 break;
1187 case B38400:
1188 lpdcb->BaudRate = 38400;
1189 break;
1190 #ifdef B57600
1191 case B57600:
1192 lpdcb->BaudRate = 57600;
1193 break;
1194 #endif
1195 #ifdef B115200
1196 case B115200:
1197 lpdcb->BaudRate = 57601;
1198 break;
1199 #endif
1201 #endif
1202 switch (port.c_cflag & CSIZE) {
1203 case CS5:
1204 lpdcb->ByteSize = 5;
1205 break;
1206 case CS6:
1207 lpdcb->ByteSize = 6;
1208 break;
1209 case CS7:
1210 lpdcb->ByteSize = 7;
1211 break;
1212 case CS8:
1213 lpdcb->ByteSize = 8;
1214 break;
1217 if(port.c_iflag & INPCK)
1218 lpdcb->fParity = TRUE;
1219 else
1220 lpdcb->fParity = FALSE;
1221 #ifdef CMSPAR
1222 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1223 #else
1224 switch (port.c_cflag & (PARENB | PARODD))
1225 #endif
1227 case 0:
1228 lpdcb->Parity = NOPARITY;
1229 break;
1230 case PARENB:
1231 lpdcb->Parity = EVENPARITY;
1232 break;
1233 case (PARENB | PARODD):
1234 lpdcb->Parity = ODDPARITY;
1235 break;
1236 #ifdef CMSPAR
1237 case (PARENB | CMSPAR):
1238 lpdcb->Parity = MARKPARITY;
1239 break;
1240 case (PARENB | PARODD | CMSPAR):
1241 lpdcb->Parity = SPACEPARITY;
1242 break;
1243 #endif
1246 if (port.c_cflag & CSTOPB)
1247 if(lpdcb->ByteSize == 5)
1248 lpdcb->StopBits = ONE5STOPBITS;
1249 else
1250 lpdcb->StopBits = TWOSTOPBITS;
1251 else
1252 lpdcb->StopBits = ONESTOPBIT;
1254 lpdcb->RlsTimeout = 50;
1255 lpdcb->CtsTimeout = 50;
1256 lpdcb->DsrTimeout = 50;
1257 lpdcb->fNull = 0;
1258 lpdcb->fChEvt = 0;
1259 lpdcb->fBinary = 1;
1260 lpdcb->fDtrDisable = 0;
1262 #ifdef CRTSCTS
1264 if (port.c_cflag & CRTSCTS) {
1265 lpdcb->fDtrflow = 1;
1266 lpdcb->fRtsflow = 1;
1267 lpdcb->fOutxCtsFlow = 1;
1268 lpdcb->fOutxDsrFlow = 1;
1269 } else
1270 #endif
1271 lpdcb->fDtrDisable = 1;
1273 if (port.c_iflag & IXON)
1274 lpdcb->fInX = 1;
1275 else
1276 lpdcb->fInX = 0;
1278 if (port.c_iflag & IXOFF)
1279 lpdcb->fOutX = 1;
1280 else
1281 lpdcb->fOutX = 0;
1283 lpdcb->XonChar =
1284 lpdcb->XoffChar =
1286 lpdcb->XonLim = 10;
1287 lpdcb->XoffLim = 10;
1289 lpdcb->EvtChar = ptr->evtchar;
1291 ptr->commerror = 0;
1292 return 0;
1295 /*****************************************************************************
1296 * TransmitCommChar16 (USER.206)
1298 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1300 struct DosDeviceStruct *ptr;
1302 TRACE("cid %d, data %d \n", cid, chTransmit);
1303 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1304 FIXME("no handle for cid = %0x!\n",cid);
1305 return -1;
1308 if (ptr->suspended) {
1309 ptr->commerror = IE_HARDWARE;
1310 return -1;
1313 if (ptr->xmit >= 0) {
1314 /* character already queued */
1315 /* FIXME: which error would Windows return? */
1316 ptr->commerror = CE_TXFULL;
1317 return -1;
1320 if (ptr->obuf_head == ptr->obuf_tail) {
1321 /* transmit queue empty, try to transmit directly */
1322 if (write(ptr->fd, &chTransmit, 1) == -1) {
1323 /* didn't work, queue it */
1324 ptr->xmit = chTransmit;
1325 comm_waitwrite(ptr);
1327 } else {
1328 /* data in queue, let this char be transmitted next */
1329 ptr->xmit = chTransmit;
1330 comm_waitwrite(ptr);
1333 ptr->commerror = 0;
1334 return 0;
1337 /*****************************************************************************
1338 * UngetCommChar16 (USER.212)
1340 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1342 struct DosDeviceStruct *ptr;
1344 TRACE("cid %d (char %d)\n", cid, chUnget);
1345 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1346 FIXME("no handle for cid = %0x!\n",cid);
1347 return -1;
1350 if (ptr->suspended) {
1351 ptr->commerror = IE_HARDWARE;
1352 return -1;
1355 if (ptr->unget>=0) {
1356 /* character already queued */
1357 /* FIXME: which error would Windows return? */
1358 ptr->commerror = CE_RXOVER;
1359 return -1;
1362 ptr->unget = chUnget;
1364 ptr->commerror = 0;
1365 return 0;
1368 /*****************************************************************************
1369 * ReadComm16 (USER.204)
1371 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1373 int status, length;
1374 struct DosDeviceStruct *ptr;
1375 LPSTR orgBuf = lpvBuf;
1377 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1378 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1379 FIXME("no handle for cid = %0x!\n",cid);
1380 return -1;
1383 if (ptr->suspended) {
1384 ptr->commerror = IE_HARDWARE;
1385 return -1;
1388 /* read unget character */
1389 if (ptr->unget>=0) {
1390 *lpvBuf++ = ptr->unget;
1391 ptr->unget = -1;
1393 length = 1;
1394 } else
1395 length = 0;
1397 /* read from receive buffer */
1398 while (length < cbRead) {
1399 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1400 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1401 if (!status) break;
1402 if ((cbRead - length) < status)
1403 status = cbRead - length;
1405 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1406 ptr->ibuf_tail += status;
1407 if (ptr->ibuf_tail >= ptr->ibuf_size)
1408 ptr->ibuf_tail = 0;
1409 lpvBuf += status;
1410 length += status;
1413 TRACE("%.*s\n", length, orgBuf);
1414 ptr->commerror = 0;
1415 return length;
1418 /*****************************************************************************
1419 * WriteComm16 (USER.205)
1421 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1423 int status, length;
1424 struct DosDeviceStruct *ptr;
1426 TRACE("cid %d, ptr %p, length %d\n",
1427 cid, lpvBuf, cbWrite);
1428 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1429 FIXME("no handle for cid = %0x!\n",cid);
1430 return -1;
1433 if (ptr->suspended) {
1434 ptr->commerror = IE_HARDWARE;
1435 return -1;
1438 TRACE("%.*s\n", cbWrite, lpvBuf );
1440 length = 0;
1441 while (length < cbWrite) {
1442 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1443 /* no data queued, try to write directly */
1444 status = write(ptr->fd, lpvBuf, cbWrite - length);
1445 if (status > 0) {
1446 lpvBuf += status;
1447 length += status;
1448 continue;
1451 /* can't write directly, put into transmit buffer */
1452 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1453 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1454 if (!status) break;
1455 if ((cbWrite - length) < status)
1456 status = cbWrite - length;
1457 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1458 ptr->obuf_head += status;
1459 if (ptr->obuf_head >= ptr->obuf_size)
1460 ptr->obuf_head = 0;
1461 lpvBuf += status;
1462 length += status;
1463 comm_waitwrite(ptr);
1466 ptr->commerror = 0;
1467 return length;
1470 /***********************************************************************
1471 * EnableCommNotification16 (USER.246)
1473 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1474 INT16 cbWriteNotify, INT16 cbOutQueue )
1476 struct DosDeviceStruct *ptr;
1478 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1479 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1480 FIXME("no handle for cid = %0x!\n",cid);
1481 return -1;
1483 ptr->wnd = hwnd;
1484 ptr->n_read = cbWriteNotify;
1485 ptr->n_write = cbOutQueue;
1486 return TRUE;
1490 /**************************************************************************
1491 * BuildCommDCBA (KERNEL32.14)
1493 * Updates a device control block data structure with values from an
1494 * ascii device control string. The device control string has two forms
1495 * normal and extended, it must be exclusively in one or the other form.
1497 * RETURNS
1499 * True on success, false on an malformed control string.
1501 BOOL WINAPI BuildCommDCBA(
1502 LPCSTR device, /* The ascii device control string used to update the DCB. */
1503 LPDCB lpdcb /* The device control block to be updated. */)
1505 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1508 /**************************************************************************
1509 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1511 * Updates a device control block data structure with values from an
1512 * ascii device control string. Taking time out values from a time outs
1513 * struct if desired by the control string.
1515 * RETURNS
1517 * True on success, false bad handles etc
1519 BOOL WINAPI BuildCommDCBAndTimeoutsA(
1520 LPCSTR device, /* The ascii device control string. */
1521 LPDCB lpdcb, /* The device control block to be updated. */
1522 LPCOMMTIMEOUTS lptimeouts /* The time outs to use if asked to set them by the control string. */)
1524 int port;
1525 char *ptr,*temp;
1527 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1529 if (!strncasecmp(device,"COM",3)) {
1530 port=device[3]-'0';
1531 if (port--==0) {
1532 ERR("BUG! COM0 can't exist!\n");
1533 return FALSE;
1535 if (!ValidCOMPort(port))
1536 return FALSE;
1537 if (*(device+4)!=':')
1538 return FALSE;
1539 temp=(LPSTR)(device+5);
1540 } else
1541 temp=(LPSTR)device;
1543 lpdcb->DCBlength = sizeof(DCB);
1544 if (strchr(temp,',')) { /* old style */
1545 DCB16 dcb16;
1546 BOOL16 ret;
1547 char last=temp[strlen(temp)-1];
1549 ret=BuildCommDCB16(device,&dcb16);
1550 if (ret)
1551 return FALSE;
1552 lpdcb->BaudRate = dcb16.BaudRate;
1553 lpdcb->ByteSize = dcb16.ByteSize;
1554 lpdcb->fBinary = dcb16.fBinary;
1555 lpdcb->Parity = dcb16.Parity;
1556 lpdcb->fParity = dcb16.fParity;
1557 lpdcb->fNull = dcb16.fNull;
1558 lpdcb->StopBits = dcb16.StopBits;
1559 if (last == 'x') {
1560 lpdcb->fInX = TRUE;
1561 lpdcb->fOutX = TRUE;
1562 lpdcb->fOutxCtsFlow = FALSE;
1563 lpdcb->fOutxDsrFlow = FALSE;
1564 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1565 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1566 } else if (last=='p') {
1567 lpdcb->fInX = FALSE;
1568 lpdcb->fOutX = FALSE;
1569 lpdcb->fOutxCtsFlow = TRUE;
1570 lpdcb->fOutxDsrFlow = TRUE;
1571 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1572 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1573 } else {
1574 lpdcb->fInX = FALSE;
1575 lpdcb->fOutX = FALSE;
1576 lpdcb->fOutxCtsFlow = FALSE;
1577 lpdcb->fOutxDsrFlow = FALSE;
1578 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1579 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1581 lpdcb->XonChar = dcb16.XonChar;
1582 lpdcb->XoffChar = dcb16.XoffChar;
1583 lpdcb->ErrorChar= dcb16.PeChar;
1584 lpdcb->fErrorChar= dcb16.fPeChar;
1585 lpdcb->EofChar = dcb16.EofChar;
1586 lpdcb->EvtChar = dcb16.EvtChar;
1587 lpdcb->XonLim = dcb16.XonLim;
1588 lpdcb->XoffLim = dcb16.XoffLim;
1589 return TRUE;
1591 ptr=strtok(temp," ");
1592 while (ptr) {
1593 DWORD flag,x;
1595 flag=0;
1596 if (!strncmp("baud=",ptr,5)) {
1597 if (!sscanf(ptr+5,"%ld",&x))
1598 WARN("Couldn't parse %s\n",ptr);
1599 lpdcb->BaudRate = x;
1600 flag=1;
1602 if (!strncmp("stop=",ptr,5)) {
1603 if (!sscanf(ptr+5,"%ld",&x))
1604 WARN("Couldn't parse %s\n",ptr);
1605 lpdcb->StopBits = x;
1606 flag=1;
1608 if (!strncmp("data=",ptr,5)) {
1609 if (!sscanf(ptr+5,"%ld",&x))
1610 WARN("Couldn't parse %s\n",ptr);
1611 lpdcb->ByteSize = x;
1612 flag=1;
1614 if (!strncmp("parity=",ptr,7)) {
1615 lpdcb->fParity = TRUE;
1616 switch (ptr[8]) {
1617 case 'N':case 'n':
1618 lpdcb->fParity = FALSE;
1619 lpdcb->Parity = NOPARITY;
1620 break;
1621 case 'E':case 'e':
1622 lpdcb->Parity = EVENPARITY;
1623 break;
1624 case 'O':case 'o':
1625 lpdcb->Parity = ODDPARITY;
1626 break;
1627 case 'M':case 'm':
1628 lpdcb->Parity = MARKPARITY;
1629 break;
1631 flag=1;
1633 if (!flag)
1634 ERR("Unhandled specifier '%s', please report.\n",ptr);
1635 ptr=strtok(NULL," ");
1637 if (lpdcb->BaudRate==110)
1638 lpdcb->StopBits = 2;
1639 return TRUE;
1642 /**************************************************************************
1643 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1645 * Updates a device control block data structure with values from an
1646 * unicode device control string. Taking time out values from a time outs
1647 * struct if desired by the control string.
1649 * RETURNS
1651 * True on success, false bad handles etc.
1653 BOOL WINAPI BuildCommDCBAndTimeoutsW(
1654 LPCWSTR devid, /* The unicode device control string. */
1655 LPDCB lpdcb, /* The device control block to be updated. */
1656 LPCOMMTIMEOUTS lptimeouts /* The time outs to use if asked to set them by the control string. */)
1658 BOOL ret = FALSE;
1659 LPSTR devidA;
1661 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1662 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1663 if (devidA)
1665 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1666 HeapFree( GetProcessHeap(), 0, devidA );
1668 return ret;
1671 /**************************************************************************
1672 * BuildCommDCBW (KERNEL32.17)
1674 * Updates a device control block structure with values from an
1675 * unicode device control string. The device control string has two forms
1676 * normal and extended, it must be exclusively in one or the other form.
1678 * RETURNS
1680 * True on success, false on an malformed control string.
1682 BOOL WINAPI BuildCommDCBW(
1683 LPCWSTR devid, /* The unicode device control string. */
1684 LPDCB lpdcb /* The device control block to be updated. */)
1686 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1689 /* FIXME: having these global for win32 for now */
1690 int commerror=0;
1692 /*****************************************************************************
1693 * SetCommBreak (KERNEL32.449)
1695 * Halts the transmission of characters to a communications device.
1697 * RETURNS
1699 * True on success, and false if the communications device could not be found,
1700 * the control is not supported.
1702 * BUGS
1704 * Only TIOCSBRK and TIOCCBRK are supported.
1706 BOOL WINAPI SetCommBreak(
1707 HANDLE handle /* The communictions device to suspend. */)
1709 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1710 int fd,result;
1712 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
1713 if(fd<0) {
1714 TRACE("FILE_GetUnixHandle failed\n");
1715 return FALSE;
1717 result = ioctl(fd,TIOCSBRK,0);
1718 close(fd);
1719 if (result ==-1)
1721 TRACE("ioctl failed\n");
1722 SetLastError(ERROR_NOT_SUPPORTED);
1723 return FALSE;
1725 return TRUE;
1726 #else
1727 FIXME("ioctl not available\n");
1728 SetLastError(ERROR_NOT_SUPPORTED);
1729 return FALSE;
1730 #endif
1733 /*****************************************************************************
1734 * ClearCommBreak (KERNEL32.20)
1736 * Resumes character transmission from a communication device.
1738 * RETURNS
1740 * True on success and false if the communications device could not be found.
1742 * BUGS
1744 * Only TIOCSBRK and TIOCCBRK are supported.
1746 BOOL WINAPI ClearCommBreak(
1747 HANDLE handle /* The halted communication device whose character transmission is to be resumed. */)
1749 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1750 int fd,result;
1752 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
1753 if(fd<0) {
1754 TRACE("FILE_GetUnixHandle failed\n");
1755 return FALSE;
1757 result = ioctl(fd,TIOCCBRK,0);
1758 close(fd);
1759 if (result ==-1)
1761 TRACE("ioctl failed\n");
1762 SetLastError(ERROR_NOT_SUPPORTED);
1763 return FALSE;
1765 return TRUE;
1766 #else
1767 FIXME("ioctl not available\n");
1768 SetLastError(ERROR_NOT_SUPPORTED);
1769 return FALSE;
1770 #endif
1773 /*****************************************************************************
1774 * EscapeCommFunction (KERNEL32.214)
1776 * Directs a communication device to perform an extended function.
1778 * RETURNS
1780 * True or requested data on successful completion of the command,
1781 * false if the device is not present cannot execute the command
1782 * or the command failed.
1784 BOOL WINAPI EscapeCommFunction(
1785 HANDLE handle, /* The communication device to perform the extended function. */
1786 UINT nFunction /* The extended function to be performed. */)
1788 int fd,direct=FALSE,result=FALSE;
1789 struct termios port;
1791 TRACE("handle %d, function=%d\n", handle, nFunction);
1792 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
1793 if(fd<0) {
1794 FIXME("handle %d not found.\n",handle);
1795 return FALSE;
1798 if (tcgetattr(fd,&port) == -1) {
1799 commerror=WinError();
1800 close(fd);
1801 return FALSE;
1804 switch (nFunction) {
1805 case RESETDEV:
1806 TRACE("\n");
1807 break;
1809 case CLRDTR:
1810 TRACE("CLRDTR\n");
1811 #ifdef TIOCM_DTR
1812 direct=TRUE;
1813 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1814 break;
1815 #endif
1817 case CLRRTS:
1818 TRACE("CLRRTS\n");
1819 #ifdef TIOCM_RTS
1820 direct=TRUE;
1821 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1822 break;
1823 #endif
1825 case SETDTR:
1826 TRACE("SETDTR\n");
1827 #ifdef TIOCM_DTR
1828 direct=TRUE;
1829 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1830 break;
1831 #endif
1833 case SETRTS:
1834 TRACE("SETRTS\n");
1835 #ifdef TIOCM_DTR
1836 direct=TRUE;
1837 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1838 break;
1839 #endif
1841 case SETXOFF:
1842 TRACE("SETXOFF\n");
1843 port.c_iflag |= IXOFF;
1844 break;
1846 case SETXON:
1847 TRACE("SETXON\n");
1848 port.c_iflag |= IXON;
1849 break;
1850 case SETBREAK:
1851 TRACE("setbreak\n");
1852 #ifdef TIOCSBRK
1853 direct=TRUE;
1854 result = ioctl(fd,TIOCSBRK,0);
1855 break;
1856 #endif
1857 case CLRBREAK:
1858 TRACE("clrbreak\n");
1859 #ifdef TIOCSBRK
1860 direct=TRUE;
1861 result = ioctl(fd,TIOCCBRK,0);
1862 break;
1863 #endif
1864 default:
1865 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1866 handle, nFunction);
1867 break;
1870 if (!direct)
1871 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1872 commerror = WinError();
1873 close(fd);
1874 return FALSE;
1875 } else
1876 result= TRUE;
1877 else
1879 if (result == -1)
1881 result= FALSE;
1882 commerror=WinError();
1884 else
1885 result = TRUE;
1887 close(fd);
1888 return result;
1891 /********************************************************************
1892 * PurgeComm (KERNEL32.557)
1894 * Terminates pending operations and/or discards buffers on a
1895 * communication resource.
1897 * RETURNS
1899 * True on success and false if the communications handle is bad.
1901 BOOL WINAPI PurgeComm(
1902 HANDLE handle, /* The communication resource to be purged. */
1903 DWORD flags /* Flags for clear pending/buffer on input/output. */)
1905 int fd;
1907 TRACE("handle %d, flags %lx\n", handle, flags);
1909 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
1910 if(fd<0) {
1911 FIXME("no handle %d found\n",handle);
1912 return FALSE;
1916 ** not exactly sure how these are different
1917 ** Perhaps if we had our own internal queues, one flushes them
1918 ** and the other flushes the kernel's buffers.
1920 if(flags&PURGE_TXABORT)
1921 tcflush(fd,TCOFLUSH);
1922 if(flags&PURGE_RXABORT)
1923 tcflush(fd,TCIFLUSH);
1924 if(flags&PURGE_TXCLEAR)
1925 tcflush(fd,TCOFLUSH);
1926 if(flags&PURGE_RXCLEAR)
1927 tcflush(fd,TCIFLUSH);
1928 close(fd);
1930 return 1;
1933 /*****************************************************************************
1934 * ClearCommError (KERNEL32.21)
1936 * Enables further I/O operations on a communications resource after
1937 * supplying error and current status information.
1939 * RETURNS
1941 * True on success, false if the communication resource handle is bad.
1943 BOOL WINAPI ClearCommError(
1944 HANDLE handle, /* The communication resource with the error. */
1945 LPDWORD errors, /* Flags indicating error the resource experienced. */
1946 LPCOMSTAT lpStat /* The status of the communication resource. */)
1948 int fd;
1950 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
1951 if(0>fd)
1953 FIXME("no handle %d found\n",handle);
1954 return FALSE;
1957 if (lpStat)
1959 lpStat->status = 0;
1961 #ifdef TIOCOUTQ
1962 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1963 WARN("ioctl returned error\n");
1964 #else
1965 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1966 #endif
1968 #ifdef TIOCINQ
1969 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1970 WARN("ioctl returned error\n");
1971 #endif
1973 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1974 handle, lpStat->cbInQue, lpStat->cbOutQue);
1977 close(fd);
1979 if(errors)
1980 *errors = 0;
1983 ** After an asynchronous write opperation, the
1984 ** app will call ClearCommError to see if the
1985 ** results are ready yet. It waits for ERROR_IO_PENDING
1987 commerror = ERROR_IO_PENDING;
1989 return TRUE;
1992 /*****************************************************************************
1993 * SetupComm (KERNEL32.676)
1995 * Called after CreateFile to hint to the communication resource to use
1996 * specified sizes for input and output buffers rather than the default values.
1998 * RETURNS
2000 * True if successful, false if the communications resource handle is bad.
2002 * BUGS
2004 * Stub.
2006 BOOL WINAPI SetupComm(
2007 HANDLE handle, /* The just created communication resource handle. */
2008 DWORD insize, /* The suggested size of the communication resources input buffer in bytes. */
2009 DWORD outsize /* The suggested size of the communication resources output buffer in bytes. */)
2011 int fd;
2013 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
2014 fd=FILE_GetUnixHandle( handle, GENERIC_WRITE );
2015 if(0>fd) {
2016 FIXME("handle %d not found?\n",handle);
2017 return FALSE;
2019 close(fd);
2020 return TRUE;
2023 /*****************************************************************************
2024 * GetCommMask (KERNEL32.156)
2026 * Obtain the events associated with a communication device that will cause a call
2027 * WaitCommEvent to return.
2029 * RETURNS
2031 * True on success, fail on bad device handle etc.
2033 BOOL WINAPI GetCommMask(
2034 HANDLE handle, /* The communications device. */
2035 LPDWORD evtmask /* The events which cause WaitCommEvent to return. */)
2037 BOOL ret;
2039 TRACE("handle %d, mask %p\n", handle, evtmask);
2041 SERVER_START_REQ
2043 struct get_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2044 req->handle = handle;
2045 if ((ret = !server_call( REQ_GET_SERIAL_INFO )))
2047 if (evtmask) *evtmask = req->eventmask;
2050 SERVER_END_REQ;
2051 return ret;
2054 /*****************************************************************************
2055 * SetCommMask (KERNEL32.451)
2057 * There be some things we need to hear about yon there communications device.
2058 * (Set which events associated with a communication device should cause
2059 * a call WaitCommEvent to return.)
2061 * RETURNS
2063 * True on success, false on bad handle etc.
2065 BOOL WINAPI SetCommMask(
2066 HANDLE handle, /* The communications device. */
2067 DWORD evtmask /* The events that to be monitored. */)
2069 BOOL ret;
2071 TRACE("handle %d, mask %lx\n", handle, evtmask);
2073 SERVER_START_REQ
2075 struct set_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2076 req->handle = handle;
2077 req->flags = SERIALINFO_SET_MASK;
2078 req->eventmask = evtmask;
2079 ret = !server_call( REQ_SET_SERIAL_INFO );
2081 SERVER_END_REQ;
2082 return ret;
2085 /*****************************************************************************
2086 * SetCommState (KERNEL32.452)
2088 * Re-initializes all hardware and control settings of a communications device,
2089 * with values from a device control block without effecting the input and output
2090 * queues.
2092 * RETURNS
2094 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
2096 BOOL WINAPI SetCommState(
2097 HANDLE handle, /* The communications device. */
2098 LPDCB lpdcb /* The device control block. */)
2100 struct termios port;
2101 int fd, bytesize, stopbits;
2103 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2104 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2105 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2106 (lpdcb->StopBits == ONESTOPBIT)?1:
2107 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2108 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2109 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2111 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
2112 if (fd < 0) {
2113 FIXME("no handle %d found\n",handle);
2114 return FALSE;
2117 if ((tcgetattr(fd,&port)) == -1) {
2118 int save_error = errno;
2119 commerror = WinError();
2120 close( fd );
2121 ERR("tcgetattr error '%s'\n", strerror(save_error));
2122 return FALSE;
2125 port.c_cc[VMIN] = 0;
2126 port.c_cc[VTIME] = 1;
2128 #ifdef IMAXBEL
2129 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
2130 #else
2131 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
2132 #endif
2133 port.c_iflag |= (IGNBRK);
2135 port.c_oflag &= ~(OPOST);
2137 port.c_cflag &= ~(HUPCL);
2138 port.c_cflag |= CLOCAL | CREAD;
2140 port.c_lflag &= ~(ICANON|ECHO|ISIG);
2141 port.c_lflag |= NOFLSH;
2144 ** MJM - removed default baudrate settings
2145 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2147 #ifdef CBAUD
2148 port.c_cflag &= ~CBAUD;
2149 switch (lpdcb->BaudRate) {
2150 case 110:
2151 case CBR_110:
2152 port.c_cflag |= B110;
2153 break;
2154 case 300:
2155 case CBR_300:
2156 port.c_cflag |= B300;
2157 break;
2158 case 600:
2159 case CBR_600:
2160 port.c_cflag |= B600;
2161 break;
2162 case 1200:
2163 case CBR_1200:
2164 port.c_cflag |= B1200;
2165 break;
2166 case 2400:
2167 case CBR_2400:
2168 port.c_cflag |= B2400;
2169 break;
2170 case 4800:
2171 case CBR_4800:
2172 port.c_cflag |= B4800;
2173 break;
2174 case 9600:
2175 case CBR_9600:
2176 port.c_cflag |= B9600;
2177 break;
2178 case 19200:
2179 case CBR_19200:
2180 port.c_cflag |= B19200;
2181 break;
2182 case 38400:
2183 case CBR_38400:
2184 port.c_cflag |= B38400;
2185 break;
2186 #ifdef B57600
2187 case 57600:
2188 port.c_cflag |= B57600;
2189 break;
2190 #endif
2191 #ifdef B115200
2192 case 115200:
2193 port.c_cflag |= B115200;
2194 break;
2195 #endif
2196 #ifdef B230400
2197 case 230400:
2198 port.c_cflag |= B230400;
2199 break;
2200 #endif
2201 #ifdef B460800
2202 case 460600:
2203 port.c_cflag |= B460800;
2204 break;
2205 #endif
2206 default:
2207 commerror = IE_BAUDRATE;
2208 close( fd );
2209 ERR("baudrate %ld\n",lpdcb->BaudRate);
2210 return FALSE;
2212 #elif !defined(__EMX__)
2213 switch (lpdcb->BaudRate) {
2214 case 110:
2215 case CBR_110:
2216 port.c_ospeed = B110;
2217 break;
2218 case 300:
2219 case CBR_300:
2220 port.c_ospeed = B300;
2221 break;
2222 case 600:
2223 case CBR_600:
2224 port.c_ospeed = B600;
2225 break;
2226 case 1200:
2227 case CBR_1200:
2228 port.c_ospeed = B1200;
2229 break;
2230 case 2400:
2231 case CBR_2400:
2232 port.c_ospeed = B2400;
2233 break;
2234 case 4800:
2235 case CBR_4800:
2236 port.c_ospeed = B4800;
2237 break;
2238 case 9600:
2239 case CBR_9600:
2240 port.c_ospeed = B9600;
2241 break;
2242 case 19200:
2243 case CBR_19200:
2244 port.c_ospeed = B19200;
2245 break;
2246 case 38400:
2247 case CBR_38400:
2248 port.c_ospeed = B38400;
2249 break;
2250 default:
2251 commerror = IE_BAUDRATE;
2252 close( fd );
2253 ERR("baudrate %ld\n",lpdcb->BaudRate);
2254 return FALSE;
2256 port.c_ispeed = port.c_ospeed;
2257 #endif
2258 bytesize=lpdcb->ByteSize;
2259 stopbits=lpdcb->StopBits;
2261 #ifdef CMSPAR
2262 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
2263 #else
2264 port.c_cflag &= ~(PARENB | PARODD);
2265 #endif
2266 if (lpdcb->fParity)
2267 port.c_iflag |= INPCK;
2268 else
2269 port.c_iflag &= ~INPCK;
2270 switch (lpdcb->Parity) {
2271 case NOPARITY:
2272 break;
2273 case ODDPARITY:
2274 port.c_cflag |= (PARENB | PARODD);
2275 break;
2276 case EVENPARITY:
2277 port.c_cflag |= PARENB;
2278 break;
2279 #ifdef CMSPAR
2280 /* Linux defines mark/space (stick) parity */
2281 case MARKPARITY:
2282 port.c_cflag |= (PARENB | CMSPAR);
2283 break;
2284 case SPACEPARITY:
2285 port.c_cflag |= (PARENB | PARODD | CMSPAR);
2286 break;
2287 #else
2288 /* try the POSIX way */
2289 case MARKPARITY:
2290 if( stopbits == ONESTOPBIT) {
2291 stopbits = TWOSTOPBITS;
2292 port.c_iflag &= ~INPCK;
2293 } else {
2294 commerror = IE_BYTESIZE;
2295 close( fd );
2296 ERR("Cannot set MARK Parity\n");
2297 return FALSE;
2299 break;
2300 case SPACEPARITY:
2301 if( bytesize < 8) {
2302 bytesize +=1;
2303 port.c_iflag &= ~INPCK;
2304 } else {
2305 commerror = IE_BYTESIZE;
2306 close( fd );
2307 ERR("Cannot set SPACE Parity\n");
2308 return FALSE;
2310 break;
2311 #endif
2312 default:
2313 commerror = IE_BYTESIZE;
2314 close( fd );
2315 ERR("Parity\n");
2316 return FALSE;
2320 port.c_cflag &= ~CSIZE;
2321 switch (bytesize) {
2322 case 5:
2323 port.c_cflag |= CS5;
2324 break;
2325 case 6:
2326 port.c_cflag |= CS6;
2327 break;
2328 case 7:
2329 port.c_cflag |= CS7;
2330 break;
2331 case 8:
2332 port.c_cflag |= CS8;
2333 break;
2334 default:
2335 commerror = IE_BYTESIZE;
2336 close( fd );
2337 ERR("ByteSize\n");
2338 return FALSE;
2341 switch (stopbits) {
2342 case ONESTOPBIT:
2343 port.c_cflag &= ~CSTOPB;
2344 break;
2345 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
2346 case TWOSTOPBITS:
2347 port.c_cflag |= CSTOPB;
2348 break;
2349 default:
2350 commerror = IE_BYTESIZE;
2351 close( fd );
2352 ERR("StopBits\n");
2353 return FALSE;
2355 #ifdef CRTSCTS
2356 if ( lpdcb->fOutxCtsFlow ||
2357 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2358 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2361 port.c_cflag |= CRTSCTS;
2362 TRACE("CRTSCTS\n");
2365 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2367 port.c_cflag &= ~CRTSCTS;
2368 TRACE("~CRTSCTS\n");
2371 #endif
2372 if (lpdcb->fInX)
2373 port.c_iflag |= IXON;
2374 else
2375 port.c_iflag &= ~IXON;
2376 if (lpdcb->fOutX)
2377 port.c_iflag |= IXOFF;
2378 else
2379 port.c_iflag &= ~IXOFF;
2381 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2382 int save_error=errno;
2383 commerror = WinError();
2384 close( fd );
2385 ERR("tcgetattr error '%s'\n", strerror(save_error));
2386 return FALSE;
2387 } else {
2388 commerror = 0;
2389 close( fd );
2390 return TRUE;
2395 /*****************************************************************************
2396 * GetCommState (KERNEL32.159)
2398 * Fills in a device control block with information from a communications device.
2400 * RETURNS
2402 * True on success, false if the communication device handle is bad etc
2404 * BUGS
2406 * XonChar and XoffChar are not set.
2408 BOOL WINAPI GetCommState(
2409 HANDLE handle, /* The communications device. */
2410 LPDCB lpdcb /* The device control block. */)
2412 struct termios port;
2413 int fd,speed;
2415 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2417 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
2418 if (fd < 0)
2420 ERR("FILE_GetUnixHandle failed\n");
2421 return FALSE;
2423 if (tcgetattr(fd, &port) == -1) {
2424 int save_error=errno;
2425 ERR("tcgetattr error '%s'\n", strerror(save_error));
2426 commerror = WinError();
2427 close( fd );
2428 return FALSE;
2430 close( fd );
2431 #ifndef __EMX__
2432 #ifdef CBAUD
2433 speed= (port.c_cflag & CBAUD);
2434 #else
2435 speed= (cfgetospeed(&port));
2436 #endif
2437 switch (speed) {
2438 case B110:
2439 lpdcb->BaudRate = 110;
2440 break;
2441 case B300:
2442 lpdcb->BaudRate = 300;
2443 break;
2444 case B600:
2445 lpdcb->BaudRate = 600;
2446 break;
2447 case B1200:
2448 lpdcb->BaudRate = 1200;
2449 break;
2450 case B2400:
2451 lpdcb->BaudRate = 2400;
2452 break;
2453 case B4800:
2454 lpdcb->BaudRate = 4800;
2455 break;
2456 case B9600:
2457 lpdcb->BaudRate = 9600;
2458 break;
2459 case B19200:
2460 lpdcb->BaudRate = 19200;
2461 break;
2462 case B38400:
2463 lpdcb->BaudRate = 38400;
2464 break;
2465 #ifdef B57600
2466 case B57600:
2467 lpdcb->BaudRate = 57600;
2468 break;
2469 #endif
2470 #ifdef B115200
2471 case B115200:
2472 lpdcb->BaudRate = 115200;
2473 break;
2474 #endif
2475 #ifdef B230400
2476 case B230400:
2477 lpdcb->BaudRate = 230400;
2478 break;
2479 #endif
2480 #ifdef B460800
2481 case B460800:
2482 lpdcb->BaudRate = 460800;
2483 break;
2484 #endif
2485 default:
2486 ERR("unknown speed %x \n",speed);
2488 #endif
2489 switch (port.c_cflag & CSIZE) {
2490 case CS5:
2491 lpdcb->ByteSize = 5;
2492 break;
2493 case CS6:
2494 lpdcb->ByteSize = 6;
2495 break;
2496 case CS7:
2497 lpdcb->ByteSize = 7;
2498 break;
2499 case CS8:
2500 lpdcb->ByteSize = 8;
2501 break;
2502 default:
2503 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2506 if(port.c_iflag & INPCK)
2507 lpdcb->fParity = TRUE;
2508 else
2509 lpdcb->fParity = FALSE;
2510 #ifdef CMSPAR
2511 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
2512 #else
2513 switch (port.c_cflag & (PARENB | PARODD))
2514 #endif
2516 case 0:
2517 lpdcb->Parity = NOPARITY;
2518 break;
2519 case PARENB:
2520 lpdcb->Parity = EVENPARITY;
2521 break;
2522 case (PARENB | PARODD):
2523 lpdcb->Parity = ODDPARITY;
2524 break;
2525 #ifdef CMSPAR
2526 case (PARENB | CMSPAR):
2527 lpdcb->Parity = MARKPARITY;
2528 break;
2529 case (PARENB | PARODD | CMSPAR):
2530 lpdcb->Parity = SPACEPARITY;
2531 break;
2532 #endif
2535 if (port.c_cflag & CSTOPB)
2536 if(lpdcb->ByteSize == 5)
2537 lpdcb->StopBits = ONE5STOPBITS;
2538 else
2539 lpdcb->StopBits = TWOSTOPBITS;
2540 else
2541 lpdcb->StopBits = ONESTOPBIT;
2543 lpdcb->fNull = 0;
2544 lpdcb->fBinary = 1;
2546 #ifdef CRTSCTS
2548 if (port.c_cflag & CRTSCTS) {
2549 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2550 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2551 lpdcb->fOutxCtsFlow = 1;
2552 lpdcb->fOutxDsrFlow = 1;
2553 } else
2554 #endif
2556 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2557 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2559 if (port.c_iflag & IXON)
2560 lpdcb->fInX = 1;
2561 else
2562 lpdcb->fInX = 0;
2564 if (port.c_iflag & IXOFF)
2565 lpdcb->fOutX = 1;
2566 else
2567 lpdcb->fOutX = 0;
2569 lpdcb->XonChar =
2570 lpdcb->XoffChar =
2572 lpdcb->XonLim = 10;
2573 lpdcb->XoffLim = 10;
2575 commerror = 0;
2577 TRACE("OK\n");
2579 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2580 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2581 (lpdcb->StopBits == ONESTOPBIT)?1:
2582 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2583 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2584 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2585 #ifdef CRTSCTS
2586 if ( lpdcb->fOutxCtsFlow ||
2587 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2588 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2590 TRACE("CRTSCTS\n");
2592 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2593 TRACE("~CRTSCTS\n");
2595 #endif
2596 return TRUE;
2599 /*****************************************************************************
2600 * TransmitCommChar (KERNEL32.535)
2602 * Transmits a single character in front of any pending characters in the
2603 * output buffer. Usually used to send an interrupt character to a host.
2605 * RETURNS
2607 * True if the call succeeded, false if the previous command character to the
2608 * same device has not been sent yet the handle is bad etc.
2610 * BUGS
2612 * Stub.
2614 BOOL WINAPI TransmitCommChar(
2615 HANDLE hComm, /* The communication device in need of a command character. */
2616 CHAR chTransmit /* The character to transmit. */)
2618 FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
2619 return TRUE;
2622 /*****************************************************************************
2623 * GetCommTimeouts (KERNEL32.160)
2625 * Obtains the request time out values for the communications device.
2627 * RETURNS
2629 * True on success, false if communications device handle is bad
2630 * or the target structure is null.
2632 BOOL WINAPI GetCommTimeouts(
2633 HANDLE hComm, /* The communications device. */
2634 LPCOMMTIMEOUTS lptimeouts /* The struct of request time outs. */)
2636 BOOL ret;
2638 TRACE("(%x,%p)\n",hComm,lptimeouts);
2640 if(!lptimeouts)
2642 SetLastError(ERROR_INVALID_PARAMETER);
2643 return FALSE;
2646 SERVER_START_REQ
2648 struct get_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2649 req->handle = hComm;
2650 if ((ret = !server_call( REQ_GET_SERIAL_INFO )))
2652 lptimeouts->ReadIntervalTimeout = req->readinterval;
2653 lptimeouts->ReadTotalTimeoutMultiplier = req->readmult;
2654 lptimeouts->ReadTotalTimeoutConstant = req->readconst;
2655 lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
2656 lptimeouts->WriteTotalTimeoutConstant = req->writeconst;
2659 SERVER_END_REQ;
2660 return ret;
2663 /*****************************************************************************
2664 * SetCommTimeouts (KERNEL32.453)
2666 * Sets the timeouts used when reading and writing data to/from COMM ports.
2668 * ReadIntervalTimeout
2669 * - converted and passes to linux kernel as c_cc[VTIME]
2670 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
2671 * - used in ReadFile to calculate GetOverlappedResult's timeout
2672 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
2673 * - used in WriteFile to calculate GetOverlappedResult's timeout
2675 * RETURNS
2677 * True if the time outs were set, false otherwise.
2679 BOOL WINAPI SetCommTimeouts(
2680 HANDLE hComm, /* [in] handle of COMM device */
2681 LPCOMMTIMEOUTS lptimeouts /* [in] pointer to COMMTIMEOUTS structure */
2683 BOOL ret;
2684 int fd;
2685 struct termios tios;
2687 TRACE("(%x,%p)\n",hComm,lptimeouts);
2689 if(!lptimeouts)
2691 SetLastError(ERROR_INVALID_PARAMETER);
2692 return FALSE;
2695 SERVER_START_REQ
2697 struct set_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2698 req->handle = hComm;
2699 req->flags = SERIALINFO_SET_TIMEOUTS;
2700 req->readinterval = lptimeouts->ReadIntervalTimeout ;
2701 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
2702 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
2703 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
2704 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
2705 ret = !server_call( REQ_SET_SERIAL_INFO );
2707 SERVER_END_REQ;
2708 if (!ret) return FALSE;
2710 /* FIXME: move this stuff to the server */
2711 fd = FILE_GetUnixHandle( hComm, GENERIC_WRITE );
2712 if (fd < 0) {
2713 FIXME("no fd for handle = %0x!.\n",hComm);
2714 return FALSE;
2717 if (-1==tcgetattr(fd,&tios)) {
2718 FIXME("tcgetattr on fd %d failed!\n",fd);
2719 return FALSE;
2721 /* VTIME is in 1/10 seconds */
2722 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2723 if (-1==tcsetattr(fd,0,&tios)) {
2724 FIXME("tcsetattr on fd %d failed!\n",fd);
2725 return FALSE;
2727 close(fd);
2728 return TRUE;
2731 /***********************************************************************
2732 * GetCommModemStatus (KERNEL32.285)
2734 * Obtains the four control register bits if supported by the hardware.
2736 * RETURNS
2738 * True if the communications handle was good and for hardware that
2739 * control register access, false otherwise.
2741 BOOL WINAPI GetCommModemStatus(
2742 HANDLE hFile, /* The communications device. */
2743 LPDWORD lpModemStat /* The control register bits. */)
2745 int fd,mstat, result=FALSE;
2747 *lpModemStat=0;
2748 #ifdef TIOCMGET
2749 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
2750 if(fd<0)
2751 return FALSE;
2752 result = ioctl(fd, TIOCMGET, &mstat);
2753 close(fd);
2754 if (result == -1)
2756 TRACE("ioctl failed\n");
2757 return FALSE;
2759 #ifdef TIOCM_CTS
2760 if (mstat & TIOCM_CTS)
2761 *lpModemStat |= MS_CTS_ON;
2762 #endif
2763 #ifdef TIOCM_DSR
2764 if (mstat & TIOCM_DSR)
2765 *lpModemStat |= MS_DSR_ON;
2766 #endif
2767 #ifdef TIOCM_RNG
2768 if (mstat & TIOCM_RNG)
2769 *lpModemStat |= MS_RING_ON;
2770 #endif
2771 #ifdef TIOCM_CAR
2772 /*FIXME: Not really sure about RLSD UB 990810*/
2773 if (mstat & TIOCM_CAR)
2774 *lpModemStat |= MS_RLSD_ON;
2775 #endif
2776 TRACE("%s%s%s%s\n",
2777 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2778 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2779 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2780 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2781 return TRUE;
2782 #else
2783 return FALSE;
2784 #endif
2787 VOID COMM_WaitCommEventService(void **args)
2789 LPOVERLAPPED lpOverlapped = (LPOVERLAPPED)args[0];
2790 LPDWORD buffer = (LPDWORD)args[1];
2791 DWORD events = (DWORD)args[2];
2793 TRACE("overlapped %p wait complete %p <- %lx\n",lpOverlapped,buffer,events);
2794 if(buffer)
2795 *buffer = events;
2797 lpOverlapped->Internal = STATUS_SUCCESS;
2798 SetEvent( lpOverlapped->hEvent);
2799 CloseHandle(lpOverlapped->InternalHigh);
2802 /***********************************************************************
2803 * WaitCommEvent (KERNEL32.719)
2805 * Wait until something interesting happens on a COMM port.
2806 * Interesting things (events) are set by calling SetCommMask before
2807 * this function is called.
2809 * RETURNS:
2810 * TRUE if successful
2811 * FALSE if failure
2813 * The set of detected events will be written to *lpdwEventMask
2814 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2816 * BUGS:
2817 * Only supports EV_RXCHAR and EV_TXEMPTY
2819 BOOL WINAPI WaitCommEvent(
2820 HANDLE hFile, /* [in] handle of comm port to wait for */
2821 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2822 LPOVERLAPPED lpOverlapped /* [in/out] for Asynchronous waiting */
2824 OVERLAPPED ov;
2825 LPOVERLAPPED lpov;
2826 int ret;
2828 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2830 /* if there is no overlapped structure, create our own */
2831 if(!lpOverlapped)
2833 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
2834 lpov = &ov;
2836 else
2837 lpov = lpOverlapped;
2839 /* check that the overlapped structure has a valid event flag */
2840 if ( (lpov->hEvent==0) || (lpov->hEvent == INVALID_HANDLE_VALUE) )
2842 ERR("Couldn't create Event flag for Overlapped structure\n");
2843 SetLastError(ERROR_INVALID_PARAMETER);
2844 return FALSE;
2847 ResetEvent(lpov->hEvent);
2849 lpov->Internal = STATUS_PENDING;
2850 lpov->InternalHigh = 0;
2851 lpov->Offset = 0;
2852 lpov->OffsetHigh = 0;
2854 /* start an ASYNCHRONOUS WaitCommEvent */
2855 SERVER_START_REQ
2857 struct create_async_request *req = server_alloc_req( sizeof(*req), 0 );
2859 req->file_handle = hFile;
2860 req->overlapped = lpov;
2861 req->buffer = lpdwEvents;
2862 req->count = 0;
2863 req->func = COMM_WaitCommEventService;
2864 req->type = ASYNC_TYPE_WAIT;
2866 ret=server_call( REQ_CREATE_ASYNC );
2868 lpov->InternalHigh = req->ov_handle;
2870 SERVER_END_REQ;
2872 if(ret)
2874 if(!lpOverlapped)
2875 CloseHandle(lpov->hEvent);
2876 TRACE("server call failed.\n");
2877 return FALSE;
2880 /* activate the overlapped operation */
2881 lpov->Internal = STATUS_PENDING;
2883 /* wait ourselves if the caller didn't give us an overlapped struct */
2884 if(!lpOverlapped)
2886 GetOverlappedResult(hFile, lpov, NULL, TRUE);
2887 CloseHandle(lpov->hEvent);
2888 lpov->hEvent=0;
2890 else
2892 /* caller wants overlapped I/O using GetOverlapped result */
2893 SetLastError(ERROR_IO_PENDING);
2894 return FALSE;
2897 return TRUE;
2900 /***********************************************************************
2901 * GetCommProperties (KERNEL32.286)
2903 * This function fills in a structure with the capabilities of the
2904 * communications port driver.
2906 * RETURNS
2908 * TRUE on success, FALSE on failure
2909 * If successful, the lpCommProp structure be filled in with
2910 * properties of the comm port.
2912 BOOL WINAPI GetCommProperties(
2913 HANDLE hFile, /* [in] handle of the comm port */
2914 LPCOMMPROP lpCommProp /* [out] pointer to struct to be filled */
2916 FIXME("(%d %p )\n",hFile,lpCommProp);
2917 if(!lpCommProp)
2918 return FALSE;
2921 * These values should be valid for LINUX's serial driver
2922 * FIXME: Perhaps they deserve an #ifdef LINUX
2924 memset(lpCommProp,0,sizeof(COMMPROP));
2925 lpCommProp->wPacketLength = 1;
2926 lpCommProp->wPacketVersion = 1;
2927 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2928 lpCommProp->dwReserved1 = 0;
2929 lpCommProp->dwMaxTxQueue = 4096;
2930 lpCommProp->dwMaxRxQueue = 4096;
2931 lpCommProp->dwMaxBaud = BAUD_115200;
2932 lpCommProp->dwProvSubType = PST_RS232;
2933 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
2934 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2935 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2936 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2937 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2938 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2939 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2940 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2941 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2942 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2943 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2945 return TRUE;
2948 /***********************************************************************
2949 * FIXME:
2950 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2951 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2952 * This is dependent on the type of COMM port, but since it is doubtful
2953 * anybody will get around to implementing support for fancy serial
2954 * ports in WINE, this is hardcoded for the time being. The name of
2955 * this DLL should be stored in and read from the system registry in
2956 * the hive HKEY_LOCAL_MACHINE, key
2957 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2958 * where ???? is the port number... that is determined by PNP
2959 * The DLL should be loaded when the COMM port is opened, and closed
2960 * when the COMM port is closed. - MJM 20 June 2000
2961 ***********************************************************************/
2962 static CHAR lpszSerialUI[] = "serialui.dll";
2965 /***********************************************************************
2966 * CommConfigDialogA (KERNEL32.140)
2968 * Raises a dialog that allows the user to configure a comm port.
2969 * Fills the COMMCONFIG struct with information specified by the user.
2970 * This function should call a similar routine in the COMM driver...
2972 * RETURNS
2974 * TRUE on success, FALSE on failure
2975 * If successful, the lpCommConfig structure will contain a new
2976 * configuration for the comm port, as specified by the user.
2978 * BUGS
2979 * The library with the CommConfigDialog code is never unloaded.
2980 * Perhaps this should be done when the comm port is closed?
2982 BOOL WINAPI CommConfigDialogA(
2983 LPCSTR lpszDevice, /* [in] name of communications device */
2984 HANDLE hWnd, /* [in] parent window for the dialog */
2985 LPCOMMCONFIG lpCommConfig /* [out] pointer to struct to fill */
2987 FARPROC lpfnCommDialog;
2988 HMODULE hConfigModule;
2989 BOOL r;
2991 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
2993 hConfigModule = LoadLibraryA(lpszSerialUI);
2994 if(!hConfigModule)
2995 return FALSE;
2997 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2999 if(!lpfnCommDialog)
3000 return FALSE;
3002 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
3004 /* UnloadLibrary(hConfigModule); */
3006 return r;
3009 /***********************************************************************
3010 * CommConfigDialogW (KERNEL32.141)
3012 * see CommConfigDialogA for more info
3014 BOOL WINAPI CommConfigDialogW(
3015 LPCWSTR lpszDevice, /* [in] name of communications device */
3016 HANDLE hWnd, /* [in] parent window for the dialog */
3017 LPCOMMCONFIG lpCommConfig /* [out] pointer to struct to fill */
3019 BOOL r;
3020 LPSTR lpDeviceA;
3022 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
3023 if(lpDeviceA)
3024 return FALSE;
3025 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
3026 HeapFree( GetProcessHeap(), 0, lpDeviceA );
3027 return r;
3030 /***********************************************************************
3031 * GetCommConfig (KERNEL32.283)
3033 * Fill in the COMMCONFIG structure for the comm port hFile
3035 * RETURNS
3037 * TRUE on success, FALSE on failure
3038 * If successful, lpCommConfig contains the comm port configuration.
3040 * BUGS
3042 * The signature is missing a the parameter for the size of the COMMCONFIG
3043 * structure/buffer it should be
3044 * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
3046 BOOL WINAPI GetCommConfig(
3047 HANDLE hFile, /* The communications device. */
3048 LPCOMMCONFIG lpCommConfig /* The communications configuration of the device (if it fits). */
3049 /* LPDWORD lpdwSize Initially the size of the configuration buffer/structure,
3050 afterwards the number of bytes copied to the buffer or the needed size of the buffer. */
3052 BOOL r;
3054 TRACE("(%x %p)\n",hFile,lpCommConfig);
3056 if(lpCommConfig == NULL)
3057 return FALSE;
3059 lpCommConfig->dwSize = sizeof(COMMCONFIG);
3060 lpCommConfig->wVersion = 1;
3061 lpCommConfig->wReserved = 0;
3062 r = GetCommState(hFile,&lpCommConfig->dcb);
3063 lpCommConfig->dwProviderSubType = PST_RS232;
3064 lpCommConfig->dwProviderOffset = 0;
3065 lpCommConfig->dwProviderSize = 0;
3067 return r;
3070 /***********************************************************************
3071 * SetCommConfig (KERNEL32.617)
3073 * Sets the configuration of the commications device.
3075 * RETURNS
3077 * True on success, false if the handle was bad is not a communications device.
3079 BOOL WINAPI SetCommConfig(
3080 HANDLE hFile, /* The communications device. */
3081 LPCOMMCONFIG lpCommConfig /* The desired configuration. */
3083 TRACE("(%x %p)\n",hFile,lpCommConfig);
3084 return SetCommState(hFile,&lpCommConfig->dcb);
3087 /***********************************************************************
3088 * SetDefaultCommConfigA (KERNEL32.638)
3090 * Initializes the default configuration for the specified communication
3091 * device. (ascii)
3093 * RETURNS
3095 * True if the device was found and the defaults set, false otherwise
3097 BOOL WINAPI SetDefaultCommConfigA(
3098 LPCSTR lpszDevice, /* The ascii name of the device targeted for configuration. */
3099 LPCOMMCONFIG lpCommConfig, /* The default configuration for the device. */
3100 DWORD dwSize /* The number of bytes in the configuration structure. */
3102 FARPROC lpfnSetDefaultCommConfig;
3103 HMODULE hConfigModule;
3104 BOOL r;
3106 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
3108 hConfigModule = LoadLibraryA(lpszSerialUI);
3109 if(!hConfigModule)
3110 return FALSE;
3112 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
3114 if(! lpfnSetDefaultCommConfig)
3115 return TRUE;
3117 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
3119 /* UnloadLibrary(hConfigModule); */
3121 return r;
3125 /***********************************************************************
3126 * SetDefaultCommConfigW (KERNEL32.639)
3128 * Initializes the default configuration for the specified
3129 * communication device. (unicode)
3131 * RETURNS
3134 BOOL WINAPI SetDefaultCommConfigW(
3135 LPCWSTR lpszDevice, /* The unicode name of the device targeted for configuration. */
3136 LPCOMMCONFIG lpCommConfig, /* The default configuration for the device. */
3137 DWORD dwSize /* The number of bytes in the configuration structure. */
3139 BOOL r;
3140 LPSTR lpDeviceA;
3142 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
3144 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
3145 if(lpDeviceA)
3146 return FALSE;
3147 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
3148 HeapFree( GetProcessHeap(), 0, lpDeviceA );
3149 return r;
3153 /***********************************************************************
3154 * GetDefaultCommConfigA (KERNEL32.313)
3156 * Acquires the default configuration of the specified communication device. (unicode)
3158 * RETURNS
3160 * True on successful reading of the default configuration,
3161 * if the device is not found or the buffer is too small.
3163 BOOL WINAPI GetDefaultCommConfigA(
3164 LPCSTR lpszName, /* The ascii name of the device targeted for configuration. */
3165 LPCOMMCONFIG lpCC, /* The default configuration for the device. */
3166 LPDWORD lpdwSize ) /* Initially the size of the default configuration buffer,
3167 afterwards the number of bytes copied to the buffer or the needed size of the buffer. */
3169 LPDCB lpdcb = &(lpCC->dcb);
3170 char temp[40];
3172 if (strncasecmp(lpszName,"COM",3)) {
3173 ERR("not implemented for <%s>\n", lpszName);
3174 return FALSE;
3177 if (!ValidCOMPort(lpszName[3]-'1'))
3178 return FALSE;
3180 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
3181 if (*lpdwSize < sizeof(COMMCONFIG)) {
3182 *lpdwSize = sizeof(COMMCONFIG);
3183 return FALSE;
3186 *lpdwSize = sizeof(COMMCONFIG);
3188 lpCC->dwSize = sizeof(COMMCONFIG);
3189 lpCC->wVersion = 1;
3190 lpCC->dwProviderSubType = PST_RS232;
3191 lpCC->dwProviderOffset = 0L;
3192 lpCC->dwProviderSize = 0L;
3194 (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
3195 FIXME("setting %s as default\n", temp);
3197 return BuildCommDCBA( temp, lpdcb);
3200 /**************************************************************************
3201 * GetDefaultCommConfigW (KERNEL32.314)
3203 * Acquires the default configuration of the specified communication device. (unicode)
3205 * RETURNS
3207 * True on successful reading of the default configuration,
3208 * if the device is not found or the buffer is too small.
3210 BOOL WINAPI GetDefaultCommConfigW(
3211 LPCWSTR lpszName, /* The unicode name of the device targeted for configuration. */
3212 LPCOMMCONFIG lpCC, /* The default configuration for the device. */
3213 LPDWORD lpdwSize /* Initially the size of the default configuration buffer,
3214 afterwards the number of bytes copied to the buffer or the needed size of the buffer. */
3216 BOOL ret = FALSE;
3217 LPSTR lpszNameA;
3219 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
3220 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
3221 if (lpszNameA)
3223 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
3224 HeapFree( GetProcessHeap(), 0, lpszNameA );
3226 return ret;