~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/user32/comm16.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * DEC 93 Erik Bos <erik@xs4all.nl>
  3  *
  4  * Copyright 1996 Marcus Meissner
  5  *
  6  * Copyright 2001 Mike McCormack
  7  *
  8  * This library is free software; you can redistribute it and/or
  9  * modify it under the terms of the GNU Lesser General Public
 10  * License as published by the Free Software Foundation; either
 11  * version 2.1 of the License, or (at your option) any later version.
 12  *
 13  * This library is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * Lesser General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU Lesser General Public
 19  * License along with this library; if not, write to the Free Software
 20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 21  *
 22  * History:
 23  *
 24  * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
 25  * - Implemented buffers and EnableCommNotification.
 26  *
 27  * Apr 3, 1999.  Lawson Whitney <lawson_whitney@juno.com>
 28  * - Fixed the modem control part of EscapeCommFunction16.
 29  *
 30  * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
 31  * - Use port indices instead of unixfds for win16
 32  * - Moved things around (separated win16 and win32 routines)
 33  * - Added some hints on how to implement buffers and EnableCommNotification.
 34  *
 35  * May 26, 1997.  Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
 36  * - ptr->fd wasn't getting cleared on close.
 37  * - GetCommEventMask() and GetCommError() didn't do much of anything.
 38  *   IMHO, they are still wrong, but they at least implement the RXCHAR
 39  *   event and return I/O queue sizes, which makes the app I'm interested
 40  *   in (analog devices EZKIT DSP development system) work.
 41  *
 42  * August 12, 1997.  Take a bash at SetCommEventMask - Lawson Whitney
 43  *                                     <lawson_whitney@juno.com>
 44  * July 6, 1998. Fixes and comments by Valentijn Sessink
 45  *                                     <vsessink@ic.uva.nl> [V]
 46  * Oktober 98, Rein Klazes [RHK]
 47  * A program that wants to monitor the modem status line (RLSD/DCD) may
 48  * poll the modem status register in the commMask structure. I update the bit
 49  * in GetCommError, waiting for an implementation of communication events.
 50  *
 51  */
 52 
 53 #include "config.h"
 54 #include "wine/port.h"
 55 
 56 #include <stdlib.h>
 57 #include <stdarg.h>
 58 #include <stdio.h>
 59 #include <string.h>
 60 #include <errno.h>
 61 #include <ctype.h>
 62 
 63 #include "windef.h"
 64 #include "winbase.h"
 65 #include "wine/winuser16.h"
 66 #include "win.h"
 67 #include "user_private.h"
 68 
 69 #include "wine/debug.h"
 70 
 71 WINE_DEFAULT_DEBUG_CHANNEL(comm);
 72 
 73 /* window's semi documented modem status register */
 74 #define COMM_MSR_OFFSET  35
 75 #define MSR_CTS  0x10
 76 #define MSR_DSR  0x20
 77 #define MSR_RI   0x40
 78 #define MSR_RLSD 0x80
 79 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
 80 
 81 #define FLAG_LPT 0x80
 82 
 83 #define MAX_PORTS   9
 84 
 85 struct DosDeviceStruct {
 86     HANDLE handle;
 87     int suspended;
 88     int unget,xmit;
 89     int evtchar;
 90     /* events */
 91     int commerror, eventmask;
 92     /* buffers */
 93     char *inbuf,*outbuf;
 94     unsigned ibuf_size,ibuf_head,ibuf_tail;
 95     unsigned obuf_size,obuf_head,obuf_tail;
 96     /* notifications */
 97     HWND wnd;
 98     int n_read, n_write;
 99     OVERLAPPED read_ov, write_ov;
100     /* save terminal states */
101     DCB16 dcb;
102     /* pointer to unknown(==undocumented) comm structure */
103     SEGPTR seg_unknown;
104     BYTE unknown[40];
105 };
106 
107 static struct DosDeviceStruct COM[MAX_PORTS];
108 static struct DosDeviceStruct LPT[MAX_PORTS];
109 
110 /* update window's semi documented modem status register */
111 /* see knowledge base Q101417 */
112 static void COMM_MSRUpdate( HANDLE handle, UCHAR * pMsr )
113 {
114     UCHAR tmpmsr=0;
115     DWORD mstat=0;
116 
117     if(!GetCommModemStatus(handle,&mstat))
118         return;
119 
120     if(mstat & MS_CTS_ON) tmpmsr |= MSR_CTS;
121     if(mstat & MS_DSR_ON) tmpmsr |= MSR_DSR;
122     if(mstat & MS_RING_ON) tmpmsr |= MSR_RI;
123     if(mstat & MS_RLSD_ON) tmpmsr |= MSR_RLSD;
124     *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
125 }
126 
127 static struct DosDeviceStruct *GetDeviceStruct(int index)
128 {
129         if ((index&0x7F)<=MAX_PORTS) {
130             if (!(index&FLAG_LPT)) {
131                 if (COM[index].handle)
132                     return &COM[index];
133             } else {
134                 index &= 0x7f;
135                 if (LPT[index].handle)
136                     return &LPT[index];
137             }
138         }
139 
140         return NULL;
141 }
142 
143 static int    GetCommPort_ov(const OVERLAPPED *ov, int write)
144 {
145         int x;
146 
147         for (x=0; x<MAX_PORTS; x++) {
148                 if (ov == (write?&COM[x].write_ov:&COM[x].read_ov))
149                         return x;
150         }
151 
152         return -1;
153 }
154 
155 static int WinError(void)
156 {
157         TRACE("errno = %d\n", errno);
158         switch (errno) {
159                 default:
160                         return CE_IOE;
161                 }
162 }
163 
164 static unsigned comm_inbuf(const struct DosDeviceStruct *ptr)
165 {
166   return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
167     + ptr->ibuf_head - ptr->ibuf_tail;
168 }
169 
170 static unsigned comm_outbuf(const struct DosDeviceStruct *ptr)
171 {
172   return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
173     + ptr->obuf_head - ptr->obuf_tail;
174 }
175 
176 static void comm_waitread(struct DosDeviceStruct *ptr);
177 static void comm_waitwrite(struct DosDeviceStruct *ptr);
178 
179 static VOID WINAPI COMM16_ReadComplete(DWORD dwErrorCode, DWORD len, LPOVERLAPPED ov)
180 {
181         int prev;
182         WORD mask = 0;
183         int cid = GetCommPort_ov(ov,0);
184         struct DosDeviceStruct *ptr;
185 
186         if(cid<0) {
187                 ERR("async write with bad overlapped pointer\n");
188                 return;
189         }
190         ptr = &COM[cid];
191 
192         /* we get cancelled when CloseComm is called */
193         if (dwErrorCode==ERROR_OPERATION_ABORTED)
194         {
195                 TRACE("Cancelled\n");
196                 return;
197         }
198 
199         /* read data from comm port */
200         if (dwErrorCode != NO_ERROR) {
201                 ERR("async read failed, error %d\n",dwErrorCode);
202                 COM[cid].commerror = CE_RXOVER;
203                 return;
204         }
205         TRACE("async read completed %d bytes\n",len);
206 
207         prev = comm_inbuf(ptr);
208 
209         /* check for events */
210         if ((ptr->eventmask & EV_RXFLAG) &&
211             memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
212                 *(WORD*)(COM[cid].unknown) |= EV_RXFLAG;
213                 mask |= CN_EVENT;
214         }
215         if (ptr->eventmask & EV_RXCHAR) {
216                 *(WORD*)(COM[cid].unknown) |= EV_RXCHAR;
217                 mask |= CN_EVENT;
218         }
219 
220         /* advance buffer position */
221         ptr->ibuf_head += len;
222         if (ptr->ibuf_head >= ptr->ibuf_size)
223                 ptr->ibuf_head = 0;
224 
225         /* check for notification */
226         if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
227             (comm_inbuf(ptr)>=ptr->n_read)) {
228                 /* passed the receive notification threshold */
229                 mask |= CN_RECEIVE;
230         }
231 
232         /* send notifications, if any */
233         if (ptr->wnd && mask) {
234                 TRACE("notifying %p: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
235                 PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
236         }
237 
238         /* on real windows, this could cause problems, since it is recursive */
239         /* restart the receive */
240         comm_waitread(ptr);
241 }
242 
243 /* this is meant to work like write() */
244 static INT COMM16_WriteFile(HANDLE hComm, LPCVOID buffer, DWORD len)
245 {
246         OVERLAPPED ov;
247         DWORD count= -1;
248 
249         ZeroMemory(&ov,sizeof(ov));
250         ov.hEvent = CreateEventW(NULL,0,0,NULL);
251         if(ov.hEvent==INVALID_HANDLE_VALUE)
252                 return -1;
253 
254         if(!WriteFile(hComm,buffer,len,&count,&ov))
255         {
256                 if(GetLastError()==ERROR_IO_PENDING)
257                 {
258                         GetOverlappedResult(hComm,&ov,&count,TRUE);
259                 }
260         }
261         CloseHandle(ov.hEvent);
262 
263         return count;
264 }
265 
266 static VOID WINAPI COMM16_WriteComplete(DWORD dwErrorCode, DWORD len, LPOVERLAPPED ov)
267 {
268         int prev, bleft;
269         WORD mask = 0;
270         int cid = GetCommPort_ov(ov,1);
271         struct DosDeviceStruct *ptr;
272 
273         if(cid<0) {
274                 ERR("async write with bad overlapped pointer\n");
275                 return;
276         }
277         ptr = &COM[cid];
278 
279         /* read data from comm port */
280         if (dwErrorCode != NO_ERROR) {
281                 ERR("async write failed, error %d\n",dwErrorCode);
282                 COM[cid].commerror = CE_RXOVER;
283                 return;
284         }
285         TRACE("async write completed %d bytes\n",len);
286 
287         /* update the buffer pointers */
288         prev = comm_outbuf(&COM[cid]);
289         ptr->obuf_tail += len;
290         if (ptr->obuf_tail >= ptr->obuf_size)
291                 ptr->obuf_tail = 0;
292 
293         /* write any TransmitCommChar character */
294         if (ptr->xmit>=0) {
295                 len = COMM16_WriteFile(ptr->handle, &(ptr->xmit), 1);
296                 if (len > 0) ptr->xmit = -1;
297         }
298 
299         /* write from output queue */
300         bleft = ((ptr->obuf_tail <= ptr->obuf_head) ?
301                 ptr->obuf_head : ptr->obuf_size) - ptr->obuf_tail;
302 
303         /* check for notification */
304         if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
305           (comm_outbuf(ptr)<ptr->n_write)) {
306                 /* passed the transmit notification threshold */
307                 mask |= CN_TRANSMIT;
308         }
309 
310         /* send notifications, if any */
311         if (ptr->wnd && mask) {
312                 TRACE("notifying %p: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
313                 PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
314         }
315 
316         /* start again if necessary */
317         if(bleft)
318                 comm_waitwrite(ptr);
319 }
320 
321 static void comm_waitread(struct DosDeviceStruct *ptr)
322 {
323         unsigned int bleft;
324         COMSTAT stat;
325 
326         /* FIXME: get timeouts working properly so we can read bleft bytes */
327         bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ?
328                 (ptr->ibuf_tail-1) : ptr->ibuf_size) - ptr->ibuf_head;
329 
330         /* find out how many bytes are left in the buffer */
331         if(ClearCommError(ptr->handle,NULL,&stat))
332                 bleft = (bleft<stat.cbInQue) ? bleft : stat.cbInQue;
333         else
334                 bleft = 1;
335 
336         /* always read at least one byte */
337         if(bleft==0)
338                 bleft++;
339 
340         ReadFileEx(ptr->handle,
341                 ptr->inbuf + ptr->ibuf_head,
342                 bleft,
343                 &ptr->read_ov,
344                 COMM16_ReadComplete);
345 }
346 
347 static void comm_waitwrite(struct DosDeviceStruct *ptr)
348 {
349         int bleft;
350 
351         bleft = ((ptr->obuf_tail <= ptr->obuf_head) ?
352                 ptr->obuf_head : ptr->obuf_size) - ptr->obuf_tail;
353         WriteFileEx(ptr->handle,
354                 ptr->outbuf + ptr->obuf_tail,
355                 bleft,
356                 &ptr->write_ov,
357                 COMM16_WriteComplete);
358 }
359 
360 /*****************************************************************************
361  *      COMM16_DCBtoDCB16       (Internal)
362  */
363 static INT16 COMM16_DCBtoDCB16(const DCB *lpdcb, LPDCB16 lpdcb16)
364 {
365         if(lpdcb->BaudRate<0x10000)
366                 lpdcb16->BaudRate = lpdcb->BaudRate;
367         else if(lpdcb->BaudRate==115200)
368                         lpdcb16->BaudRate = 57601;
369         else {
370                 WARN("Baud rate can't be converted\n");
371                 lpdcb16->BaudRate = 57601;
372         }
373         lpdcb16->ByteSize = lpdcb->ByteSize;
374         lpdcb16->fParity = lpdcb->fParity;
375         lpdcb16->Parity = lpdcb->Parity;
376         lpdcb16->StopBits = lpdcb->StopBits;
377 
378         lpdcb16->RlsTimeout = 50;
379         lpdcb16->CtsTimeout = 50;
380         lpdcb16->DsrTimeout = 50;
381         lpdcb16->fNull = 0;
382         lpdcb16->fChEvt = 0;
383         lpdcb16->fBinary = 1;
384 
385         lpdcb16->fDtrflow = (lpdcb->fDtrControl==DTR_CONTROL_HANDSHAKE);
386         lpdcb16->fRtsflow = (lpdcb->fRtsControl==RTS_CONTROL_HANDSHAKE);
387         lpdcb16->fOutxCtsFlow = lpdcb->fOutxCtsFlow;
388         lpdcb16->fOutxDsrFlow = lpdcb->fOutxDsrFlow;
389         lpdcb16->fDtrDisable = (lpdcb->fDtrControl==DTR_CONTROL_DISABLE);
390 
391         lpdcb16->fInX = lpdcb->fInX;
392 
393         lpdcb16->fOutX = lpdcb->fOutX;
394 /*
395         lpdcb16->XonChar =
396         lpdcb16->XoffChar =
397  */
398         lpdcb16->XonLim = 10;
399         lpdcb16->XoffLim = 10;
400 
401         return 0;
402 }
403 
404 
405 /**************************************************************************
406  *         BuildCommDCB         (USER.213)
407  *
408  * According to the ECMA-234 (368.3) the function will return FALSE on
409  * success, otherwise it will return -1.
410  */
411 INT16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
412 {
413         /* "COM1:96,n,8,1"      */
414         /*  012345              */
415         int port;
416         DCB dcb;
417 
418         TRACE("(%s), ptr %p\n", device, lpdcb);
419 
420         if (strncasecmp(device,"COM",3))
421                 return -1;
422         port = device[3] - '';
423 
424         if (port-- == 0) {
425                 ERR("BUG ! COM0 can't exist!\n");
426                 return -1;
427         }
428 
429         memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
430 
431         lpdcb->Id = port;
432         dcb.DCBlength = sizeof(DCB);
433 
434         if (strchr(device,'=')) /* block new style */
435                 return -1;
436 
437         if(!BuildCommDCBA(device,&dcb))
438                 return -1;
439 
440         return COMM16_DCBtoDCB16(&dcb, lpdcb);
441 }
442 
443 /*****************************************************************************
444  *      OpenComm                (USER.200)
445  */
446 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
447 {
448         int port;
449         HANDLE handle;
450 
451         TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
452 
453         if (strlen(device) < 4)
454            return IE_BADID;
455 
456         port = device[3] - '';
457 
458         if (port-- == 0)
459                 ERR("BUG ! COM0 or LPT0 don't exist !\n");
460 
461         if (!strncasecmp(device,"COM",3))
462         {
463                 if (COM[port].handle)
464                         return IE_OPEN;
465 
466                 handle = CreateFileA(device, GENERIC_READ|GENERIC_WRITE,
467                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
468                         FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING, 0 );
469                 if (handle == INVALID_HANDLE_VALUE) {
470                         return IE_HARDWARE;
471                 } else {
472                         memset(COM[port].unknown, 0, sizeof(COM[port].unknown));
473                         COM[port].seg_unknown = 0;
474                         COM[port].handle = handle;
475                         COM[port].commerror = 0;
476                         COM[port].eventmask = 0;
477                         COM[port].evtchar = 0; /* FIXME: default? */
478                         /* save terminal state */
479                         GetCommState16(port,&COM[port].dcb);
480                         /* init priority characters */
481                         COM[port].unget = -1;
482                         COM[port].xmit = -1;
483                         /* allocate buffers */
484                         COM[port].ibuf_size = cbInQueue;
485                         COM[port].ibuf_head = COM[port].ibuf_tail = 0;
486                         COM[port].obuf_size = cbOutQueue;
487                         COM[port].obuf_head = COM[port].obuf_tail = 0;
488 
489                         COM[port].inbuf = HeapAlloc(GetProcessHeap(), 0, cbInQueue);
490                         if (COM[port].inbuf) {
491                           COM[port].outbuf = HeapAlloc( GetProcessHeap(), 0, cbOutQueue);
492                           if (!COM[port].outbuf)
493                             HeapFree( GetProcessHeap(), 0, COM[port].inbuf);
494                         } else COM[port].outbuf = NULL;
495                         if (!COM[port].outbuf) {
496                           /* not enough memory */
497                           CloseHandle(COM[port].handle);
498                           ERR("out of memory\n");
499                           return IE_MEMORY;
500                         }
501 
502                         ZeroMemory(&COM[port].read_ov,sizeof (OVERLAPPED));
503                         ZeroMemory(&COM[port].write_ov,sizeof (OVERLAPPED));
504 
505                         comm_waitread( &COM[port] );
506                         USER16_AlertableWait++;
507 
508                         return port;
509                 }
510         }
511         else
512         if (!strncasecmp(device,"LPT",3)) {
513 
514                 if (LPT[port].handle)
515                         return IE_OPEN;
516 
517                 handle = CreateFileA(device, GENERIC_READ|GENERIC_WRITE,
518                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
519                 if (handle == INVALID_HANDLE_VALUE) {
520                         return IE_HARDWARE;
521                 } else {
522                         LPT[port].handle = handle;
523                         LPT[port].commerror = 0;
524                         LPT[port].eventmask = 0;
525                         return port|FLAG_LPT;
526                 }
527         }
528         return IE_BADID;
529 }
530 
531 /*****************************************************************************
532  *      CloseComm               (USER.207)
533  */
534 INT16 WINAPI CloseComm16(INT16 cid)
535 {
536         struct DosDeviceStruct *ptr;
537 
538         TRACE("cid=%d\n", cid);
539         if ((ptr = GetDeviceStruct(cid)) == NULL) {
540                 FIXME("no cid=%d found!\n", cid);
541                 return -1;
542         }
543         if (!(cid&FLAG_LPT)) {
544                 /* COM port */
545                 UnMapLS( COM[cid].seg_unknown );
546                 USER16_AlertableWait--;
547                 CancelIo(ptr->handle);
548 
549                 /* free buffers */
550                 HeapFree( GetProcessHeap(), 0, ptr->outbuf);
551                 HeapFree( GetProcessHeap(), 0, ptr->inbuf);
552 
553                 /* reset modem lines */
554                 SetCommState16(&COM[cid].dcb);
555         }
556 
557         if (!CloseHandle(ptr->handle)) {
558                 ptr->commerror = WinError();
559                 /* FIXME: should we clear ptr->handle here? */
560                 return -1;
561         } else {
562                 ptr->commerror = 0;
563                 ptr->handle = 0;
564                 return 0;
565         }
566 }
567 
568 /*****************************************************************************
569  *      SetCommBreak            (USER.210)
570  */
571 INT16 WINAPI SetCommBreak16(INT16 cid)
572 {
573         struct DosDeviceStruct *ptr;
574 
575         TRACE("cid=%d\n", cid);
576         if ((ptr = GetDeviceStruct(cid)) == NULL) {
577                 FIXME("no cid=%d found!\n", cid);
578                 return -1;
579         }
580 
581         ptr->suspended = 1;
582         ptr->commerror = 0;
583         return 0;
584 }
585 
586 /*****************************************************************************
587  *      ClearCommBreak  (USER.211)
588  */
589 INT16 WINAPI ClearCommBreak16(INT16 cid)
590 {
591         struct DosDeviceStruct *ptr;
592 
593         TRACE("cid=%d\n", cid);
594         if (!(ptr = GetDeviceStruct(cid))) {
595                 FIXME("no cid=%d found!\n", cid);
596                 return -1;
597         }
598         ptr->suspended = 0;
599         ptr->commerror = 0;
600         return 0;
601 }
602 
603 /*****************************************************************************
604  *      EscapeCommFunction      (USER.214)
605  */
606 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
607 {
608         struct  DosDeviceStruct *ptr;
609 
610         TRACE("cid=%d, function=%d\n", cid, nFunction);
611 
612         switch(nFunction) {
613         case GETMAXCOM:
614                 TRACE("GETMAXCOM\n");
615                 return 4;  /* FIXME */
616 
617         case GETMAXLPT:
618                 TRACE("GETMAXLPT\n");
619                 return FLAG_LPT + 3;  /* FIXME */
620 
621         case GETBASEIRQ:
622                 TRACE("GETBASEIRQ\n");
623                 /* FIXME: use tables */
624                 /* just fake something for now */
625                 if (cid & FLAG_LPT) {
626                         /* LPT1: irq 7, LPT2: irq 5 */
627                         return (cid & 0x7f) ? 5 : 7;
628                 } else {
629                         /* COM1: irq 4, COM2: irq 3,
630                            COM3: irq 4, COM4: irq 3 */
631                         return 4 - (cid & 1);
632                 }
633         }
634 
635         if ((ptr = GetDeviceStruct(cid)) == NULL) {
636                 FIXME("no cid=%d found!\n", cid);
637                 return -1;
638         }
639 
640         switch (nFunction) {
641         case RESETDEV:
642         case CLRDTR:
643         case CLRRTS:
644         case SETDTR:
645         case SETRTS:
646         case SETXOFF:
647         case SETXON:
648                 if(EscapeCommFunction(ptr->handle,nFunction))
649                         return 0;
650                 else {
651                         ptr->commerror = WinError();
652                         return -1;
653                 }
654 
655         case CLRBREAK:
656         case SETBREAK:
657         default:
658                 WARN("(cid=%d,nFunction=%d): Unknown function\n",
659                         cid, nFunction);
660         }
661         return -1;
662 }
663 
664 /*****************************************************************************
665  *      FlushComm       (USER.215)
666  */
667 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
668 {
669         DWORD queue;
670         struct DosDeviceStruct *ptr;
671 
672         TRACE("cid=%d, queue=%d\n", cid, fnQueue);
673         if ((ptr = GetDeviceStruct(cid)) == NULL) {
674                 FIXME("no cid=%d found!\n", cid);
675                 return -1;
676         }
677         switch (fnQueue) {
678         case 0:
679                 queue = PURGE_TXABORT;
680                 ptr->obuf_tail = ptr->obuf_head;
681                 break;
682         case 1:
683                 queue = PURGE_RXABORT;
684                 ptr->ibuf_head = ptr->ibuf_tail;
685                 break;
686         default:
687                 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
688                             cid, fnQueue);
689                 return -1;
690         }
691 
692         if (!PurgeComm(ptr->handle,queue)) {
693                 ptr->commerror = WinError();
694                 return -1;
695         } else {
696                 ptr->commerror = 0;
697                 return 0;
698         }
699 }
700 
701 /********************************************************************
702  *      GetCommError    (USER.203)
703  */
704 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
705 {
706         int             temperror;
707         struct DosDeviceStruct *ptr;
708         unsigned char *stol;
709 
710         if ((ptr = GetDeviceStruct(cid)) == NULL) {
711                 FIXME("no handle for cid = %0x!\n",cid);
712                 return -1;
713         }
714         if (cid&FLAG_LPT) {
715             WARN(" cid %d not comm port\n",cid);
716             return CE_MODE;
717         }
718         stol = (unsigned char *)COM[cid].unknown + COMM_MSR_OFFSET;
719         COMM_MSRUpdate( ptr->handle, stol );
720 
721        if (lpStat) {
722                lpStat->status = 0;
723 
724                if (comm_inbuf(ptr) == 0)
725                        SleepEx(1,TRUE);
726 
727                 lpStat->cbOutQue = comm_outbuf(ptr);
728                 lpStat->cbInQue = comm_inbuf(ptr);
729 
730                 TRACE("cid %d, error %d, stat %d in %d out %d, stol %x\n",
731                              cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
732                              lpStat->cbOutQue, *stol);
733         }
734         else
735                 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
736                              cid, ptr->commerror, *stol);
737 
738         /* Return any errors and clear it */
739         temperror = ptr->commerror;
740         ptr->commerror = 0;
741         return(temperror);
742 }
743 
744 /*****************************************************************************
745  *      SetCommEventMask        (USER.208)
746  */
747 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
748 {
749         struct DosDeviceStruct *ptr;
750         unsigned char *stol;
751 
752         TRACE("cid %d,mask %d\n",cid,fuEvtMask);
753         if ((ptr = GetDeviceStruct(cid)) == NULL) {
754                 FIXME("no handle for cid = %0x!\n",cid);
755             return 0;
756         }
757 
758         ptr->eventmask = fuEvtMask;
759 
760         if (cid&FLAG_LPT) {
761             WARN(" cid %d not comm port\n",cid);
762             return 0;
763         }
764         /* it's a COM port ? -> modify flags */
765         stol = (unsigned char *)COM[cid].unknown + COMM_MSR_OFFSET;
766         COMM_MSRUpdate( ptr->handle, stol );
767 
768         TRACE(" modem dcd construct %x\n",*stol);
769         if (!COM[cid].seg_unknown) COM[cid].seg_unknown = MapLS( COM[cid].unknown );
770         return COM[cid].seg_unknown;
771 }
772 
773 /*****************************************************************************
774  *      GetCommEventMask        (USER.209)
775  */
776 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
777 {
778         struct DosDeviceStruct *ptr;
779         WORD events;
780 
781         TRACE("cid %d, mask %d\n", cid, fnEvtClear);
782         if ((ptr = GetDeviceStruct(cid)) == NULL) {
783                 FIXME("no handle for cid = %0x!\n",cid);
784             return 0;
785         }
786 
787         if (cid&FLAG_LPT) {
788             WARN(" cid %d not comm port\n",cid);
789             return 0;
790         }
791 
792         events = *(WORD*)(COM[cid].unknown) & fnEvtClear;
793         *(WORD*)(COM[cid].unknown) &= ~fnEvtClear;
794         return events;
795 }
796 
797 /*****************************************************************************
798  *      SetCommState    (USER.201)
799  */
800 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
801 {
802         struct DosDeviceStruct *ptr;
803         DCB dcb;
804 
805         TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
806         if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
807                 FIXME("no handle for cid = %0x!\n",lpdcb->Id);
808                 return -1;
809         }
810 
811         memset(&dcb,0,sizeof(dcb));
812         dcb.DCBlength = sizeof(dcb);
813 
814         /*
815          * according to MSDN, we should first interpret lpdcb->BaudRate as follows:
816          * 1. if the baud rate is a CBR constant, interpret it.
817          * 2. if it is greater than 57600, the baud rate is 115200
818          * 3. use the actual baudrate
819          * steps 2 and 3 are equivalent to 16550 baudrate divisor = 115200/BaudRate
820          */
821         switch(lpdcb->BaudRate)
822         {
823         case CBR_110:    dcb.BaudRate = 110;    break;
824         case CBR_300:    dcb.BaudRate = 300;    break;
825         case CBR_600:    dcb.BaudRate = 600;    break;
826         case CBR_1200:   dcb.BaudRate = 1200;   break;
827         case CBR_2400:   dcb.BaudRate = 2400;   break;
828         case CBR_4800:   dcb.BaudRate = 4800;   break;
829         case CBR_9600:   dcb.BaudRate = 9600;   break;
830         case CBR_14400:  dcb.BaudRate = 14400;  break;
831         case CBR_19200:  dcb.BaudRate = 19200;  break;
832         case CBR_38400:  dcb.BaudRate = 38400;  break;
833         case CBR_56000:  dcb.BaudRate = 56000;  break;
834         case CBR_128000: dcb.BaudRate = 128000; break;
835         case CBR_256000: dcb.BaudRate = 256000; break;
836         default:
837                 if(lpdcb->BaudRate>57600)
838                 dcb.BaudRate = 115200;
839         else
840                 dcb.BaudRate = lpdcb->BaudRate;
841         }
842 
843         dcb.ByteSize=lpdcb->ByteSize;
844         dcb.StopBits=lpdcb->StopBits;
845 
846         dcb.fParity=lpdcb->fParity;
847         dcb.Parity=lpdcb->Parity;
848 
849         dcb.fOutxCtsFlow = lpdcb->fOutxCtsFlow;
850 
851         if (lpdcb->fDtrflow || lpdcb->fRtsflow)
852                 dcb.fRtsControl = TRUE;
853 
854         if (lpdcb->fDtrDisable)
855                 dcb.fDtrControl = TRUE;
856 
857         ptr->evtchar = lpdcb->EvtChar;
858 
859         dcb.fInX = lpdcb->fInX;
860         dcb.fOutX = lpdcb->fOutX;
861 
862         if (!SetCommState(ptr->handle,&dcb)) {
863                 ptr->commerror = WinError();
864                 return -1;
865         } else {
866                 ptr->commerror = 0;
867                 return 0;
868         }
869 }
870 
871 /*****************************************************************************
872  *      GetCommState    (USER.202)
873  */
874 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
875 {
876         struct DosDeviceStruct *ptr;
877         DCB dcb;
878 
879         TRACE("cid %d, ptr %p\n", cid, lpdcb);
880         if ((ptr = GetDeviceStruct(cid)) == NULL) {
881                 FIXME("no handle for cid = %0x!\n",cid);
882                 return -1;
883         }
884         if (!GetCommState(ptr->handle,&dcb)) {
885                 ptr->commerror = WinError();
886                 return -1;
887         }
888 
889         lpdcb->Id = cid;
890 
891         COMM16_DCBtoDCB16(&dcb,lpdcb);
892 
893         lpdcb->EvtChar = ptr->evtchar;
894 
895         ptr->commerror = 0;
896         return 0;
897 }
898 
899 /*****************************************************************************
900  *      TransmitCommChar        (USER.206)
901  */
902 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
903 {
904         struct DosDeviceStruct *ptr;
905 
906         TRACE("cid %d, data %d\n", cid, chTransmit);
907         if ((ptr = GetDeviceStruct(cid)) == NULL) {
908                 FIXME("no handle for cid = %0x!\n",cid);
909                 return -1;
910         }
911 
912         if (ptr->suspended) {
913                 ptr->commerror = IE_HARDWARE;
914                 return -1;
915         }
916 
917         if (ptr->xmit >= 0) {
918           /* character already queued */
919           /* FIXME: which error would Windows return? */
920           ptr->commerror = CE_TXFULL;
921           return -1;
922         }
923 
924         if (ptr->obuf_head == ptr->obuf_tail) {
925           /* transmit queue empty, try to transmit directly */
926           if(1!=COMM16_WriteFile(ptr->handle, &chTransmit, 1))
927           {
928             /* didn't work, queue it */
929             ptr->xmit = chTransmit;
930             comm_waitwrite(ptr);
931           }
932         } else {
933           /* data in queue, let this char be transmitted next */
934           ptr->xmit = chTransmit;
935           comm_waitwrite(ptr);
936         }
937 
938         ptr->commerror = 0;
939         return 0;
940 }
941 
942 /*****************************************************************************
943  *      UngetCommChar   (USER.212)
944  */
945 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
946 {
947         struct DosDeviceStruct *ptr;
948 
949         TRACE("cid %d (char %d)\n", cid, chUnget);
950         if ((ptr = GetDeviceStruct(cid)) == NULL) {
951                 FIXME("no handle for cid = %0x!\n",cid);
952                 return -1;
953         }
954 
955         if (ptr->suspended) {
956                 ptr->commerror = IE_HARDWARE;
957                 return -1;
958         }
959 
960         if (ptr->unget>=0) {
961           /* character already queued */
962           /* FIXME: which error would Windows return? */
963           ptr->commerror = CE_RXOVER;
964           return -1;
965         }
966 
967         ptr->unget = chUnget;
968 
969         ptr->commerror = 0;
970         return 0;
971 }
972 
973 /*****************************************************************************
974  *      ReadComm        (USER.204)
975  */
976 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
977 {
978         int status, length;
979         struct DosDeviceStruct *ptr;
980         LPSTR orgBuf = lpvBuf;
981 
982         TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
983         if ((ptr = GetDeviceStruct(cid)) == NULL) {
984                 FIXME("no handle for cid = %0x!\n",cid);
985                 return -1;
986         }
987 
988         if (ptr->suspended) {
989                 ptr->commerror = IE_HARDWARE;
990                 return -1;
991         }
992 
993         if(0==comm_inbuf(ptr))
994                 SleepEx(1,TRUE);
995 
996         /* read unget character */
997         if (ptr->unget>=0) {
998                 *lpvBuf++ = ptr->unget;
999                 ptr->unget = -1;
1000 
1001                 length = 1;
1002         } else
1003                 length = 0;
1004 
1005         /* read from receive buffer */
1006         while (length < cbRead) {
1007           status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1008                     ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1009           if (!status) break;
1010           if ((cbRead - length) < status)
1011             status = cbRead - length;
1012 
1013           memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1014           ptr->ibuf_tail += status;
1015           if (ptr->ibuf_tail >= ptr->ibuf_size)
1016             ptr->ibuf_tail = 0;
1017           lpvBuf += status;
1018           length += status;
1019         }
1020 
1021         TRACE("%s\n", debugstr_an( orgBuf, length ));
1022         ptr->commerror = 0;
1023         return length;
1024 }
1025 
1026 /*****************************************************************************
1027  *      WriteComm       (USER.205)
1028  */
1029 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1030 {
1031         int status, length;
1032         struct DosDeviceStruct *ptr;
1033 
1034         TRACE("cid %d, ptr %p, length %d\n",
1035                 cid, lpvBuf, cbWrite);
1036         if ((ptr = GetDeviceStruct(cid)) == NULL) {
1037                 FIXME("no handle for cid = %0x!\n",cid);
1038                 return -1;
1039         }
1040 
1041         if (ptr->suspended) {
1042                 ptr->commerror = IE_HARDWARE;
1043                 return -1;
1044         }
1045 
1046         TRACE("%s\n", debugstr_an( lpvBuf, cbWrite ));
1047 
1048         length = 0;
1049         while (length < cbWrite) {
1050           if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1051             /* no data queued, try to write directly */
1052             status = COMM16_WriteFile(ptr->handle, lpvBuf, cbWrite - length);
1053             if (status > 0) {
1054               lpvBuf += status;
1055               length += status;
1056               continue;
1057             }
1058           }
1059           /* can't write directly, put into transmit buffer */
1060           status = ((ptr->obuf_tail > ptr->obuf_head) ?
1061                     (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1062           if (!status) break;
1063           if ((cbWrite - length) < status)
1064             status = cbWrite - length;
1065           memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1066           ptr->obuf_head += status;
1067           if (ptr->obuf_head >= ptr->obuf_size)
1068             ptr->obuf_head = 0;
1069           lpvBuf += status;
1070           length += status;
1071           comm_waitwrite(ptr);
1072         }
1073 
1074         ptr->commerror = 0;
1075         return length;
1076 }
1077 
1078 /***********************************************************************
1079  *           EnableCommNotification   (USER.245)
1080  */
1081 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1082                                       INT16 cbWriteNotify, INT16 cbOutQueue )
1083 {
1084         struct DosDeviceStruct *ptr;
1085 
1086         TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1087         if ((ptr = GetDeviceStruct(cid)) == NULL) {
1088                 FIXME("no handle for cid = %0x!\n",cid);
1089                 return -1;
1090         }
1091         ptr->wnd = WIN_Handle32( hwnd );
1092         ptr->n_read = cbWriteNotify;
1093         ptr->n_write = cbOutQueue;
1094         return TRUE;
1095 }
1096 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.