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.
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
51 #include <sys/ioctl.h>
54 #ifdef HAVE_SYS_MODEM_H
55 # include <sys/modem.h>
57 #ifdef HAVE_SYS_STRTIO_H
58 # include <sys/strtio.h>
67 #include "wine/port.h"
68 #include "wine/server.h"
73 #include "debugtools.h"
75 DEFAULT_DEBUG_CHANNEL(comm);
77 #if !defined(TIOCINQ) && defined(FIONREAD)
78 #define TIOCINQ FIONREAD
81 /* window's semi documented modem status register */
82 #define COMM_MSR_OFFSET 35
87 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
92 #define CMSPAR 0x40000000 /* stick parity */
97 struct DosDeviceStruct {
98 char *devicename; /* /dev/ttyS0 */
105 int commerror, eventmask;
108 unsigned ibuf_size,ibuf_head,ibuf_tail;
109 unsigned obuf_size,obuf_head,obuf_tail;
111 int wnd, n_read, n_write;
112 OVERLAPPED read_ov, write_ov;
113 /* save terminal states */
115 /* pointer to unknown(==undocumented) comm structure */
120 static struct DosDeviceStruct COM[MAX_PORTS];
121 static struct DosDeviceStruct LPT[MAX_PORTS];
123 /* update window's semi documented modem status register */
124 /* see knowledge base Q101417 */
125 static void COMM_MSRUpdate( HANDLE handle, UCHAR * pMsr )
130 if(!GetCommModemStatus(handle,&mstat))
133 if(mstat & MS_CTS_ON) tmpmsr |= MSR_CTS;
134 if(mstat & MS_DSR_ON) tmpmsr |= MSR_DSR;
135 if(mstat & MS_RING_ON) tmpmsr |= MSR_RI;
136 if(mstat & MS_RLSD_ON) tmpmsr |= MSR_RLSD;
137 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
143 char option[10], temp[256], *btemp;
146 for (x=0; x!=MAX_PORTS; x++) {
147 strcpy(option,"COMx");
151 PROFILE_GetWineIniString( "serialports", option, "*",
152 temp, sizeof(temp) );
153 if (!strcmp(temp, "*") || *temp == '\0')
154 COM[x].devicename = NULL;
156 btemp = strchr(temp,',');
159 COM[x].baudrate = atoi(btemp);
161 COM[x].baudrate = -1;
164 if (!S_ISCHR(st.st_mode))
165 WARN("Can't use `%s' as %s !\n", temp, option);
167 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
168 WARN("Can't malloc for device info!\n");
171 strcpy(COM[x].devicename, temp);
173 TRACE("%s = %s\n", option, COM[x].devicename);
176 strcpy(option, "LPTx");
180 PROFILE_GetWineIniString( "parallelports", option, "*",
181 temp, sizeof(temp) );
182 if (!strcmp(temp, "*") || *temp == '\0')
183 LPT[x].devicename = NULL;
186 if (!S_ISCHR(st.st_mode))
187 WARN("Can't use `%s' as %s !\n", temp, option);
189 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
190 WARN("Can't malloc for device info!\n");
193 strcpy(LPT[x].devicename, temp);
195 TRACE("%s = %s\n", option, LPT[x].devicename);
202 static struct DosDeviceStruct *GetDeviceStruct(int index)
204 if ((index&0x7F)<=MAX_PORTS) {
205 if (!(index&FLAG_LPT)) {
206 if (COM[index].handle)
210 if (LPT[index].handle)
218 static int GetCommPort_ov(LPOVERLAPPED ov, int write)
222 for (x=0; x<MAX_PORTS; x++) {
223 if (ov == (write?&COM[x].write_ov:&COM[x].read_ov))
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);
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;
268 return ioctl(fd, TIOCMSET, &mstat);
271 static void comm_waitread(struct DosDeviceStruct *ptr);
272 static void comm_waitwrite(struct DosDeviceStruct *ptr);
274 static VOID WINAPI COMM16_ReadComplete(DWORD status, DWORD len, LPOVERLAPPED ov)
278 int cid = GetCommPort_ov(ov,0);
279 struct DosDeviceStruct *ptr;
282 ERR("async write with bad overlapped pointer\n");
287 /* read data from comm port */
288 if (status != STATUS_SUCCESS) {
289 ERR("async read failed\n");
290 COM[cid].commerror = CE_RXOVER;
293 TRACE("async read completed %ld bytes\n",len);
295 prev = comm_inbuf(ptr);
297 /* check for events */
298 if ((ptr->eventmask & EV_RXFLAG) &&
299 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
300 *(WORD*)(COM[cid].unknown) |= EV_RXFLAG;
303 if (ptr->eventmask & EV_RXCHAR) {
304 *(WORD*)(COM[cid].unknown) |= EV_RXCHAR;
308 /* advance buffer position */
309 ptr->ibuf_head += len;
310 if (ptr->ibuf_head >= ptr->ibuf_size)
313 /* check for notification */
314 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
315 (comm_inbuf(ptr)>=ptr->n_read)) {
316 /* passed the receive notification threshold */
320 /* send notifications, if any */
321 if (ptr->wnd && mask) {
322 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
323 if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
326 /* on real windows, this could cause problems, since it is recursive */
327 /* restart the receive */
331 static VOID WINAPI COMM16_WriteComplete(DWORD status, DWORD len, LPOVERLAPPED ov)
335 int cid = GetCommPort_ov(ov,1);
336 struct DosDeviceStruct *ptr;
339 ERR("async write with bad overlapped pointer\n");
344 /* read data from comm port */
345 if (status != STATUS_SUCCESS) {
346 ERR("async write failed\n");
347 COM[cid].commerror = CE_RXOVER;
350 TRACE("async write completed %ld bytes\n",len);
352 /* update the buffer pointers */
353 prev = comm_outbuf(&COM[cid]);
354 ptr->obuf_tail += len;
355 if (ptr->obuf_tail >= ptr->obuf_size)
358 /* write any TransmitCommChar character */
360 if(!WriteFile(ptr->handle, &(ptr->xmit), 1, &len, NULL))
362 if (len > 0) ptr->xmit = -1;
365 /* write from output queue */
366 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ?
367 ptr->obuf_head : ptr->obuf_size) - ptr->obuf_tail;
369 /* check for notification */
370 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
371 (comm_outbuf(ptr)<ptr->n_write)) {
372 /* passed the transmit notification threshold */
376 /* send notifications, if any */
377 if (ptr->wnd && mask) {
378 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
379 if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
382 /* start again if necessary */
387 static void comm_waitread(struct DosDeviceStruct *ptr)
391 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ?
392 (ptr->ibuf_tail-1) : ptr->ibuf_size) - ptr->ibuf_head;
393 /* FIXME: get timeouts working properly so we can read bleft bytes */
394 ReadFileEx(ptr->handle,
395 ptr->inbuf + ptr->ibuf_head,
398 COMM16_ReadComplete);
401 static void comm_waitwrite(struct DosDeviceStruct *ptr)
405 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ?
406 ptr->obuf_head : ptr->obuf_size) - ptr->obuf_tail;
407 WriteFileEx(ptr->handle,
408 ptr->outbuf + ptr->obuf_tail,
411 COMM16_WriteComplete);
414 /**************************************************************************
415 * BuildCommDCB (USER.213)
417 * According to the ECMA-234 (368.3) the function will return FALSE on
418 * success, otherwise it will return -1.
419 * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA
422 INT16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
424 /* "COM1:96,n,8,1" */
427 char *ptr, temp[256];
429 TRACE("(%s), ptr %p\n", device, lpdcb);
431 if (!strncasecmp(device,"COM",3)) {
432 port = device[3] - '0';
436 ERR("BUG ! COM0 can't exist!\n");
440 if (!ValidCOMPort(port)) {
441 FIXME("invalid COM port %d?\n",port);
445 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
452 if (*(device+4) != ':')
455 strcpy(temp,device+5);
456 ptr = strtok(temp, ", ");
458 if (COM[port].baudrate > 0)
459 lpdcb->BaudRate = COM[port].baudrate;
463 /* DOS/Windows only compares the first two numbers
464 * and assigns an appropriate baud rate.
465 * You can supply 961324245, it still returns 9600 ! */
468 WARN("Unknown baudrate string '%s' !\n", ptr);
469 return -1; /* error: less than 2 chars */
490 WARN("Unknown baudrate indicator %d !\n", rate);
494 lpdcb->BaudRate = rate;
496 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
498 ptr = strtok(NULL, ", ");
500 *ptr = toupper(*ptr);
502 TRACE("parity (%c)\n", *ptr);
503 lpdcb->fParity = TRUE;
506 lpdcb->Parity = NOPARITY;
507 lpdcb->fParity = FALSE;
510 lpdcb->Parity = EVENPARITY;
513 lpdcb->Parity = MARKPARITY;
516 lpdcb->Parity = ODDPARITY;
519 WARN("Unknown parity `%c'!\n", *ptr);
523 ptr = strtok(NULL, ", ");
524 TRACE("charsize (%c)\n", *ptr);
525 lpdcb->ByteSize = *ptr - '0';
527 ptr = strtok(NULL, ", ");
528 TRACE("stopbits (%c)\n", *ptr);
531 lpdcb->StopBits = ONESTOPBIT;
534 lpdcb->StopBits = TWOSTOPBITS;
537 WARN("Unknown # of stopbits `%c'!\n", *ptr);
545 /*****************************************************************************
546 * OpenComm (USER.200)
548 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
553 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
555 if (strlen(device) < 4)
558 port = device[3] - '0';
561 ERR("BUG ! COM0 or LPT0 don't exist !\n");
563 if (!strncasecmp(device,"COM",3)) {
565 TRACE("%s = %s\n", device, COM[port].devicename);
567 if (!ValidCOMPort(port))
570 if (COM[port].handle)
573 handle = CreateFileA(device, GENERIC_READ|GENERIC_WRITE,
574 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
575 if (handle == INVALID_HANDLE_VALUE) {
576 ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno));
579 COM[port].unknown = SEGPTR_ALLOC(40);
580 memset(COM[port].unknown, 0, 40);
581 COM[port].handle = handle;
582 COM[port].commerror = 0;
583 COM[port].eventmask = 0;
584 COM[port].evtchar = 0; /* FIXME: default? */
585 /* save terminal state */
586 GetCommState16(port,&COM[port].dcb);
587 /* set default parameters */
588 if(COM[port].baudrate>-1){
590 memcpy(&dcb,&COM[port].dcb,sizeof dcb);
591 dcb.BaudRate=COM[port].baudrate;
593 * databits, parity, stopbits
595 SetCommState16( &dcb);
597 /* init priority characters */
598 COM[port].unget = -1;
600 /* allocate buffers */
601 COM[port].ibuf_size = cbInQueue;
602 COM[port].ibuf_head = COM[port].ibuf_tail = 0;
603 COM[port].obuf_size = cbOutQueue;
604 COM[port].obuf_head = COM[port].obuf_tail = 0;
606 COM[port].inbuf = malloc(cbInQueue);
607 if (COM[port].inbuf) {
608 COM[port].outbuf = malloc(cbOutQueue);
609 if (!COM[port].outbuf)
610 free(COM[port].inbuf);
611 } else COM[port].outbuf = NULL;
612 if (!COM[port].outbuf) {
613 /* not enough memory */
614 SetCommState16(&COM[port].dcb);
615 CloseHandle(COM[port].handle);
616 ERR("out of memory\n");
620 ZeroMemory(&COM[port].read_ov,sizeof (OVERLAPPED));
621 ZeroMemory(&COM[port].write_ov,sizeof (OVERLAPPED));
622 COM[port].read_ov.hEvent = CreateEventA(NULL,0,0,NULL);
623 COM[port].write_ov.hEvent = CreateEventA(NULL,0,0,NULL);
625 comm_waitread( &COM[port] );
631 if (!strncasecmp(device,"LPT",3)) {
633 if (!ValidLPTPort(port))
636 if (LPT[port].handle)
639 handle = CreateFileA(device, GENERIC_READ|GENERIC_WRITE,
640 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
641 if (handle == INVALID_HANDLE_VALUE) {
644 LPT[port].handle = handle;
645 LPT[port].commerror = 0;
646 LPT[port].eventmask = 0;
647 return port|FLAG_LPT;
653 /*****************************************************************************
654 * CloseComm (USER.207)
656 INT16 WINAPI CloseComm16(INT16 cid)
658 struct DosDeviceStruct *ptr;
660 TRACE("cid=%d\n", cid);
661 if ((ptr = GetDeviceStruct(cid)) == NULL) {
662 FIXME("no cid=%d found!\n", cid);
665 if (!(cid&FLAG_LPT)) {
667 SEGPTR_FREE(COM[cid].unknown); /* [LW] */
669 CloseHandle(COM[cid].read_ov.hEvent);
670 CloseHandle(COM[cid].write_ov.hEvent);
676 /* reset modem lines */
677 SetCommState16(&COM[cid].dcb);
680 if (!CloseHandle(ptr->handle)) {
681 ptr->commerror = WinError();
682 /* FIXME: should we clear ptr->handle here? */
691 /*****************************************************************************
692 * SetCommBreak (USER.210)
694 INT16 WINAPI SetCommBreak16(INT16 cid)
696 struct DosDeviceStruct *ptr;
698 TRACE("cid=%d\n", cid);
699 if ((ptr = GetDeviceStruct(cid)) == NULL) {
700 FIXME("no cid=%d found!\n", cid);
709 /*****************************************************************************
710 * ClearCommBreak (USER.211)
712 INT16 WINAPI ClearCommBreak16(INT16 cid)
714 struct DosDeviceStruct *ptr;
716 TRACE("cid=%d\n", cid);
717 if (!(ptr = GetDeviceStruct(cid))) {
718 FIXME("no cid=%d found!\n", cid);
726 /*****************************************************************************
727 * EscapeCommFunction (USER.214)
729 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
731 struct DosDeviceStruct *ptr;
734 TRACE("cid=%d, function=%d\n", cid, nFunction);
738 TRACE("GETMAXCOM\n");
739 for (max = MAX_PORTS;!COM[max].devicename;max--)
744 TRACE("GETMAXLPT\n");
745 for (max = MAX_PORTS;!LPT[max].devicename;max--)
747 return FLAG_LPT + max;
750 TRACE("GETBASEIRQ\n");
751 /* FIXME: use tables */
752 /* just fake something for now */
753 if (cid & FLAG_LPT) {
754 /* LPT1: irq 7, LPT2: irq 5 */
755 return (cid & 0x7f) ? 5 : 7;
757 /* COM1: irq 4, COM2: irq 3,
758 COM3: irq 4, COM4: irq 3 */
759 return 4 - (cid & 1);
763 if ((ptr = GetDeviceStruct(cid)) == NULL) {
764 FIXME("no cid=%d found!\n", cid);
776 if(EscapeCommFunction(ptr->handle,nFunction))
779 ptr->commerror = WinError();
786 WARN("(cid=%d,nFunction=%d): Unknown function\n",
792 /*****************************************************************************
793 * FlushComm (USER.215)
795 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
798 struct DosDeviceStruct *ptr;
800 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
801 if ((ptr = GetDeviceStruct(cid)) == NULL) {
802 FIXME("no cid=%d found!\n", cid);
807 queue = PURGE_TXABORT;
808 ptr->obuf_tail = ptr->obuf_head;
811 queue = PURGE_RXABORT;
812 ptr->ibuf_head = ptr->ibuf_tail;
815 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
820 if (!PurgeComm(ptr->handle,queue)) {
821 ptr->commerror = WinError();
829 /********************************************************************
830 * GetCommError (USER.203)
832 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
835 struct DosDeviceStruct *ptr;
838 if ((ptr = GetDeviceStruct(cid)) == NULL) {
839 FIXME("no handle for cid = %0x!\n",cid);
843 WARN(" cid %d not comm port\n",cid);
846 stol = (unsigned char *)COM[cid].unknown + COMM_MSR_OFFSET;
847 COMM_MSRUpdate( ptr->handle, stol );
854 rw_events[0] = COM[cid].read_ov.hEvent;
855 rw_events[1] = COM[cid].write_ov.hEvent;
857 WaitForMultipleObjectsEx(2,&rw_events[0],FALSE,1,TRUE);
859 lpStat->cbOutQue = comm_outbuf(ptr);
860 lpStat->cbInQue = comm_inbuf(ptr);
862 TRACE("cid %d, error %d, stat %d in %d out %d, stol %x\n",
863 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
864 lpStat->cbOutQue, *stol);
867 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
868 cid, ptr->commerror, *stol);
870 /* Return any errors and clear it */
871 temperror = ptr->commerror;
876 /*****************************************************************************
877 * SetCommEventMask (USER.208)
879 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
881 struct DosDeviceStruct *ptr;
884 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
885 if ((ptr = GetDeviceStruct(cid)) == NULL) {
886 FIXME("no handle for cid = %0x!\n",cid);
890 ptr->eventmask = fuEvtMask;
892 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
893 WARN(" cid %d not comm port\n",cid);
896 /* it's a COM port ? -> modify flags */
897 stol = (unsigned char *)COM[cid].unknown + COMM_MSR_OFFSET;
898 COMM_MSRUpdate( ptr->handle, stol );
900 TRACE(" modem dcd construct %x\n",*stol);
901 return SEGPTR_GET(COM[cid].unknown);
904 /*****************************************************************************
905 * GetCommEventMask (USER.209)
907 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
909 struct DosDeviceStruct *ptr;
912 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
913 if ((ptr = GetDeviceStruct(cid)) == NULL) {
914 FIXME("no handle for cid = %0x!\n",cid);
918 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
919 WARN(" cid %d not comm port\n",cid);
923 events = *(WORD*)(COM[cid].unknown) & fnEvtClear;
924 *(WORD*)(COM[cid].unknown) &= ~fnEvtClear;
928 /*****************************************************************************
929 * SetCommState (USER.201)
931 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
933 struct DosDeviceStruct *ptr;
936 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
937 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
938 FIXME("no handle for cid = %0x!\n",lpdcb->Id);
942 memset(&dcb,0,sizeof dcb);
943 dcb.DCBlength = sizeof dcb;
944 if(lpdcb->BaudRate==57601)
945 dcb.BaudRate = 115200;
947 dcb.BaudRate = lpdcb->BaudRate;
949 dcb.ByteSize=lpdcb->ByteSize;
950 dcb.StopBits=lpdcb->StopBits;
952 dcb.fParity=lpdcb->fParity;
953 dcb.Parity=lpdcb->Parity;
955 dcb.fOutxCtsFlow = lpdcb->fOutxCtsFlow;
957 if (lpdcb->fDtrflow || lpdcb->fRtsflow)
958 dcb.fRtsControl = TRUE;
960 if (lpdcb->fDtrDisable)
961 dcb.fDtrControl = TRUE;
963 ptr->evtchar = lpdcb->EvtChar;
965 dcb.fInX = lpdcb->fInX;
966 dcb.fOutX = lpdcb->fOutX;
968 if (!SetCommState(ptr->handle,&dcb)) {
969 ptr->commerror = WinError();
977 /*****************************************************************************
978 * GetCommState (USER.202)
980 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
982 struct DosDeviceStruct *ptr;
985 TRACE("cid %d, ptr %p\n", cid, lpdcb);
986 if ((ptr = GetDeviceStruct(cid)) == NULL) {
987 FIXME("no handle for cid = %0x!\n",cid);
990 if (!GetCommState(ptr->handle,&dcb)) {
991 ptr->commerror = WinError();
996 if(dcb.BaudRate<0x10000)
997 lpdcb->BaudRate = dcb.BaudRate;
998 else if(dcb.BaudRate==115200)
999 lpdcb->BaudRate = 57601;
1001 WARN("Baud rate can't be converted\n");
1002 lpdcb->BaudRate = 57601;
1004 lpdcb->ByteSize = dcb.ByteSize;
1005 lpdcb->fParity = dcb.fParity;
1006 lpdcb->Parity = dcb.Parity;
1007 lpdcb->StopBits = dcb.StopBits;
1009 lpdcb->RlsTimeout = 50;
1010 lpdcb->CtsTimeout = 50;
1011 lpdcb->DsrTimeout = 50;
1015 lpdcb->fDtrDisable = 0;
1017 lpdcb->fDtrflow = (dcb.fDtrControl==DTR_CONTROL_ENABLE);
1018 lpdcb->fRtsflow = (dcb.fRtsControl==RTS_CONTROL_ENABLE);
1019 lpdcb->fOutxCtsFlow = dcb.fOutxCtsFlow;
1020 lpdcb->fOutxDsrFlow = dcb.fOutxDsrFlow;
1021 lpdcb->fDtrDisable = (dcb.fDtrControl==DTR_CONTROL_DISABLE);
1023 lpdcb->fInX = dcb.fInX;
1025 lpdcb->fOutX = dcb.fOutX;
1031 lpdcb->XoffLim = 10;
1033 lpdcb->EvtChar = ptr->evtchar;
1039 /*****************************************************************************
1040 * TransmitCommChar (USER.206)
1042 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1044 struct DosDeviceStruct *ptr;
1046 TRACE("cid %d, data %d \n", cid, chTransmit);
1047 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1048 FIXME("no handle for cid = %0x!\n",cid);
1052 if (ptr->suspended) {
1053 ptr->commerror = IE_HARDWARE;
1057 if (ptr->xmit >= 0) {
1058 /* character already queued */
1059 /* FIXME: which error would Windows return? */
1060 ptr->commerror = CE_TXFULL;
1064 if (ptr->obuf_head == ptr->obuf_tail) {
1065 /* transmit queue empty, try to transmit directly */
1067 if(!WriteFile(ptr->handle, &chTransmit, 1, &len, NULL)) {
1068 /* didn't work, queue it */
1069 ptr->xmit = chTransmit;
1070 comm_waitwrite(ptr);
1073 /* data in queue, let this char be transmitted next */
1074 ptr->xmit = chTransmit;
1075 comm_waitwrite(ptr);
1082 /*****************************************************************************
1083 * UngetCommChar (USER.212)
1085 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1087 struct DosDeviceStruct *ptr;
1089 TRACE("cid %d (char %d)\n", cid, chUnget);
1090 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1091 FIXME("no handle for cid = %0x!\n",cid);
1095 if (ptr->suspended) {
1096 ptr->commerror = IE_HARDWARE;
1100 if (ptr->unget>=0) {
1101 /* character already queued */
1102 /* FIXME: which error would Windows return? */
1103 ptr->commerror = CE_RXOVER;
1107 ptr->unget = chUnget;
1113 /*****************************************************************************
1114 * ReadComm (USER.204)
1116 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1119 struct DosDeviceStruct *ptr;
1120 LPSTR orgBuf = lpvBuf;
1122 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1123 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1124 FIXME("no handle for cid = %0x!\n",cid);
1128 if (ptr->suspended) {
1129 ptr->commerror = IE_HARDWARE;
1133 /* read unget character */
1134 if (ptr->unget>=0) {
1135 *lpvBuf++ = ptr->unget;
1142 /* read from receive buffer */
1143 while (length < cbRead) {
1144 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1145 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1147 if ((cbRead - length) < status)
1148 status = cbRead - length;
1150 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1151 ptr->ibuf_tail += status;
1152 if (ptr->ibuf_tail >= ptr->ibuf_size)
1158 TRACE("%.*s\n", length, orgBuf);
1163 /*****************************************************************************
1164 * WriteComm (USER.205)
1166 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1169 struct DosDeviceStruct *ptr;
1171 TRACE("cid %d, ptr %p, length %d\n",
1172 cid, lpvBuf, cbWrite);
1173 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1174 FIXME("no handle for cid = %0x!\n",cid);
1178 if (ptr->suspended) {
1179 ptr->commerror = IE_HARDWARE;
1183 TRACE("%.*s\n", cbWrite, lpvBuf );
1186 while (length < cbWrite) {
1187 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1188 /* no data queued, try to write directly */
1189 if(!WriteFile(ptr->handle, lpvBuf, cbWrite - length, (LPDWORD)&status, NULL))
1197 /* can't write directly, put into transmit buffer */
1198 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1199 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1201 if ((cbWrite - length) < status)
1202 status = cbWrite - length;
1203 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1204 ptr->obuf_head += status;
1205 if (ptr->obuf_head >= ptr->obuf_size)
1209 comm_waitwrite(ptr);
1216 /***********************************************************************
1217 * EnableCommNotification (USER.245)
1219 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1220 INT16 cbWriteNotify, INT16 cbOutQueue )
1222 struct DosDeviceStruct *ptr;
1224 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1225 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1226 FIXME("no handle for cid = %0x!\n",cid);
1230 ptr->n_read = cbWriteNotify;
1231 ptr->n_write = cbOutQueue;
1236 /**************************************************************************
1237 * BuildCommDCBA (KERNEL32.@)
1239 * Updates a device control block data structure with values from an
1240 * ascii device control string. The device control string has two forms
1241 * normal and extended, it must be exclusively in one or the other form.
1245 * True on success, false on an malformed control string.
1247 BOOL WINAPI BuildCommDCBA(
1248 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
1249 LPDCB lpdcb) /* [out] The device control block to be updated. */
1251 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1254 /**************************************************************************
1255 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
1257 * Updates a device control block data structure with values from an
1258 * ascii device control string. Taking time out values from a time outs
1259 * struct if desired by the control string.
1263 * True on success, false bad handles etc
1265 BOOL WINAPI BuildCommDCBAndTimeoutsA(
1266 LPCSTR device, /* [in] The ascii device control string. */
1267 LPDCB lpdcb, /* [out] The device control block to be updated. */
1268 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
1273 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1275 if (!strncasecmp(device,"COM",3)) {
1278 ERR("BUG! COM0 can't exist!\n");
1281 if (!ValidCOMPort(port))
1283 if (*(device+4)!=':')
1285 temp=(LPSTR)(device+5);
1289 lpdcb->DCBlength = sizeof(DCB);
1290 if (strchr(temp,',')) { /* old style */
1293 char last=temp[strlen(temp)-1];
1295 ret=BuildCommDCB16(device,&dcb16);
1298 lpdcb->BaudRate = dcb16.BaudRate;
1299 lpdcb->ByteSize = dcb16.ByteSize;
1300 lpdcb->fBinary = dcb16.fBinary;
1301 lpdcb->Parity = dcb16.Parity;
1302 lpdcb->fParity = dcb16.fParity;
1303 lpdcb->fNull = dcb16.fNull;
1304 lpdcb->StopBits = dcb16.StopBits;
1307 lpdcb->fOutX = TRUE;
1308 lpdcb->fOutxCtsFlow = FALSE;
1309 lpdcb->fOutxDsrFlow = FALSE;
1310 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1311 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1312 } else if (last=='p') {
1313 lpdcb->fInX = FALSE;
1314 lpdcb->fOutX = FALSE;
1315 lpdcb->fOutxCtsFlow = TRUE;
1316 lpdcb->fOutxDsrFlow = TRUE;
1317 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1318 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1320 lpdcb->fInX = FALSE;
1321 lpdcb->fOutX = FALSE;
1322 lpdcb->fOutxCtsFlow = FALSE;
1323 lpdcb->fOutxDsrFlow = FALSE;
1324 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1325 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1327 lpdcb->XonChar = dcb16.XonChar;
1328 lpdcb->XoffChar = dcb16.XoffChar;
1329 lpdcb->ErrorChar= dcb16.PeChar;
1330 lpdcb->fErrorChar= dcb16.fPeChar;
1331 lpdcb->EofChar = dcb16.EofChar;
1332 lpdcb->EvtChar = dcb16.EvtChar;
1333 lpdcb->XonLim = dcb16.XonLim;
1334 lpdcb->XoffLim = dcb16.XoffLim;
1337 ptr=strtok(temp," ");
1342 if (!strncmp("baud=",ptr,5)) {
1343 if (!sscanf(ptr+5,"%ld",&x))
1344 WARN("Couldn't parse %s\n",ptr);
1345 lpdcb->BaudRate = x;
1348 if (!strncmp("stop=",ptr,5)) {
1349 if (!sscanf(ptr+5,"%ld",&x))
1350 WARN("Couldn't parse %s\n",ptr);
1351 lpdcb->StopBits = x;
1354 if (!strncmp("data=",ptr,5)) {
1355 if (!sscanf(ptr+5,"%ld",&x))
1356 WARN("Couldn't parse %s\n",ptr);
1357 lpdcb->ByteSize = x;
1360 if (!strncmp("parity=",ptr,7)) {
1361 lpdcb->fParity = TRUE;
1364 lpdcb->fParity = FALSE;
1365 lpdcb->Parity = NOPARITY;
1368 lpdcb->Parity = EVENPARITY;
1371 lpdcb->Parity = ODDPARITY;
1374 lpdcb->Parity = MARKPARITY;
1380 ERR("Unhandled specifier '%s', please report.\n",ptr);
1381 ptr=strtok(NULL," ");
1383 if (lpdcb->BaudRate==110)
1384 lpdcb->StopBits = 2;
1388 /**************************************************************************
1389 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
1391 * Updates a device control block data structure with values from an
1392 * unicode device control string. Taking time out values from a time outs
1393 * struct if desired by the control string.
1397 * True on success, false bad handles etc.
1399 BOOL WINAPI BuildCommDCBAndTimeoutsW(
1400 LPCWSTR devid, /* [in] The unicode device control string. */
1401 LPDCB lpdcb, /* [out] The device control block to be updated. */
1402 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
1407 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1408 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1411 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1412 HeapFree( GetProcessHeap(), 0, devidA );
1417 /**************************************************************************
1418 * BuildCommDCBW (KERNEL32.@)
1420 * Updates a device control block structure with values from an
1421 * unicode device control string. The device control string has two forms
1422 * normal and extended, it must be exclusively in one or the other form.
1426 * True on success, false on an malformed control string.
1428 BOOL WINAPI BuildCommDCBW(
1429 LPCWSTR devid, /* [in] The unicode device control string. */
1430 LPDCB lpdcb) /* [out] The device control block to be updated. */
1432 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1435 /* FIXME: having these global for win32 for now */
1438 /*****************************************************************************
1439 * SetCommBreak (KERNEL32.@)
1441 * Halts the transmission of characters to a communications device.
1445 * True on success, and false if the communications device could not be found,
1446 * the control is not supported.
1450 * Only TIOCSBRK and TIOCCBRK are supported.
1452 BOOL WINAPI SetCommBreak(
1453 HANDLE handle) /* [in] The communictions device to suspend. */
1455 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1458 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1460 TRACE("FILE_GetUnixHandle failed\n");
1463 result = ioctl(fd,TIOCSBRK,0);
1467 TRACE("ioctl failed\n");
1468 SetLastError(ERROR_NOT_SUPPORTED);
1473 FIXME("ioctl not available\n");
1474 SetLastError(ERROR_NOT_SUPPORTED);
1479 /*****************************************************************************
1480 * ClearCommBreak (KERNEL32.@)
1482 * Resumes character transmission from a communication device.
1486 * True on success and false if the communications device could not be found.
1490 * Only TIOCSBRK and TIOCCBRK are supported.
1492 BOOL WINAPI ClearCommBreak(
1493 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
1495 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1498 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1500 TRACE("FILE_GetUnixHandle failed\n");
1503 result = ioctl(fd,TIOCCBRK,0);
1507 TRACE("ioctl failed\n");
1508 SetLastError(ERROR_NOT_SUPPORTED);
1513 FIXME("ioctl not available\n");
1514 SetLastError(ERROR_NOT_SUPPORTED);
1519 /*****************************************************************************
1520 * EscapeCommFunction (KERNEL32.@)
1522 * Directs a communication device to perform an extended function.
1526 * True or requested data on successful completion of the command,
1527 * false if the device is not present cannot execute the command
1528 * or the command failed.
1530 BOOL WINAPI EscapeCommFunction(
1531 HANDLE handle, /* [in] The communication device to perform the extended function. */
1532 UINT nFunction) /* [in] The extended function to be performed. */
1534 int fd,direct=FALSE,result=FALSE;
1535 struct termios port;
1537 TRACE("handle %d, function=%d\n", handle, nFunction);
1538 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1540 FIXME("handle %d not found.\n",handle);
1544 if (tcgetattr(fd,&port) == -1) {
1545 commerror=WinError();
1550 switch (nFunction) {
1559 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1567 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1575 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1583 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1589 port.c_iflag |= IXOFF;
1594 port.c_iflag |= IXON;
1597 TRACE("setbreak\n");
1600 result = ioctl(fd,TIOCSBRK,0);
1604 TRACE("clrbreak\n");
1607 result = ioctl(fd,TIOCCBRK,0);
1611 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1617 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1618 commerror = WinError();
1628 commerror=WinError();
1637 /********************************************************************
1638 * PurgeComm (KERNEL32.@)
1640 * Terminates pending operations and/or discards buffers on a
1641 * communication resource.
1645 * True on success and false if the communications handle is bad.
1647 BOOL WINAPI PurgeComm(
1648 HANDLE handle, /* [in] The communication resource to be purged. */
1649 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
1653 TRACE("handle %d, flags %lx\n", handle, flags);
1655 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1657 FIXME("no handle %d found\n",handle);
1662 ** not exactly sure how these are different
1663 ** Perhaps if we had our own internal queues, one flushes them
1664 ** and the other flushes the kernel's buffers.
1666 if(flags&PURGE_TXABORT)
1667 tcflush(fd,TCOFLUSH);
1668 if(flags&PURGE_RXABORT)
1669 tcflush(fd,TCIFLUSH);
1670 if(flags&PURGE_TXCLEAR)
1671 tcflush(fd,TCOFLUSH);
1672 if(flags&PURGE_RXCLEAR)
1673 tcflush(fd,TCIFLUSH);
1679 /*****************************************************************************
1680 * ClearCommError (KERNEL32.@)
1682 * Enables further I/O operations on a communications resource after
1683 * supplying error and current status information.
1687 * True on success, false if the communication resource handle is bad.
1689 BOOL WINAPI ClearCommError(
1690 HANDLE handle, /* [in] The communication resource with the error. */
1691 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
1692 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
1696 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
1699 FIXME("no handle %d found\n",handle);
1708 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1709 WARN("ioctl returned error\n");
1711 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1715 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1716 WARN("ioctl returned error\n");
1719 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1720 handle, lpStat->cbInQue, lpStat->cbOutQue);
1729 ** After an asynchronous write opperation, the
1730 ** app will call ClearCommError to see if the
1731 ** results are ready yet. It waits for ERROR_IO_PENDING
1733 commerror = ERROR_IO_PENDING;
1738 /*****************************************************************************
1739 * SetupComm (KERNEL32.@)
1741 * Called after CreateFile to hint to the communication resource to use
1742 * specified sizes for input and output buffers rather than the default values.
1746 * True if successful, false if the communications resource handle is bad.
1752 BOOL WINAPI SetupComm(
1753 HANDLE handle, /* [in] The just created communication resource handle. */
1754 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
1755 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
1759 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1760 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
1762 FIXME("handle %d not found?\n",handle);
1769 /*****************************************************************************
1770 * GetCommMask (KERNEL32.@)
1772 * Obtain the events associated with a communication device that will cause a call
1773 * WaitCommEvent to return.
1777 * True on success, fail on bad device handle etc.
1779 BOOL WINAPI GetCommMask(
1780 HANDLE handle, /* [in] The communications device. */
1781 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1785 TRACE("handle %d, mask %p\n", handle, evtmask);
1787 SERVER_START_REQ( get_serial_info )
1789 req->handle = handle;
1790 if ((ret = !SERVER_CALL_ERR()))
1792 if (evtmask) *evtmask = req->eventmask;
1799 /*****************************************************************************
1800 * SetCommMask (KERNEL32.@)
1802 * There be some things we need to hear about yon there communications device.
1803 * (Set which events associated with a communication device should cause
1804 * a call WaitCommEvent to return.)
1808 * True on success, false on bad handle etc.
1810 BOOL WINAPI SetCommMask(
1811 HANDLE handle, /* [in] The communications device. */
1812 DWORD evtmask) /* [in] The events that to be monitored. */
1816 TRACE("handle %d, mask %lx\n", handle, evtmask);
1818 SERVER_START_REQ( set_serial_info )
1820 req->handle = handle;
1821 req->flags = SERIALINFO_SET_MASK;
1822 req->eventmask = evtmask;
1823 ret = !SERVER_CALL_ERR();
1829 /*****************************************************************************
1830 * SetCommState (KERNEL32.@)
1832 * Re-initializes all hardware and control settings of a communications device,
1833 * with values from a device control block without effecting the input and output
1838 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1840 BOOL WINAPI SetCommState(
1841 HANDLE handle, /* [in] The communications device. */
1842 LPDCB lpdcb) /* [out] The device control block. */
1844 struct termios port;
1845 int fd, bytesize, stopbits;
1847 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1848 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1849 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1850 (lpdcb->StopBits == ONESTOPBIT)?1:
1851 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1852 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1853 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1855 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1857 FIXME("no handle %d found\n",handle);
1861 if ((tcgetattr(fd,&port)) == -1) {
1862 int save_error = errno;
1863 commerror = WinError();
1865 ERR("tcgetattr error '%s'\n", strerror(save_error));
1869 port.c_cc[VMIN] = 0;
1870 port.c_cc[VTIME] = 1;
1873 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1875 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1877 port.c_iflag |= (IGNBRK);
1879 port.c_oflag &= ~(OPOST);
1881 port.c_cflag &= ~(HUPCL);
1882 port.c_cflag |= CLOCAL | CREAD;
1884 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1885 port.c_lflag |= NOFLSH;
1888 ** MJM - removed default baudrate settings
1889 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1892 port.c_cflag &= ~CBAUD;
1893 switch (lpdcb->BaudRate) {
1896 port.c_cflag |= B110;
1900 port.c_cflag |= B300;
1904 port.c_cflag |= B600;
1908 port.c_cflag |= B1200;
1912 port.c_cflag |= B2400;
1916 port.c_cflag |= B4800;
1920 port.c_cflag |= B9600;
1924 port.c_cflag |= B19200;
1928 port.c_cflag |= B38400;
1932 port.c_cflag |= B57600;
1937 port.c_cflag |= B115200;
1942 port.c_cflag |= B230400;
1947 port.c_cflag |= B460800;
1951 commerror = IE_BAUDRATE;
1953 ERR("baudrate %ld\n",lpdcb->BaudRate);
1956 #elif !defined(__EMX__)
1957 switch (lpdcb->BaudRate) {
1960 port.c_ospeed = B110;
1964 port.c_ospeed = B300;
1968 port.c_ospeed = B600;
1972 port.c_ospeed = B1200;
1976 port.c_ospeed = B2400;
1980 port.c_ospeed = B4800;
1984 port.c_ospeed = B9600;
1988 port.c_ospeed = B19200;
1992 port.c_ospeed = B38400;
1995 commerror = IE_BAUDRATE;
1997 ERR("baudrate %ld\n",lpdcb->BaudRate);
2000 port.c_ispeed = port.c_ospeed;
2002 bytesize=lpdcb->ByteSize;
2003 stopbits=lpdcb->StopBits;
2006 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
2008 port.c_cflag &= ~(PARENB | PARODD);
2011 port.c_iflag |= INPCK;
2013 port.c_iflag &= ~INPCK;
2014 switch (lpdcb->Parity) {
2018 port.c_cflag |= (PARENB | PARODD);
2021 port.c_cflag |= PARENB;
2024 /* Linux defines mark/space (stick) parity */
2026 port.c_cflag |= (PARENB | CMSPAR);
2029 port.c_cflag |= (PARENB | PARODD | CMSPAR);
2032 /* try the POSIX way */
2034 if( stopbits == ONESTOPBIT) {
2035 stopbits = TWOSTOPBITS;
2036 port.c_iflag &= ~INPCK;
2038 commerror = IE_BYTESIZE;
2040 ERR("Cannot set MARK Parity\n");
2047 port.c_iflag &= ~INPCK;
2049 commerror = IE_BYTESIZE;
2051 ERR("Cannot set SPACE Parity\n");
2057 commerror = IE_BYTESIZE;
2064 port.c_cflag &= ~CSIZE;
2067 port.c_cflag |= CS5;
2070 port.c_cflag |= CS6;
2073 port.c_cflag |= CS7;
2076 port.c_cflag |= CS8;
2079 commerror = IE_BYTESIZE;
2087 port.c_cflag &= ~CSTOPB;
2089 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
2091 port.c_cflag |= CSTOPB;
2094 commerror = IE_BYTESIZE;
2100 if ( lpdcb->fOutxCtsFlow ||
2101 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2104 port.c_cflag |= CRTSCTS;
2108 if (lpdcb->fDtrControl == DTR_CONTROL_ENABLE)
2110 port.c_cflag &= ~CRTSCTS;
2111 TRACE("~CRTSCTS\n");
2116 port.c_iflag |= IXON;
2118 port.c_iflag &= ~IXON;
2120 port.c_iflag |= IXOFF;
2122 port.c_iflag &= ~IXOFF;
2124 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2125 int save_error=errno;
2126 commerror = WinError();
2128 ERR("tcsetattr error '%s'\n", strerror(save_error));
2138 /*****************************************************************************
2139 * GetCommState (KERNEL32.@)
2141 * Fills in a device control block with information from a communications device.
2145 * True on success, false if the communication device handle is bad etc
2149 * XonChar and XoffChar are not set.
2151 BOOL WINAPI GetCommState(
2152 HANDLE handle, /* [in] The communications device. */
2153 LPDCB lpdcb) /* [out] The device control block. */
2155 struct termios port;
2158 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2160 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
2163 ERR("FILE_GetUnixHandle failed\n");
2166 if (tcgetattr(fd, &port) == -1) {
2167 int save_error=errno;
2168 ERR("tcgetattr error '%s'\n", strerror(save_error));
2169 commerror = WinError();
2176 speed= (port.c_cflag & CBAUD);
2178 speed= (cfgetospeed(&port));
2182 lpdcb->BaudRate = 110;
2185 lpdcb->BaudRate = 300;
2188 lpdcb->BaudRate = 600;
2191 lpdcb->BaudRate = 1200;
2194 lpdcb->BaudRate = 2400;
2197 lpdcb->BaudRate = 4800;
2200 lpdcb->BaudRate = 9600;
2203 lpdcb->BaudRate = 19200;
2206 lpdcb->BaudRate = 38400;
2210 lpdcb->BaudRate = 57600;
2215 lpdcb->BaudRate = 115200;
2220 lpdcb->BaudRate = 230400;
2225 lpdcb->BaudRate = 460800;
2229 ERR("unknown speed %x \n",speed);
2232 switch (port.c_cflag & CSIZE) {
2234 lpdcb->ByteSize = 5;
2237 lpdcb->ByteSize = 6;
2240 lpdcb->ByteSize = 7;
2243 lpdcb->ByteSize = 8;
2246 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2249 if(port.c_iflag & INPCK)
2250 lpdcb->fParity = TRUE;
2252 lpdcb->fParity = FALSE;
2254 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
2256 switch (port.c_cflag & (PARENB | PARODD))
2260 lpdcb->Parity = NOPARITY;
2263 lpdcb->Parity = EVENPARITY;
2265 case (PARENB | PARODD):
2266 lpdcb->Parity = ODDPARITY;
2269 case (PARENB | CMSPAR):
2270 lpdcb->Parity = MARKPARITY;
2272 case (PARENB | PARODD | CMSPAR):
2273 lpdcb->Parity = SPACEPARITY;
2278 if (port.c_cflag & CSTOPB)
2279 if(lpdcb->ByteSize == 5)
2280 lpdcb->StopBits = ONE5STOPBITS;
2282 lpdcb->StopBits = TWOSTOPBITS;
2284 lpdcb->StopBits = ONESTOPBIT;
2291 if (port.c_cflag & CRTSCTS) {
2292 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2293 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2294 lpdcb->fOutxCtsFlow = 1;
2295 lpdcb->fOutxDsrFlow = 1;
2299 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2300 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2302 if (port.c_iflag & IXON)
2307 if (port.c_iflag & IXOFF)
2316 lpdcb->XoffLim = 10;
2322 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2323 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2324 (lpdcb->StopBits == ONESTOPBIT)?1:
2325 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2326 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2327 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2329 if ( lpdcb->fOutxCtsFlow ||
2330 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2331 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2335 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2336 TRACE("~CRTSCTS\n");
2342 /*****************************************************************************
2343 * TransmitCommChar (KERNEL32.@)
2345 * Transmits a single character in front of any pending characters in the
2346 * output buffer. Usually used to send an interrupt character to a host.
2350 * True if the call succeeded, false if the previous command character to the
2351 * same device has not been sent yet the handle is bad etc.
2357 BOOL WINAPI TransmitCommChar(
2358 HANDLE hComm, /* [in] The communication device in need of a command character. */
2359 CHAR chTransmit) /* [in] The character to transmit. */
2361 FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
2365 /*****************************************************************************
2366 * GetCommTimeouts (KERNEL32.@)
2368 * Obtains the request time out values for the communications device.
2372 * True on success, false if communications device handle is bad
2373 * or the target structure is null.
2375 BOOL WINAPI GetCommTimeouts(
2376 HANDLE hComm, /* [in] The communications device. */
2377 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request time outs. */
2381 TRACE("(%x,%p)\n",hComm,lptimeouts);
2385 SetLastError(ERROR_INVALID_PARAMETER);
2389 SERVER_START_REQ( get_serial_info )
2391 req->handle = hComm;
2392 if ((ret = !SERVER_CALL_ERR()))
2394 lptimeouts->ReadIntervalTimeout = req->readinterval;
2395 lptimeouts->ReadTotalTimeoutMultiplier = req->readmult;
2396 lptimeouts->ReadTotalTimeoutConstant = req->readconst;
2397 lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
2398 lptimeouts->WriteTotalTimeoutConstant = req->writeconst;
2405 /*****************************************************************************
2406 * SetCommTimeouts (KERNEL32.@)
2408 * Sets the timeouts used when reading and writing data to/from COMM ports.
2410 * ReadIntervalTimeout
2411 * - converted and passes to linux kernel as c_cc[VTIME]
2412 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
2413 * - used in ReadFile to calculate GetOverlappedResult's timeout
2414 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
2415 * - used in WriteFile to calculate GetOverlappedResult's timeout
2419 * True if the time outs were set, false otherwise.
2421 BOOL WINAPI SetCommTimeouts(
2422 HANDLE hComm, /* [in] handle of COMM device */
2423 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
2427 struct termios tios;
2429 TRACE("(%x,%p)\n",hComm,lptimeouts);
2433 SetLastError(ERROR_INVALID_PARAMETER);
2437 SERVER_START_REQ( set_serial_info )
2439 req->handle = hComm;
2440 req->flags = SERIALINFO_SET_TIMEOUTS;
2441 req->readinterval = lptimeouts->ReadIntervalTimeout ;
2442 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
2443 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
2444 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
2445 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
2446 ret = !SERVER_CALL_ERR();
2449 if (!ret) return FALSE;
2451 /* FIXME: move this stuff to the server */
2452 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
2454 FIXME("no fd for handle = %0x!.\n",hComm);
2458 if (-1==tcgetattr(fd,&tios)) {
2459 FIXME("tcgetattr on fd %d failed!\n",fd);
2463 /* VTIME is in 1/10 seconds */
2465 unsigned int ux_timeout;
2467 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
2473 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
2476 ux_timeout = 1; /* must be at least some timeout */
2479 tios.c_cc[VTIME] = ux_timeout;
2482 if (-1==tcsetattr(fd,0,&tios)) {
2483 FIXME("tcsetattr on fd %d failed!\n",fd);
2490 /***********************************************************************
2491 * GetCommModemStatus (KERNEL32.@)
2493 * Obtains the four control register bits if supported by the hardware.
2497 * True if the communications handle was good and for hardware that
2498 * control register access, false otherwise.
2500 BOOL WINAPI GetCommModemStatus(
2501 HANDLE hFile, /* [in] The communications device. */
2502 LPDWORD lpModemStat) /* [out] The control register bits. */
2504 int fd,mstat, result=FALSE;
2508 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
2511 result = ioctl(fd, TIOCMGET, &mstat);
2515 WARN("ioctl failed\n");
2519 if (mstat & TIOCM_CTS)
2520 *lpModemStat |= MS_CTS_ON;
2523 if (mstat & TIOCM_DSR)
2524 *lpModemStat |= MS_DSR_ON;
2527 if (mstat & TIOCM_RNG)
2528 *lpModemStat |= MS_RING_ON;
2531 /*FIXME: Not really sure about RLSD UB 990810*/
2532 if (mstat & TIOCM_CAR)
2533 *lpModemStat |= MS_RLSD_ON;
2535 TRACE("%04x -> %s%s%s%s\n", mstat,
2536 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2537 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2538 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2539 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2546 /***********************************************************************
2547 * COMM_WaitCommEventService (INTERNAL)
2549 * This function is called while the client is waiting on the
2550 * server, so we can't make any server calls here.
2552 static void COMM_WaitCommEventService(async_private *ovp, int events)
2554 LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
2556 TRACE("overlapped %p wait complete %p <- %x\n",lpOverlapped,ovp->buffer,events);
2559 lpOverlapped->Internal = STATUS_HANDLES_CLOSED;
2565 *ovp->buffer = EV_RXCHAR;
2568 lpOverlapped->Internal = STATUS_SUCCESS;
2573 /***********************************************************************
2574 * COMM_WaitCommEvent (INTERNAL)
2576 * This function must have an lpOverlapped.
2578 static BOOL COMM_WaitCommEvent(
2579 HANDLE hFile, /* [in] handle of comm port to wait for */
2580 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2581 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2588 SetLastError(ERROR_INVALID_PARAMETER);
2592 if(NtResetEvent(lpOverlapped->hEvent,NULL))
2595 lpOverlapped->Internal = STATUS_PENDING;
2596 lpOverlapped->InternalHigh = 0;
2597 lpOverlapped->Offset = 0;
2598 lpOverlapped->OffsetHigh = 0;
2600 /* start an ASYNCHRONOUS WaitCommEvent */
2601 SERVER_START_REQ( create_async )
2603 req->file_handle = hFile;
2605 req->type = ASYNC_TYPE_WAIT;
2607 ret=SERVER_CALL_ERR();
2614 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
2618 ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
2624 ovp->lpOverlapped = lpOverlapped;
2627 ovp->tv.tv_usec = 0;
2628 ovp->event = POLLIN;
2629 ovp->func = COMM_WaitCommEventService;
2630 ovp->buffer = (char *)lpdwEvents;
2633 ovp->completion_func = 0;
2635 ovp->next = NtCurrentTeb()->pending_list;
2638 ovp->next->prev=ovp;
2639 NtCurrentTeb()->pending_list = ovp;
2641 SetLastError(ERROR_IO_PENDING);
2646 /***********************************************************************
2647 * WaitCommEvent (KERNEL32.@)
2649 * Wait until something interesting happens on a COMM port.
2650 * Interesting things (events) are set by calling SetCommMask before
2651 * this function is called.
2654 * TRUE if successful
2657 * The set of detected events will be written to *lpdwEventMask
2658 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2661 * Only supports EV_RXCHAR and EV_TXEMPTY
2663 BOOL WINAPI WaitCommEvent(
2664 HANDLE hFile, /* [in] handle of comm port to wait for */
2665 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2666 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2671 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2674 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2676 /* if there is no overlapped structure, create our own */
2677 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
2679 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2681 if(GetLastError()!=STATUS_PENDING)
2683 CloseHandle(ov.hEvent);
2687 /* wait for the overlapped to complete */
2688 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
2689 CloseHandle(ov.hEvent);
2694 /***********************************************************************
2695 * GetCommProperties (KERNEL32.@)
2697 * This function fills in a structure with the capabilities of the
2698 * communications port driver.
2702 * TRUE on success, FALSE on failure
2703 * If successful, the lpCommProp structure be filled in with
2704 * properties of the comm port.
2706 BOOL WINAPI GetCommProperties(
2707 HANDLE hFile, /* [in] handle of the comm port */
2708 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2710 FIXME("(%d %p )\n",hFile,lpCommProp);
2715 * These values should be valid for LINUX's serial driver
2716 * FIXME: Perhaps they deserve an #ifdef LINUX
2718 memset(lpCommProp,0,sizeof(COMMPROP));
2719 lpCommProp->wPacketLength = 1;
2720 lpCommProp->wPacketVersion = 1;
2721 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2722 lpCommProp->dwReserved1 = 0;
2723 lpCommProp->dwMaxTxQueue = 4096;
2724 lpCommProp->dwMaxRxQueue = 4096;
2725 lpCommProp->dwMaxBaud = BAUD_115200;
2726 lpCommProp->dwProvSubType = PST_RS232;
2727 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
2728 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2729 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2730 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2731 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2732 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2733 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2734 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2735 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2736 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2737 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2742 /***********************************************************************
2744 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2745 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2746 * This is dependent on the type of COMM port, but since it is doubtful
2747 * anybody will get around to implementing support for fancy serial
2748 * ports in WINE, this is hardcoded for the time being. The name of
2749 * this DLL should be stored in and read from the system registry in
2750 * the hive HKEY_LOCAL_MACHINE, key
2751 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2752 * where ???? is the port number... that is determined by PNP
2753 * The DLL should be loaded when the COMM port is opened, and closed
2754 * when the COMM port is closed. - MJM 20 June 2000
2755 ***********************************************************************/
2756 static CHAR lpszSerialUI[] = "serialui.dll";
2759 /***********************************************************************
2760 * CommConfigDialogA (KERNEL32.@)
2762 * Raises a dialog that allows the user to configure a comm port.
2763 * Fills the COMMCONFIG struct with information specified by the user.
2764 * This function should call a similar routine in the COMM driver...
2768 * TRUE on success, FALSE on failure
2769 * If successful, the lpCommConfig structure will contain a new
2770 * configuration for the comm port, as specified by the user.
2773 * The library with the CommConfigDialog code is never unloaded.
2774 * Perhaps this should be done when the comm port is closed?
2776 BOOL WINAPI CommConfigDialogA(
2777 LPCSTR lpszDevice, /* [in] name of communications device */
2778 HANDLE hWnd, /* [in] parent window for the dialog */
2779 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2781 FARPROC lpfnCommDialog;
2782 HMODULE hConfigModule;
2785 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
2787 hConfigModule = LoadLibraryA(lpszSerialUI);
2791 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2796 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2798 /* UnloadLibrary(hConfigModule); */
2803 /***********************************************************************
2804 * CommConfigDialogW (KERNEL32.@)
2806 * see CommConfigDialogA for more info
2808 BOOL WINAPI CommConfigDialogW(
2809 LPCWSTR lpszDevice, /* [in] name of communications device */
2810 HANDLE hWnd, /* [in] parent window for the dialog */
2811 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2816 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2819 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2820 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2824 /***********************************************************************
2825 * GetCommConfig (KERNEL32.@)
2827 * Fill in the COMMCONFIG structure for the comm port hFile
2831 * TRUE on success, FALSE on failure
2832 * If successful, lpCommConfig contains the comm port configuration.
2836 * The signature is missing a the parameter for the size of the COMMCONFIG
2837 * structure/buffer it should be
2838 * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
2840 BOOL WINAPI GetCommConfig(
2841 HANDLE hFile, /* [in] The communications device. */
2842 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2843 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2844 afterwards the number of bytes copied to the buffer or
2845 the needed size of the buffer. */
2849 TRACE("(%x %p)\n",hFile,lpCommConfig);
2851 if(lpCommConfig == NULL)
2854 r = *lpdwSize < sizeof(COMMCONFIG);
2855 *lpdwSize = sizeof(COMMCONFIG);
2859 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2860 lpCommConfig->wVersion = 1;
2861 lpCommConfig->wReserved = 0;
2862 r = GetCommState(hFile,&lpCommConfig->dcb);
2863 lpCommConfig->dwProviderSubType = PST_RS232;
2864 lpCommConfig->dwProviderOffset = 0;
2865 lpCommConfig->dwProviderSize = 0;
2870 /***********************************************************************
2871 * SetCommConfig (KERNEL32.@)
2873 * Sets the configuration of the commications device.
2877 * True on success, false if the handle was bad is not a communications device.
2879 BOOL WINAPI SetCommConfig(
2880 HANDLE hFile, /* [in] The communications device. */
2881 LPCOMMCONFIG lpCommConfig) /* [in] The desired configuration. */
2883 TRACE("(%x %p)\n",hFile,lpCommConfig);
2884 return SetCommState(hFile,&lpCommConfig->dcb);
2887 /***********************************************************************
2888 * SetDefaultCommConfigA (KERNEL32.@)
2890 * Initializes the default configuration for the specified communication
2895 * True if the device was found and the defaults set, false otherwise
2897 BOOL WINAPI SetDefaultCommConfigA(
2898 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2899 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2900 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2902 FARPROC lpfnSetDefaultCommConfig;
2903 HMODULE hConfigModule;
2906 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2908 hConfigModule = LoadLibraryA(lpszSerialUI);
2912 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2914 if(! lpfnSetDefaultCommConfig)
2917 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2919 /* UnloadLibrary(hConfigModule); */
2925 /***********************************************************************
2926 * SetDefaultCommConfigW (KERNEL32.@)
2928 * Initializes the default configuration for the specified
2929 * communication device. (unicode)
2934 BOOL WINAPI SetDefaultCommConfigW(
2935 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2936 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2937 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2942 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2944 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2947 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2948 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2953 /***********************************************************************
2954 * GetDefaultCommConfigA (KERNEL32.@)
2956 * Acquires the default configuration of the specified communication device. (unicode)
2960 * True on successful reading of the default configuration,
2961 * if the device is not found or the buffer is too small.
2963 BOOL WINAPI GetDefaultCommConfigA(
2964 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2965 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2966 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2967 afterwards the number of bytes copied to the buffer or
2968 the needed size of the buffer. */
2970 LPDCB lpdcb = &(lpCC->dcb);
2973 if (strncasecmp(lpszName,"COM",3)) {
2974 ERR("not implemented for <%s>\n", lpszName);
2978 if (!ValidCOMPort(lpszName[3]-'1'))
2981 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2982 if (*lpdwSize < sizeof(COMMCONFIG)) {
2983 *lpdwSize = sizeof(COMMCONFIG);
2987 *lpdwSize = sizeof(COMMCONFIG);
2989 lpCC->dwSize = sizeof(COMMCONFIG);
2991 lpCC->dwProviderSubType = PST_RS232;
2992 lpCC->dwProviderOffset = 0L;
2993 lpCC->dwProviderSize = 0L;
2995 (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2996 FIXME("setting %s as default\n", temp);
2998 return BuildCommDCBA( temp, lpdcb);
3001 /**************************************************************************
3002 * GetDefaultCommConfigW (KERNEL32.@)
3004 * Acquires the default configuration of the specified communication device. (unicode)
3008 * True on successful reading of the default configuration,
3009 * if the device is not found or the buffer is too small.
3011 BOOL WINAPI GetDefaultCommConfigW(
3012 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
3013 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
3014 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
3015 afterwards the number of bytes copied to the buffer or
3016 the needed size of the buffer. */
3021 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
3022 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
3025 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
3026 HeapFree( GetProcessHeap(), 0, lpszNameA );