1 #ifdef HAVE_CONFIG_H
2 #include "hamlib/rig.h"
3 #include <config.h>
4 #endif
5
6 #if defined(WIN32) && !defined(HAVE_TERMIOS_H)
7
8 #undef DEBUG
9 #undef TRACE
10
11 #ifdef DEBUG
12 #define DEBUG_VERBOSE
13 #define DEBUG_ERRORS
14 #define report(a) fprintf(stderr,a)
15 #define report_warning(a) fprintf(stderr,a)
16 #define report_error(a) fprintf(stderr,a)
17 #else
18 #define report(a) do {} while (0)
19 #define report_warning(a) do {} while (0)
20 #define report_error(a) do {} while (0)
21 #endif /* DEBUG */
22 /*-------------------------------------------------------------------------
23 | rxtx is a native interface to serial ports in java.
24 | Copyright 1997-2002 by Trent Jarvi taj@www.linux.org.uk.
25 | Copyright 1997-2006 by Trent Jarvi taj@www.linux.org.uk.
26 |
27 | This library is free software; you can redistribute it and/or
28 | modify it under the terms of the GNU Lesser General Public
29 | License as published by the Free Software Foundation; either
30 | version 2.1 of the License, or (at your option) any later version.
31 |
32 | If you compile this program with cygwin32 tools this package falls
33 | under the GPL. See COPYING.CYGNUS for details.
34 |
35 | This library is distributed in the hope that it will be useful,
36 | but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 | Lesser General Public License for more details.
39 |
40 | You should have received a copy of the GNU Lesser General Public
41 | License along with this library; if not, write to the Free Software
42 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
43 |
44 | This file was taken from rxtx-2.1-7 and adapted for Hamlib.
45 --------------------------------------------------------------------------*/
46 #include <windows.h>
47 #include <stdio.h>
48 #include <errno.h>
49 #include <time.h>
50 #include <limits.h>
51 #include "win32termios.h"
52
53 /*
54 * odd malloc.h error with lcc compiler
55 * winsock has FIONREAD with lcc
56 */
57
58 #ifdef __LCC__
59 # include <winsock.h>
60 #else
61 # include <malloc.h>
62 #endif /* __LCC__ */
63
64 #define SIGIO 0
65
66 int my_errno;
67 #if 0
68 extern int errno;
69 #endif
70 struct termios_list
71 {
72 char filename[512];
73 int my_errno;
74 int interrupt;
75 int event_flag;
76 int tx_happened;
77 unsigned long *hComm;
78 struct termios *ttyset;
79 struct serial_struct *sstruct;
80 /* for DTR DSR */
81 unsigned char MSR;
82 struct async_struct *astruct;
83 struct serial_icounter_struct *sis;
84 int open_flags;
85 OVERLAPPED rol;
86 OVERLAPPED wol;
87 OVERLAPPED sol;
88 int fd;
89 struct termios_list *next;
90 struct termios_list *prev;
91 };
92 struct termios_list *first_tl = NULL;
93
94 static struct termios_list *find_port(int);
95
96 /*----------------------------------------------------------
97 serial_test
98
99 accept: filename to test
100 perform:
101 return: 1 on success 0 on failure
102 exceptions:
103 win32api: CreateFile CloseHandle
104 comments: if the file opens it should be ok.
105 ----------------------------------------------------------*/
win32_serial_test(char * filename)106 int win32_serial_test(char *filename)
107 {
108 unsigned long *hcomm;
109 int ret;
110 hcomm = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
111 0, 0);
112
113 if (hcomm == INVALID_HANDLE_VALUE)
114 {
115 if (GetLastError() == ERROR_ACCESS_DENIED)
116 {
117 ret = 1;
118 }
119 else
120 {
121 ret = 0;
122 }
123 }
124 else
125 {
126 ret = 1;
127 }
128
129 CloseHandle(hcomm);
130 return (ret);
131 }
132
termios_setflags(int fd,int termios_flags[])133 static void termios_setflags(int fd, int termios_flags[])
134 {
135 struct termios_list *index = find_port(fd);
136 int i, result;
137 int windows_flags[11] = { 0, EV_RXCHAR, EV_TXEMPTY, EV_CTS, EV_DSR,
138 EV_RING | 0x2000, EV_RLSD, EV_ERR,
139 EV_ERR, EV_ERR, EV_BREAK
140 };
141
142 if (!index)
143 {
144 LEAVE("termios_setflags");
145 return;
146 }
147
148 index->event_flag = 0;
149
150 for (i = 0; i < 11; i++)
151 if (termios_flags[i])
152 {
153 index->event_flag |= windows_flags[i];
154 }
155
156 result = SetCommMask(index->hComm, index->event_flag);
157
158 /*
159 This is rank. 0x2000 was used to detect the trailing edge of ring.
160 The leading edge is detedted by EV_RING.
161
162 The trailing edge is reliable. The leading edge is not.
163 Softie no longer allows the trailing edge to be detected in NTsp2
164 and beyond.
165
166 So... Try the reliable option above and if it fails, use the less
167 reliable means.
168
169 The screams for a giveio solution that bypasses the kernel.
170 */
171 if (index->event_flag & 0x2000 && result == 0)
172 {
173 index->event_flag &= ~0x2000;
174 SetCommMask(index->hComm, index->event_flag);
175 }
176 }
177
178 #if 0
179 /*----------------------------------------------------------
180 get_fd()
181
182 accept: filename
183 perform: find the file descriptor associated with the filename
184 return: fd
185 exceptions:
186 win32api: None
187 comments: This is not currently called by anything
188 ----------------------------------------------------------*/
189
190 int get_fd(char *filename)
191 {
192 struct termios_list *index = first_tl;
193
194 ENTER("get_fd");
195
196 if (!index)
197 {
198 return -1;
199 }
200
201 while (strcmp(index->filename, filename))
202 {
203 index = index->next;
204
205 if (!index->next)
206 {
207 return (-1);
208 }
209 }
210
211 LEAVE("get_fd");
212 return (index->fd);
213 }
214
215 /*----------------------------------------------------------
216 get_filename()
217
218 accept: file descriptor
219 perform: find the filename associated with the file descriptor
220 return: the filename associated with the fd
221 exceptions: None
222 win32api: None
223 comments: This is not currently called by anything
224 ----------------------------------------------------------*/
225
226 char *get_filename(int fd)
227 {
228 struct termios_list *index = first_tl;
229
230 ENTER("get_filename");
231
232 if (!index)
233 {
234 return ("bad");
235 }
236
237 while (index->fd != fd)
238 {
239 if (index->next == NULL)
240 {
241 return ("bad");
242 }
243
244 index = index->next;
245 }
246
247 LEAVE("get_filename");
248 return (index->filename);
249 }
250
251 /*----------------------------------------------------------
252 dump_termios_list()
253
254 accept: string to print out.
255 perform:
256 return:
257 exceptions:
258 win32api: None
259 comments: used only for debugging eg serial_close()
260 ----------------------------------------------------------*/
261
262 void dump_termios_list(char *foo)
263 {
264 #ifdef DEBUG
265 struct termios_list *index = first_tl;
266 printf("============== %s start ===============\n", foo);
267
268 if (index)
269 {
270 printf("%i filename | %s\n", index->fd, index->filename);
271 }
272
273 /*
274 if ( index->next )
275 {
276 printf( "%i filename | %s\n", index->fd, index->filename );
277 }
278 */
279 printf("============== %s end ===============\n", foo);
280 #endif
281 }
282 #endif
283
284 /*----------------------------------------------------------
285 set_errno()
286
287 accept:
288 perform:
289 return:
290 exceptions:
291 win32api: None
292 comments: FIXME
293 ----------------------------------------------------------*/
294
set_errno(int error)295 static void set_errno(int error)
296 {
297 my_errno = error;
298 }
299
300 #if 0
301 /*----------------------------------------------------------
302 usleep()
303
304 accept:
305 perform:
306 return:
307 exceptions:
308 win32api: Sleep()
309 comments:
310 ----------------------------------------------------------*/
311
312 static void usleep(unsigned long usec)
313 {
314 Sleep(usec / 1000);
315 }
316 #endif
317
318 /*----------------------------------------------------------
319 CBR_toB()
320
321 accept:
322 perform:
323 return:
324 exceptions:
325 win32api: None
326 comments:
327 ----------------------------------------------------------*/
328
CBR_to_B(int Baud)329 static int CBR_to_B(int Baud)
330 {
331 ENTER("CBR_to_B");
332
333 switch (Baud)
334 {
335
336 case 0: return (B0);
337
338 case 50: return (B50);
339
340 case 75: return (B75);
341
342 case CBR_110: return (B110);
343
344 case 134: return (B134);
345
346 case 150: return (B150);
347
348 case 200: return (B200);
349
350 case CBR_300: return (B300);
351
352 case CBR_600: return (B600);
353
354 case CBR_1200: return (B1200);
355
356 case 1800: return (B1800);
357
358 case CBR_2400: return (B2400);
359
360 case CBR_4800: return (B4800);
361
362 case CBR_9600: return (B9600);
363
364 case CBR_14400: return (B14400);
365
366 case CBR_19200: return (B19200);
367
368 case CBR_28800: return (B28800);
369
370 case CBR_38400: return (B38400);
371
372 case CBR_57600: return (B57600);
373
374 case CBR_115200: return (B115200);
375
376 case CBR_128000: return (B128000);
377
378 case CBR_230400: return (B230400);
379
380 case CBR_256000: return (B256000);
381
382 case CBR_460800: return (B460800);
383
384 case CBR_500000: return (B500000);
385
386 case CBR_576000: return (B576000);
387
388 case CBR_921600: return (B921600);
389
390 case CBR_1000000: return (B1000000);
391
392 case CBR_1152000: return (B1152000);
393
394 case CBR_1500000: return (B1500000);
395
396 case CBR_2000000: return (B2000000);
397
398 case CBR_2500000: return (B2500000);
399
400 case CBR_3000000: return (B3000000);
401
402 case CBR_3500000: return (B3500000);
403
404 case CBR_4000000: return (B4000000);
405
406 default:
407 /* assume custom baudrate */
408 return (Baud);
409 }
410 }
411
412 /*----------------------------------------------------------
413 B_to_CBR()
414
415 accept:
416 perform:
417 return:
418 exceptions:
419 win32api:
420 comments: None
421 ----------------------------------------------------------*/
422
B_to_CBR(int Baud)423 static int B_to_CBR(int Baud)
424 {
425 int ret;
426 ENTER("B_to_CBR");
427
428 switch (Baud)
429 {
430 case 0: ret = 0; break;
431
432 case B50: ret = 50; break;
433
434 case B75: ret = 75; break;
435
436 case B110: ret = CBR_110; break;
437
438 case B134: ret = 134; break;
439
440 case B150: ret = 150; break;
441
442 case B200: ret = 200; break;
443
444 case B300: ret = CBR_300; break;
445
446 case B600: ret = CBR_600; break;
447
448 case B1200: ret = CBR_1200; break;
449
450 case B1800: ret = 1800; break;
451
452 case B2400: ret = CBR_2400; break;
453
454 case B4800: ret = CBR_4800; break;
455
456 case B9600: ret = CBR_9600; break;
457
458 case B14400: ret = CBR_14400; break;
459
460 case B19200: ret = CBR_19200; break;
461
462 case B28800: ret = CBR_28800; break;
463
464 case B38400: ret = CBR_38400; break;
465
466 case B57600: ret = CBR_57600; break;
467
468 case B115200: ret = CBR_115200; break;
469
470 case B128000: ret = CBR_128000; break;
471
472 case B230400: ret = CBR_230400; break;
473
474 case B256000: ret = CBR_256000; break;
475
476 case B460800: ret = CBR_460800; break;
477
478 case B500000: ret = CBR_500000; break;
479
480 case B576000: ret = CBR_576000; break;
481
482 case B921600: ret = CBR_921600; break;
483
484 case B1000000: ret = CBR_1000000; break;
485
486 case B1152000: ret = CBR_1152000; break;
487
488 case B1500000: ret = CBR_1500000; break;
489
490 case B2000000: ret = CBR_2000000; break;
491
492 case B2500000: ret = CBR_2500000; break;
493
494 case B3000000: ret = CBR_3000000; break;
495
496 case B3500000: ret = CBR_3500000; break;
497
498 case B4000000: ret = CBR_4000000; break;
499
500 default:
501 /* assume custom baudrate */
502 return Baud;
503 }
504
505 LEAVE("B_to_CBR");
506 return ret;
507 }
508
509 /*----------------------------------------------------------
510 bytesize_to_termios()
511
512 accept:
513 perform:
514 return:
515 exceptions:
516 win32api: None
517 comments:
518 ----------------------------------------------------------*/
519
bytesize_to_termios(int ByteSize)520 static int bytesize_to_termios(int ByteSize)
521 {
522 ENTER("bytesize_to_termios");
523
524 switch (ByteSize)
525 {
526 case 5: return (CS5);
527
528 case 6: return (CS6);
529
530 case 7: return (CS7);
531
532 case 8:
533 default: return (CS8);
534 }
535 }
536
537 /*----------------------------------------------------------
538 termios_to_bytesize()
539
540 accept:
541 perform:
542 return:
543 exceptions:
544 win32api: None
545 comments:
546 ----------------------------------------------------------*/
547
termios_to_bytesize(int cflag)548 static int termios_to_bytesize(int cflag)
549 {
550 ENTER("termios_to_bytesize");
551
552 switch (cflag & CSIZE)
553 {
554 case CS5: return (5);
555
556 case CS6: return (6);
557
558 case CS7: return (7);
559
560 case CS8:
561 default: return (8);
562 }
563 }
564
565 #if 0
566 /*----------------------------------------------------------
567 get_dos_port()
568
569 accept:
570 perform:
571 return:
572 exceptions:
573 win32api: None
574 comments:
575 ----------------------------------------------------------*/
576
577 static const char *get_dos_port(char const *name)
578 {
579 ENTER("get_dos_port");
580
581 if (!strcmp(name, "/dev/cua0")) { return ("COM1"); }
582
583 if (!strcmp(name, "/dev/cua1")) { return ("COM2"); }
584
585 if (!strcmp(name, "/dev/cua2")) { return ("COM3"); }
586
587 if (!strcmp(name, "/dev/cua3")) { return ("COM4"); }
588
589 LEAVE("get_dos_port");
590 return ((const char *) name);
591 }
592 #endif
593
594 /*----------------------------------------------------------
595 ClearErrors()
596
597 accept:
598 perform: keep track of errors for the eventLoop() (SerialImp.c)
599 return: the return value of ClearCommError()
600 exceptions:
601 win32api: ClearCommError()
602 comments:
603 ----------------------------------------------------------*/
604
ClearErrors(struct termios_list * index,COMSTAT * Stat)605 static int ClearErrors(struct termios_list *index, COMSTAT *Stat)
606 {
607 unsigned long ErrCode;
608 int ret;
609
610 ret = ClearCommError(index->hComm, &ErrCode, Stat);
611
612 if (ret == 0)
613 {
614 YACK();
615 return (ret);
616 }
617
618 #ifdef DEBUG_ERRORS
619
620 if (ErrCode)
621 {
622 printf("%i frame %i %i overrun %li %i parity %u %i brk %i %i\n",
623 (int) ErrCode,
624 (int) ErrCode & CE_FRAME,
625 index->sis->frame,
626 (int)(ErrCode & CE_OVERRUN) | (ErrCode & CE_RXOVER),
627 index->sis->overrun,
628 (int) ErrCode & CE_RXPARITY,
629 index->sis->parity,
630 (int) ErrCode & CE_BREAK,
631 index->sis->brk
632 );
633 }
634
635 #endif /* DEBUG_ERRORS */
636
637 if (ErrCode & CE_FRAME)
638 {
639 index->sis->frame++;
640 ErrCode &= ~CE_FRAME;
641 }
642
643 #ifdef LIFE_IS_GOOD
644 FIXME OVERRUN is spewing
645
646 if (ErrCode & CE_OVERRUN)
647 {
648 index->sis->overrun++;
649 ErrCode &= ~CE_OVERRUN;
650 }
651 /* should this be here? */
652 else if (ErrCode & CE_RXOVER)
653 {
654 index->sis->overrun++;
655 ErrCode &= ~CE_OVERRUN;
656 }
657
658 #endif /* LIFE_IS_GOOD */
659
660 if (ErrCode & CE_RXPARITY)
661 {
662 index->sis->parity++;
663 ErrCode &= ~CE_RXPARITY;
664 }
665
666 if (ErrCode & CE_BREAK)
667 {
668 index->sis->brk++;
669 ErrCode &= ~CE_BREAK;
670 }
671
672 return (ret);
673 }
674
675 #if 0
676 /*----------------------------------------------------------
677 FillDCB()
678
679 accept:
680 perform:
681 return:
682 exceptions:
683 win32api: GetCommState(), SetCommState(), SetCommTimeouts()
684 comments:
685 ----------------------------------------------------------*/
686
687 static BOOL FillDCB(DCB *dcb, unsigned long *hCommPort, COMMTIMEOUTS Timeout)
688 {
689
690 ENTER("FillDCB");
691 dcb->DCBlength = sizeof(dcb);
692
693 if (!GetCommState(hCommPort, dcb))
694 {
695 report("GetCommState\n");
696 return (-1);
697 }
698
699 dcb->BaudRate = CBR_9600 ;
700 dcb->ByteSize = 8;
701 dcb->Parity = NOPARITY;
702 dcb->StopBits = ONESTOPBIT;
703 dcb->fDtrControl = DTR_CONTROL_ENABLE;
704 dcb->fRtsControl = RTS_CONTROL_ENABLE;
705 dcb->fOutxCtsFlow = FALSE;
706 dcb->fOutxDsrFlow = FALSE;
707 dcb->fDsrSensitivity = FALSE;
708 dcb->fOutX = FALSE;
709 dcb->fInX = FALSE;
710 dcb->fTXContinueOnXoff = FALSE;
711 dcb->XonChar = 0x11;
712 dcb->XoffChar = 0x13;
713 dcb->XonLim = 0;
714 dcb->XoffLim = 0;
715 dcb->fParity = TRUE;
716
717 if (EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | (EV_RLSD & EV_RXFLAG))
718 {
719 dcb->EvtChar = '\n';
720 }
721 else { dcb->EvtChar = '\0'; }
722
723 if (!SetCommState(hCommPort, dcb))
724 {
725 report("SetCommState\n");
726 YACK();
727 return (-1);
728 }
729
730 if (!SetCommTimeouts(hCommPort, &Timeout))
731 {
732 YACK();
733 report("SetCommTimeouts\n");
734 return (-1);
735 }
736
737 LEAVE("FillDCB");
738 return (TRUE) ;
739 }
740 #endif
741
742 /*----------------------------------------------------------
743 serial_close()
744
745 accept:
746 perform:
747 return:
748 exceptions:
749 win32api: SetCommMask(), CloseHandle()
750 comments:
751 ----------------------------------------------------------*/
752
win32_serial_close(int fd)753 int win32_serial_close(int fd)
754 {
755 struct termios_list *index;
756 /* char message[80]; */
757
758 ENTER("serial_close");
759
760 if (!first_tl || !first_tl->hComm)
761 {
762 report("gotit!");
763 return (0);
764 }
765
766 index = find_port(fd);
767
768 if (!index)
769 {
770 LEAVE("serial_close");
771 return -1;
772 }
773
774 /* WaitForSingleObject( index->wol.hEvent, INFINITE ); */
775 /*
776 if ( index->hComm != INVALID_HANDLE_VALUE )
777 {
778 if ( !SetCommMask( index->hComm, EV_RXCHAR ) )
779 {
780 YACK();
781 report( "eventLoop hung\n" );
782 }
783 CloseHandle( index->hComm );
784 }
785 else
786 {
787 sprintf( message, "serial_ close(): Invalid Port Reference for %s\n",
788 index->filename );
789 report( message );
790 }
791 */
792 if (index->next && index->prev)
793 {
794 index->next->prev = index->prev;
795 index->prev->next = index->next;
796 }
797 else if (index->prev)
798 {
799 index->prev->next = NULL;
800 }
801 else if (index->next)
802 {
803 index->next->prev = NULL;
804 first_tl = index->next;
805 }
806 else
807 {
808 first_tl = NULL;
809 }
810
811 if (index->rol.hEvent) { CloseHandle(index->rol.hEvent); }
812
813 if (index->wol.hEvent) { CloseHandle(index->wol.hEvent); }
814
815 if (index->sol.hEvent) { CloseHandle(index->sol.hEvent); }
816
817 if (index->hComm) { CloseHandle(index->hComm); }
818
819 if (index->ttyset) { free(index->ttyset); }
820
821 if (index->astruct) { free(index->astruct); }
822
823 if (index->sstruct) { free(index->sstruct); }
824
825 if (index->sis) { free(index->sis); }
826
827 /* had problems with strdup
828 if ( index->filename ) free( index->filename );
829 */
830 free(index);
831
832
833 LEAVE("serial_close");
834 return 0;
835 }
836
837 /*----------------------------------------------------------
838 cfmakeraw()
839
840 accept:
841 perform:
842 return:
843 exceptions:
844 win32api: None
845 comments:
846 ----------------------------------------------------------*/
847
cfmakeraw(struct termios * s_termios)848 void cfmakeraw(struct termios *s_termios)
849 {
850 ENTER("cfmakeraw");
851 s_termios->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
852 | INLCR | IGNCR | ICRNL | IXON);
853 s_termios->c_oflag &= ~OPOST;
854 s_termios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
855 s_termios->c_cflag &= ~(CSIZE | PARENB);
856 s_termios->c_cflag |= CS8;
857 LEAVE("cfmakeraw");
858 }
859
860 /*----------------------------------------------------------
861 init_serial_struct()
862
863 accept:
864 perform:
865 return:
866 exceptions:
867 win32api:
868 comments:
869 ----------------------------------------------------------*/
870
init_serial_struct(struct serial_struct * sstruct)871 static BOOL init_serial_struct(struct serial_struct *sstruct)
872 {
873 ENTER("init_serial_struct");
874
875 /*
876 FIXME
877
878 This needs to use inb() to read the actual baud_base
879 and divisor from the UART registers. Question is how
880 far do we take this?
881
882 */
883
884 sstruct->custom_divisor = 0;
885 sstruct->baud_base = 115200;
886
887 /* not currently used check values before using */
888
889 /* unsigned short */
890
891 sstruct->close_delay = 0;
892 sstruct->closing_wait = 0;
893 sstruct->iomem_reg_shift = 0;
894
895 /* int */
896
897 sstruct->type = 0;
898 sstruct->line = 0;
899 sstruct->irq = 0;
900 sstruct->flags = 0;
901 sstruct->xmit_fifo_size = 0;
902 sstruct->hub6 = 0;
903
904 /* unsigned int */
905
906 sstruct->port = 0;
907 sstruct->port_high = 0;
908
909 /* char */
910
911 sstruct->io_type = 0;
912
913 /* unsigned char * */
914
915 sstruct->iomem_base = NULL;
916
917 LEAVE("init_serial_struct");
918 return TRUE;
919
920 }
921 /*----------------------------------------------------------
922 init_termios()
923
924 accept:
925 perform:
926 return:
927 exceptions:
928 win32api:
929 comments:
930 ----------------------------------------------------------*/
931
init_termios(struct termios * ttyset)932 static BOOL init_termios(struct termios *ttyset)
933 {
934 ENTER("init_termios");
935
936 if (!ttyset)
937 {
938 return FALSE;
939 }
940
941 memset(ttyset, 0, sizeof(struct termios));
942 cfsetospeed(ttyset, B9600);
943 cfmakeraw(ttyset);
944 ttyset->c_cc[VINTR] = 0x03; /* 0: C-c */
945 ttyset->c_cc[VQUIT] = 0x1c; /* 1: C-\ */
946 ttyset->c_cc[VERASE] = 0x7f; /* 2: <del> */
947 ttyset->c_cc[VKILL] = 0x15; /* 3: C-u */
948 ttyset->c_cc[VEOF] = 0x04; /* 4: C-d */
949 ttyset->c_cc[VTIME] = 0; /* 5: read timeout */
950 ttyset->c_cc[VMIN] = 1; /* 6: read returns after this
951 many bytes */
952 ttyset->c_cc[VSUSP] = 0x1a; /* 10: C-z */
953 ttyset->c_cc[VEOL] = '\r'; /* 11: */
954 ttyset->c_cc[VREPRINT] = 0x12; /* 12: C-r */
955 /*
956 ttyset->c_cc[VDISCARD] = 0x; 13: IEXTEN only
957 */
958 ttyset->c_cc[VWERASE] = 0x17; /* 14: C-w */
959 ttyset->c_cc[VLNEXT] = 0x16; /* 15: C-w */
960 ttyset->c_cc[VEOL2] = '\n'; /* 16: */
961 LEAVE("init_termios");
962 return TRUE;
963 /* default VTIME = 0, VMIN = 1: read blocks forever until one byte */
964 }
965
966 /*----------------------------------------------------------
967 port_opened()
968
969 accept:
970 perform:
971 return:
972 exceptions:
973 win32api: None
974 comments:
975 ----------------------------------------------------------*/
976
port_opened(const char * filename)977 static int port_opened(const char *filename)
978 {
979 struct termios_list *index = first_tl;
980
981 ENTER("port_opened");
982
983 if (! index)
984 {
985 return 0;
986 }
987
988 if (!strcmp(index->filename, filename))
989 {
990 return index->fd;
991 }
992
993 while (index->next)
994 {
995 index = index->next;
996
997 if (!strcmp(index->filename, filename))
998 {
999 return index->fd;
1000 }
1001 }
1002
1003 LEAVE("port_opened");
1004 return 0;
1005 }
1006
1007 /*----------------------------------------------------------
1008 open_port()
1009
1010 accept:
1011 perform:
1012 return:
1013 exceptions:
1014 win32api: CreateFile(), SetupComm(), CreateEvent()
1015 comments:
1016 FILE_FLAG_OVERLAPPED allows one to break out the select()
1017 so RXTXPort.close() does not hang.
1018
1019 The setDTR() and setDSR() are the functions that noticed
1020 to be blocked in the java close. Basically ioctl(TIOCM[GS]ET)
1021 are where it hangs.
1022
1023 FILE_FLAG_OVERLAPPED also means we need to create valid OVERLAPPED
1024 structure in Serial_select.
1025 ----------------------------------------------------------*/
1026
open_port(struct termios_list * port)1027 static int open_port(struct termios_list *port)
1028 {
1029 ENTER("open_port");
1030 port->hComm = CreateFile(port->filename,
1031 GENERIC_READ | GENERIC_WRITE,
1032 0,
1033 0,
1034 OPEN_EXISTING,
1035 FILE_FLAG_OVERLAPPED,
1036 0
1037 );
1038
1039 if (port->hComm == INVALID_HANDLE_VALUE)
1040 {
1041 YACK();
1042 set_errno(EINVAL);
1043 /*
1044 printf( "serial_open failed %s\n", port->filename );
1045 */
1046 return -1;
1047 }
1048
1049 if (!SetupComm(port->hComm, 2048, 1024))
1050 {
1051 YACK();
1052 return -1;
1053 }
1054
1055 memset(&port->rol, 0, sizeof(OVERLAPPED));
1056 memset(&port->wol, 0, sizeof(OVERLAPPED));
1057 memset(&port->sol, 0, sizeof(OVERLAPPED));
1058
1059 port->rol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1060
1061 if (!port->rol.hEvent)
1062 {
1063 YACK();
1064 report("Could not create read overlapped\n");
1065 goto fail;
1066 }
1067
1068 port->sol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1069
1070 if (!port->sol.hEvent)
1071 {
1072 YACK();
1073 report("Could not create select overlapped\n");
1074 goto fail;
1075 }
1076
1077 port->wol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1078
1079 if (!port->wol.hEvent)
1080 {
1081 YACK();
1082 report("Could not create write overlapped\n");
1083 goto fail;
1084 }
1085
1086 LEAVE("open_port");
1087 return (0);
1088 fail:
1089 return (-1);
1090 }
1091
1092 /*----------------------------------------------------------
1093 termios_list()
1094
1095 accept: fd which is a fake # for the port assigned when the port
1096 is opened
1097 perform: walk through a double linked list to see if the given
1098 fd is in any of the termios_list members.
1099 return: the termios_list if it is found.
1100 NULL if no matches are found.
1101 exceptions: None
1102 win32api: None
1103 comments:
1104 ----------------------------------------------------------*/
1105
find_port(int fd)1106 static struct termios_list *find_port(int fd)
1107 {
1108
1109 char message[80];
1110 struct termios_list *index = first_tl;
1111
1112 ENTER("find_port");
1113
1114 if (fd <= 0 || !first_tl) { goto fail; }
1115
1116 while (index->fd)
1117 {
1118 if (index->fd == fd)
1119 {
1120 LEAVE("find_port");
1121 return index;
1122 }
1123
1124 if (!index->next)
1125 {
1126 break;
1127 }
1128
1129 index = index->next;
1130 }
1131
1132 fail:
1133 sprintf(message, "No info known about the port. %i\n", fd);
1134 report(message);
1135 set_errno(EBADF);
1136 LEAVE("find_port");
1137 return NULL;
1138 }
1139
1140 /*----------------------------------------------------------
1141 get_free_fd()
1142
1143 accept:
1144 perform:
1145 return:
1146 exceptions:
1147 win32api: None
1148 comments:
1149 ----------------------------------------------------------*/
1150
get_free_fd()1151 static int get_free_fd()
1152 {
1153 int next, last;
1154 struct termios_list *index = first_tl;
1155
1156 ENTER("get_free_fd");
1157
1158 if (!index)
1159 {
1160 return (1);
1161 }
1162
1163 if (!index->fd)
1164 {
1165 report("!index->fd\n");
1166 return (1);
1167 }
1168
1169 if (index->fd > 1)
1170 {
1171 first_tl = index;
1172 return (1);
1173 }
1174
1175 last = index->fd;
1176
1177 while (index->next)
1178 {
1179 next = index->next->fd;
1180
1181 if (next != last + 1)
1182 {
1183 return (last + 1);
1184
1185 }
1186
1187 index = index->next;
1188 last = next;
1189 }
1190
1191 LEAVE("get_free_fd");
1192 return (index->fd + 1);
1193 }
1194
1195 /*----------------------------------------------------------
1196 add_port()
1197
1198 accept:
1199 perform:
1200 return:
1201 exceptions:
1202 win32api: None
1203 comments:
1204 ----------------------------------------------------------*/
1205
add_port(const char * filename)1206 static struct termios_list *add_port(const char *filename)
1207 {
1208 struct termios_list *index = first_tl;
1209 struct termios_list *port;
1210
1211 ENTER("add_port");
1212
1213 port = malloc(sizeof(struct termios_list));
1214
1215 if (!port)
1216 {
1217 goto fail;
1218 }
1219
1220 memset(port, 0, sizeof(struct termios_list));
1221
1222 port->ttyset = malloc(sizeof(struct termios));
1223
1224 if (! port->ttyset)
1225 {
1226 goto fail;
1227 }
1228
1229 memset(port->ttyset, 0, sizeof(struct termios));
1230
1231 port->sstruct = malloc(sizeof(struct serial_struct));
1232
1233 if (! port->sstruct)
1234 {
1235 goto fail;
1236 }
1237
1238 memset(port->sstruct, 0, sizeof(struct serial_struct));
1239 port->sis = malloc(sizeof(struct serial_icounter_struct));
1240
1241 if (! port->sis)
1242 {
1243 goto fail;
1244 }
1245
1246 memset(port->sis, 0, sizeof(struct serial_icounter_struct));
1247
1248 /* FIXME the async_struct is being defined by mingw32 headers?
1249 port->astruct = malloc( sizeof( struct async_struct ) );
1250 if( ! port->astruct )
1251 goto fail;
1252 memset( port->astruct, 0, sizeof( struct async_struct ) );
1253 */
1254 port->MSR = 0;
1255
1256 strncpy(port->filename, filename, sizeof(port->filename) - 1);
1257
1258 /* didn't free well? strdup( filename ); */
1259 if (! port->filename)
1260 {
1261 goto fail;
1262 }
1263
1264 port->fd = get_free_fd();
1265
1266
1267 if (!first_tl)
1268 {
1269 port->prev = NULL;
1270 first_tl = port;
1271 }
1272 else
1273 {
1274 while (index->next)
1275 {
1276 index = index->next;
1277 }
1278
1279 if (port == first_tl)
1280 {
1281 port->prev = NULL;
1282 port->next = first_tl;
1283 first_tl->prev = port;
1284 first_tl = port;
1285 }
1286 else
1287 {
1288 port->prev = index;
1289 index->next = port;
1290 }
1291 }
1292
1293 port->next = NULL;
1294 LEAVE("add_port");
1295 return port;
1296
1297 fail:
1298 report("add_port: Out Of Memory\n");
1299
1300 if (port->ttyset) { free(port->ttyset); }
1301
1302 if (port->astruct) { free(port->astruct); }
1303
1304 if (port->sstruct) { free(port->sstruct); }
1305
1306 if (port->sis) { free(port->sis); }
1307
1308 /* had problems with strdup
1309 if ( port->filename ) free( port->filename );
1310 */
1311 if (port) { free(port); }
1312
1313 return port;
1314 }
1315
1316 /*----------------------------------------------------------
1317 check_port_capabilities()
1318
1319 accept:
1320 perform:
1321 return:
1322 exceptions:
1323 win32api: GetCommProperties(), GetCommState()
1324 comments:
1325 ----------------------------------------------------------*/
1326
check_port_capabilities(struct termios_list * index)1327 static int check_port_capabilities(struct termios_list *index)
1328 {
1329 COMMPROP cp;
1330 DCB dcb;
1331 char message[80];
1332
1333 ENTER("check_port_capabilities");
1334 /* check for capabilities */
1335 GetCommProperties(index->hComm, &cp);
1336
1337 if (!(cp.dwProvCapabilities & PCF_DTRDSR))
1338 {
1339 sprintf(message,
1340 "%s: no DTR & DSR support\n", __func__);
1341 report(message);
1342 }
1343
1344 if (!(cp.dwProvCapabilities & PCF_RLSD))
1345 {
1346 sprintf(message, "%s: no carrier detect (RLSD) support\n",
1347 __func__);
1348 report(message);
1349 }
1350
1351 if (!(cp.dwProvCapabilities & PCF_RTSCTS))
1352 {
1353 sprintf(message,
1354 "%s: no RTS & CTS support\n", __func__);
1355 report(message);
1356 }
1357
1358 if (!(cp.dwProvCapabilities & PCF_TOTALTIMEOUTS))
1359 {
1360 sprintf(message, "%s: no timeout support\n", __func__);
1361 report(message);
1362 }
1363
1364 if (!GetCommState(index->hComm, &dcb))
1365 {
1366 YACK();
1367 report("GetCommState\n");
1368 return -1;
1369 }
1370
1371 LEAVE("check_port_capabilities");
1372 return 0;
1373
1374 }
1375
1376 /*----------------------------------------------------------
1377 serial_open()
1378
1379 accept:
1380 perform:
1381 return:
1382 exceptions:
1383 win32api: None
1384 comments:
1385 ----------------------------------------------------------*/
1386
win32_serial_open(const char * filename,int flags,...)1387 int win32_serial_open(const char *filename, int flags, ...)
1388 {
1389 struct termios_list *index;
1390 char message[756];
1391 char fullfilename[256];
1392
1393 ENTER("serial_open");
1394
1395 fullfilename[sizeof(fullfilename) - 1] = '\0';
1396
1397 /* according to http://support.microsoft.com/kb/115831
1398 * this is necessary for COM ports larger than COM9 */
1399 if (memcmp(filename, "\\\\.\\", 4) != 0)
1400 {
1401 snprintf(fullfilename, sizeof(fullfilename) - 1, "\\\\.\\%s", filename);
1402 }
1403 else
1404 {
1405 strncpy(fullfilename, filename, sizeof(fullfilename) - 1);
1406 }
1407
1408 if (port_opened(fullfilename))
1409 {
1410 report("Port is already opened\n");
1411 return (-1);
1412 }
1413
1414 index = add_port(fullfilename);
1415
1416 if (!index)
1417 {
1418 report("serial_open !index\n");
1419 return (-1);
1420 }
1421
1422 index->interrupt = 0;
1423 index->tx_happened = 0;
1424
1425 if (open_port(index))
1426 {
1427 sprintf(message, "serial_open(): Invalid Port Reference for %s\n",
1428 fullfilename);
1429 report(message);
1430 win32_serial_close(index->fd);
1431 return -1;
1432 }
1433
1434 if (check_port_capabilities(index))
1435 {
1436 report("check_port_capabilities!");
1437 win32_serial_close(index->fd);
1438 return -1;
1439 }
1440
1441 init_termios(index->ttyset);
1442 init_serial_struct(index->sstruct);
1443
1444 /* set default condition */
1445 tcsetattr(index->fd, 0, index->ttyset);
1446
1447 /* if opened with non-blocking, then operating non-blocking */
1448 if (flags & O_NONBLOCK)
1449 {
1450 index->open_flags = O_NONBLOCK;
1451 }
1452 else
1453 {
1454 index->open_flags = 0;
1455 }
1456
1457
1458 if (!first_tl->hComm)
1459 {
1460 sprintf(message, "open(): Invalid Port Reference for %s\n",
1461 index->filename);
1462 report(message);
1463 }
1464
1465 if (first_tl->hComm == INVALID_HANDLE_VALUE)
1466 {
1467 report("serial_open: test\n");
1468 }
1469
1470 LEAVE("serial_open");
1471 return (index->fd);
1472 }
1473
1474
1475 /*----------------------------------------------------------
1476 serial_write()
1477
1478 accept:
1479 perform:
1480 return:
1481 exceptions:
1482 win32api: WriteFile(), GetLastError(),
1483 WaitForSingleObject(), GetOverlappedResult(),
1484 FlushFileBuffers(), Sleep()
1485 comments:
1486 ----------------------------------------------------------*/
1487
win32_serial_write(int fd,const char * Str,int length)1488 int win32_serial_write(int fd, const char *Str, int length)
1489 {
1490 unsigned long nBytes;
1491 struct termios_list *index;
1492 /* COMSTAT Stat; */
1493 int old_flag;
1494
1495 ENTER("serial_write");
1496
1497 if (fd <= 0)
1498 {
1499 return 0;
1500 }
1501
1502 index = find_port(fd);
1503
1504 if (!index)
1505 {
1506 LEAVE("serial_write");
1507 return -1;
1508 }
1509
1510 old_flag = index->event_flag;
1511 /*
1512 index->event_flag &= ~EV_TXEMPTY;
1513 SetCommMask( index->hComm, index->event_flag );
1514 index->tx_happened = 1;
1515 */
1516 index->wol.Offset = index->wol.OffsetHigh = 0;
1517 ResetEvent(index->wol.hEvent);
1518
1519 if (!WriteFile(index->hComm, Str, length, &nBytes, &index->wol))
1520 {
1521 WaitForSingleObject(index->wol.hEvent, 100);
1522
1523 if (GetLastError() != ERROR_IO_PENDING)
1524 {
1525 /* ClearErrors( index, &Stat ); */
1526 report("serial_write error\n");
1527 /* report("Condition 1 Detected in write()\n"); */
1528 YACK();
1529 errno = EIO;
1530 nBytes = -1;
1531 goto end;
1532 }
1533 /* This is breaking on Win2K, WinXP for some reason */
1534 else while (!GetOverlappedResult(index->hComm, &index->wol,
1535 &nBytes, TRUE))
1536 {
1537 if (GetLastError() != ERROR_IO_INCOMPLETE)
1538 {
1539 /* report("Condition 2 Detected in write()\n"); */
1540 YACK();
1541 errno = EIO;
1542 nBytes = -1;
1543 goto end;
1544 /* ClearErrors( index, &Stat ); */
1545 }
1546 }
1547 }
1548 else
1549 {
1550 /* Write finished synchronously. That is ok!
1551 * I have seen this with USB to Serial
1552 * devices like TI's.
1553 */
1554 }
1555
1556 end:
1557 /* FlushFileBuffers( index->hComm ); */
1558 index->event_flag |= EV_TXEMPTY;
1559 /* ClearErrors( index, &Stat ); */
1560 SetCommMask(index->hComm, index->event_flag);
1561 /* ClearErrors( index, &Stat ); */
1562 index->event_flag = old_flag;
1563 index->tx_happened = 1;
1564 LEAVE("serial_write");
1565 return nBytes;
1566 }
1567
1568 /*----------------------------------------------------------
1569 serial_read()
1570
1571 accept:
1572 perform:
1573 return:
1574 exceptions:
1575 win32api: ReadFile(), GetLastError(), WaitForSingleObject()
1576 GetOverLappedResult()
1577 comments: If setting errno make sure not to use EWOULDBLOCK
1578 In that case use EAGAIN. See SerialImp.c:testRead()
1579 ----------------------------------------------------------*/
1580
win32_serial_read(int fd,void * vb,int size)1581 int win32_serial_read(int fd, void *vb, int size)
1582 {
1583 long start, now;
1584 unsigned long nBytes = 0, total = 0;
1585 /* unsigned long waiting = 0; */
1586 int err;
1587 struct termios_list *index;
1588 char message[80];
1589 COMSTAT stat;
1590 clock_t c;
1591 unsigned char *dest = vb;
1592
1593 start = GetTickCount();
1594 ENTER("serial_read");
1595
1596 if (fd <= 0)
1597 {
1598 return 0;
1599 }
1600
1601 index = find_port(fd);
1602
1603 if (!index)
1604 {
1605 LEAVE("serial_read");
1606 return -1;
1607 }
1608
1609 /* FIXME: CREAD: without this, data cannot be read
1610 FIXME: PARMRK: mark framing & parity errors
1611 FIXME: IGNCR: ignore \r
1612 FIXME: ICRNL: convert \r to \n
1613 FIXME: INLCR: convert \n to \r
1614 */
1615
1616 if (index->open_flags & O_NONBLOCK)
1617 {
1618 /* pull mucho-cpu here? */
1619 do
1620 {
1621 #ifdef DEBUG_VERBOSE
1622 report("vmin=0\n");
1623 #endif /* DEBUG_VERBOSE */
1624 ClearErrors(index, &stat);
1625
1626 if (stat.cbInQue < index->ttyset->c_cc[VMIN])
1627 {
1628 /*
1629 hl_usleep(50);
1630 */
1631 hl_usleep(100); /* don't hog the CPU while waiting */
1632
1633 /* we should use -1 instead of 0 for disabled timeout */
1634 now = GetTickCount();
1635
1636 if (index->ttyset->c_cc[VTIME] &&
1637 now - start >= (index->ttyset->c_cc[VTIME] * 100))
1638 {
1639 /*
1640 sprintf( message, "now = %i start = %i time = %i total =%i\n", now, start, index->ttyset->c_cc[VTIME]*100, total);
1641 report( message );
1642 */
1643 return total; /* read timeout */
1644 }
1645 }
1646 }
1647 while (size > 1 && stat.cbInQue < index->ttyset->c_cc[VMIN]);
1648 }
1649 else
1650 {
1651 /* VTIME is in units of 0.1 seconds */
1652
1653 #ifdef DEBUG_VERBOSE
1654 report("vmin!=0\n");
1655 #endif /* DEBUG_VERBOSE */
1656 /* vmin = index->ttyset->c_cc[VMIN]; */
1657
1658 c = clock() + index->ttyset->c_cc[VTIME] * CLOCKS_PER_SEC / 10;
1659
1660 do
1661 {
1662 ClearErrors(index, &stat);
1663 hl_usleep(1000);
1664 }
1665 while (stat.cbInQue < index->ttyset->c_cc[VMIN] && c > clock());
1666
1667 }
1668
1669 total = 0;
1670
1671 while (size > 0)
1672 {
1673 nBytes = 0;
1674 /* ClearErrors( index, &stat); */
1675
1676 index->rol.Offset = index->rol.OffsetHigh = 0;
1677 ResetEvent(index->rol.hEvent);
1678
1679 err = ReadFile(index->hComm, dest + total, size, &nBytes, &index->rol);
1680 #ifdef DEBUG_VERBOSE
1681 /* warning Roy Rogers! */
1682 sprintf(message, " ========== ReadFile = %i 0x%x\n",
1683 (int) nBytes, *((char *) dest + total));
1684 report(message);
1685 #endif /* DEBUG_VERBOSE */
1686
1687 if (!err)
1688 {
1689 switch (GetLastError())
1690 {
1691 case ERROR_BROKEN_PIPE:
1692 report("ERROR_BROKEN_PIPE\n ");
1693 nBytes = 0;
1694 break;
1695
1696 case ERROR_MORE_DATA:
1697 /*
1698 hl_usleep(1000);
1699 */
1700 report("ERROR_MORE_DATA\n");
1701 break;
1702
1703 case ERROR_IO_PENDING:
1704 while (! GetOverlappedResult(
1705 index->hComm,
1706 &index->rol,
1707 &nBytes,
1708 TRUE))
1709 {
1710 if (GetLastError() !=
1711 ERROR_IO_INCOMPLETE)
1712 {
1713 ClearErrors(
1714 index,
1715 &stat);
1716 return (total);
1717 }
1718 }
1719
1720 size -= nBytes;
1721 total += nBytes;
1722
1723 if (size > 0)
1724 {
1725 now = GetTickCount();
1726 sprintf(message, "size > 0: spent=%ld have=%d\n", now - start,
1727 index->ttyset->c_cc[VTIME] * 100);
1728 report(message);
1729
1730 /* we should use -1 for disabled
1731 timouts */
1732 if (index->ttyset->c_cc[VTIME]
1733 && now - start >= (index->ttyset->c_cc[VTIME] * 100))
1734 {
1735 report("TO ");
1736 /* read timeout */
1737 return total;
1738 }
1739 }
1740
1741 sprintf(message, "end nBytes=%lu] ", nBytes);
1742 report(message);
1743 /*
1744 hl_usleep(1000);
1745 */
1746 report("ERROR_IO_PENDING\n");
1747 break;
1748
1749 default:
1750 /*
1751 hl_usleep(1000);
1752 */
1753 YACK();
1754 return -1;
1755 }
1756 }
1757 else
1758 {
1759 size -= nBytes;
1760 total += nBytes;
1761
1762 /*
1763 hl_usleep(1000);
1764 */
1765 ClearErrors(index, &stat);
1766 return (total);
1767 }
1768 }
1769
1770 LEAVE("serial_read");
1771 return total;
1772 }
1773
1774 #ifdef asdf
win32_serial_read(int fd,void * vb,int size)1775 int win32_serial_read(int fd, void *vb, int size)
1776 {
1777 long start, now;
1778 unsigned long nBytes = 0, total = 0, error;
1779 /* unsigned long waiting = 0; */
1780 int err, vmin;
1781 struct termios_list *index;
1782 char message[80];
1783 COMSTAT Stat;
1784 clock_t c;
1785 unsigned char *dest = vb;
1786
1787 start = GetTickCount();
1788 ENTER("serial_read");
1789
1790 if (fd <= 0)
1791 {
1792 printf("1\n");
1793 return 0;
1794 }
1795
1796 index = find_port(fd);
1797
1798 if (!index)
1799 {
1800 LEAVE("serial_read 7");
1801 errno = EIO;
1802 printf("2\n");
1803 return -1;
1804 }
1805
1806 /* FIXME: CREAD: without this, data cannot be read
1807 FIXME: PARMRK: mark framing & parity errors
1808 FIXME: IGNCR: ignore \r
1809 FIXME: ICRNL: convert \r to \n
1810 FIXME: INLCR: convert \n to \r
1811 */
1812
1813 ClearErrors(index, &Stat);
1814
1815 if (index->open_flags & O_NONBLOCK)
1816 {
1817 vmin = 0;
1818
1819 /* pull mucho-cpu here? */
1820 do
1821 {
1822 #ifdef DEBUG_VERBOSE
1823 report("vmin=0\n");
1824 #endif /* DEBUG_VERBOSE */
1825 ClearErrors(index, &Stat);
1826 /*
1827 hl_usleep(1000);
1828 hl_usleep(50);
1829 */
1830 /* we should use -1 instead of 0 for disabled timeout */
1831 now = GetTickCount();
1832
1833 if (index->ttyset->c_cc[VTIME] &&
1834 now - start >= (index->ttyset->c_cc[VTIME] * 100))
1835 {
1836 /*
1837 sprintf( message, "now = %i start = %i time = %i total =%i\n", now, start, index->ttyset->c_cc[VTIME]*100, total);
1838 report( message );
1839 */
1840 errno = EAGAIN;
1841 printf("3\n");
1842 return -1; /* read timeout */
1843 }
1844 }
1845 while (Stat.cbInQue < size && size > 1);
1846 }
1847 else
1848 {
1849 /* VTIME is in units of 0.1 seconds */
1850
1851 #ifdef DEBUG_VERBOSE
1852 report("vmin!=0\n");
1853 #endif /* DEBUG_VERBOSE */
1854 vmin = index->ttyset->c_cc[VMIN];
1855
1856 c = clock() + index->ttyset->c_cc[VTIME] * CLOCKS_PER_SEC / 10;
1857
1858 do
1859 {
1860 error = ClearErrors(index, &Stat);
1861 hl_usleep(1000);
1862 }
1863 while (c > clock());
1864
1865 }
1866
1867 total = 0;
1868
1869 while (size > 0)
1870 {
1871 nBytes = 0;
1872 /* ClearErrors( index, &Stat); */
1873
1874 index->rol.Offset = index->rol.OffsetHigh = 0;
1875 ResetEvent(index->rol.hEvent);
1876
1877 err = ReadFile(index->hComm, dest + total, size, &nBytes, &index->rol);
1878 #ifdef DEBUG_VERBOSE
1879 /* warning Roy Rogers! */
1880 sprintf(message, " ========== ReadFile = %i %s\n",
1881 (int) nBytes, (char *) dest + total);
1882 report(message);
1883 #endif /* DEBUG_VERBOSE */
1884
1885 if (!err)
1886 {
1887 switch (GetLastError())
1888 {
1889 case ERROR_BROKEN_PIPE:
1890 report("ERROR_BROKEN_PIPE\n ");
1891 nBytes = 0;
1892 break;
1893
1894 case ERROR_MORE_DATA:
1895 /*
1896 hl_usleep(1000);
1897 */
1898 report("ERROR_MORE_DATA\n");
1899 break;
1900
1901 case ERROR_IO_PENDING:
1902 while (! GetOverlappedResult(
1903 index->hComm,
1904 &index->rol,
1905 &nBytes,
1906 TRUE))
1907 {
1908 if (GetLastError() !=
1909 ERROR_IO_INCOMPLETE)
1910 {
1911 ClearErrors(
1912 index,
1913 &Stat);
1914 printf("4\n");
1915 return (total);
1916 }
1917 }
1918
1919 size -= nBytes;
1920 total += nBytes;
1921
1922 if (size > 0)
1923 {
1924 now = GetTickCount();
1925 sprintf(message, "size > 0: spent=%ld have=%d\n", now - start,
1926 index->ttyset->c_cc[VTIME] * 100);
1927 report(message);
1928
1929 /* we should use -1 for disabled
1930 timouts */
1931 if (index->ttyset->c_cc[VTIME]
1932 && now - start >= (index->ttyset->c_cc[VTIME] * 100))
1933 {
1934 report("TO ");
1935 /* read timeout */
1936 printf("5\n");
1937 return total;
1938 }
1939 }
1940
1941 sprintf(message, "end nBytes=%ld] ", nBytes);
1942 report(message);
1943 /*
1944 hl_usleep(1000);
1945 */
1946 report("ERROR_IO_PENDING\n");
1947 break;
1948
1949 default:
1950 /*
1951 hl_usleep(1000);
1952 */
1953 YACK();
1954 errno = EIO;
1955 printf("6\n");
1956 return -1;
1957 }
1958 }
1959 else
1960 {
1961 size -= nBytes;
1962 total += nBytes;
1963
1964 /*
1965 hl_usleep(1000);
1966 */
1967 ClearErrors(index, &Stat);
1968 printf("7\n");
1969 return (total);
1970 }
1971 }
1972
1973 LEAVE("serial_read");
1974 ClearErrors(index, &Stat);
1975 return total;
1976 }
1977 #endif /* asdf */
1978
1979 /*----------------------------------------------------------
1980 cfsetospeed()
1981
1982 accept:
1983 perform:
1984 return:
1985 exceptions:
1986 win32api: None
1987 comments:
1988 ----------------------------------------------------------*/
1989
cfsetospeed(struct termios * s_termios,speed_t speed)1990 int cfsetospeed(struct termios *s_termios, speed_t speed)
1991 {
1992 char message[80];
1993 ENTER("cfsetospeed");
1994 /* clear baudrate */
1995 s_termios->c_cflag &= ~CBAUD;
1996
1997 if (speed & ~CBAUD)
1998 {
1999 sprintf(message, "cfsetospeed: not speed: %#o\n", speed);
2000 report(message);
2001 /* continue assuming its a custom baudrate */
2002 s_termios->c_cflag |= B38400; /* use 38400 during custom */
2003 s_termios->c_cflag |= CBAUDEX; /* use CBAUDEX for custom */
2004 }
2005 else if (speed)
2006 {
2007 s_termios->c_cflag |= speed;
2008 }
2009 else
2010 {
2011 /* PC blows up with speed 0 handled in Java */
2012 s_termios->c_cflag |= B9600;
2013 }
2014
2015 s_termios->c_ispeed = s_termios->c_ospeed = speed;
2016 LEAVE("cfsetospeed");
2017 return 1;
2018 }
2019
2020 /*----------------------------------------------------------
2021 cfsetispeed()
2022
2023 accept:
2024 perform:
2025 return:
2026 exceptions:
2027 win32api: None
2028 comments:
2029 ----------------------------------------------------------*/
2030
cfsetispeed(struct termios * s_termios,speed_t speed)2031 int cfsetispeed(struct termios *s_termios, speed_t speed)
2032 {
2033 return cfsetospeed(s_termios, speed);
2034 }
2035
2036 /*----------------------------------------------------------
2037 cfsetspeed()
2038
2039 accept:
2040 perform:
2041 return:
2042 exceptions:
2043 win32api: None
2044 comments:
2045 ----------------------------------------------------------*/
2046
cfsetspeed(struct termios * s_termios,speed_t speed)2047 int cfsetspeed(struct termios *s_termios, speed_t speed)
2048 {
2049 return cfsetospeed(s_termios, speed);
2050 }
2051
2052 /*----------------------------------------------------------
2053 cfgetospeed()
2054
2055 accept:
2056 perform:
2057 return:
2058 exceptions:
2059 win32api: None
2060 comments:
2061 ----------------------------------------------------------*/
2062
cfgetospeed(struct termios * s_termios)2063 speed_t cfgetospeed(struct termios *s_termios)
2064 {
2065 ENTER("cfgetospeed");
2066 return s_termios->c_ospeed;
2067 }
2068
2069 /*----------------------------------------------------------
2070 cfgetispeed()
2071
2072 accept:
2073 perform:
2074 return:
2075 exceptions:
2076 win32api: None
2077 comments:
2078 ----------------------------------------------------------*/
2079
cfgetispeed(struct termios * s_termios)2080 speed_t cfgetispeed(struct termios *s_termios)
2081 {
2082 ENTER("cfgetospeed");
2083 return s_termios->c_ispeed;
2084 }
2085
2086 /*----------------------------------------------------------
2087 serial_struct_to_DCB()
2088
2089 accept:
2090 perform:
2091 return:
2092 exceptions:
2093 win32api: None
2094 comments:
2095 ----------------------------------------------------------*/
serial_struct_to_DCB(struct serial_struct * sstruct,DCB * dcb)2096 int serial_struct_to_DCB(struct serial_struct *sstruct, DCB *dcb)
2097 {
2098 /* 5 Baud rate fix
2099 sstruct.baud_base
2100 sstruct.custom_divisor = ( sstruct.baud_base/cspeed );
2101 */
2102 return (0);
2103 }
2104
2105 /*----------------------------------------------------------
2106 termios_to_DCB()
2107
2108 accept:
2109 perform:
2110 return:
2111 exceptions:
2112 win32api: None
2113 comments:
2114 ----------------------------------------------------------*/
termios_to_DCB(struct termios * s_termios,DCB * dcb)2115 static int termios_to_DCB(struct termios *s_termios, DCB *dcb)
2116 {
2117 ENTER("termios_to_DCB");
2118
2119 if (!(s_termios->c_cflag & CBAUDEX))
2120 {
2121 s_termios->c_ispeed = s_termios->c_ospeed = s_termios->c_cflag & CBAUD;
2122 }
2123
2124 dcb->BaudRate = B_to_CBR(s_termios->c_ispeed);
2125 dcb->ByteSize = termios_to_bytesize(s_termios->c_cflag);
2126
2127 if (s_termios->c_cflag & PARENB)
2128 {
2129 if (s_termios->c_cflag & PARODD
2130 && s_termios->c_cflag & CMSPAR)
2131 {
2132 dcb->Parity = MARKPARITY;
2133 }
2134 else if (s_termios->c_cflag & PARODD)
2135 {
2136 dcb->Parity = ODDPARITY;
2137 }
2138 else if (s_termios->c_cflag & CMSPAR)
2139 {
2140 dcb->Parity = SPACEPARITY;
2141 }
2142 else
2143 {
2144 dcb->Parity = EVENPARITY;
2145 }
2146 }
2147 else
2148 {
2149 dcb->Parity = NOPARITY;
2150 }
2151
2152 if (s_termios->c_cflag & CSTOPB) { dcb->StopBits = TWOSTOPBITS; }
2153 else { dcb->StopBits = ONESTOPBIT; }
2154
2155 if (s_termios->c_cflag & HARDWARE_FLOW_CONTROL)
2156 {
2157 dcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
2158 dcb->fOutxCtsFlow = TRUE;
2159 }
2160 else
2161 {
2162 dcb->fRtsControl = RTS_CONTROL_DISABLE;
2163 dcb->fOutxCtsFlow = FALSE;
2164 }
2165
2166 LEAVE("termios_to_DCB");
2167 return 0;
2168 }
2169
2170 /*----------------------------------------------------------
2171 DCB_to_serial_struct()
2172
2173 accept:
2174 perform:
2175 return:
2176 exceptions:
2177 win32api: None
2178 comments:
2179 ----------------------------------------------------------*/
DCB_to_serial_struct(DCB * dcb,struct serial_struct * sstruct)2180 int DCB_to_serial_struct(DCB *dcb, struct serial_struct *sstruct)
2181 {
2182 return (0);
2183 }
2184 /*----------------------------------------------------------
2185 DCB_to_termios()
2186
2187 accept:
2188 perform:
2189 return:
2190 exceptions:
2191 win32api: None
2192 comments:
2193 ----------------------------------------------------------*/
DCB_to_termios(DCB * dcb,struct termios * s_termios)2194 static void DCB_to_termios(DCB *dcb, struct termios *s_termios)
2195 {
2196 ENTER("DCB_to_termios");
2197 s_termios->c_ispeed = CBR_to_B(dcb->BaudRate);
2198 s_termios->c_ospeed = s_termios->c_ispeed;
2199 s_termios->c_cflag |= s_termios->c_ispeed & CBAUD;
2200 LEAVE("DCB_to_termios");
2201 }
2202
2203 /*----------------------------------------------------------
2204 show_DCB()
2205
2206 accept:
2207 perform:
2208 return:
2209 exceptions:
2210 win32api: None
2211 comments:
2212 ----------------------------------------------------------*/
show_DCB(DCB myDCB)2213 static void show_DCB(DCB myDCB)
2214 {
2215
2216 #ifdef DEBUG_HOSED
2217 char message[80];
2218
2219 sprintf(message, "DCBlength: %ld\n", myDCB.DCBlength);
2220 report(message);
2221 sprintf("BaudRate: %ld\n", myDCB.BaudRate);
2222 report(message);
2223
2224 if (myDCB.fBinary)
2225 {
2226 report("fBinary\n");
2227 }
2228
2229 if (myDCB.fParity)
2230 {
2231 report("fParity: ");
2232
2233 if (myDCB.fErrorChar)
2234 {
2235 sprintf(message, "fErrorChar: %#x\n", myDCB.ErrorChar);
2236 report(message);
2237 }
2238 else
2239 {
2240 report("fErrorChar == false\n");
2241 }
2242 }
2243
2244 if (myDCB.fOutxCtsFlow)
2245 {
2246 report("fOutxCtsFlow\n");
2247 }
2248
2249 if (myDCB.fOutxDsrFlow)
2250 {
2251 report("fOutxDsrFlow\n");
2252 }
2253
2254 if (myDCB.fDtrControl & DTR_CONTROL_HANDSHAKE);
2255
2256 report("DTR_CONTROL_HANDSHAKE\n");
2257
2258 if (myDCB.fDtrControl & DTR_CONTROL_ENABLE);
2259
2260 report("DTR_CONTROL_ENABLE\n");
2261
2262 if (myDCB.fDtrControl & DTR_CONTROL_DISABLE);
2263
2264 report("DTR_CONTROL_DISABLE\n");
2265
2266 if (myDCB.fDsrSensitivity)
2267 {
2268 report("fDsrSensitivity\n");
2269 }
2270
2271 if (myDCB.fTXContinueOnXoff)
2272 {
2273 report("fTXContinueOnXoff\n");
2274 }
2275
2276 if (myDCB.fOutX)
2277 {
2278 report("fOutX\n");
2279 }
2280
2281 if (myDCB.fInX)
2282 {
2283 report("fInX\n");
2284 }
2285
2286 if (myDCB.fNull)
2287 {
2288 report("fNull\n");
2289 }
2290
2291 if (myDCB.fRtsControl & RTS_CONTROL_TOGGLE)
2292 {
2293 report("RTS_CONTROL_TOGGLE\n");
2294 }
2295
2296 if (myDCB.fRtsControl == 0)
2297 {
2298 report("RTS_CONTROL_HANDSHAKE ( fRtsControl==0 )\n");
2299 }
2300
2301 if (myDCB.fRtsControl & RTS_CONTROL_HANDSHAKE)
2302 {
2303 report("RTS_CONTROL_HANDSHAKE\n");
2304 }
2305
2306 if (myDCB.fRtsControl & RTS_CONTROL_ENABLE)
2307 {
2308 report("RTS_CONTROL_ENABLE\n");
2309 }
2310
2311 if (myDCB.fRtsControl & RTS_CONTROL_DISABLE)
2312 {
2313 report("RTS_CONTROL_DISABLE\n");
2314 }
2315
2316 if (myDCB.fAbortOnError)
2317 {
2318 report("fAbortOnError\n");
2319 }
2320
2321 sprintf(message, "XonLim: %d\n", myDCB.XonLim);
2322 report(message);
2323 sprintf(message, "XoffLim: %d\n", myDCB.XoffLim);
2324 report(message);
2325 sprintf(message, "ByteSize: %d\n", myDCB.ByteSize);
2326 report(message);
2327
2328 switch (myDCB.Parity)
2329 {
2330 case EVENPARITY:
2331 report("EVENPARITY");
2332 break;
2333
2334 case MARKPARITY:
2335 report("MARKPARITY");
2336 break;
2337
2338 case NOPARITY:
2339 report("NOPARITY");
2340 break;
2341
2342 case ODDPARITY:
2343 report("ODDPARITY");
2344 break;
2345
2346 default:
2347 sprintf(message,
2348 "unknown Parity (%#x ):", myDCB.Parity);
2349 report(message);
2350 break;
2351 }
2352
2353 report("\n");
2354
2355 switch (myDCB.StopBits)
2356 {
2357 case ONESTOPBIT:
2358 report("ONESTOPBIT");
2359 break;
2360
2361 case ONE5STOPBITS:
2362 report("ONE5STOPBITS");
2363 break;
2364
2365 case TWOSTOPBITS:
2366 report("TWOSTOPBITS");
2367 break;
2368
2369 default:
2370 report("unknown StopBits (%#x ):", myDCB.StopBits);
2371 break;
2372 }
2373
2374 report("\n");
2375 sprintf(message, "XonChar: %#x\n", myDCB.XonChar);
2376 report(message);
2377 sprintf(message, "XoffChar: %#x\n", myDCB.XoffChar);
2378 report(message);
2379 sprintf(message, "EofChar: %#x\n", myDCB.EofChar);
2380 report(message);
2381 sprintf(message, "EvtChar: %#x\n", myDCB.EvtChar);
2382 report(message);
2383 report("\n");
2384 #endif /* DEBUG_HOSED */
2385 }
2386
2387 /*----------------------------------------------------------
2388 tcgetattr()
2389
2390 accept:
2391 perform:
2392 return:
2393 exceptions:
2394 win32api: GetCommState(), GetCommTimeouts()
2395 comments:
2396 ----------------------------------------------------------*/
2397
tcgetattr(int fd,struct termios * s_termios)2398 int tcgetattr(int fd, struct termios *s_termios)
2399 {
2400 DCB myDCB;
2401 COMMTIMEOUTS timeouts;
2402 struct termios_list *index;
2403 char message[80];
2404
2405 ENTER("tcgetattr");
2406
2407 if (fd <= 0)
2408 {
2409 return 0;
2410 }
2411
2412 index = find_port(fd);
2413
2414 if (!index)
2415 {
2416 LEAVE("tcgetattr");
2417 return -1;
2418 }
2419
2420 if (!GetCommState(index->hComm, &myDCB))
2421 {
2422 sprintf(message, "GetCommState failed\n");
2423 report(message);
2424 return -1;
2425 }
2426
2427 memcpy(s_termios, index->ttyset, sizeof(struct termios));
2428
2429 show_DCB(myDCB);
2430
2431 /***** input mode flags (c_iflag ) ****/
2432 /* parity check enable */
2433 if (myDCB.fParity)
2434 {
2435 s_termios->c_iflag |= INPCK;
2436 s_termios->c_iflag &= ~IGNPAR;
2437 }
2438 else
2439 {
2440 s_termios->c_iflag &= ~INPCK;
2441 s_termios->c_iflag |= IGNPAR;
2442 }
2443
2444 /* FIXME: IGNBRK: ignore break */
2445 /* FIXME: BRKINT: interrupt on break */
2446
2447 if (myDCB.fOutX)
2448 {
2449 s_termios->c_iflag |= IXON;
2450 }
2451 else
2452 {
2453 /* IXON: output start/stop control */
2454 s_termios->c_iflag &= ~IXON;
2455 }
2456
2457 if (myDCB.fInX)
2458 {
2459 s_termios->c_iflag |= IXOFF;
2460 }
2461 else
2462 {
2463 /* IXOFF: input start/stop control */
2464 s_termios->c_iflag &= ~IXOFF;
2465 }
2466
2467 if (myDCB.fTXContinueOnXoff)
2468 {
2469 s_termios->c_iflag |= IXANY;
2470 }
2471 else
2472 {
2473 /* IXANY: any char restarts output */
2474 s_termios->c_iflag &= ~IXANY;
2475 }
2476
2477 /* FIXME: IMAXBEL: if input buffer full, send bell */
2478
2479 /***** control mode flags (c_cflag ) *****/
2480 /* FIXME: CLOCAL: DONT send SIGHUP on modem disconnect */
2481 /* FIXME: HUPCL: generate modem disconnect when all has closed or
2482 exited */
2483 /* CSTOPB two stop bits ( otherwise one) */
2484 if (myDCB.StopBits == TWOSTOPBITS)
2485 {
2486 s_termios->c_cflag |= CSTOPB;
2487 }
2488
2489 if (myDCB.StopBits == ONESTOPBIT)
2490 {
2491 s_termios->c_cflag &= ~CSTOPB;
2492 }
2493
2494 /* PARENB enable parity bit */
2495 s_termios->c_cflag &= ~(PARENB | PARODD | CMSPAR);
2496 myDCB.fParity = 1;
2497
2498 #if 0 // redundant
2499
2500 if (myDCB.fParity)
2501 {
2502 #endif
2503 report("tcgetattr getting parity\n");
2504 s_termios->c_cflag |= PARENB;
2505
2506 if (myDCB.Parity == MARKPARITY)
2507 {
2508 s_termios->c_cflag |= (PARODD | CMSPAR);
2509 }
2510 else if (myDCB.Parity == SPACEPARITY)
2511 {
2512 s_termios->c_cflag |= CMSPAR;
2513 }
2514 else if (myDCB.Parity == ODDPARITY)
2515 {
2516 report("ODDPARITY\n");
2517 s_termios->c_cflag |= PARODD;
2518 }
2519 else if (myDCB.Parity == EVENPARITY)
2520 {
2521 report("EVENPARITY\n");
2522 s_termios->c_cflag &= ~PARODD;
2523 }
2524 else if (myDCB.Parity == NOPARITY)
2525 {
2526 s_termios->c_cflag &= ~(PARODD | CMSPAR | PARENB);
2527 }
2528
2529 #if 0 // see redundant above
2530 }
2531 else
2532 {
2533 s_termios->c_cflag &= ~PARENB;
2534 }
2535
2536 #endif
2537
2538 /* CSIZE */
2539 s_termios->c_cflag |= bytesize_to_termios(myDCB.ByteSize);
2540
2541 /* HARDWARE_FLOW_CONTROL: hardware flow control */
2542 if ((myDCB.fOutxCtsFlow == TRUE) ||
2543 (myDCB.fRtsControl == RTS_CONTROL_HANDSHAKE))
2544 {
2545 s_termios->c_cflag |= HARDWARE_FLOW_CONTROL;
2546 }
2547 else
2548 {
2549 s_termios->c_cflag &= ~HARDWARE_FLOW_CONTROL;
2550 }
2551
2552 /* MDMBUF: carrier based flow control of output */
2553 /* CIGNORE: tcsetattr will ignore control modes & baudrate */
2554
2555 /***** NOT SUPPORTED: local mode flags (c_lflag) *****/
2556 /* ICANON: canonical (not raw) mode */
2557 /* ECHO: echo back to terminal */
2558 /* ECHOE: echo erase */
2559 /* ECHOPRT: hardcopy echo erase */
2560 /* ECHOK: show KILL char */
2561 /* ECHOKE: BSD ECHOK */
2562 /* ECHONL: ICANON only: echo newline even with no ECHO */
2563 /* ECHOCTL: if ECHO, then control-A are printed as '^A' */
2564 /* ISIG: recognize INTR, QUIT & SUSP */
2565 /* IEXTEN: implementation defined */
2566 /* NOFLSH: dont clear i/o queues on INTR, QUIT or SUSP */
2567 /* TOSTOP: background process generate SIGTTOU */
2568 /* ALTWERASE: alt-w erase distance */
2569 /* FLUSHO: user DISCARD char */
2570 /* NOKERNINFO: disable STATUS char */
2571 /* PENDIN: input line needsd reprinting, set by REPRINT char */
2572 /***** END - NOT SUPPORTED *****/
2573
2574 /***** control characters (c_cc[NCCS] ) *****/
2575
2576 if (!GetCommTimeouts(index->hComm, &timeouts))
2577 {
2578 YACK();
2579 report("GetCommTimeouts\n");
2580 return -1;
2581 }
2582
2583 s_termios->c_cc[VTIME] = timeouts.ReadTotalTimeoutConstant / 100;
2584 /*
2585 handled in SerialImp.c?
2586 s_termios->c_cc[VMIN] = ?
2587 */
2588
2589 s_termios->c_cc[VSTART] = myDCB.XonChar;
2590 s_termios->c_cc[VSTOP] = myDCB.XoffChar;
2591 s_termios->c_cc[VEOF] = myDCB.EofChar;
2592
2593 #ifdef DEBUG_VERBOSE
2594 sprintf(message,
2595 "tcgetattr: VTIME:%d, VMIN:%d\n", s_termios->c_cc[VTIME],
2596 s_termios->c_cc[VMIN]);
2597 report(message);
2598 #endif /* DEBUG_VERBOSE */
2599
2600 /***** line discipline ( c_line ) ( == c_cc[33] ) *****/
2601
2602 DCB_to_termios(&myDCB, s_termios); /* baudrate */
2603 LEAVE("tcgetattr");
2604 return 0;
2605 }
2606
2607 /*
2608 `TCSANOW'
2609 Make the change immediately.
2610
2611 `TCSADRAIN'
2612 Make the change after waiting until all queued output has
2613 been written. You should usually use this option when
2614 changing parameters that affect output.
2615
2616 `TCSAFLUSH'
2617 This is like `TCSADRAIN', but also discards any queued input.
2618
2619 `TCSASOFT'
2620 This is a flag bit that you can add to any of the above
2621 alternatives. Its meaning is to inhibit alteration of the
2622 state of the terminal hardware. It is a BSD extension; it is
2623 only supported on BSD systems and the GNU system.
2624
2625 Using `TCSASOFT' is exactly the same as setting the `CIGNORE'
2626 bit in the `c_cflag' member of the structure TERMIOS-P points
2627 to. *Note Control Modes::, for a description of `CIGNORE'.
2628 */
2629
2630 /*----------------------------------------------------------
2631 tcsetattr()
2632
2633 accept:
2634 perform:
2635 return:
2636 exceptions:
2637 win32api: GetCommState(), GetCommTimeouts(), SetCommState(),
2638 SetCommTimeouts()
2639 comments:
2640 ----------------------------------------------------------*/
tcsetattr(int fd,int when,struct termios * s_termios)2641 int tcsetattr(int fd, int when, struct termios *s_termios)
2642 {
2643 int vtime;
2644 DCB dcb;
2645 COMMTIMEOUTS timeouts;
2646 struct termios_list *index;
2647
2648 ENTER("tcsetattr");
2649
2650 if (fd <= 0)
2651 {
2652 return 0;
2653 }
2654
2655 index = find_port(fd);
2656
2657 if (!index)
2658 {
2659 LEAVE("tcsetattr");
2660 return -1;
2661 }
2662
2663 fflush(stdout);
2664
2665 if (s_termios->c_lflag & ICANON)
2666 {
2667 report("tcsetattr: no canonical mode support\n");
2668 /* and all other c_lflags too */
2669 return -1;
2670 }
2671
2672 if (!GetCommState(index->hComm, &dcb))
2673 {
2674 YACK();
2675 report("tcsetattr:GetCommState\n");
2676 return -1;
2677 }
2678
2679 if (!GetCommTimeouts(index->hComm, &timeouts))
2680 {
2681 YACK();
2682 report("tcsetattr:GetCommTimeouts\n");
2683 return -1;
2684 }
2685
2686 /*** control flags, c_cflag **/
2687 if (!(s_termios->c_cflag & CIGNORE))
2688 {
2689 dcb.fParity = 1;
2690
2691 /* CIGNORE: ignore control modes and baudrate */
2692 /* baudrate */
2693 if (termios_to_DCB(s_termios, &dcb) < 0) { return -1; }
2694 }
2695 else
2696 {
2697 }
2698
2699 /*** input flags, c_iflag **/
2700 /* This is wrong. It disables Parity FIXME
2701 if( ( s_termios->c_iflag & INPCK ) && !( s_termios->c_iflag & IGNPAR ) )
2702 {
2703 dcb.fParity = TRUE;
2704 } else
2705 {
2706 dcb.fParity = FALSE;
2707 }
2708 */
2709 /* not in win95?
2710 Some years later...
2711 eww.. FIXME This is used for changing the Parity
2712 error character
2713
2714 I think this code is hosed. See VEOF below
2715
2716 Trent
2717 */
2718
2719 if (s_termios->c_iflag & ISTRIP) { dcb.fBinary = FALSE; }
2720 /* ISTRIP: strip to seven bits */
2721 else { dcb.fBinary = TRUE; }
2722
2723 /* FIXME: IGNBRK: ignore break */
2724 /* FIXME: BRKINT: interrupt on break */
2725 if (s_termios->c_iflag & IXON)
2726 {
2727 dcb.fOutX = TRUE;
2728 }
2729 else
2730 {
2731 dcb.fOutX = FALSE;
2732 }
2733
2734 if (s_termios->c_iflag & IXOFF)
2735 {
2736 dcb.fInX = TRUE;
2737 }
2738 else
2739 {
2740 dcb.fInX = FALSE;
2741 }
2742
2743 dcb.fTXContinueOnXoff = (s_termios->c_iflag & IXANY) ? TRUE : FALSE;
2744 /* FIXME: IMAXBEL: if input buffer full, send bell */
2745
2746 /* no DTR control in termios? */
2747 dcb.fDtrControl = DTR_CONTROL_DISABLE;
2748 /* no DSR control in termios? */
2749 dcb.fOutxDsrFlow = FALSE;
2750 /* DONT ignore rx bytes when DSR is OFF */
2751 dcb.fDsrSensitivity = FALSE;
2752 dcb.XonChar = s_termios->c_cc[VSTART];
2753 dcb.XoffChar = s_termios->c_cc[VSTOP];
2754 dcb.XonLim = 0; /* ? */
2755 dcb.XoffLim = 0; /* ? */
2756 dcb.EofChar = s_termios->c_cc[VEOF];
2757
2758 if (dcb.EofChar != '\0')
2759 {
2760 dcb.fBinary = FALSE;
2761 }
2762 else
2763 {
2764 dcb.fBinary = TRUE;
2765 }
2766
2767 if (EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | (EV_RLSD & EV_RXFLAG))
2768 {
2769 dcb.EvtChar = '\n';
2770 }
2771 else
2772 {
2773 dcb.EvtChar = '\0';
2774 }
2775
2776 if (!SetCommState(index->hComm, &dcb))
2777 {
2778 report("SetCommState error\n");
2779 YACK();
2780 return -1;
2781 }
2782
2783 #ifdef DEBUG_VERBOSE
2784 {
2785 char message[32];
2786 sprintf(message, "VTIME:%d, VMIN:%d\n", s_termios->c_cc[VTIME],
2787 s_termios->c_cc[VMIN]);
2788 report(message);
2789 }
2790 #endif /* DEBUG_VERBOSE */
2791 vtime = s_termios->c_cc[VTIME] * 100;
2792 timeouts.ReadTotalTimeoutConstant = vtime;
2793 timeouts.ReadIntervalTimeout = 0;
2794 timeouts.ReadTotalTimeoutMultiplier = 0;
2795
2796 timeouts.WriteTotalTimeoutConstant = vtime;
2797 timeouts.WriteTotalTimeoutMultiplier = 0;
2798
2799 /* max between bytes */
2800 if (s_termios->c_cc[VMIN] > 0 && vtime > 0)
2801 {
2802 /* read blocks forever on VMIN chars */
2803 }
2804 else if (s_termios->c_cc[VMIN] == 0 && vtime == 0)
2805 {
2806 /* read returns immediately */
2807 timeouts.ReadIntervalTimeout = MAXDWORD;
2808 timeouts.ReadTotalTimeoutConstant = 0;
2809 timeouts.ReadTotalTimeoutMultiplier = 0;
2810 }
2811
2812 #ifdef DEBUG_VERBOSE
2813 {
2814 char message[64];
2815 sprintf(message, "ReadIntervalTimeout=%ld\n",
2816 timeouts.ReadIntervalTimeout);
2817 report(message);
2818 sprintf(message, "c_cc[VTIME] = %d, c_cc[VMIN] = %d\n",
2819 s_termios->c_cc[VTIME], s_termios->c_cc[VMIN]);
2820 report(message);
2821 sprintf(message, "ReadTotalTimeoutConstant: %ld\n",
2822 timeouts.ReadTotalTimeoutConstant);
2823 report(message);
2824 sprintf(message, "ReadIntervalTimeout : %ld\n",
2825 timeouts.ReadIntervalTimeout);
2826 report(message);
2827 sprintf(message, "ReadTotalTimeoutMultiplier: %ld\n",
2828 timeouts.ReadTotalTimeoutMultiplier);
2829 report(message);
2830 }
2831 #endif /* DEBUG_VERBOSE */
2832
2833 if (!SetCommTimeouts(index->hComm, &timeouts))
2834 {
2835 YACK();
2836 report("SetCommTimeouts\n");
2837 return -1;
2838 }
2839
2840 memcpy(index->ttyset, s_termios, sizeof(struct termios));
2841 LEAVE("tcsetattr");
2842 return 0;
2843 }
2844
2845 /*----------------------------------------------------------
2846 tcsendbreak()
2847
2848 accept:
2849 perform:
2850 return:
2851 exceptions:
2852 win32api: None
2853 comments:
2854 break for duration*0.25 seconds or
2855 0.25 seconds if duration = 0.
2856 ----------------------------------------------------------*/
2857
tcsendbreak(int fd,int duration)2858 int tcsendbreak(int fd, int duration)
2859 {
2860 struct termios_list *index;
2861 COMSTAT Stat;
2862
2863 ENTER("tcsendbreak");
2864
2865 index = find_port(fd);
2866
2867 if (!index)
2868 {
2869 LEAVE("tcdrain");
2870 return -1;
2871 }
2872
2873 if (duration <= 0) { duration = 1; }
2874
2875 if (!SetCommBreak(index->hComm))
2876 {
2877 ClearErrors(index, &Stat);
2878 }
2879
2880 /* 0.25 seconds == 250000 usec */
2881 hl_usleep(duration * 250000);
2882
2883 if (!ClearCommBreak(index->hComm))
2884 {
2885 ClearErrors(index, &Stat);
2886 }
2887
2888 LEAVE("tcsendbreak");
2889 return 1;
2890 }
2891
2892 /*----------------------------------------------------------
2893 tcdrain()
2894
2895 accept: file descriptor
2896 perform: wait for output to be written.
2897 return: 0 on success, -1 otherwise
2898 exceptions: None
2899 win32api: FlushFileBuffers
2900 comments:
2901 ----------------------------------------------------------*/
2902
tcdrain(int fd)2903 int tcdrain(int fd)
2904 {
2905 struct termios_list *index;
2906 char message[80];
2907 int old_flag;
2908
2909 ENTER("tcdrain");
2910 index = find_port(fd);
2911
2912 if (!index)
2913 {
2914 LEAVE("tcdrain");
2915 return -1;
2916 }
2917
2918 old_flag = index->event_flag;
2919
2920 /*
2921 index->event_flag &= ~EV_TXEMPTY;
2922 SetCommMask( index->hComm, index->event_flag );
2923 index->tx_happened = 1;
2924 */
2925 if (!FlushFileBuffers(index->hComm))
2926 {
2927 /* FIXME Need to figure out what the various errors are in
2928 windows. YACK() should report them and we can
2929 handle them as we find them
2930
2931
2932 Something funky is happening on NT. GetLastError =
2933 0.
2934 */
2935 sprintf(message, "FlushFileBuffers() %i\n",
2936 (int) GetLastError());
2937 report(message);
2938
2939 if (GetLastError() == 0)
2940 {
2941 set_errno(0);
2942 return (0);
2943 }
2944
2945 set_errno(EAGAIN);
2946 YACK();
2947 LEAVE("tcdrain");
2948 return -1;
2949 }
2950
2951 /*
2952 sprintf( message, "FlushFileBuffers() %i\n",
2953 (int) GetLastError() );
2954 report( message );
2955 */
2956 LEAVE("tcdrain success");
2957 index->event_flag |= EV_TXEMPTY;
2958 SetCommMask(index->hComm, index->event_flag);
2959 index->event_flag = old_flag;
2960 /*
2961 index->tx_happened = 1;
2962 */
2963 return 0;
2964 }
2965
2966 /*----------------------------------------------------------
2967 tcflush()
2968
2969 accept: file descriptor, queue_selector
2970 perform: discard data not transmitted or read
2971 TCIFLUSH: flush data not read
2972 TCOFLUSH: flush data not transmitted
2973 TCIOFLUSH: flush both
2974 return: 0 on success, -1 on error
2975 exceptions: none
2976 win32api: PurgeComm
2977 comments:
2978 ----------------------------------------------------------*/
2979
tcflush(int fd,int queue_selector)2980 int tcflush(int fd, int queue_selector)
2981 {
2982 struct termios_list *index;
2983 int old_flag;
2984
2985 ENTER("tcflush");
2986
2987 index = find_port(fd);
2988
2989 if (!index)
2990 {
2991 LEAVE("tclflush");
2992 return (-1);
2993 }
2994
2995 old_flag = index->event_flag;
2996 /*
2997 index->event_flag &= ~EV_TXEMPTY;
2998 SetCommMask( index->hComm, index->event_flag );
2999 index->tx_happened = 1;
3000 */
3001
3002 index->tx_happened = 1;
3003
3004 switch (queue_selector)
3005 {
3006 case TCIFLUSH:
3007 if (!PurgeComm(index->hComm, PURGE_RXABORT | PURGE_RXCLEAR))
3008 {
3009 goto fail;
3010 }
3011
3012 break;
3013
3014 case TCOFLUSH:
3015 if (!PurgeComm(index->hComm, PURGE_TXABORT | PURGE_TXCLEAR))
3016 {
3017 goto fail;
3018 }
3019
3020 break;
3021
3022 case TCIOFLUSH:
3023 if (!PurgeComm(index->hComm, PURGE_TXABORT | PURGE_TXCLEAR))
3024 {
3025 goto fail;
3026 }
3027
3028 if (!PurgeComm(index->hComm, PURGE_RXABORT | PURGE_RXCLEAR))
3029 {
3030 goto fail;
3031 }
3032
3033 break;
3034
3035 default:
3036 /*
3037 set_errno( ENOTSUP );
3038 */
3039 report("tcflush: Unknown queue_selector\n");
3040 LEAVE("tcflush");
3041 return -1;
3042 }
3043
3044 index->event_flag |= EV_TXEMPTY;
3045 SetCommMask(index->hComm, index->event_flag);
3046 index->event_flag = old_flag;
3047 index->tx_happened = 1;
3048 LEAVE("tcflush");
3049 return (0);
3050
3051 /* FIXME Need to figure out what the various errors are in
3052 windows. YACK() should report them and we can
3053 handle them as we find them
3054 */
3055
3056 fail:
3057 LEAVE("tcflush");
3058 set_errno(EAGAIN);
3059 YACK();
3060 return -1;
3061
3062 }
3063
3064 /*----------------------------------------------------------
3065 tcflow()
3066
3067 accept:
3068 perform:
3069 return:
3070 exceptions:
3071 win32api: None
3072 comments: FIXME
3073 ----------------------------------------------------------*/
3074
tcflow(int fd,int action)3075 int tcflow(int fd, int action)
3076 {
3077 ENTER("tcflow");
3078
3079 switch (action)
3080 {
3081 /* Suspend transmission of output */
3082 case TCOOFF: break;
3083
3084 /* Restart transmission of output */
3085 case TCOON: break;
3086
3087 /* Transmit a STOP character */
3088 case TCIOFF: break;
3089
3090 /* Transmit a START character */
3091 case TCION: break;
3092
3093 default: return -1;
3094 }
3095
3096 LEAVE("tcflow");
3097 return 1;
3098 }
3099 /*----------------------------------------------------------
3100 fstat()
3101
3102 accept:
3103 perform:
3104 return:
3105 exceptions:
3106 win32api:
3107 comments: this is just to keep the eventLoop happy.
3108 ----------------------------------------------------------*/
3109
3110 #if 0
3111 int fstat(int fd, ...)
3112 {
3113 return (0);
3114 }
3115 #endif
3116
3117 /*----------------------------------------------------------
3118 ioctl()
3119
3120 accept:
3121 perform:
3122 return:
3123 exceptions:
3124 win32api: GetCommError(), GetCommModemStatus, EscapeCommFunction()
3125 comments: FIXME
3126 the DCB struct is:
3127
3128 typedef struct _DCB
3129 {
3130 unsigned long DCBlength, BaudRate, fBinary:1, fParity:1;
3131 unsigned long fOutxCtsFlow:1, fOutxDsrFlow:1, fDtrControl:2;
3132 unsigned long fDsrSensitivity:1, fTXContinueOnXoff:1;
3133 unsigned long fOutX:1, fInX:1, fErrorChar:1, fNull:1;
3134 unsigned long fRtsControl:2, fAbortOnError:1, fDummy2:17;
3135 WORD wReserved, XonLim, XoffLim;
3136 BYTE ByteSize, Parity, StopBits;
3137 char XonChar, XoffChar, ErrorChar, EofChar, EvtChar;
3138 WORD wReserved1;
3139 } DCB;
3140
3141 ----------------------------------------------------------*/
3142
win32_serial_ioctl(int fd,int request,...)3143 int win32_serial_ioctl(int fd, int request, ...)
3144 {
3145 unsigned long dwStatus = 0;
3146 va_list ap;
3147 int *arg, ret, old_flag;
3148 char message[80];
3149
3150 #ifdef TIOCGSERIAL
3151 DCB *dcb;
3152 struct serial_struct *sstruct;
3153 #endif /* TIOCGSERIAL */
3154 COMSTAT Stat;
3155
3156 struct termios_list *index;
3157 #ifdef TIOCGICOUNT
3158 struct serial_icounter_struct *sistruct;
3159 #endif /* TIOCGICOUNT */
3160
3161 ENTER("ioctl");
3162
3163 if (fd <= 0)
3164 {
3165 return 0;
3166 }
3167
3168 index = find_port(fd);
3169
3170 if (!index)
3171 {
3172 LEAVE("ioctl");
3173 return -1;
3174 }
3175
3176 va_start(ap, request);
3177
3178 ret = ClearErrors(index, &Stat);
3179
3180 if (ret == 0)
3181 {
3182 set_errno(EBADFD);
3183 YACK();
3184 report("ClearError Failed! ernno EBADFD");
3185 arg = va_arg(ap, int *);
3186 va_end(ap);
3187 return -1;
3188 }
3189
3190 switch (request)
3191 {
3192 case TCSBRK:
3193 arg = va_arg(ap, int *);
3194 va_end(ap);
3195 return -ENOIOCTLCMD;
3196
3197 case TCSBRKP:
3198 arg = va_arg(ap, int *);
3199 va_end(ap);
3200 return -ENOIOCTLCMD;
3201
3202 case TIOCGSOFTCAR:
3203 arg = va_arg(ap, int *);
3204 va_end(ap);
3205 return -ENOIOCTLCMD;
3206
3207 case TIOCSSOFTCAR:
3208 arg = va_arg(ap, int *);
3209 va_end(ap);
3210 return -ENOIOCTLCMD;
3211
3212 case TIOCCBRK:
3213 case TIOCSBRK:
3214 arg = va_arg(ap, int *);
3215
3216 if (EscapeCommFunction(index->hComm,
3217 (request == TIOCSBRK) ? SETBREAK :
3218 CLRBREAK))
3219 {
3220 report("EscapeCommFunction: True\n");
3221 }
3222 else
3223 {
3224 report("EscapeCommFunction: False\n");
3225 }
3226
3227 break;
3228
3229 case TIOCMGET:
3230 arg = va_arg(ap, int *);
3231
3232 /* DORITOS */
3233 if (!GetCommModemStatus(index->hComm, &dwStatus))
3234 {
3235 report_error("GetCommMOdemStatus failed!\n");
3236 }
3237
3238 if (dwStatus & MS_RLSD_ON) { *arg |= TIOCM_CAR; }
3239 else { *arg &= ~TIOCM_CAR; }
3240
3241 if (dwStatus & MS_RING_ON) { *arg |= TIOCM_RNG; }
3242 else { *arg &= ~TIOCM_RNG; }
3243
3244 if (dwStatus & MS_DSR_ON) { *arg |= TIOCM_DSR; }
3245 else { *arg &= ~TIOCM_DSR; }
3246
3247 if (dwStatus & MS_CTS_ON) { *arg |= TIOCM_CTS; }
3248 else { *arg &= ~TIOCM_CTS; }
3249
3250 /* I'm not seeing a way to read the MSR directly
3251 we store the state using TIOCM_*
3252
3253 Trent
3254 */
3255 if (index->MSR & TIOCM_DTR)
3256 {
3257 *arg |= TIOCM_DTR;
3258 }
3259 else { *arg &= ~TIOCM_DTR; }
3260
3261 if (index->MSR & TIOCM_RTS)
3262 {
3263 *arg |= TIOCM_RTS;
3264 }
3265 else { *arg &= ~TIOCM_RTS; }
3266
3267 /*
3268
3269 TIOCM_LE
3270 TIOCM_ST
3271 TIOCM_SR
3272 */
3273 va_end(ap);
3274 return (0);
3275
3276 case TIOCMBIS:
3277 arg = va_arg(ap, int *);
3278
3279 if (*arg & TIOCM_DTR)
3280 {
3281 index->MSR |= TIOCM_DTR;
3282
3283 if (EscapeCommFunction(index->hComm, SETDTR))
3284 {
3285 report("EscapeCommFunction: True\n");
3286 }
3287 else
3288 {
3289 report("EscapeCommFunction: False\n");
3290 }
3291 }
3292
3293 if (*arg & TIOCM_RTS)
3294 {
3295 index->MSR |= TIOCM_RTS;
3296
3297 if (EscapeCommFunction(index->hComm, SETRTS))
3298 {
3299 report("EscapeCommFunction: True\n");
3300 }
3301 else
3302 {
3303 report("EscapeCommFunction: False\n");
3304 }
3305 }
3306
3307 break;
3308
3309 case TIOCMBIC:
3310 arg = va_arg(ap, int *);
3311
3312 if (*arg & TIOCM_DTR)
3313 {
3314 index->MSR &= ~TIOCM_DTR;
3315
3316 if (EscapeCommFunction(index->hComm, CLRDTR))
3317 {
3318 report("EscapeCommFunction: True\n");
3319 }
3320 else
3321 {
3322 report("EscapeCommFunction: False\n");
3323 }
3324 }
3325
3326 if (*arg & TIOCM_RTS)
3327 {
3328 index->MSR &= ~TIOCM_RTS;
3329
3330 if (EscapeCommFunction(index->hComm, CLRRTS))
3331 {
3332 report("EscapeCommFunction: True\n");
3333 }
3334 else
3335 {
3336 report("EscapeCommFunction: False\n");
3337 }
3338 }
3339
3340 break;
3341
3342 case TIOCMSET:
3343 arg = va_arg(ap, int *);
3344
3345 if ((*arg & TIOCM_DTR) == (index->MSR & TIOCM_DTR))
3346 {
3347 report("DTR is unchanged\n");
3348 }
3349
3350 sprintf(message, "DTR %i %i\n", *arg & TIOCM_DTR, index->MSR & TIOCM_DTR);
3351 report(message);
3352
3353 if (*arg & TIOCM_DTR)
3354 {
3355 index->MSR |= TIOCM_DTR;
3356 }
3357 else
3358 {
3359 index->MSR &= ~TIOCM_DTR;
3360 }
3361
3362 if (EscapeCommFunction(index->hComm,
3363 (*arg & TIOCM_DTR) ? SETDTR :
3364 CLRDTR))
3365 {
3366 report("EscapeCommFunction: True\n");
3367 }
3368 else
3369 {
3370 report("EscapeCommFunction: False\n");
3371 }
3372
3373 if ((*arg & TIOCM_RTS) == (index->MSR & TIOCM_RTS))
3374 {
3375 report("RTS is unchanged\n");
3376 }
3377
3378 sprintf(message, "RTS %i %i\n", *arg & TIOCM_RTS, index->MSR & TIOCM_RTS);
3379 report(message);
3380
3381 if (*arg & TIOCM_RTS)
3382 {
3383 index->MSR |= TIOCM_RTS;
3384 }
3385 else
3386 {
3387 index->MSR &= ~TIOCM_RTS;
3388 }
3389
3390 if (EscapeCommFunction(index->hComm,
3391 (*arg & TIOCM_RTS) ? SETRTS : CLRRTS))
3392 {
3393 report("EscapeCommFunction: True\n");
3394 }
3395 else
3396 {
3397 report("EscapeCommFunction: False\n");
3398 }
3399
3400 break;
3401
3402 #ifdef TIOCGSERIAL
3403
3404 case TIOCGSERIAL:
3405 report("TIOCGSERIAL\n");
3406
3407 dcb = malloc(sizeof(DCB));
3408
3409 if (!dcb)
3410 {
3411 va_end(ap);
3412 return -1;
3413 }
3414
3415 memset(dcb, 0, sizeof(DCB));
3416 GetCommState(index->hComm, dcb);
3417
3418 sstruct = va_arg(ap, struct serial_struct *);
3419
3420 if (DCB_to_serial_struct(dcb, sstruct) < 0)
3421 {
3422 va_end(ap);
3423 return -1;
3424 }
3425
3426 index->sstruct = sstruct;
3427
3428 report("TIOCGSERIAL\n");
3429 free(dcb);
3430 break;
3431
3432 #endif /* TIOCGSERIAL */
3433 #ifdef TIOCSSERIAL
3434
3435 case TIOCSSERIAL:
3436 report("TIOCSSERIAL\n");
3437
3438 dcb = malloc(sizeof(DCB));
3439
3440 if (!dcb)
3441 {
3442 va_end(ap);
3443 return -1;
3444 }
3445
3446 memset(dcb, 0, sizeof(DCB));
3447 GetCommState(index->hComm, dcb);
3448
3449 index->sstruct = va_arg(ap, struct serial_struct *);
3450
3451 if (serial_struct_to_DCB(index->sstruct, dcb) < 0)
3452 {
3453 va_end(ap);
3454 return -1;
3455 }
3456
3457 report("TIOCSSERIAL\n");
3458 free(dcb);
3459 break;
3460
3461 #endif /* TIOCSSERIAL */
3462
3463 case TIOCSERCONFIG:
3464 case TIOCSERGETLSR:
3465 arg = va_arg(ap, int *);
3466 /*
3467 do {
3468 wait = WaitForSingleObject( index->sol.hEvent, 5000 );
3469 } while ( wait == WAIT_TIMEOUT );
3470 */
3471 ret = ClearErrors(index, &Stat);
3472
3473 if (ret == 0)
3474 {
3475 /* FIXME ? */
3476 set_errno(EBADFD);
3477 YACK();
3478 report("TIOCSERGETLSR EBADFD");
3479 va_end(ap);
3480 return -1;
3481 }
3482
3483 if ((int) Stat.cbOutQue == 0)
3484 {
3485 /* output is empty */
3486 if (index->tx_happened == 1)
3487 {
3488 old_flag = index->event_flag;
3489 index->event_flag &= ~EV_TXEMPTY;
3490 SetCommMask(index->hComm,
3491 index->event_flag);
3492 index->event_flag = old_flag;
3493 *arg = 1;
3494 index->tx_happened = 0;
3495 report("ioctl: output empty\n");
3496 }
3497 else
3498 {
3499 *arg = 0;
3500 }
3501
3502 ret = 0;
3503 }
3504 else
3505 {
3506 /* still data out there */
3507 *arg = 0;
3508 ret = 0;
3509 }
3510
3511 va_end(ap);
3512 return (0);
3513 break;
3514
3515 case TIOCSERGSTRUCT:
3516 case TIOCSERGETMULTI:
3517 case TIOCSERSETMULTI:
3518 va_end(ap);
3519 return -ENOIOCTLCMD;
3520
3521 case TIOCMIWAIT:
3522 arg = va_arg(ap, int *);
3523 va_end(ap);
3524 return -ENOIOCTLCMD;
3525 /*
3526 On linux this fills a struct with all the line info
3527 (data available, bytes sent, ...
3528 */
3529 #ifdef TIOCGICOUNT
3530
3531 case TIOCGICOUNT:
3532 sistruct = va_arg(ap, struct serial_icounter_struct *);
3533 ret = ClearErrors(index, &Stat);
3534
3535 if (ret == 0)
3536 {
3537 /* FIXME ? */
3538 report("TIOCGICOUNT failed\n");
3539 set_errno(EBADFD);
3540 va_end(ap);
3541 return -1;
3542 }
3543
3544 sistruct->frame = index->sis->frame;
3545 sistruct->overrun = index->sis->overrun;
3546 sistruct->parity = index->sis->parity;
3547 sistruct->brk = index->sis->brk;
3548
3549 va_end(ap);
3550 return 0;
3551 /* abolete ioctls */
3552 #endif /* TIOCGICOUNT */
3553
3554 case TIOCSERGWILD:
3555 case TIOCSERSWILD:
3556 report("TIOCSER[GS]WILD absolete\n");
3557 va_end(ap);
3558 return 0;
3559
3560 /* number of bytes available for reading */
3561 case FIONREAD:
3562 arg = va_arg(ap, int *);
3563 ret = ClearErrors(index, &Stat);
3564
3565 if (ret == 0)
3566 {
3567 /* FIXME ? */
3568 report("FIONREAD failed\n");
3569 set_errno(EBADFD);
3570 va_end(ap);
3571 return -1;
3572 }
3573
3574 *arg = (int) Stat.cbInQue;
3575 #ifdef DEBUG_VERBOSE
3576 sprintf(message, "FIONREAD: %i bytes available\n",
3577 (int) Stat.cbInQue);
3578 report(message);
3579
3580 if (*arg)
3581 {
3582 sprintf(message, "FIONREAD: %i\n", *arg);
3583 report(message);
3584 }
3585
3586 #endif /* DEBUG_VERBOSE */
3587 ret = 0;
3588 break;
3589
3590 /* pending bytes to be sent */
3591 case TIOCOUTQ:
3592 arg = va_arg(ap, int *);
3593 va_end(ap);
3594 return -ENOIOCTLCMD;
3595
3596 default:
3597 sprintf(message,
3598 "FIXME: ioctl: unknown request: %#x\n",
3599 request);
3600 report(message);
3601 va_end(ap);
3602 return -ENOIOCTLCMD;
3603 }
3604
3605 va_end(ap);
3606 LEAVE("ioctl");
3607 return 0;
3608 }
3609
3610 /*----------------------------------------------------------
3611 fcntl()
3612
3613 accept:
3614 perform:
3615 return:
3616 exceptions:
3617 win32api: None
3618 comments: FIXME
3619 ----------------------------------------------------------*/
3620
win32_serial_fcntl(int fd,int command,...)3621 int win32_serial_fcntl(int fd, int command, ...)
3622 {
3623 int arg, ret = 0;
3624 va_list ap;
3625 struct termios_list *index;
3626 char message[80];
3627
3628 ENTER("fcntl");
3629
3630 if (fd <= 0)
3631 {
3632 return 0;
3633 }
3634
3635 index = find_port(fd);
3636
3637 if (!index)
3638 {
3639 LEAVE("fcntl");
3640 return -1;
3641 }
3642
3643 va_start(ap, command);
3644
3645 arg = va_arg(ap, int);
3646
3647 switch (command)
3648 {
3649 case F_SETOWN: /* set ownership of fd */
3650 break;
3651
3652 case F_SETFL: /* set operating flags */
3653 #ifdef DEBUG
3654 sprintf(message, "F_SETFL fd=%d flags=%d\n", fd, arg);
3655 report(message);
3656 #endif
3657 index->open_flags = arg;
3658 break;
3659
3660 case F_GETFL: /* get operating flags */
3661 ret = index->open_flags;
3662 break;
3663
3664 default:
3665 sprintf(message, "unknown fcntl command %#x\n", command);
3666 report(message);
3667 break;
3668 }
3669
3670 va_end(ap);
3671 LEAVE("fcntl");
3672 return ret;
3673 }
3674
3675 #if 0
3676 /*----------------------------------------------------------
3677 termios_interrupt_event_loop()
3678
3679 accept:
3680 perform:
3681 return: let Serial_select break out so the thread can die
3682 exceptions:
3683 win32api:
3684 comments:
3685 ----------------------------------------------------------*/
3686 static void termios_interrupt_event_loop(int fd, int flag)
3687 {
3688 struct termios_list *index = find_port(fd);
3689
3690 if (!index)
3691 {
3692 LEAVE("termios_interrupt_event_loop");
3693 return;
3694 }
3695
3696 /*
3697 index->event_flag = 0;
3698 TRENT SetCommMask( index->hComm, index->event_flag );
3699 hl_usleep(2000);
3700 tcdrain( index->fd );
3701 SetEvent( index->sol.hEvent );
3702 */
3703 index->interrupt = flag;
3704 return;
3705 }
3706 #endif
3707
3708 /*----------------------------------------------------------
3709 Serial_select()
3710
3711 accept:
3712 perform:
3713 return: number of fd's changed on success or -1 on error.
3714 exceptions:
3715 win32api: SetCommMask(), GetCommEvent(), WaitSingleObject()
3716 comments:
3717 ----------------------------------------------------------*/
3718 #ifndef __LCC__
win32_serial_select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)3719 int win32_serial_select(int n, fd_set *readfds, fd_set *writefds,
3720 fd_set *exceptfds, struct timeval *timeout)
3721 {
3722
3723 unsigned long dwCommEvent, wait = WAIT_TIMEOUT;
3724 int fd = n - 1;
3725 struct termios_list *index;
3726 char message[80];
3727 COMSTAT Stat;
3728 int ret;
3729
3730 ENTER("serial_select");
3731
3732 if (fd <= 0)
3733 {
3734 /* Baby did a bad baad thing */
3735 goto fail;
3736 }
3737
3738 index = find_port(fd);
3739
3740 if (!index)
3741 {
3742 goto fail;
3743 }
3744
3745 #define DATA_AVAILABLE 1
3746
3747 //nativeSetEventFlag( fd, SerialPortEvent.DATA_AVAILABLE, enable );
3748 if (readfds)
3749 {
3750 int eventflags[12];
3751 memset(eventflags, 0, sizeof(eventflags));
3752
3753 eventflags[DATA_AVAILABLE] = 1;
3754 termios_setflags(fd, eventflags);
3755 }
3756
3757 if (!index->event_flag)
3758 {
3759 /* still setting up the port? hold off for a Sec so
3760 things can fire up
3761
3762 this does happen. loops ~twice on a 350 Mzh with
3763 hl_usleep(1000000)
3764 */
3765 /* hl_usleep(10000); */
3766 LEAVE("serial_uselect");
3767 return (0);
3768 }
3769
3770 ResetEvent(index->wol.hEvent);
3771 ResetEvent(index->sol.hEvent);
3772 ResetEvent(index->rol.hEvent);
3773 ret = ClearErrors(index, &Stat);
3774 #if 1
3775
3776 if (ret == 0)
3777 {
3778 goto fail;
3779 }
3780
3781 /* look only after read */
3782 if (readfds && !writefds && !exceptfds)
3783 {
3784 int timeout_usec = timeout ? timeout->tv_sec * 1000000 + timeout->tv_usec :
3785 INT_MAX;
3786
3787 while (timeout_usec > 0)
3788 {
3789 sprintf(message, "wait for data in read buffer%d\n", (int)Stat.cbInQue);
3790 report(message);
3791
3792 if (Stat.cbInQue != 0)
3793 {
3794 goto end;
3795 }
3796
3797 hl_usleep(10000);
3798 /* FIXME: not very accurate wrt process time */
3799 timeout_usec -= 10000;
3800
3801 report("sleep...\n");
3802
3803 ret = ClearErrors(index, &Stat);
3804
3805 if (ret == 0)
3806 {
3807 goto fail;
3808 }
3809 }
3810
3811 goto timeout;
3812 }
3813
3814 #endif
3815
3816 while (wait == WAIT_TIMEOUT && index->sol.hEvent)
3817 {
3818 if (index->interrupt == 1)
3819 {
3820 goto fail;
3821 }
3822
3823 SetCommMask(index->hComm, index->event_flag);
3824 ClearErrors(index, &Stat);
3825
3826 if (!WaitCommEvent(index->hComm, &dwCommEvent,
3827 &index->rol))
3828 {
3829 /* WaitCommEvent failed probably overlapped though */
3830 if (GetLastError() != ERROR_IO_PENDING)
3831 {
3832 ClearErrors(index, &Stat);
3833 goto fail;
3834 }
3835
3836 /* thought so... */
3837 }
3838
3839 /* could use the select timeout here but it should not
3840 be needed
3841 */
3842 ClearErrors(index, &Stat);
3843 wait = WaitForSingleObject(index->rol.hEvent, 100);
3844
3845 switch (wait)
3846 {
3847 case WAIT_OBJECT_0:
3848 goto end;
3849
3850 case WAIT_TIMEOUT:
3851 goto timeout;
3852
3853 case WAIT_ABANDONED:
3854 default:
3855 goto fail;
3856
3857 }
3858 }
3859
3860 end:
3861 /* You may want to chop this out for lower latency */
3862 /* hl_usleep(1000); */
3863 LEAVE("serial_select");
3864 return (1);
3865 timeout:
3866 LEAVE("serial_select");
3867 return (0);
3868 fail:
3869 YACK();
3870 sprintf(message, "< select called error %i\n", n);
3871 report(message);
3872 errno = EBADFD;
3873 LEAVE("serial_select");
3874 return (-1);
3875 }
3876 #ifdef asdf
win32_serial_select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout)3877 int win32_serial_select(int n, fd_set *readfds, fd_set *writefds,
3878 fd_set *exceptfds, struct timeval *timeout)
3879 {
3880
3881 unsigned long nBytes, dwCommEvent, wait = WAIT_TIMEOUT;
3882 int fd = n - 1;
3883 struct termios_list *index;
3884 char message[80];
3885
3886 ENTER("serial_select");
3887
3888 if (fd <= 0)
3889 {
3890 /* hl_usleep(1000); */
3891 return 1;
3892 }
3893
3894 index = find_port(fd);
3895
3896 if (!index)
3897 {
3898 LEAVE("serial_select");
3899 return -1;
3900 }
3901
3902 if (index->interrupt == 1)
3903 {
3904 goto end;
3905 }
3906
3907 while (!index->event_flag)
3908 {
3909 /* hl_usleep(1000); */
3910 return -1;
3911 }
3912
3913 while (wait == WAIT_TIMEOUT && index->sol.hEvent)
3914 {
3915 if (index->interrupt == 1)
3916 {
3917 goto end;
3918 }
3919
3920 if (!index->sol.hEvent)
3921 {
3922 return 1;
3923 }
3924
3925 if (!WaitCommEvent(index->hComm, &dwCommEvent,
3926 &index->sol))
3927 {
3928 /* WaitCommEvent failed */
3929 if (index->interrupt == 1)
3930 {
3931 goto end;
3932 }
3933
3934 if (GetLastError() != ERROR_IO_PENDING)
3935 {
3936 sprintf(message, "WaitCommEvent filename = %s\n", index->filename);
3937 report(message);
3938 return (1);
3939 /*
3940 goto fail;
3941 */
3942 }
3943
3944 return (1);
3945 }
3946
3947 if (index->interrupt == 1)
3948 {
3949 goto end;
3950 }
3951
3952 wait = WaitForSingleObject(index->sol.hEvent, 1000);
3953
3954 switch (wait)
3955 {
3956 case WAIT_OBJECT_0:
3957 if (index->interrupt == 1)
3958 {
3959 goto end;
3960 }
3961
3962 if (!index->sol.hEvent) { return (1); }
3963
3964 if (!GetOverlappedResult(index->hComm,
3965 &index->sol, &nBytes, TRUE))
3966 {
3967 goto end;
3968 }
3969 else if (index->tx_happened == 1)
3970 {
3971 goto end;
3972 }
3973 else
3974 {
3975 goto end;
3976 }
3977
3978 break;
3979
3980 case WAIT_TIMEOUT:
3981 default:
3982 return (1); /* WaitFor error */
3983
3984 }
3985 }
3986
3987 end:
3988 /*
3989 hl_usleep(1000);
3990 */
3991 LEAVE("serial_select");
3992 return (1);
3993 #ifdef asdf
3994 /* FIXME this needs to be cleaned up... */
3995 fail:
3996 sprintf(message, "< select called error %i\n", n);
3997 YACK();
3998 report(message);
3999 set_errno(EBADFD);
4000 LEAVE("serial_select");
4001 return (1);
4002 #endif /* asdf */
4003
4004 }
4005 #endif /* asdf */
4006 #endif /* __LCC__ */
4007
4008 #if 0
4009 /*----------------------------------------------------------
4010 termiosSetParityError()
4011
4012 accept: fd The device opened
4013 perform: Get the Parity Error Char
4014 return: the Parity Error Char
4015 exceptions: none
4016 win32api: GetCommState()
4017 comments: No idea how to do this in Unix (handle in read?)
4018 ----------------------------------------------------------*/
4019
4020 static int termiosGetParityErrorChar(int fd)
4021 {
4022 struct termios_list *index;
4023 DCB dcb;
4024
4025 ENTER("termiosGetParityErrorChar");
4026 index = find_port(fd);
4027
4028 if (!index)
4029 {
4030 LEAVE("termiosGetParityErrorChar");
4031 return (-1);
4032 }
4033
4034 GetCommState(index->hComm, &dcb);
4035 LEAVE("termiosGetParityErrorChar");
4036 return (dcb.ErrorChar);
4037 }
4038
4039 /*----------------------------------------------------------
4040 termiosSetParityError()
4041
4042 accept: fd The device opened, value the new Parity Error Char
4043 perform: Set the Parity Error Char
4044 return: void
4045 exceptions: none
4046 win32api: GetCommState(), SetCommState()
4047 comments: No idea how to do this in Unix (handle in read?)
4048 ----------------------------------------------------------*/
4049
4050 static void termiosSetParityError(int fd, char value)
4051 {
4052 DCB dcb;
4053 struct termios_list *index;
4054
4055 ENTER("termiosSetParityErrorChar");
4056 index = find_port(fd);
4057
4058 if (!index)
4059 {
4060 LEAVE("termiosSetParityError");
4061 return;
4062 }
4063
4064 GetCommState(index->hComm, &dcb);
4065 dcb.ErrorChar = value;
4066 SetCommState(index->hComm, &dcb);
4067 LEAVE("termiosSetParityErrorChar");
4068 }
4069 #endif
4070
4071 /*----------------------- END OF LIBRARY -----------------*/
4072
4073 #endif /* WIN32 */
4074