blob: 745ebb5abcc3090fd5ae5f68c13989ff436ceab8 [file] [log] [blame]
Alexandre Julliard77b99181997-09-14 17:17:23 +00001 /*
Alexandre Julliardecc37121994-11-22 16:31:29 +00002 * DEC 93 Erik Bos <erik@xs4all.nl>
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00003 *
4 * Copyright 1996 Marcus Meissner
Ove Kaavena1c45a51999-03-21 15:45:41 +00005 *
Ove Kaavena4dd1be1999-04-01 11:52:16 +00006 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
8 *
Lawson Whitney96b93bb1999-04-04 12:38:35 +00009 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
11 *
Ove Kaavena1c45a51999-03-21 15:45:41 +000012 * 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.
Alexandre Julliard23946ad1997-06-16 17:43:53 +000016 *
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.
Alexandre Julliard77b99181997-09-14 17:17:23 +000023 *
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
Alexandre Julliard642d3131998-07-12 19:29:36 +000026 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
Rein Klazescd7986b1998-10-11 14:02:09 +000028 * 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.
32 *
Alexandre Julliard5f721f81994-01-04 20:14:34 +000033 */
34
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000035#include "config.h"
36
Alexandre Julliard5f721f81994-01-04 20:14:34 +000037#include <stdlib.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000038#include <stdio.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000039#include <termios.h>
40#include <fcntl.h>
41#include <string.h>
Alexandre Julliardf90efa91998-06-14 15:24:15 +000042#ifdef HAVE_STRINGS_H
43# include <strings.h>
44#endif
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000045#include <errno.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000046#include <ctype.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000047#include <sys/stat.h>
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000048#ifdef HAVE_SYS_FILIO_H
49# include <sys/filio.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000050#endif
Alexandre Julliard33072e11997-06-29 18:08:02 +000051#include <sys/ioctl.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000052#include <unistd.h>
53
Jeremy Whited3e22d92000-02-10 19:03:02 +000054#include "windef.h"
Alexandre Julliardf90efa91998-06-14 15:24:15 +000055#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
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000061#include "heap.h"
Alexandre Julliard7e56f681996-01-31 19:02:28 +000062#include "options.h"
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +000063#include "wine/port.h"
Michael McCormacka8486071999-03-14 12:25:36 +000064#include "server.h"
Michael McCormacka8486071999-03-14 12:25:36 +000065#include "winerror.h"
Alexandre Julliardc9c2a591999-08-01 14:46:51 +000066#include "services.h"
Alexandre Julliard6ec108a2000-03-24 21:42:15 +000067#include "callback.h"
Alexandre Julliardc9c2a591999-08-01 14:46:51 +000068#include "file.h"
Michael McCormacka8486071999-03-14 12:25:36 +000069
Alexandre Julliard61fece01999-06-26 19:09:08 +000070#include "debugtools.h"
Marcus Meissner7bea8691999-03-16 10:52:17 +000071
Jeremy Whited3e22d92000-02-10 19:03:02 +000072DEFAULT_DEBUG_CHANNEL(comm);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000073
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +000074#if !defined(TIOCINQ) && defined(FIONREAD)
Alexandre Julliard33072e11997-06-29 18:08:02 +000075#define TIOCINQ FIONREAD
76#endif
Rein Klazes7f383a82000-03-30 20:23:32 +000077
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)
85
Andreas Mohreed04941999-04-11 18:47:07 +000086#define FLAG_LPT 0x80
Alexandre Julliard5f721f81994-01-04 20:14:34 +000087
Rein Klazes0a54d5a2000-04-28 14:44:33 +000088#ifdef linux
89#define CMSPAR 0x40000000 /* stick parity */
90#endif
91
Mike McCormack11776c12000-10-13 17:11:30 +000092#define MAX_PORTS 9
93
94struct DosDeviceStruct {
Andreas Mohra6d83eb2000-12-27 04:02:46 +000095 char *devicename; /* /dev/ttyS0 */
Mike McCormack11776c12000-10-13 17:11:30 +000096 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;
110};
111
112
113static struct DosDeviceStruct COM[MAX_PORTS];
114static struct DosDeviceStruct LPT[MAX_PORTS];
Rein Klazescd7986b1998-10-11 14:02:09 +0000115/* pointers to unknown(==undocumented) comm structure */
Mike McCormack11776c12000-10-13 17:11:30 +0000116static LPCVOID *unknown[MAX_PORTS];
Rein Klazescd7986b1998-10-11 14:02:09 +0000117/* save terminal states */
118static struct termios m_stat[MAX_PORTS];
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000119
Rein Klazes7f383a82000-03-30 20:23:32 +0000120/* update window's semi documented modem status register */
121/* see knowledge base Q101417 */
122static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
123{
124 UCHAR tmpmsr=0;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +0000125#ifdef TIOCM_CTS
Rein Klazes7f383a82000-03-30 20:23:32 +0000126 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +0000127#endif
128#ifdef TIOCM_DSR
Rein Klazes7f383a82000-03-30 20:23:32 +0000129 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +0000130#endif
131#ifdef TIOCM_RI
Rein Klazes7f383a82000-03-30 20:23:32 +0000132 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +0000133#endif
134#ifdef TIOCM_CAR
Rein Klazes7f383a82000-03-30 20:23:32 +0000135 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +0000136#endif
Rein Klazes7f383a82000-03-30 20:23:32 +0000137 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
138}
139
Alexandre Julliard594997c1995-04-30 10:05:20 +0000140void COMM_Init(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000141{
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000142 int x;
143 char option[10], temp[256], *btemp;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000144 struct stat st;
145
146 for (x=0; x!=MAX_PORTS; x++) {
147 strcpy(option,"COMx");
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000148 option[3] = '1' + x;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000149 option[4] = '\0';
150
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000151 PROFILE_GetWineIniString( "serialports", option, "*",
152 temp, sizeof(temp) );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000153 if (!strcmp(temp, "*") || *temp == '\0')
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000154 COM[x].devicename = NULL;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000155 else {
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000156 btemp = strchr(temp,',');
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000157 if (btemp != NULL) {
158 *btemp++ = '\0';
159 COM[x].baudrate = atoi(btemp);
160 } else {
161 COM[x].baudrate = -1;
162 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000163 stat(temp, &st);
164 if (!S_ISCHR(st.st_mode))
Alexandre Julliard61fece01999-06-26 19:09:08 +0000165 WARN("Can't use `%s' as %s !\n", temp, option);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000166 else
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000167 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
Alexandre Julliard61fece01999-06-26 19:09:08 +0000168 WARN("Can't malloc for device info!\n");
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000169 else {
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000170 COM[x].fd = 0;
171 strcpy(COM[x].devicename, temp);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000172 }
Alexandre Julliard61fece01999-06-26 19:09:08 +0000173 TRACE("%s = %s\n", option, COM[x].devicename);
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000174 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000175
176 strcpy(option, "LPTx");
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000177 option[3] = '1' + x;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000178 option[4] = '\0';
179
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000180 PROFILE_GetWineIniString( "parallelports", option, "*",
181 temp, sizeof(temp) );
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000182 if (!strcmp(temp, "*") || *temp == '\0')
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000183 LPT[x].devicename = NULL;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000184 else {
185 stat(temp, &st);
186 if (!S_ISCHR(st.st_mode))
Alexandre Julliard61fece01999-06-26 19:09:08 +0000187 WARN("Can't use `%s' as %s !\n", temp, option);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000188 else
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000189 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
Alexandre Julliard61fece01999-06-26 19:09:08 +0000190 WARN("Can't malloc for device info!\n");
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000191 else {
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000192 LPT[x].fd = 0;
193 strcpy(LPT[x].devicename, temp);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000194 }
Alexandre Julliard61fece01999-06-26 19:09:08 +0000195 TRACE("%s = %s\n", option, LPT[x].devicename);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000196 }
197
198 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000199}
200
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000201
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000202static struct DosDeviceStruct *GetDeviceStruct(int fd)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000203{
204 if ((fd&0x7F)<=MAX_PORTS) {
Andreas Mohreed04941999-04-11 18:47:07 +0000205 if (!(fd&FLAG_LPT)) {
Ove Kaavena1c45a51999-03-21 15:45:41 +0000206 if (COM[fd].fd)
207 return &COM[fd];
208 } else {
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000209 fd &= 0x7f;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000210 if (LPT[fd].fd)
211 return &LPT[fd];
212 }
213 }
214
215 return NULL;
216}
217
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000218static int GetCommPort_fd(int fd)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000219{
220 int x;
221
222 for (x=0; x<MAX_PORTS; x++) {
223 if (COM[x].fd == fd)
224 return x;
225 }
226
227 return -1;
228}
229
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000230static int ValidCOMPort(int x)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000231{
232 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
233}
234
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000235static int ValidLPTPort(int x)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000236{
237 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
238}
239
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000240static int WinError(void)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000241{
Alexandre Julliard61fece01999-06-26 19:09:08 +0000242 TRACE("errno = %d\n", errno);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000243 switch (errno) {
244 default:
245 return CE_IOE;
246 }
247}
248
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000249static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000250{
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000251 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
252 + ptr->ibuf_head - ptr->ibuf_tail;
253}
254
255static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
256{
257 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
258 + ptr->obuf_head - ptr->obuf_tail;
259}
260
Lawson Whitney96b93bb1999-04-04 12:38:35 +0000261static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
262{
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);
269}
270
Alexandre Julliardc9c2a591999-08-01 14:46:51 +0000271static void CALLBACK comm_notification( ULONG_PTR private )
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000272{
273 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
274 int prev, bleft, len;
275 WORD mask = 0;
Alexandre Julliardc9c2a591999-08-01 14:46:51 +0000276 int cid = GetCommPort_fd(ptr->fd);
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000277
Alexandre Julliard61fece01999-06-26 19:09:08 +0000278 TRACE("async notification\n");
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000279 /* 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;
Alexandre Julliardc9c2a591999-08-01 14:46:51 +0000284 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000285 if (len > 0) {
286 if (!bleft) {
287 ptr->commerror = CE_RXOVER;
288 } else {
Ove Kaavena88444e1999-06-12 06:43:48 +0000289 /* check for events */
290 if ((ptr->eventmask & EV_RXFLAG) &&
Ove Kaaven1c08ac61999-07-31 13:00:24 +0000291 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
Ove Kaavena88444e1999-06-12 06:43:48 +0000292 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
293 mask |= CN_EVENT;
294 }
Ove Kaavena811ea51999-05-29 11:05:38 +0000295 if (ptr->eventmask & EV_RXCHAR) {
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000296 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
Ove Kaavena811ea51999-05-29 11:05:38 +0000297 mask |= CN_EVENT;
298 }
Ove Kaavena88444e1999-06-12 06:43:48 +0000299 /* advance buffer position */
300 ptr->ibuf_head += len;
301 if (ptr->ibuf_head >= ptr->ibuf_size)
302 ptr->ibuf_head = 0;
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000303 }
304 }
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;
311 }
312
313 /* write any TransmitCommChar character */
314 if (ptr->xmit>=0) {
Alexandre Julliardc9c2a591999-08-01 14:46:51 +0000315 len = write(ptr->fd, &(ptr->xmit), 1);
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000316 if (len > 0) ptr->xmit = -1;
317 }
318 /* write from output queue */
319 prev = comm_outbuf(ptr);
320 do {
Ove Kaavene85220d1999-05-01 10:18:21 +0000321 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000322 - ptr->obuf_tail;
Alexandre Julliardc9c2a591999-08-01 14:46:51 +0000323 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000324 if (len > 0) {
325 ptr->obuf_tail += len;
326 if (ptr->obuf_tail >= ptr->obuf_size)
327 ptr->obuf_tail = 0;
328 /* flag event */
Ove Kaaven542b29d1999-11-25 21:57:32 +0000329 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;
333 }
334 if (ptr->eventmask & EV_TXEMPTY) {
335 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
336 mask |= CN_EVENT;
337 }
Ove Kaavena811ea51999-05-29 11:05:38 +0000338 }
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000339 }
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;
346 }
347
348 /* send notifications, if any */
349 if (ptr->wnd && mask) {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000350 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
Alexandre Julliard4e951ea2000-11-08 22:47:53 +0000351 if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000352 }
Ove Kaavena1c45a51999-03-21 15:45:41 +0000353}
354
Ove Kaaven542b29d1999-11-25 21:57:32 +0000355static void comm_waitread(struct DosDeviceStruct *ptr)
356{
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 );
362}
363
364static void comm_waitwrite(struct DosDeviceStruct *ptr)
365{
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 );
371}
372
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000373/**************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000374 * BuildCommDCB16 (USER.213)
Stefan Leichterdcb97332000-07-09 12:19:44 +0000375 *
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
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000380 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000381BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000382{
383 /* "COM1:9600,n,8,1" */
384 /* 012345 */
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000385 int port;
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000386 char *ptr, temp[256];
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000387
Alexandre Julliard61fece01999-06-26 19:09:08 +0000388 TRACE("(%s), ptr %p\n", device, lpdcb);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000389
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000390 if (!strncasecmp(device,"COM",3)) {
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000391 port = device[3] - '0';
392
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000393
394 if (port-- == 0) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000395 ERR("BUG ! COM0 can't exist!\n");
Ove Kaavena1c45a51999-03-21 15:45:41 +0000396 return -1;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000397 }
398
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000399 if (!ValidCOMPort(port)) {
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000400 FIXME("invalid COM port %d?\n",port);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000401 return -1;
402 }
403
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000404 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
405
Ove Kaavena1c45a51999-03-21 15:45:41 +0000406 lpdcb->Id = port;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000407
408 if (!*(device+4))
409 return 0;
410
411 if (*(device+4) != ':')
412 return -1;
413
414 strcpy(temp,device+5);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000415 ptr = strtok(temp, ", ");
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000416
Alexandre Julliard3a405ba1994-10-30 16:25:19 +0000417 if (COM[port].baudrate > 0)
418 lpdcb->BaudRate = COM[port].baudrate;
419 else
420 lpdcb->BaudRate = atoi(ptr);
Alexandre Julliard61fece01999-06-26 19:09:08 +0000421 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000422
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000423 ptr = strtok(NULL, ", ");
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000424 if (islower(*ptr))
425 *ptr = toupper(*ptr);
426
Alexandre Julliard61fece01999-06-26 19:09:08 +0000427 TRACE("parity (%c)\n", *ptr);
Cliff Wright28d3d211998-11-22 15:05:18 +0000428 lpdcb->fParity = TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000429 switch (*ptr) {
430 case 'N':
431 lpdcb->Parity = NOPARITY;
Cliff Wright28d3d211998-11-22 15:05:18 +0000432 lpdcb->fParity = FALSE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000433 break;
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000434 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:
Alexandre Julliard61fece01999-06-26 19:09:08 +0000444 WARN("Unknown parity `%c'!\n", *ptr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000445 return -1;
446 }
447
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000448 ptr = strtok(NULL, ", ");
Alexandre Julliard61fece01999-06-26 19:09:08 +0000449 TRACE("charsize (%c)\n", *ptr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000450 lpdcb->ByteSize = *ptr - '0';
451
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000452 ptr = strtok(NULL, ", ");
Alexandre Julliard61fece01999-06-26 19:09:08 +0000453 TRACE("stopbits (%c)\n", *ptr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000454 switch (*ptr) {
455 case '1':
456 lpdcb->StopBits = ONESTOPBIT;
457 break;
458 case '2':
459 lpdcb->StopBits = TWOSTOPBITS;
460 break;
461 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +0000462 WARN("Unknown # of stopbits `%c'!\n", *ptr);
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000463 return -1;
464 }
465 }
466
467 return 0;
468}
469
Ove Kaavena1c45a51999-03-21 15:45:41 +0000470/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000471 * OpenComm16 (USER.200)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000472 */
473INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
474{
475 int port,fd;
476
Alexandre Julliard61fece01999-06-26 19:09:08 +0000477 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000478
Eric Pouechf2163101999-07-12 13:39:58 +0000479 if (strlen(device) < 4)
480 return IE_BADID;
481
482 port = device[3] - '0';
Ove Kaavena1c45a51999-03-21 15:45:41 +0000483
Andreas Mohreed04941999-04-11 18:47:07 +0000484 if (port-- == 0)
Alexandre Julliard61fece01999-06-26 19:09:08 +0000485 ERR("BUG ! COM0 or LPT0 don't exist !\n");
Andreas Mohreed04941999-04-11 18:47:07 +0000486
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000487 if (!strncasecmp(device,"COM",3)) {
Ove Kaavena1c45a51999-03-21 15:45:41 +0000488
Alexandre Julliard61fece01999-06-26 19:09:08 +0000489 TRACE("%s = %s\n", device, COM[port].devicename);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000490
Andreas Mohreed04941999-04-11 18:47:07 +0000491 if (!ValidCOMPort(port))
Ove Kaavena1c45a51999-03-21 15:45:41 +0000492 return IE_BADID;
Andreas Mohreed04941999-04-11 18:47:07 +0000493
494 if (COM[port].fd)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000495 return IE_OPEN;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000496
497 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
498 if (fd == -1) {
Andreas Mohr34965562000-08-26 20:31:48 +0000499 ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno));
Andreas Mohreed04941999-04-11 18:47:07 +0000500 return IE_HARDWARE;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000501 } 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;
Ove Kaavena88444e1999-06-12 06:43:48 +0000507 COM[port].evtchar = 0; /* FIXME: default? */
Ove Kaavena1c45a51999-03-21 15:45:41 +0000508 /* save terminal state */
509 tcgetattr(fd,&m_stat[port]);
Rein Klazes58a38b81999-03-23 13:44:51 +0000510 /* 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
517 */
518 SetCommState16( &dcb);
519 }
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000520 /* init priority characters */
521 COM[port].unget = -1;
522 COM[port].xmit = -1;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000523 /* allocate buffers */
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000524 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;
528
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);
Andreas Mohr217a6822000-08-25 21:56:19 +0000539 ERR("out of memory\n");
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000540 return IE_MEMORY;
541 }
542
Ove Kaaven542b29d1999-11-25 21:57:32 +0000543 COM[port].s_read = INVALID_HANDLE_VALUE;
544 COM[port].s_write = INVALID_HANDLE_VALUE;
545 comm_waitread( &COM[port] );
Ove Kaavena1c45a51999-03-21 15:45:41 +0000546 return port;
547 }
548 }
549 else
Alexandre Julliard072dfb52000-09-25 23:30:56 +0000550 if (!strncasecmp(device,"LPT",3)) {
Ove Kaavena1c45a51999-03-21 15:45:41 +0000551
Andreas Mohreed04941999-04-11 18:47:07 +0000552 if (!ValidLPTPort(port))
Ove Kaavena1c45a51999-03-21 15:45:41 +0000553 return IE_BADID;
Andreas Mohreed04941999-04-11 18:47:07 +0000554
555 if (LPT[port].fd)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000556 return IE_OPEN;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000557
558 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
559 if (fd == -1) {
Andreas Mohreed04941999-04-11 18:47:07 +0000560 return IE_HARDWARE;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000561 } else {
562 LPT[port].fd = fd;
563 LPT[port].commerror = 0;
564 LPT[port].eventmask = 0;
Andreas Mohreed04941999-04-11 18:47:07 +0000565 return port|FLAG_LPT;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000566 }
567 }
568 return 0;
569}
570
571/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000572 * CloseComm16 (USER.207)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000573 */
574INT16 WINAPI CloseComm16(INT16 cid)
575{
576 struct DosDeviceStruct *ptr;
577
Alexandre Julliard61fece01999-06-26 19:09:08 +0000578 TRACE("cid=%d\n", cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000579 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000580 FIXME("no cid=%d found!\n", cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000581 return -1;
582 }
Andreas Mohreed04941999-04-11 18:47:07 +0000583 if (!(cid&FLAG_LPT)) {
Ove Kaavena1c45a51999-03-21 15:45:41 +0000584 /* COM port */
585 SEGPTR_FREE(unknown[cid]); /* [LW] */
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000586
Ove Kaaven542b29d1999-11-25 21:57:32 +0000587 SERVICE_Delete( COM[cid].s_write );
588 SERVICE_Delete( COM[cid].s_read );
Ove Kaavena1c45a51999-03-21 15:45:41 +0000589 /* free buffers */
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000590 free(ptr->outbuf);
591 free(ptr->inbuf);
592
Ove Kaavena1c45a51999-03-21 15:45:41 +0000593 /* reset modem lines */
594 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
595 }
596
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;
605 }
606}
607
608/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000609 * SetCommBreak16 (USER.210)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000610 */
611INT16 WINAPI SetCommBreak16(INT16 cid)
612{
613 struct DosDeviceStruct *ptr;
614
Alexandre Julliard61fece01999-06-26 19:09:08 +0000615 TRACE("cid=%d\n", cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000616 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000617 FIXME("no cid=%d found!\n", cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000618 return -1;
619 }
620
621 ptr->suspended = 1;
622 ptr->commerror = 0;
623 return 0;
624}
625
626/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000627 * ClearCommBreak16 (USER.211)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000628 */
629INT16 WINAPI ClearCommBreak16(INT16 cid)
630{
631 struct DosDeviceStruct *ptr;
632
Alexandre Julliard61fece01999-06-26 19:09:08 +0000633 TRACE("cid=%d\n", cid);
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000634 if (!(ptr = GetDeviceStruct(cid))) {
635 FIXME("no cid=%d found!\n", cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000636 return -1;
637 }
Ove Kaavena1c45a51999-03-21 15:45:41 +0000638 ptr->suspended = 0;
639 ptr->commerror = 0;
640 return 0;
641}
642
643/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000644 * EscapeCommFunction16 (USER.214)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000645 */
646LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
647{
648 int max;
649 struct DosDeviceStruct *ptr;
650 struct termios port;
651
Alexandre Julliard61fece01999-06-26 19:09:08 +0000652 TRACE("cid=%d, function=%d\n", cid, nFunction);
Ove Kaaven1c08ac61999-07-31 13:00:24 +0000653 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
654 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000655 FIXME("no cid=%d found!\n", cid);
Ove Kaaven1c08ac61999-07-31 13:00:24 +0000656 return -1;
657 }
658 if (tcgetattr(ptr->fd,&port) == -1) {
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000659 TRACE("tcgetattr failed\n");
Ove Kaaven1c08ac61999-07-31 13:00:24 +0000660 ptr->commerror=WinError();
661 return -1;
662 }
663 } else ptr = NULL;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000664
665 switch (nFunction) {
666 case RESETDEV:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000667 TRACE("RESETDEV\n");
Ove Kaavena1c45a51999-03-21 15:45:41 +0000668 break;
669
670 case GETMAXCOM:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000671 TRACE("GETMAXCOM\n");
Ove Kaavena1c45a51999-03-21 15:45:41 +0000672 for (max = MAX_PORTS;!COM[max].devicename;max--)
673 ;
674 return max;
675 break;
676
677 case GETMAXLPT:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000678 TRACE("GETMAXLPT\n");
Ove Kaavena1c45a51999-03-21 15:45:41 +0000679 for (max = MAX_PORTS;!LPT[max].devicename;max--)
680 ;
Andreas Mohreed04941999-04-11 18:47:07 +0000681 return FLAG_LPT + max;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000682 break;
683
Ove Kaaven1c08ac61999-07-31 13:00:24 +0000684 case GETBASEIRQ:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000685 TRACE("GETBASEIRQ\n");
Ove Kaaven1c08ac61999-07-31 13:00:24 +0000686 /* 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);
695 }
696 break;
697
Ove Kaavena1c45a51999-03-21 15:45:41 +0000698 case CLRDTR:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000699 TRACE("CLRDTR\n");
700#ifdef TIOCM_DTR
Lawson Whitney96b93bb1999-04-04 12:38:35 +0000701 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000702#endif
Ove Kaavena1c45a51999-03-21 15:45:41 +0000703 case CLRRTS:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000704 TRACE("CLRRTS\n");
705#ifdef TIOCM_RTS
Lawson Whitney96b93bb1999-04-04 12:38:35 +0000706 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000707#endif
708
Ove Kaavena1c45a51999-03-21 15:45:41 +0000709 case SETDTR:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000710 TRACE("SETDTR\n");
711#ifdef TIOCM_DTR
Lawson Whitney96b93bb1999-04-04 12:38:35 +0000712 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
713#endif
Ove Kaavena1c45a51999-03-21 15:45:41 +0000714
715 case SETRTS:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000716 TRACE("SETRTS\n");
717#ifdef TIOCM_RTS
Lawson Whitney96b93bb1999-04-04 12:38:35 +0000718 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000719#endif
720
721 case SETXOFF:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000722 TRACE("SETXOFF\n");
Ove Kaavena1c45a51999-03-21 15:45:41 +0000723 port.c_iflag |= IXOFF;
724 break;
725
726 case SETXON:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +0000727 TRACE("SETXON\n");
Ove Kaavena1c45a51999-03-21 15:45:41 +0000728 port.c_iflag |= IXON;
729 break;
730
731 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +0000732 WARN("(cid=%d,nFunction=%d): Unknown function\n",
Ove Kaavena1c45a51999-03-21 15:45:41 +0000733 cid, nFunction);
734 break;
735 }
736
737 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
738 ptr->commerror = WinError();
739 return -1;
740 } else {
741 ptr->commerror = 0;
742 return 0;
743 }
744}
745
746/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000747 * FlushComm16 (USER.215)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000748 */
749INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
750{
751 int queue;
752 struct DosDeviceStruct *ptr;
753
Alexandre Julliard61fece01999-06-26 19:09:08 +0000754 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000755 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000756 FIXME("no cid=%d found!\n", cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000757 return -1;
758 }
759 switch (fnQueue) {
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000760 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:
Alexandre Julliard61fece01999-06-26 19:09:08 +0000769 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000770 cid, fnQueue);
771 return -1;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000772 }
773 if (tcflush(ptr->fd, queue)) {
774 ptr->commerror = WinError();
775 return -1;
776 } else {
777 ptr->commerror = 0;
778 return 0;
779 }
780}
781
782/********************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000783 * GetCommError16 (USER.203)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000784 */
785INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
786{
787 int temperror;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000788 struct DosDeviceStruct *ptr;
789 unsigned char *stol;
790 unsigned int mstat;
791
792 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000793 FIXME("no handle for cid = %0x!\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000794 return -1;
795 }
Andreas Mohreed04941999-04-11 18:47:07 +0000796 if (cid&FLAG_LPT) {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000797 WARN(" cid %d not comm port\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000798 return CE_MODE;
799 }
800 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
801 ioctl(ptr->fd,TIOCMGET,&mstat);
Rein Klazes7f383a82000-03-30 20:23:32 +0000802 COMM_MSRUpdate( stol, mstat);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000803
804 if (lpStat) {
805 lpStat->status = 0;
806
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000807 lpStat->cbOutQue = comm_outbuf(ptr);
808 lpStat->cbInQue = comm_inbuf(ptr);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000809
Alexandre Julliard61fece01999-06-26 19:09:08 +0000810 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
Ove Kaavena1c45a51999-03-21 15:45:41 +0000811 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
812 lpStat->cbOutQue, *stol);
813 }
814 else
Alexandre Julliard61fece01999-06-26 19:09:08 +0000815 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
Ove Kaavena1c45a51999-03-21 15:45:41 +0000816 cid, ptr->commerror, *stol);
817
818 /* Return any errors and clear it */
819 temperror = ptr->commerror;
820 ptr->commerror = 0;
821 return(temperror);
822}
823
824/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000825 * SetCommEventMask16 (USER.208)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000826 */
827SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
828{
829 struct DosDeviceStruct *ptr;
830 unsigned char *stol;
831 int repid;
832 unsigned int mstat;
833
Alexandre Julliard61fece01999-06-26 19:09:08 +0000834 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000835 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000836 FIXME("no handle for cid = %0x!\n",cid);
Andreas Mohreed04941999-04-11 18:47:07 +0000837 return (SEGPTR)NULL;
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000838 }
Andreas Mohreed04941999-04-11 18:47:07 +0000839
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000840 ptr->eventmask = fuEvtMask;
Andreas Mohreed04941999-04-11 18:47:07 +0000841
842 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000843 WARN(" cid %d not comm port\n",cid);
Andreas Mohreed04941999-04-11 18:47:07 +0000844 return (SEGPTR)NULL;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000845 }
Andreas Mohreed04941999-04-11 18:47:07 +0000846 /* it's a COM port ? -> modify flags */
Ove Kaavena1c45a51999-03-21 15:45:41 +0000847 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
848 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
Alexandre Julliard61fece01999-06-26 19:09:08 +0000849 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
Rein Klazes7f383a82000-03-30 20:23:32 +0000850 COMM_MSRUpdate( stol, mstat);
Andreas Mohreed04941999-04-11 18:47:07 +0000851
Alexandre Julliard61fece01999-06-26 19:09:08 +0000852 TRACE(" modem dcd construct %x\n",*stol);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000853 return SEGPTR_GET(unknown[cid]);
854}
855
856/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +0000857 * GetCommEventMask16 (USER.209)
Ove Kaavena1c45a51999-03-21 15:45:41 +0000858 */
859UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
860{
Ove Kaavena1c45a51999-03-21 15:45:41 +0000861 struct DosDeviceStruct *ptr;
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000862 WORD events;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000863
Alexandre Julliard61fece01999-06-26 19:09:08 +0000864 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000865 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000866 FIXME("no handle for cid = %0x!\n",cid);
Andreas Mohreed04941999-04-11 18:47:07 +0000867 return 0;
Marcus Meissner7547d4d2000-01-05 01:46:53 +0000868 }
Andreas Mohreed04941999-04-11 18:47:07 +0000869
870 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000871 WARN(" cid %d not comm port\n",cid);
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000872 return 0;
873 }
Ove Kaavena1c45a51999-03-21 15:45:41 +0000874
Ove Kaavena4dd1be1999-04-01 11:52:16 +0000875 events = *(WORD*)(unknown[cid]) & fnEvtClear;
876 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000877 return events;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000878}
879
880/*****************************************************************************
881 * SetCommState16 (USER.201)
882 */
883INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
884{
885 struct termios port;
886 struct DosDeviceStruct *ptr;
Rein Klazes0a54d5a2000-04-28 14:44:33 +0000887 int bytesize, stopbits;
888 int fail=0;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000889
Alexandre Julliard61fece01999-06-26 19:09:08 +0000890 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000891 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +0000892 FIXME("no handle for cid = %0x!\n",lpdcb->Id);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000893 return -1;
894 }
895 if (tcgetattr(ptr->fd, &port) == -1) {
896 ptr->commerror = WinError();
897 return -1;
898 }
899
900 port.c_cc[VMIN] = 0;
901 port.c_cc[VTIME] = 1;
902
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);
909
910 port.c_oflag &= ~(OPOST);
911
912 port.c_cflag &= ~(HUPCL);
913 port.c_cflag |= CLOCAL | CREAD;
914
915 port.c_lflag &= ~(ICANON|ECHO|ISIG);
916 port.c_lflag |= NOFLSH;
917
Alexandre Julliard61fece01999-06-26 19:09:08 +0000918 TRACE("baudrate %d\n",lpdcb->BaudRate);
Ove Kaavena1c45a51999-03-21 15:45:41 +0000919#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;
Rein Klazes0a54d5a2000-04-28 14:44:33 +0000970 fail=1;
Ove Kaavena1c45a51999-03-21 15:45:41 +0000971 }
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;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001012 fail=1;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001013 }
1014 port.c_ispeed = port.c_ospeed;
1015#endif
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001016 bytesize=lpdcb->ByteSize;
1017 stopbits=lpdcb->StopBits;
1018
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;
1055 }
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;
1064 }
1065 break;
1066#endif
1067 default:
1068 ptr->commerror = IE_BYTESIZE;
1069 fail=1;
1070 }
1071
1072 TRACE("bytesize %d\n",bytesize);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001073 port.c_cflag &= ~CSIZE;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001074 switch (bytesize) {
Ove Kaavena1c45a51999-03-21 15:45:41 +00001075 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;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001089 fail=1;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001090 }
1091
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001092 TRACE("stopbits %d\n",stopbits);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001093
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001094 switch (stopbits) {
Ove Kaavena1c45a51999-03-21 15:45:41 +00001095 case ONESTOPBIT:
1096 port.c_cflag &= ~CSTOPB;
1097 break;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001098 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
Ove Kaavena1c45a51999-03-21 15:45:41 +00001099 case TWOSTOPBITS:
1100 port.c_cflag |= CSTOPB;
1101 break;
1102 default:
1103 ptr->commerror = IE_BYTESIZE;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001104 fail=1;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001105 }
1106#ifdef CRTSCTS
1107
1108 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1109 port.c_cflag |= CRTSCTS;
1110
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;
1122
Ove Kaavena88444e1999-06-12 06:43:48 +00001123 ptr->evtchar = lpdcb->EvtChar;
1124
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001125 if(fail)
1126 return -1;
1127
Ove Kaavena1c45a51999-03-21 15:45:41 +00001128 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1129 ptr->commerror = WinError();
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001130 return -1;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001131 } else {
1132 ptr->commerror = 0;
1133 return 0;
1134 }
1135}
1136
1137/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +00001138 * GetCommState16 (USER.202)
Ove Kaavena1c45a51999-03-21 15:45:41 +00001139 */
1140INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1141{
Patrik Stridvallfe28f251999-09-23 11:44:52 +00001142 int speed;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001143 struct DosDeviceStruct *ptr;
1144 struct termios port;
1145
Alexandre Julliard61fece01999-06-26 19:09:08 +00001146 TRACE("cid %d, ptr %p\n", cid, lpdcb);
Rein Klazes58a38b81999-03-23 13:44:51 +00001147 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001148 FIXME("no handle for cid = %0x!\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001149 return -1;
1150 }
1151 if (tcgetattr(ptr->fd, &port) == -1) {
1152 ptr->commerror = WinError();
1153 return -1;
1154 }
1155 lpdcb->Id = cid;
1156#ifndef __EMX__
1157#ifdef CBAUD
Patrik Stridvallfe28f251999-09-23 11:44:52 +00001158 speed = port.c_cflag & CBAUD;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001159#else
Patrik Stridvallfe28f251999-09-23 11:44:52 +00001160 speed = port.c_ospeed;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001161#endif
Patrik Stridvallfe28f251999-09-23 11:44:52 +00001162 switch(speed) {
Ove Kaavena1c45a51999-03-21 15:45:41 +00001163 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
1200 }
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;
1215 }
1216
Rein Klazes58a38b81999-03-23 13:44:51 +00001217 if(port.c_iflag & INPCK)
1218 lpdcb->fParity = TRUE;
1219 else
1220 lpdcb->fParity = FALSE;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001221#ifdef CMSPAR
Patrik Stridvallc77ff5e2000-04-29 14:26:13 +00001222 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001223#else
Patrik Stridvallc77ff5e2000-04-29 14:26:13 +00001224 switch (port.c_cflag & (PARENB | PARODD))
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001225#endif
Patrik Stridvallc77ff5e2000-04-29 14:26:13 +00001226 {
Ove Kaavena1c45a51999-03-21 15:45:41 +00001227 case 0:
Ove Kaavena1c45a51999-03-21 15:45:41 +00001228 lpdcb->Parity = NOPARITY;
1229 break;
1230 case PARENB:
Ove Kaavena1c45a51999-03-21 15:45:41 +00001231 lpdcb->Parity = EVENPARITY;
1232 break;
1233 case (PARENB | PARODD):
Ove Kaavena1c45a51999-03-21 15:45:41 +00001234 lpdcb->Parity = ODDPARITY;
1235 break;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001236#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
Ove Kaavena1c45a51999-03-21 15:45:41 +00001244 }
1245
1246 if (port.c_cflag & CSTOPB)
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001247 if(lpdcb->ByteSize == 5)
1248 lpdcb->StopBits = ONE5STOPBITS;
1249 else
1250 lpdcb->StopBits = TWOSTOPBITS;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001251 else
Rein Klazes0a54d5a2000-04-28 14:44:33 +00001252 lpdcb->StopBits = ONESTOPBIT;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001253
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;
1261
1262#ifdef CRTSCTS
1263
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;
1272
1273 if (port.c_iflag & IXON)
1274 lpdcb->fInX = 1;
1275 else
1276 lpdcb->fInX = 0;
1277
1278 if (port.c_iflag & IXOFF)
1279 lpdcb->fOutX = 1;
1280 else
1281 lpdcb->fOutX = 0;
1282/*
1283 lpdcb->XonChar =
1284 lpdcb->XoffChar =
1285 */
1286 lpdcb->XonLim = 10;
1287 lpdcb->XoffLim = 10;
1288
Ove Kaavena88444e1999-06-12 06:43:48 +00001289 lpdcb->EvtChar = ptr->evtchar;
1290
Ove Kaavena1c45a51999-03-21 15:45:41 +00001291 ptr->commerror = 0;
1292 return 0;
1293}
1294
1295/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +00001296 * TransmitCommChar16 (USER.206)
Ove Kaavena1c45a51999-03-21 15:45:41 +00001297 */
1298INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1299{
1300 struct DosDeviceStruct *ptr;
1301
Alexandre Julliard61fece01999-06-26 19:09:08 +00001302 TRACE("cid %d, data %d \n", cid, chTransmit);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001303 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001304 FIXME("no handle for cid = %0x!\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001305 return -1;
1306 }
1307
1308 if (ptr->suspended) {
1309 ptr->commerror = IE_HARDWARE;
1310 return -1;
1311 }
1312
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001313 if (ptr->xmit >= 0) {
1314 /* character already queued */
1315 /* FIXME: which error would Windows return? */
1316 ptr->commerror = CE_TXFULL;
1317 return -1;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001318 }
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001319
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;
Ove Kaaven542b29d1999-11-25 21:57:32 +00001325 comm_waitwrite(ptr);
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001326 }
1327 } else {
1328 /* data in queue, let this char be transmitted next */
1329 ptr->xmit = chTransmit;
Ove Kaaven542b29d1999-11-25 21:57:32 +00001330 comm_waitwrite(ptr);
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001331 }
1332
1333 ptr->commerror = 0;
1334 return 0;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001335}
1336
1337/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +00001338 * UngetCommChar16 (USER.212)
Ove Kaavena1c45a51999-03-21 15:45:41 +00001339 */
1340INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1341{
1342 struct DosDeviceStruct *ptr;
1343
Alexandre Julliard61fece01999-06-26 19:09:08 +00001344 TRACE("cid %d (char %d)\n", cid, chUnget);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001345 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001346 FIXME("no handle for cid = %0x!\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001347 return -1;
1348 }
1349
1350 if (ptr->suspended) {
1351 ptr->commerror = IE_HARDWARE;
1352 return -1;
1353 }
1354
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001355 if (ptr->unget>=0) {
1356 /* character already queued */
1357 /* FIXME: which error would Windows return? */
1358 ptr->commerror = CE_RXOVER;
1359 return -1;
1360 }
1361
1362 ptr->unget = chUnget;
1363
Ove Kaavena1c45a51999-03-21 15:45:41 +00001364 ptr->commerror = 0;
1365 return 0;
1366}
1367
1368/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +00001369 * ReadComm16 (USER.204)
Ove Kaavena1c45a51999-03-21 15:45:41 +00001370 */
1371INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1372{
1373 int status, length;
1374 struct DosDeviceStruct *ptr;
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001375 LPSTR orgBuf = lpvBuf;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001376
Alexandre Julliard61fece01999-06-26 19:09:08 +00001377 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001378 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001379 FIXME("no handle for cid = %0x!\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001380 return -1;
1381 }
1382
1383 if (ptr->suspended) {
1384 ptr->commerror = IE_HARDWARE;
1385 return -1;
1386 }
1387
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001388 /* read unget character */
1389 if (ptr->unget>=0) {
1390 *lpvBuf++ = ptr->unget;
1391 ptr->unget = -1;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001392
1393 length = 1;
1394 } else
1395 length = 0;
1396
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001397 /* 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;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001404
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001405 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;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001411 }
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001412
Alexandre Julliard61fece01999-06-26 19:09:08 +00001413 TRACE("%.*s\n", length, orgBuf);
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001414 ptr->commerror = 0;
1415 return length;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001416}
1417
1418/*****************************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +00001419 * WriteComm16 (USER.205)
Ove Kaavena1c45a51999-03-21 15:45:41 +00001420 */
1421INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1422{
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001423 int status, length;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001424 struct DosDeviceStruct *ptr;
1425
Alexandre Julliard61fece01999-06-26 19:09:08 +00001426 TRACE("cid %d, ptr %p, length %d\n",
Ove Kaavena1c45a51999-03-21 15:45:41 +00001427 cid, lpvBuf, cbWrite);
1428 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001429 FIXME("no handle for cid = %0x!\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001430 return -1;
1431 }
1432
1433 if (ptr->suspended) {
1434 ptr->commerror = IE_HARDWARE;
1435 return -1;
1436 }
1437
Alexandre Julliard61fece01999-06-26 19:09:08 +00001438 TRACE("%.*s\n", cbWrite, lpvBuf );
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001439
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;
1449 }
1450 }
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;
Ove Kaaven542b29d1999-11-25 21:57:32 +00001463 comm_waitwrite(ptr);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001464 }
Ove Kaavena4dd1be1999-04-01 11:52:16 +00001465
1466 ptr->commerror = 0;
1467 return length;
Ove Kaavena1c45a51999-03-21 15:45:41 +00001468}
1469
1470/***********************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +00001471 * EnableCommNotification16 (USER.246)
Ove Kaavena1c45a51999-03-21 15:45:41 +00001472 */
1473BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1474 INT16 cbWriteNotify, INT16 cbOutQueue )
1475{
1476 struct DosDeviceStruct *ptr;
1477
Alexandre Julliard61fece01999-06-26 19:09:08 +00001478 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001479 if ((ptr = GetDeviceStruct(cid)) == NULL) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001480 FIXME("no handle for cid = %0x!\n",cid);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001481 return -1;
1482 }
1483 ptr->wnd = hwnd;
1484 ptr->n_read = cbWriteNotify;
1485 ptr->n_write = cbOutQueue;
1486 return TRUE;
1487}
1488
1489
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001490/**************************************************************************
1491 * BuildCommDCBA (KERNEL32.14)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001492 *
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.
1496 *
1497 * RETURNS
1498 *
1499 * True on success, false on an malformed control string.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001500 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001501BOOL 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. */)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001504{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001505 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001506}
1507
1508/**************************************************************************
1509 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001510 *
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.
1514 *
1515 * RETURNS
1516 *
1517 * True on success, false bad handles etc
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001518 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001519BOOL 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. */)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001523{
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001524 int port;
1525 char *ptr,*temp;
1526
Alexandre Julliard61fece01999-06-26 19:09:08 +00001527 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001528
Alexandre Julliard072dfb52000-09-25 23:30:56 +00001529 if (!strncasecmp(device,"COM",3)) {
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001530 port=device[3]-'0';
1531 if (port--==0) {
Andreas Mohra6d83eb2000-12-27 04:02:46 +00001532 ERR("BUG! COM0 can't exist!\n");
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001533 return FALSE;
1534 }
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;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001542
Alexandre Julliarda3960291999-02-26 11:11:13 +00001543 lpdcb->DCBlength = sizeof(DCB);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001544 if (strchr(temp,',')) { /* old style */
1545 DCB16 dcb16;
1546 BOOL16 ret;
1547 char last=temp[strlen(temp)-1];
1548
1549 ret=BuildCommDCB16(device,&dcb16);
Stefan Leichterdcb97332000-07-09 12:19:44 +00001550 if (ret)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001551 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;
1580 }
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;
1590 }
1591 ptr=strtok(temp," ");
1592 while (ptr) {
1593 DWORD flag,x;
1594
1595 flag=0;
1596 if (!strncmp("baud=",ptr,5)) {
1597 if (!sscanf(ptr+5,"%ld",&x))
Alexandre Julliard61fece01999-06-26 19:09:08 +00001598 WARN("Couldn't parse %s\n",ptr);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001599 lpdcb->BaudRate = x;
1600 flag=1;
1601 }
1602 if (!strncmp("stop=",ptr,5)) {
1603 if (!sscanf(ptr+5,"%ld",&x))
Alexandre Julliard61fece01999-06-26 19:09:08 +00001604 WARN("Couldn't parse %s\n",ptr);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001605 lpdcb->StopBits = x;
1606 flag=1;
1607 }
1608 if (!strncmp("data=",ptr,5)) {
1609 if (!sscanf(ptr+5,"%ld",&x))
Alexandre Julliard61fece01999-06-26 19:09:08 +00001610 WARN("Couldn't parse %s\n",ptr);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001611 lpdcb->ByteSize = x;
1612 flag=1;
1613 }
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;
1630 }
1631 flag=1;
1632 }
1633 if (!flag)
Alexandre Julliard61fece01999-06-26 19:09:08 +00001634 ERR("Unhandled specifier '%s', please report.\n",ptr);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001635 ptr=strtok(NULL," ");
1636 }
1637 if (lpdcb->BaudRate==110)
1638 lpdcb->StopBits = 2;
1639 return TRUE;
1640}
1641
1642/**************************************************************************
1643 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001644 *
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.
1648 *
1649 * RETURNS
1650 *
1651 * True on success, false bad handles etc.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001652 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001653BOOL 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. */)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001657{
Andrew Johnston03131aa2000-12-19 23:33:03 +00001658 BOOL ret = FALSE;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001659 LPSTR devidA;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001660
Alexandre Julliard61fece01999-06-26 19:09:08 +00001661 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001662 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
Andrew Johnston03131aa2000-12-19 23:33:03 +00001663 if (devidA)
1664 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001665 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001666 HeapFree( GetProcessHeap(), 0, devidA );
Andrew Johnston03131aa2000-12-19 23:33:03 +00001667 }
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001668 return ret;
1669}
1670
1671/**************************************************************************
1672 * BuildCommDCBW (KERNEL32.17)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001673 *
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.
1677 *
1678 * RETURNS
1679 *
1680 * True on success, false on an malformed control string.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001681 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001682BOOL WINAPI BuildCommDCBW(
1683 LPCWSTR devid, /* The unicode device control string. */
1684 LPDCB lpdcb /* The device control block to be updated. */)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001685{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001686 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001687}
1688
Ove Kaavena1c45a51999-03-21 15:45:41 +00001689/* FIXME: having these global for win32 for now */
Mike McCormack556d11d2000-09-18 01:41:07 +00001690int commerror=0;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001691
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001692/*****************************************************************************
1693 * SetCommBreak (KERNEL32.449)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001694 *
1695 * Halts the transmission of characters to a communications device.
1696 *
1697 * RETURNS
1698 *
1699 * True on success, and false if the communications device could not be found,
1700 * the control is not supported.
1701 *
1702 * BUGS
1703 *
1704 * Only TIOCSBRK and TIOCCBRK are supported.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001705 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001706BOOL WINAPI SetCommBreak(
1707 HANDLE handle /* The communictions device to suspend. */)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001708{
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001709#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1710 int fd,result;
1711
Mike McCormack556d11d2000-09-18 01:41:07 +00001712 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001713 if(fd<0) {
Mike McCormack556d11d2000-09-18 01:41:07 +00001714 TRACE("FILE_GetUnixHandle failed\n");
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001715 return FALSE;
1716 }
1717 result = ioctl(fd,TIOCSBRK,0);
1718 close(fd);
1719 if (result ==-1)
1720 {
1721 TRACE("ioctl failed\n");
1722 SetLastError(ERROR_NOT_SUPPORTED);
1723 return FALSE;
1724 }
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001725 return TRUE;
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001726#else
1727 FIXME("ioctl not available\n");
1728 SetLastError(ERROR_NOT_SUPPORTED);
1729 return FALSE;
1730#endif
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001731}
1732
1733/*****************************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001734 * ClearCommBreak (KERNEL32.20)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001735 *
1736 * Resumes character transmission from a communication device.
1737 *
1738 * RETURNS
1739 *
1740 * True on success and false if the communications device could not be found.
1741 *
1742 * BUGS
1743 *
1744 * Only TIOCSBRK and TIOCCBRK are supported.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001745 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001746BOOL WINAPI ClearCommBreak(
1747 HANDLE handle /* The halted communication device whose character transmission is to be resumed. */)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001748{
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001749#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1750 int fd,result;
1751
Mike McCormack556d11d2000-09-18 01:41:07 +00001752 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001753 if(fd<0) {
Mike McCormack556d11d2000-09-18 01:41:07 +00001754 TRACE("FILE_GetUnixHandle failed\n");
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001755 return FALSE;
1756 }
1757 result = ioctl(fd,TIOCCBRK,0);
1758 close(fd);
1759 if (result ==-1)
1760 {
1761 TRACE("ioctl failed\n");
1762 SetLastError(ERROR_NOT_SUPPORTED);
1763 return FALSE;
1764 }
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001765 return TRUE;
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001766#else
1767 FIXME("ioctl not available\n");
1768 SetLastError(ERROR_NOT_SUPPORTED);
1769 return FALSE;
1770#endif
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001771}
1772
1773/*****************************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001774 * EscapeCommFunction (KERNEL32.214)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001775 *
1776 * Directs a communication device to perform an extended function.
1777 *
1778 * RETURNS
1779 *
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.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001783 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001784BOOL WINAPI EscapeCommFunction(
1785 HANDLE handle, /* The communication device to perform the extended function. */
1786 UINT nFunction /* The extended function to be performed. */)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001787{
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001788 int fd,direct=FALSE,result=FALSE;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001789 struct termios port;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001790
Alexandre Julliard61fece01999-06-26 19:09:08 +00001791 TRACE("handle %d, function=%d\n", handle, nFunction);
Mike McCormack556d11d2000-09-18 01:41:07 +00001792 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
Marcus Meissner7547d4d2000-01-05 01:46:53 +00001793 if(fd<0) {
1794 FIXME("handle %d not found.\n",handle);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001795 return FALSE;
Marcus Meissner7547d4d2000-01-05 01:46:53 +00001796 }
Ove Kaavena1c45a51999-03-21 15:45:41 +00001797
1798 if (tcgetattr(fd,&port) == -1) {
1799 commerror=WinError();
1800 close(fd);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001801 return FALSE;
1802 }
1803
1804 switch (nFunction) {
1805 case RESETDEV:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001806 TRACE("\n");
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001807 break;
1808
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001809 case CLRDTR:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001810 TRACE("CLRDTR\n");
1811#ifdef TIOCM_DTR
1812 direct=TRUE;
1813 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001814 break;
1815#endif
1816
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001817 case CLRRTS:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001818 TRACE("CLRRTS\n");
1819#ifdef TIOCM_RTS
1820 direct=TRUE;
1821 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001822 break;
1823#endif
1824
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001825 case SETDTR:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001826 TRACE("SETDTR\n");
1827#ifdef TIOCM_DTR
1828 direct=TRUE;
1829 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001830 break;
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001831#endif
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001832
1833 case SETRTS:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001834 TRACE("SETRTS\n");
1835#ifdef TIOCM_DTR
1836 direct=TRUE;
1837 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001838 break;
1839#endif
1840
1841 case SETXOFF:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001842 TRACE("SETXOFF\n");
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001843 port.c_iflag |= IXOFF;
1844 break;
1845
1846 case SETXON:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001847 TRACE("SETXON\n");
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001848 port.c_iflag |= IXON;
1849 break;
1850 case SETBREAK:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001851 TRACE("setbreak\n");
1852#ifdef TIOCSBRK
1853 direct=TRUE;
1854 result = ioctl(fd,TIOCSBRK,0);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001855 break;
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001856#endif
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001857 case CLRBREAK:
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001858 TRACE("clrbreak\n");
1859#ifdef TIOCSBRK
1860 direct=TRUE;
1861 result = ioctl(fd,TIOCCBRK,0);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001862 break;
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001863#endif
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001864 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +00001865 WARN("(handle=%d,nFunction=%d): Unknown function\n",
Ove Kaavena1c45a51999-03-21 15:45:41 +00001866 handle, nFunction);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001867 break;
1868 }
1869
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001870 if (!direct)
1871 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001872 commerror = WinError();
Ove Kaavena1c45a51999-03-21 15:45:41 +00001873 close(fd);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001874 return FALSE;
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00001875 } else
1876 result= TRUE;
1877 else
1878 {
1879 if (result == -1)
1880 {
1881 result= FALSE;
1882 commerror=WinError();
1883 }
1884 else
1885 result = TRUE;
1886 }
1887 close(fd);
1888 return result;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001889}
1890
Alexandre Julliard77b99181997-09-14 17:17:23 +00001891/********************************************************************
1892 * PurgeComm (KERNEL32.557)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001893 *
1894 * Terminates pending operations and/or discards buffers on a
1895 * communication resource.
1896 *
1897 * RETURNS
1898 *
1899 * True on success and false if the communications handle is bad.
Alexandre Julliard77b99181997-09-14 17:17:23 +00001900 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001901BOOL WINAPI PurgeComm(
1902 HANDLE handle, /* The communication resource to be purged. */
1903 DWORD flags /* Flags for clear pending/buffer on input/output. */)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001904{
Michael McCormacka8486071999-03-14 12:25:36 +00001905 int fd;
Michael McCormacka8486071999-03-14 12:25:36 +00001906
Alexandre Julliard61fece01999-06-26 19:09:08 +00001907 TRACE("handle %d, flags %lx\n", handle, flags);
Michael McCormacka8486071999-03-14 12:25:36 +00001908
Mike McCormack556d11d2000-09-18 01:41:07 +00001909 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
Marcus Meissner7547d4d2000-01-05 01:46:53 +00001910 if(fd<0) {
1911 FIXME("no handle %d found\n",handle);
1912 return FALSE;
1913 }
Michael McCormacka8486071999-03-14 12:25:36 +00001914
1915 /*
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.
1919 */
1920 if(flags&PURGE_TXABORT)
Michael McCormacka8486071999-03-14 12:25:36 +00001921 tcflush(fd,TCOFLUSH);
Michael McCormacka8486071999-03-14 12:25:36 +00001922 if(flags&PURGE_RXABORT)
Michael McCormacka8486071999-03-14 12:25:36 +00001923 tcflush(fd,TCIFLUSH);
Michael McCormacka8486071999-03-14 12:25:36 +00001924 if(flags&PURGE_TXCLEAR)
Michael McCormacka8486071999-03-14 12:25:36 +00001925 tcflush(fd,TCOFLUSH);
Michael McCormacka8486071999-03-14 12:25:36 +00001926 if(flags&PURGE_RXCLEAR)
Michael McCormacka8486071999-03-14 12:25:36 +00001927 tcflush(fd,TCIFLUSH);
Ove Kaavena1c45a51999-03-21 15:45:41 +00001928 close(fd);
Michael McCormacka8486071999-03-14 12:25:36 +00001929
1930 return 1;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001931}
1932
Michael McCormacka8486071999-03-14 12:25:36 +00001933/*****************************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001934 * ClearCommError (KERNEL32.21)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001935 *
1936 * Enables further I/O operations on a communications resource after
1937 * supplying error and current status information.
1938 *
1939 * RETURNS
1940 *
1941 * True on success, false if the communication resource handle is bad.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001942 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00001943BOOL 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. */)
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001947{
Michael McCormacka8486071999-03-14 12:25:36 +00001948 int fd;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001949
Mike McCormack556d11d2000-09-18 01:41:07 +00001950 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
Michael McCormacka8486071999-03-14 12:25:36 +00001951 if(0>fd)
1952 {
Marcus Meissner7547d4d2000-01-05 01:46:53 +00001953 FIXME("no handle %d found\n",handle);
Michael McCormacka8486071999-03-14 12:25:36 +00001954 return FALSE;
1955 }
1956
1957 if (lpStat)
1958 {
1959 lpStat->status = 0;
1960
Marcus Meissner7547d4d2000-01-05 01:46:53 +00001961#ifdef TIOCOUTQ
Michael McCormacka8486071999-03-14 12:25:36 +00001962 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
Alexandre Julliard61fece01999-06-26 19:09:08 +00001963 WARN("ioctl returned error\n");
Marcus Meissner7547d4d2000-01-05 01:46:53 +00001964#else
1965 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1966#endif
Michael McCormacka8486071999-03-14 12:25:36 +00001967
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +00001968#ifdef TIOCINQ
Michael McCormacka8486071999-03-14 12:25:36 +00001969 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
Alexandre Julliard61fece01999-06-26 19:09:08 +00001970 WARN("ioctl returned error\n");
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +00001971#endif
Eric Pouechf2163101999-07-12 13:39:58 +00001972
1973 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1974 handle, lpStat->cbInQue, lpStat->cbOutQue);
Michael McCormacka8486071999-03-14 12:25:36 +00001975 }
1976
1977 close(fd);
1978
Michael McCormacka8486071999-03-14 12:25:36 +00001979 if(errors)
1980 *errors = 0;
1981
1982 /*
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
1986 */
1987 commerror = ERROR_IO_PENDING;
1988
1989 return TRUE;
Alexandre Julliard5f721f81994-01-04 20:14:34 +00001990}
1991
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001992/*****************************************************************************
Alexandre Julliard77b99181997-09-14 17:17:23 +00001993 * SetupComm (KERNEL32.676)
Andrew Johnston03131aa2000-12-19 23:33:03 +00001994 *
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.
1997 *
1998 * RETURNS
1999 *
2000 * True if successful, false if the communications resource handle is bad.
2001 *
2002 * BUGS
2003 *
2004 * Stub.
Alexandre Julliard77b99181997-09-14 17:17:23 +00002005 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002006BOOL 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. */)
Alexandre Julliard77b99181997-09-14 17:17:23 +00002010{
Michael McCormacka8486071999-03-14 12:25:36 +00002011 int fd;
2012
Alexandre Julliard61fece01999-06-26 19:09:08 +00002013 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
Mike McCormack556d11d2000-09-18 01:41:07 +00002014 fd=FILE_GetUnixHandle( handle, GENERIC_WRITE );
Marcus Meissner7547d4d2000-01-05 01:46:53 +00002015 if(0>fd) {
2016 FIXME("handle %d not found?\n",handle);
Michael McCormacka8486071999-03-14 12:25:36 +00002017 return FALSE;
2018 }
2019 close(fd);
2020 return TRUE;
Alexandre Julliard77b99181997-09-14 17:17:23 +00002021}
2022
2023/*****************************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002024 * GetCommMask (KERNEL32.156)
Andrew Johnston03131aa2000-12-19 23:33:03 +00002025 *
2026 * Obtain the events associated with a communication device that will cause a call
2027 * WaitCommEvent to return.
2028 *
2029 * RETURNS
2030 *
2031 * True on success, fail on bad device handle etc.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002032 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002033BOOL WINAPI GetCommMask(
2034 HANDLE handle, /* The communications device. */
2035 LPDWORD evtmask /* The events which cause WaitCommEvent to return. */)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002036{
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002037 BOOL ret;
Michael McCormacka8486071999-03-14 12:25:36 +00002038
Alexandre Julliard61fece01999-06-26 19:09:08 +00002039 TRACE("handle %d, mask %p\n", handle, evtmask);
Mike McCormack654fcc72000-09-16 20:55:12 +00002040
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002041 SERVER_START_REQ
2042 {
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 )))
2046 {
2047 if (evtmask) *evtmask = req->eventmask;
2048 }
2049 }
2050 SERVER_END_REQ;
2051 return ret;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002052}
2053
2054/*****************************************************************************
2055 * SetCommMask (KERNEL32.451)
Andrew Johnston03131aa2000-12-19 23:33:03 +00002056 *
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.)
2060 *
2061 * RETURNS
2062 *
2063 * True on success, false on bad handle etc.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002064 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002065BOOL WINAPI SetCommMask(
2066 HANDLE handle, /* The communications device. */
2067 DWORD evtmask /* The events that to be monitored. */)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002068{
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002069 BOOL ret;
Michael McCormacka8486071999-03-14 12:25:36 +00002070
Alexandre Julliard61fece01999-06-26 19:09:08 +00002071 TRACE("handle %d, mask %lx\n", handle, evtmask);
Mike McCormack654fcc72000-09-16 20:55:12 +00002072
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002073 SERVER_START_REQ
2074 {
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 );
2080 }
2081 SERVER_END_REQ;
2082 return ret;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002083}
2084
2085/*****************************************************************************
Michael McCormacka8486071999-03-14 12:25:36 +00002086 * SetCommState (KERNEL32.452)
Andrew Johnston03131aa2000-12-19 23:33:03 +00002087 *
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.
2091 *
2092 * RETURNS
2093 *
2094 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002095 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002096BOOL WINAPI SetCommState(
2097 HANDLE handle, /* The communications device. */
2098 LPDCB lpdcb /* The device control block. */)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002099{
Michael McCormacka8486071999-03-14 12:25:36 +00002100 struct termios port;
Andrew Johnston03131aa2000-12-19 23:33:03 +00002101 int fd, bytesize, stopbits;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002102
Alexandre Julliard61fece01999-06-26 19:09:08 +00002103 TRACE("handle %d, ptr %p\n", handle, lpdcb);
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002104 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");
Michael McCormacka8486071999-03-14 12:25:36 +00002110
Mike McCormack556d11d2000-09-18 01:41:07 +00002111 fd = FILE_GetUnixHandle( handle, GENERIC_WRITE );
2112 if (fd < 0) {
Marcus Meissner7547d4d2000-01-05 01:46:53 +00002113 FIXME("no handle %d found\n",handle);
2114 return FALSE;
2115 }
Michael McCormacka8486071999-03-14 12:25:36 +00002116
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002117 if ((tcgetattr(fd,&port)) == -1) {
2118 int save_error = errno;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002119 commerror = WinError();
2120 close( fd );
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002121 ERR("tcgetattr error '%s'\n", strerror(save_error));
Michael McCormacka8486071999-03-14 12:25:36 +00002122 return FALSE;
2123 }
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002124
2125 port.c_cc[VMIN] = 0;
2126 port.c_cc[VTIME] = 1;
2127
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);
2134
2135 port.c_oflag &= ~(OPOST);
2136
2137 port.c_cflag &= ~(HUPCL);
2138 port.c_cflag |= CLOCAL | CREAD;
2139
2140 port.c_lflag &= ~(ICANON|ECHO|ISIG);
2141 port.c_lflag |= NOFLSH;
2142
Michael McCormacka8486071999-03-14 12:25:36 +00002143 /*
2144 ** MJM - removed default baudrate settings
2145 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2146 */
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002147#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;
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002186#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:
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002207 commerror = IE_BAUDRATE;
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002208 close( fd );
2209 ERR("baudrate %ld\n",lpdcb->BaudRate);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002210 return FALSE;
2211 }
Alexandre Julliard349a9531997-02-02 19:01:52 +00002212#elif !defined(__EMX__)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002213 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;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002252 close( fd );
Gerald Pfeifer093af592000-05-30 15:28:37 +00002253 ERR("baudrate %ld\n",lpdcb->BaudRate);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002254 return FALSE;
2255 }
2256 port.c_ispeed = port.c_ospeed;
2257#endif
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002258 bytesize=lpdcb->ByteSize;
2259 stopbits=lpdcb->StopBits;
2260
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;
2298 }
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;
2309 }
2310 break;
2311#endif
2312 default:
2313 commerror = IE_BYTESIZE;
2314 close( fd );
2315 ERR("Parity\n");
2316 return FALSE;
2317 }
2318
2319
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002320 port.c_cflag &= ~CSIZE;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002321 switch (bytesize) {
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002322 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;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002336 close( fd );
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002337 ERR("ByteSize\n");
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002338 return FALSE;
2339 }
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002340
2341 switch (stopbits) {
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002342 case ONESTOPBIT:
2343 port.c_cflag &= ~CSTOPB;
2344 break;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002345 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002346 case TWOSTOPBITS:
2347 port.c_cflag |= CSTOPB;
2348 break;
2349 default:
2350 commerror = IE_BYTESIZE;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002351 close( fd );
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002352 ERR("StopBits\n");
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002353 return FALSE;
2354 }
2355#ifdef CRTSCTS
2356 if ( lpdcb->fOutxCtsFlow ||
2357 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2358 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002359 )
2360 {
2361 port.c_cflag |= CRTSCTS;
2362 TRACE("CRTSCTS\n");
2363 }
2364
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002365 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002366 {
2367 port.c_cflag &= ~CRTSCTS;
2368 TRACE("~CRTSCTS\n");
2369 }
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002370
2371#endif
2372 if (lpdcb->fInX)
2373 port.c_iflag |= IXON;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002374 else
2375 port.c_iflag &= ~IXON;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002376 if (lpdcb->fOutX)
2377 port.c_iflag |= IXOFF;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002378 else
2379 port.c_iflag &= ~IXOFF;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002380
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002381 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2382 int save_error=errno;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002383 commerror = WinError();
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002384 close( fd );
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002385 ERR("tcgetattr error '%s'\n", strerror(save_error));
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002386 return FALSE;
2387 } else {
2388 commerror = 0;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002389 close( fd );
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002390 return TRUE;
2391 }
2392}
2393
2394
2395/*****************************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002396 * GetCommState (KERNEL32.159)
Andrew Johnston03131aa2000-12-19 23:33:03 +00002397 *
2398 * Fills in a device control block with information from a communications device.
2399 *
2400 * RETURNS
2401 *
2402 * True on success, false if the communication device handle is bad etc
2403 *
2404 * BUGS
2405 *
2406 * XonChar and XoffChar are not set.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002407 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002408BOOL WINAPI GetCommState(
2409 HANDLE handle, /* The communications device. */
2410 LPDCB lpdcb /* The device control block. */)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002411{
Michael McCormacka8486071999-03-14 12:25:36 +00002412 struct termios port;
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002413 int fd,speed;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002414
Alexandre Julliard61fece01999-06-26 19:09:08 +00002415 TRACE("handle %d, ptr %p\n", handle, lpdcb);
Michael McCormacka8486071999-03-14 12:25:36 +00002416
Mike McCormack556d11d2000-09-18 01:41:07 +00002417 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
2418 if (fd < 0)
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002419 {
Mike McCormack556d11d2000-09-18 01:41:07 +00002420 ERR("FILE_GetUnixHandle failed\n");
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002421 return FALSE;
2422 }
Michael McCormacka8486071999-03-14 12:25:36 +00002423 if (tcgetattr(fd, &port) == -1) {
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002424 int save_error=errno;
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002425 ERR("tcgetattr error '%s'\n", strerror(save_error));
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002426 commerror = WinError();
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002427 close( fd );
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002428 return FALSE;
2429 }
Alexandre Julliardebe29ef1999-06-26 08:43:26 +00002430 close( fd );
Alexandre Julliard349a9531997-02-02 19:01:52 +00002431#ifndef __EMX__
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002432#ifdef CBAUD
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002433 speed= (port.c_cflag & CBAUD);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002434#else
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002435 speed= (cfgetospeed(&port));
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002436#endif
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002437 switch (speed) {
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002438 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;
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002465#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);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002487 }
Alexandre Julliard349a9531997-02-02 19:01:52 +00002488#endif
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002489 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;
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002502 default:
2503 ERR("unknown size %x \n",port.c_cflag & CSIZE);
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002504 }
2505
Rein Klazes58a38b81999-03-23 13:44:51 +00002506 if(port.c_iflag & INPCK)
2507 lpdcb->fParity = TRUE;
2508 else
2509 lpdcb->fParity = FALSE;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002510#ifdef CMSPAR
Patrik Stridvallc77ff5e2000-04-29 14:26:13 +00002511 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002512#else
Patrik Stridvallc77ff5e2000-04-29 14:26:13 +00002513 switch (port.c_cflag & (PARENB | PARODD))
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002514#endif
Patrik Stridvallc77ff5e2000-04-29 14:26:13 +00002515 {
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002516 case 0:
Cliff Wright28d3d211998-11-22 15:05:18 +00002517 lpdcb->Parity = NOPARITY;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002518 break;
2519 case PARENB:
Cliff Wright28d3d211998-11-22 15:05:18 +00002520 lpdcb->Parity = EVENPARITY;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002521 break;
2522 case (PARENB | PARODD):
Cliff Wright28d3d211998-11-22 15:05:18 +00002523 lpdcb->Parity = ODDPARITY;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002524 break;
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002525#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
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002533 }
2534
2535 if (port.c_cflag & CSTOPB)
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002536 if(lpdcb->ByteSize == 5)
2537 lpdcb->StopBits = ONE5STOPBITS;
2538 else
2539 lpdcb->StopBits = TWOSTOPBITS;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002540 else
Rein Klazes0a54d5a2000-04-28 14:44:33 +00002541 lpdcb->StopBits = ONESTOPBIT;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002542
2543 lpdcb->fNull = 0;
2544 lpdcb->fBinary = 1;
2545
2546#ifdef CRTSCTS
2547
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
2555 {
2556 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2557 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2558 }
2559 if (port.c_iflag & IXON)
2560 lpdcb->fInX = 1;
2561 else
2562 lpdcb->fInX = 0;
2563
2564 if (port.c_iflag & IXOFF)
2565 lpdcb->fOutX = 1;
2566 else
2567 lpdcb->fOutX = 0;
2568/*
2569 lpdcb->XonChar =
2570 lpdcb->XoffChar =
2571 */
2572 lpdcb->XonLim = 10;
2573 lpdcb->XoffLim = 10;
2574
2575 commerror = 0;
Michael McCormacka8486071999-03-14 12:25:36 +00002576
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002577 TRACE("OK\n");
Michael McCormacka8486071999-03-14 12:25:36 +00002578
Uwe Bonnesf57ef1d1999-08-07 12:28:09 +00002579 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
2589 )
2590 TRACE("CRTSCTS\n");
2591
2592 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2593 TRACE("~CRTSCTS\n");
2594
2595#endif
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002596 return TRUE;
2597}
2598
2599/*****************************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002600 * TransmitCommChar (KERNEL32.535)
Andrew Johnston03131aa2000-12-19 23:33:03 +00002601 *
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.
2604 *
2605 * RETURNS
2606 *
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.
2609 *
2610 * BUGS
2611 *
2612 * Stub.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002613 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002614BOOL WINAPI TransmitCommChar(
2615 HANDLE hComm, /* The communication device in need of a command character. */
2616 CHAR chTransmit /* The character to transmit. */)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002617{
Mike McCormack6a31f962000-06-15 00:15:11 +00002618 FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
2619 return TRUE;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002620}
2621
2622/*****************************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002623 * GetCommTimeouts (KERNEL32.160)
Andrew Johnston03131aa2000-12-19 23:33:03 +00002624 *
2625 * Obtains the request time out values for the communications device.
2626 *
2627 * RETURNS
2628 *
2629 * True on success, false if communications device handle is bad
2630 * or the target structure is null.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002631 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002632BOOL WINAPI GetCommTimeouts(
2633 HANDLE hComm, /* The communications device. */
2634 LPCOMMTIMEOUTS lptimeouts /* The struct of request time outs. */)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002635{
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002636 BOOL ret;
Mike McCormack654fcc72000-09-16 20:55:12 +00002637
2638 TRACE("(%x,%p)\n",hComm,lptimeouts);
2639
2640 if(!lptimeouts)
2641 {
2642 SetLastError(ERROR_INVALID_PARAMETER);
2643 return FALSE;
2644 }
2645
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002646 SERVER_START_REQ
2647 {
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 )))
2651 {
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;
2657 }
2658 }
2659 SERVER_END_REQ;
2660 return ret;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002661}
2662
2663/*****************************************************************************
2664 * SetCommTimeouts (KERNEL32.453)
Mike McCormack654fcc72000-09-16 20:55:12 +00002665 *
2666 * Sets the timeouts used when reading and writing data to/from COMM ports.
2667 *
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
Andrew Johnston03131aa2000-12-19 23:33:03 +00002674 *
2675 * RETURNS
2676 *
2677 * True if the time outs were set, false otherwise.
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00002678 */
Mike McCormack654fcc72000-09-16 20:55:12 +00002679BOOL WINAPI SetCommTimeouts(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00002680 HANDLE hComm, /* [in] handle of COMM device */
2681 LPCOMMTIMEOUTS lptimeouts /* [in] pointer to COMMTIMEOUTS structure */
Mike McCormack654fcc72000-09-16 20:55:12 +00002682) {
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002683 BOOL ret;
2684 int fd;
Mike McCormack654fcc72000-09-16 20:55:12 +00002685 struct termios tios;
Marcus Meissner7547d4d2000-01-05 01:46:53 +00002686
Mike McCormack654fcc72000-09-16 20:55:12 +00002687 TRACE("(%x,%p)\n",hComm,lptimeouts);
Marcus Meissner7547d4d2000-01-05 01:46:53 +00002688
Mike McCormack654fcc72000-09-16 20:55:12 +00002689 if(!lptimeouts)
2690 {
2691 SetLastError(ERROR_INVALID_PARAMETER);
Mike McCormack654fcc72000-09-16 20:55:12 +00002692 return FALSE;
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002693 }
2694
2695 SERVER_START_REQ
2696 {
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 );
2706 }
2707 SERVER_END_REQ;
2708 if (!ret) return FALSE;
Mike McCormack654fcc72000-09-16 20:55:12 +00002709
2710 /* FIXME: move this stuff to the server */
Mike McCormack556d11d2000-09-18 01:41:07 +00002711 fd = FILE_GetUnixHandle( hComm, GENERIC_WRITE );
Mike McCormack654fcc72000-09-16 20:55:12 +00002712 if (fd < 0) {
2713 FIXME("no fd for handle = %0x!.\n",hComm);
2714 return FALSE;
2715 }
Marcus Meissner7547d4d2000-01-05 01:46:53 +00002716
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002717 if (-1==tcgetattr(fd,&tios)) {
2718 FIXME("tcgetattr on fd %d failed!\n",fd);
2719 return FALSE;
2720 }
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;
2726 }
Mike McCormack654fcc72000-09-16 20:55:12 +00002727 close(fd);
Alexandre Julliard57f05e12000-10-15 00:40:25 +00002728 return TRUE;
Alexandre Julliard641ee761997-08-04 16:34:36 +00002729}
2730
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002731/***********************************************************************
2732 * GetCommModemStatus (KERNEL32.285)
Andrew Johnston03131aa2000-12-19 23:33:03 +00002733 *
2734 * Obtains the four control register bits if supported by the hardware.
2735 *
2736 * RETURNS
2737 *
2738 * True if the communications handle was good and for hardware that
2739 * control register access, false otherwise.
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002740 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00002741BOOL WINAPI GetCommModemStatus(
2742 HANDLE hFile, /* The communications device. */
2743 LPDWORD lpModemStat /* The control register bits. */)
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002744{
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002745 int fd,mstat, result=FALSE;
2746
2747 *lpModemStat=0;
2748#ifdef TIOCMGET
Mike McCormack556d11d2000-09-18 01:41:07 +00002749 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002750 if(fd<0)
2751 return FALSE;
2752 result = ioctl(fd, TIOCMGET, &mstat);
2753 close(fd);
2754 if (result == -1)
2755 {
2756 TRACE("ioctl failed\n");
2757 return FALSE;
2758 }
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +00002759#ifdef TIOCM_CTS
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002760 if (mstat & TIOCM_CTS)
2761 *lpModemStat |= MS_CTS_ON;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +00002762#endif
2763#ifdef TIOCM_DSR
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002764 if (mstat & TIOCM_DSR)
2765 *lpModemStat |= MS_DSR_ON;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +00002766#endif
2767#ifdef TIOCM_RNG
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002768 if (mstat & TIOCM_RNG)
2769 *lpModemStat |= MS_RING_ON;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +00002770#endif
2771#ifdef TIOCM_CAR
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002772 /*FIXME: Not really sure about RLSD UB 990810*/
2773 if (mstat & TIOCM_CAR)
2774 *lpModemStat |= MS_RLSD_ON;
Dimitrie O. Paun5bea4f82000-11-25 01:29:00 +00002775#endif
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002776 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 ":"");
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002781 return TRUE;
Uwe Bonnes684ee2c1999-08-14 15:53:50 +00002782#else
2783 return FALSE;
2784#endif
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002785}
Mike McCormack1eac1912000-11-13 19:27:21 +00002786
2787VOID COMM_WaitCommEventService(void **args)
2788{
2789 LPOVERLAPPED lpOverlapped = (LPOVERLAPPED)args[0];
2790 LPDWORD buffer = (LPDWORD)args[1];
2791 DWORD events = (DWORD)args[2];
2792
2793 TRACE("overlapped %p wait complete %p <- %lx\n",lpOverlapped,buffer,events);
2794 if(buffer)
2795 *buffer = events;
2796
Mike McCormack1c80bc92000-12-29 19:35:25 +00002797 lpOverlapped->Internal = STATUS_SUCCESS;
Mike McCormack1eac1912000-11-13 19:27:21 +00002798 SetEvent( lpOverlapped->hEvent);
Mike McCormack1c80bc92000-12-29 19:35:25 +00002799 CloseHandle(lpOverlapped->InternalHigh);
Mike McCormack1eac1912000-11-13 19:27:21 +00002800}
2801
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002802/***********************************************************************
2803 * WaitCommEvent (KERNEL32.719)
Mike McCormack1eac1912000-11-13 19:27:21 +00002804 *
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.
2808 *
2809 * RETURNS:
2810 * TRUE if successful
2811 * FALSE if failure
2812 *
2813 * The set of detected events will be written to *lpdwEventMask
2814 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2815 *
2816 * BUGS:
2817 * Only supports EV_RXCHAR and EV_TXEMPTY
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002818 */
Mike McCormack1eac1912000-11-13 19:27:21 +00002819BOOL WINAPI WaitCommEvent(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00002820 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 */
Mike McCormack1eac1912000-11-13 19:27:21 +00002823) {
2824 OVERLAPPED ov;
2825 LPOVERLAPPED lpov;
2826 int ret;
2827
2828 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2829
2830 /* if there is no overlapped structure, create our own */
2831 if(!lpOverlapped)
2832 {
2833 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
2834 lpov = &ov;
2835 }
2836 else
2837 lpov = lpOverlapped;
2838
2839 /* check that the overlapped structure has a valid event flag */
2840 if ( (lpov->hEvent==0) || (lpov->hEvent == INVALID_HANDLE_VALUE) )
Mike McCormack1c80bc92000-12-29 19:35:25 +00002841 {
Mike McCormack1eac1912000-11-13 19:27:21 +00002842 ERR("Couldn't create Event flag for Overlapped structure\n");
2843 SetLastError(ERROR_INVALID_PARAMETER);
2844 return FALSE;
2845 }
2846
Mike McCormack1c80bc92000-12-29 19:35:25 +00002847 ResetEvent(lpov->hEvent);
2848
2849 lpov->Internal = STATUS_PENDING;
2850 lpov->InternalHigh = 0;
Mike McCormack1eac1912000-11-13 19:27:21 +00002851 lpov->Offset = 0;
2852 lpov->OffsetHigh = 0;
2853
2854 /* start an ASYNCHRONOUS WaitCommEvent */
2855 SERVER_START_REQ
2856 {
2857 struct create_async_request *req = server_alloc_req( sizeof(*req), 0 );
2858
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;
2865
2866 ret=server_call( REQ_CREATE_ASYNC );
2867
Mike McCormack1c80bc92000-12-29 19:35:25 +00002868 lpov->InternalHigh = req->ov_handle;
Mike McCormack1eac1912000-11-13 19:27:21 +00002869 }
2870 SERVER_END_REQ;
2871
2872 if(ret)
2873 {
2874 if(!lpOverlapped)
2875 CloseHandle(lpov->hEvent);
2876 TRACE("server call failed.\n");
2877 return FALSE;
2878 }
2879
Mike McCormack1c80bc92000-12-29 19:35:25 +00002880 /* activate the overlapped operation */
2881 lpov->Internal = STATUS_PENDING;
2882
Mike McCormack1eac1912000-11-13 19:27:21 +00002883 /* wait ourselves if the caller didn't give us an overlapped struct */
2884 if(!lpOverlapped)
2885 {
2886 GetOverlappedResult(hFile, lpov, NULL, TRUE);
2887 CloseHandle(lpov->hEvent);
2888 lpov->hEvent=0;
2889 }
2890 else
2891 {
2892 /* caller wants overlapped I/O using GetOverlapped result */
2893 SetLastError(ERROR_IO_PENDING);
2894 return FALSE;
2895 }
2896
2897 return TRUE;
Uwe Bonnes94113fa1998-11-30 10:40:02 +00002898}
2899
Michael McCormacka8486071999-03-14 12:25:36 +00002900/***********************************************************************
Mike McCormacka341a962000-07-15 21:36:31 +00002901 * GetCommProperties (KERNEL32.286)
2902 *
2903 * This function fills in a structure with the capabilities of the
2904 * communications port driver.
2905 *
2906 * RETURNS
2907 *
2908 * TRUE on success, FALSE on failure
2909 * If successful, the lpCommProp structure be filled in with
2910 * properties of the comm port.
Michael McCormacka8486071999-03-14 12:25:36 +00002911 */
Mike McCormacka341a962000-07-15 21:36:31 +00002912BOOL WINAPI GetCommProperties(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00002913 HANDLE hFile, /* [in] handle of the comm port */
2914 LPCOMMPROP lpCommProp /* [out] pointer to struct to be filled */
Mike McCormacka341a962000-07-15 21:36:31 +00002915) {
Mike McCormack6a31f962000-06-15 00:15:11 +00002916 FIXME("(%d %p )\n",hFile,lpCommProp);
Mike McCormacka341a962000-07-15 21:36:31 +00002917 if(!lpCommProp)
2918 return FALSE;
2919
2920 /*
2921 * These values should be valid for LINUX's serial driver
2922 * FIXME: Perhaps they deserve an #ifdef LINUX
2923 */
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;
2944
Michael McCormacka8486071999-03-14 12:25:36 +00002945 return TRUE;
2946}
2947
Stefan Leichter00e7c332000-07-08 18:29:54 +00002948/***********************************************************************
Mike McCormacka341a962000-07-15 21:36:31 +00002949 * 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 ***********************************************************************/
2962static CHAR lpszSerialUI[] = "serialui.dll";
2963
2964
2965/***********************************************************************
2966 * CommConfigDialogA (KERNEL32.140)
2967 *
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...
2971 *
2972 * RETURNS
2973 *
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.
2977 *
2978 * BUGS
2979 * The library with the CommConfigDialog code is never unloaded.
2980 * Perhaps this should be done when the comm port is closed?
2981 */
2982BOOL WINAPI CommConfigDialogA(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00002983 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 */
Mike McCormacka341a962000-07-15 21:36:31 +00002986) {
2987 FARPROC lpfnCommDialog;
2988 HMODULE hConfigModule;
2989 BOOL r;
2990
2991 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
2992
2993 hConfigModule = LoadLibraryA(lpszSerialUI);
2994 if(!hConfigModule)
2995 return FALSE;
2996
2997 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2998
2999 if(!lpfnCommDialog)
3000 return FALSE;
3001
3002 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
3003
3004 /* UnloadLibrary(hConfigModule); */
3005
3006 return r;
3007}
3008
3009/***********************************************************************
3010 * CommConfigDialogW (KERNEL32.141)
3011 *
3012 * see CommConfigDialogA for more info
3013 */
3014BOOL WINAPI CommConfigDialogW(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00003015 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 */
Mike McCormacka341a962000-07-15 21:36:31 +00003018) {
3019 BOOL r;
3020 LPSTR lpDeviceA;
3021
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;
3028}
3029
3030/***********************************************************************
3031 * GetCommConfig (KERNEL32.283)
3032 *
3033 * Fill in the COMMCONFIG structure for the comm port hFile
3034 *
3035 * RETURNS
3036 *
3037 * TRUE on success, FALSE on failure
3038 * If successful, lpCommConfig contains the comm port configuration.
Andrew Johnston03131aa2000-12-19 23:33:03 +00003039 *
3040 * BUGS
3041 *
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)
Mike McCormacka341a962000-07-15 21:36:31 +00003045 */
3046BOOL WINAPI GetCommConfig(
Andrew Johnston03131aa2000-12-19 23:33:03 +00003047 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. */
Mike McCormacka341a962000-07-15 21:36:31 +00003051) {
3052 BOOL r;
3053
3054 TRACE("(%x %p)\n",hFile,lpCommConfig);
3055
3056 if(lpCommConfig == NULL)
3057 return FALSE;
3058
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;
3066
3067 return r;
3068}
3069
3070/***********************************************************************
3071 * SetCommConfig (KERNEL32.617)
3072 *
Andrew Johnston03131aa2000-12-19 23:33:03 +00003073 * Sets the configuration of the commications device.
3074 *
3075 * RETURNS
3076 *
3077 * True on success, false if the handle was bad is not a communications device.
Mike McCormacka341a962000-07-15 21:36:31 +00003078 */
3079BOOL WINAPI SetCommConfig(
Andrew Johnston03131aa2000-12-19 23:33:03 +00003080 HANDLE hFile, /* The communications device. */
3081 LPCOMMCONFIG lpCommConfig /* The desired configuration. */
Mike McCormacka341a962000-07-15 21:36:31 +00003082) {
Mike McCormacka341a962000-07-15 21:36:31 +00003083 TRACE("(%x %p)\n",hFile,lpCommConfig);
Andrew Johnston03131aa2000-12-19 23:33:03 +00003084 return SetCommState(hFile,&lpCommConfig->dcb);
Mike McCormacka341a962000-07-15 21:36:31 +00003085}
3086
3087/***********************************************************************
Mike McCormack556d11d2000-09-18 01:41:07 +00003088 * SetDefaultCommConfigA (KERNEL32.638)
Andrew Johnston03131aa2000-12-19 23:33:03 +00003089 *
3090 * Initializes the default configuration for the specified communication
3091 * device. (ascii)
3092 *
3093 * RETURNS
3094 *
3095 * True if the device was found and the defaults set, false otherwise
Mike McCormacka341a962000-07-15 21:36:31 +00003096 */
3097BOOL WINAPI SetDefaultCommConfigA(
Andrew Johnston03131aa2000-12-19 23:33:03 +00003098 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. */
Mike McCormacka341a962000-07-15 21:36:31 +00003101) {
3102 FARPROC lpfnSetDefaultCommConfig;
3103 HMODULE hConfigModule;
3104 BOOL r;
3105
3106 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
3107
3108 hConfigModule = LoadLibraryA(lpszSerialUI);
3109 if(!hConfigModule)
3110 return FALSE;
3111
3112 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
3113
3114 if(! lpfnSetDefaultCommConfig)
3115 return TRUE;
3116
3117 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
3118
3119 /* UnloadLibrary(hConfigModule); */
3120
3121 return r;
3122}
3123
3124
3125/***********************************************************************
3126 * SetDefaultCommConfigW (KERNEL32.639)
3127 *
Andrew Johnston03131aa2000-12-19 23:33:03 +00003128 * Initializes the default configuration for the specified
3129 * communication device. (unicode)
3130 *
3131 * RETURNS
3132 *
Mike McCormacka341a962000-07-15 21:36:31 +00003133 */
3134BOOL WINAPI SetDefaultCommConfigW(
Andrew Johnston03131aa2000-12-19 23:33:03 +00003135 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. */
Mike McCormacka341a962000-07-15 21:36:31 +00003138) {
3139 BOOL r;
3140 LPSTR lpDeviceA;
3141
3142 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
3143
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;
3150}
3151
3152
3153/***********************************************************************
Stefan Leichter00e7c332000-07-08 18:29:54 +00003154 * GetDefaultCommConfigA (KERNEL32.313)
Andrew Johnston03131aa2000-12-19 23:33:03 +00003155 *
3156 * Acquires the default configuration of the specified communication device. (unicode)
3157 *
3158 * RETURNS
3159 *
3160 * True on successful reading of the default configuration,
3161 * if the device is not found or the buffer is too small.
Stefan Leichter00e7c332000-07-08 18:29:54 +00003162 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00003163BOOL 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. */
3168{
Stefan Leichter00e7c332000-07-08 18:29:54 +00003169 LPDCB lpdcb = &(lpCC->dcb);
3170 char temp[40];
3171
3172 if (strncasecmp(lpszName,"COM",3)) {
3173 ERR("not implemented for <%s>\n", lpszName);
3174 return FALSE;
3175 }
3176
3177 if (!ValidCOMPort(lpszName[3]-'1'))
3178 return FALSE;
3179
3180 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
3181 if (*lpdwSize < sizeof(COMMCONFIG)) {
3182 *lpdwSize = sizeof(COMMCONFIG);
3183 return FALSE;
3184 }
3185
3186 *lpdwSize = sizeof(COMMCONFIG);
3187
3188 lpCC->dwSize = sizeof(COMMCONFIG);
3189 lpCC->wVersion = 1;
3190 lpCC->dwProviderSubType = PST_RS232;
3191 lpCC->dwProviderOffset = 0L;
3192 lpCC->dwProviderSize = 0L;
3193
3194 (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
3195 FIXME("setting %s as default\n", temp);
3196
3197 return BuildCommDCBA( temp, lpdcb);
3198}
3199
3200/**************************************************************************
3201 * GetDefaultCommConfigW (KERNEL32.314)
Andrew Johnston03131aa2000-12-19 23:33:03 +00003202 *
3203 * Acquires the default configuration of the specified communication device. (unicode)
3204 *
3205 * RETURNS
3206 *
3207 * True on successful reading of the default configuration,
3208 * if the device is not found or the buffer is too small.
Stefan Leichter00e7c332000-07-08 18:29:54 +00003209 */
Andrew Johnston03131aa2000-12-19 23:33:03 +00003210BOOL 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. */
3215) {
3216 BOOL ret = FALSE;
Stefan Leichter00e7c332000-07-08 18:29:54 +00003217 LPSTR lpszNameA;
Stefan Leichter00e7c332000-07-08 18:29:54 +00003218
Gerald Pfeifer5dae3822000-07-15 14:58:32 +00003219 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
Stefan Leichter00e7c332000-07-08 18:29:54 +00003220 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
Andrew Johnston03131aa2000-12-19 23:33:03 +00003221 if (lpszNameA)
3222 {
Stefan Leichter00e7c332000-07-08 18:29:54 +00003223 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
3224 HeapFree( GetProcessHeap(), 0, lpszNameA );
Andrew Johnston03131aa2000-12-19 23:33:03 +00003225 }
Stefan Leichter00e7c332000-07-08 18:29:54 +00003226 return ret;
3227}
Mike McCormack44b5bf52000-09-07 18:39:51 +00003228