2 * Simulator of microcontrollers (fwio.cc)
4 * Copyright (C) 1997 Drotos Daniel
6 * To contact author send email to dr.dkdb@gmail.com
10 /* This file is part of microcontroller simulator: ucsim.
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
28 // Need to define _WIN32_WINNT as 0x500 or higher for GetConsoleWindow()
29 // _WIN32_WINNT will be indirectly defined from WINVER
38 # include HEADER_SOCKET
48 #ifdef HAVE_WINSOCK2_H
62 void deb(const char *format
, ...)
67 dd= cp_io(stdout,"w");
72 //dd->vprintf(format, ap);
81 static bool is_initialized
= false;
88 int iResult
= WSAStartup(MAKEWORD(2,2), &wsaData
);
91 fprintf(stderr
, "WSAStartup failed: %d\n", iResult
);
94 //fprintf(stderr, "WSAStartup called\n");
95 is_initialized
= true;
99 cl_io::cl_io(): cl_f()
104 cl_io::cl_io(chars fn
, chars mode
): cl_f(fn
, mode
)
108 cl_io::cl_io(int the_server_port
): cl_f(the_server_port
)
116 if (/*file_f*/file_id
>=0)
126 cl_io::determine_type()
128 DWORD _file_type
= GetFileType(handle
);
130 deb("wio determine type fid=%d\n", file_id
);
135 DWORD err
, NumPending
;
138 if ((err
= GetNumberOfConsoleInputEvents(handle
, &NumPending
)) == 0)
140 deb("wio file_id=%d (handle=%p) type=console1\n", file_id
, handle
);
144 deb("wio file_id=%d (handle=%p) cons_det1 err=%d\n", file_id
, handle
, (int)err
);
145 if (GetConsoleWindow() != NULL
)
147 deb("wio file_id=%d (handle=%p) type=console2\n", file_id
, handle
);
151 deb("wio file_id=%d (handle=%p) cons_det2 NULL\n", file_id
, handle
);
152 if (!ClearCommError(handle
, &err
, NULL
))
154 switch (GetLastError())
156 case ERROR_INVALID_HANDLE
:
157 deb("wio file_id=%d (handle=%p) type=console3\n", file_id
, handle
);
160 case ERROR_INVALID_FUNCTION
:
162 * In case of NUL device return type F_FILE.
163 * Is this the correct way to test it?
165 deb("wio file_id=%d (handle=%p) type=file\n", file_id
, handle
);
170 deb("wio file_id=%d (handle=%p) type=unknown\n", file_id
, handle
);
175 deb("wio file_id=%d (handle=%p) type=serial\n", file_id
, handle
);
179 deb("wio file_id=%d (handle=%p) type=file2\n", file_id
, handle
);
185 int optlen
= sizeof(sockbuf
);
188 i
= getsockopt((SOCKET
)handle
, SOL_SOCKET
, SO_TYPE
, sockbuf
, &optlen
);
189 int e
= WSAGetLastError();
190 deb("Checking if fid=%d handle=%p is a socket, i=%d e=%d\n", file_id
, handle
, i
, e
);
194 deb("wio file_id=%d (handle=%p) type=socket\n", file_id
, handle
);
199 deb("wio file_id=%d (handle=%p) type=pipe\n", file_id
, handle
);
204 cl_io::check_dev(void)
206 //e_handle_type type= F_UNKNOWN;
207 //if (F_UNKNOWN == type)
208 //type = get_handle_type();
215 struct timeval tv
= {0, 0};
217 //assert(INVALID_HANDLE_VALUE != handle);
221 FD_SET((SOCKET
)handle
, &s
);
223 int ret
= select(0, &s
, NULL
, NULL
, &tv
);
224 if (SOCKET_ERROR
== ret
)
226 fprintf(stderr
, "Can't select: %d fid=%d handle=%p type=%d\n",
227 WSAGetLastError(), file_id
, handle
, type
);
230 if (type
== F_LISTENER
)
233 if ((ret
!= SOCKET_ERROR
) &&
238 return last_used
!= first_free
;
244 return last_used
!= first_free
;
248 INPUT_RECORD
*pIRBuf
;
252 bool ret
= last_used
!= first_free
;
254 * Peek all pending console events
256 //printf("win input check on console id=%d handle=%p\n", file_id, handle);
257 if (INVALID_HANDLE_VALUE
== handle
)
259 if (!GetNumberOfConsoleInputEvents(handle
, &NumPending
))
263 if (NULL
== (pIRBuf
= (PINPUT_RECORD
)/*_*/malloc
/*a*/(NumPending
* sizeof(INPUT_RECORD
))))
266 if (ReadConsoleInput(handle
, pIRBuf
, NumPending
, &NumPeeked
) == 0)
267 return free(pIRBuf
), ret
;
269 return free(pIRBuf
), ret
;
270 if (NumPeeked
> NumPending
)
271 return free(pIRBuf
), ret
;
274 * Scan all of the peeked events to determine if any is a key event
275 * which should be recognized.
278 for (p
= pIRBuf
; NumPeeked
> 0 ; NumPeeked
--, p
++ )
280 if (KEY_EVENT
== p
->EventType
&&
281 p
->Event
.KeyEvent
.bKeyDown
)
283 int vk
= p
->Event
.KeyEvent
.wVirtualKeyCode
;
284 char c
= p
->Event
.KeyEvent
.uChar
.AsciiChar
;
285 unsigned long int ctrl
= p
->Event
.KeyEvent
.dwControlKeyState
;
287 if (vk
== VK_BACK
) pick(8);
288 else if (vk
== VK_TAB
) pick(9);
289 else if (vk
== VK_RETURN
) pick('\n');
290 else if (vk
== VK_ESCAPE
) pick(0x1b);
291 else if (vk
== VK_SPACE
) pick(' ');
292 else if (vk
== VK_PRIOR
) pick("\033[5~");
293 else if (vk
== VK_NEXT
) pick("\033[6~");
294 else if (vk
== VK_END
) pick("\033[4~");
295 else if (vk
== VK_HOME
) pick("\033[1~");
296 else if (vk
== VK_LEFT
) pick("\033[D");
297 else if (vk
== VK_RIGHT
) pick("\033[C");
298 else if (vk
== VK_UP
) pick("\033[A");
299 else if (vk
== VK_DOWN
) pick("\033[B");
300 else if (vk
== VK_INSERT
) pick("\033[2~");
301 else if (vk
== VK_DELETE
) pick("\033[3~");
302 else if ((vk
>= 0x30) &&
303 (vk
<= 0x39)) pick(c
);
304 else if ((vk
>= 0x41) &&
305 (vk
<= 0x5a)) pick(c
);
306 else if ((vk
>= 0xb8) &&
307 (vk
<= 0xd7)) pick(c
);
308 else if ((vk
>= 0xdb) &&
309 (vk
<= 0xdf)) pick(c
);
310 else if ((vk
>= 0xe1) &&
311 (vk
<= 0xe4)) pick(c
);
312 else if ((vk
>= 0xe6) &&
313 (vk
<= 0xf5)) pick(c
);
314 else if ((vk
>= VK_NUMPAD0
) &&
317 if (ctrl
& NUMLOCK_ON
) pick(vk
-VK_NUMPAD0
+'0');
320 case VK_NUMPAD0
: pick("\033[2~"); break;
321 case VK_NUMPAD1
: pick("\033[4~"); break;
322 case VK_NUMPAD2
: pick("\033[B"); break;
323 case VK_NUMPAD3
: pick("\033[6~"); break;
324 case VK_NUMPAD4
: pick("\033[D"); break;
325 case VK_NUMPAD5
: break;
326 case VK_NUMPAD6
: pick("\033[C"); break;
327 case VK_NUMPAD7
: pick("\033[1~"); break;
328 case VK_NUMPAD8
: pick("\033[A"); break;
329 case VK_NUMPAD9
: pick("\033[5~"); break;
332 else if (vk
== VK_MULTIPLY
) pick('*');
333 else if (vk
== VK_ADD
) pick('+');
334 else if (vk
== VK_SEPARATOR
) ;
335 else if (vk
== VK_SUBTRACT
) pick('-');
336 else if (vk
== VK_DECIMAL
) pick('.');
337 else if (vk
== VK_DIVIDE
) pick('/');
338 else if ((vk
>= VK_F1
) &&
342 sprintf(s
, "%d", vk
-VK_F1
+11);
343 pick("\033["),pick(s
[0]);
344 if (s
[1]) pick(s
[1]);
347 else if ((vk
>= VK_F13
) &&
349 //else printf("vk=%d 0x%x c='%c'\n",vk,vk,c);
354 return last_used
!= first_free
;
362 bool res
= ClearCommError(handle
, &err
, &comStat
);
366 while (res
&& (comStat
.cbInQue
> 0))
369 res
= ClearCommError(handle
, &err
, &comStat
);
371 return last_used
!= first_free
;
383 if (type
== F_CONSOLE
)
388 cl_io::writable(void)
393 case F_UNKNOWN
: break;
396 case F_LISTENER
: return false;
399 struct timeval tv
= {0,0};
402 FD_SET((SOCKET
)handle
, &s
);
403 int ret
= select(0, NULL
, &s
, NULL
, &tv
);
404 if (!FD_ISSET((SOCKET
)handle
, &s
))
411 if (GetDiskFreeSpaceExA(NULL
, NULL
, &s
, NULL
))
412 return s
.QuadPart
>1024;
417 case F_CONSOLE
: return true;
421 bool res
= ClearCommError(handle
, &err
, &comStat
);
424 if (comStat
.cbOutQue
!= 0)
434 //printf("win_f changed fid=%d\n", file_id);
438 //printf("Closing fid=%d\n", file_id);
439 if ((F_SOCKET
== type
) ||
440 (F_LISTENER
== type
))
442 //printf("Closing sock, handle=%p\n", handle);
443 shutdown((SOCKET
)handle
, SD_BOTH
);
444 closesocket((SOCKET
)handle
);
446 handle
= INVALID_HANDLE_VALUE
;
454 //printf("win opened socket id=%d\n", file_id);
455 handle
= (void *)((ULONG_PTR
)file_id
);
457 deb("assuming TTY on socket %d\n", file_id
);
462 handle
= (HANDLE
)_get_osfhandle(file_id
);
463 type
= determine_type();
464 /*if (type == F_CONSOLE)
466 if (strcmp("r", file_mode) == 0)
468 printf("wio: console mode 0\n");
469 SetConsoleMode(handle, 0);
472 if (type
== F_SOCKET
)
474 deb("determined socket, assume TTY... id=%d\n", file_id
);
478 //printf("win opened file id=%d\n", file_id);
479 //printf("win handle=%p type=%d\n", handle, type);
483 cl_io::prepare_terminal()
485 deb("wio set_attr fid=%d type=%d\n",file_id
,type
);
486 if (type
== F_CONSOLE
)
488 deb("wio: console mode 0 fid=%d handle=%p\n", file_id
, handle
);
489 SetConsoleMode(handle
,0);
490 //ENABLE_PROCESSED_OUTPUT|4/*ENABLE_VIRTUAL_TERMINAL_PROCESSING*/);
492 else if (type
== F_SOCKET
)
495 sprintf(s
, "%c%c%c%c%c%c", 0xff, 0xfb, 1, 0xff, 0xfb, 3 );
502 mk_srv_socket(int port
)
504 struct sockaddr_in name
;
507 //fprintf(stderr, "make_server_socket(%d)\n", port);
508 /* Create the socket. */
509 /*SOCKET*/unsigned int sock
= WSASocket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, NULL
, 0, 0);
510 if (INVALID_SOCKET
== sock
)
512 fprintf(stderr
, "socket: %d\n", WSAGetLastError());
513 return -1;/*INVALID_SOCKET*/;
516 name
.sin_family
= AF_INET
;
517 name
.sin_port
= htons(port
);
518 name
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
519 if (SOCKET_ERROR
== bind(sock
, (struct sockaddr
*)&name
, sizeof(name
)))
521 /*wchar_t*/LPWSTR s
= NULL
;
522 int e
= WSAGetLastError();
523 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
524 FORMAT_MESSAGE_FROM_SYSTEM
|
525 FORMAT_MESSAGE_IGNORE_INSERTS
,
527 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
528 (LPWSTR
)&s
, 0, NULL
);
529 fprintf(stderr
, "bind of port %d: %d %S\n", port
, e
, s
);
531 return -1/*INVALID_SOCKET*/;
534 //printf("socket=%d\n", sock);
540 mk_io(const char *fn
, const char *mode
)
550 else if (strcmp(fn
, "-") == 0)
552 if (strcmp(mode
, "r") == 0)
554 return cp_io(fileno(stdin
), mode
);
556 else if (strcmp(mode
, "w") == 0)
558 return cp_io(fileno(stdout
), mode
);
561 io
= new cl_io(fn
, mode
);
567 cp_io(/*FILE *f*/int file_id
, const char *mode
)
573 io
->use_opened(/*fileno(f)*/file_id
, mode
);
578 mk_srv(int server_port
)
582 //printf("mk_srv(%d)\n", server_port);
583 io
= new cl_io(server_port
);
585 io
->type
= F_LISTENER
;
590 srv_accept(class cl_f
*listen_io
,
591 class cl_f
**fin
, class cl_f
**fout
)
594 //ACCEPT_SOCKLEN_T size;
595 //struct sockaddr_in sock_addr;
598 //size= sizeof(struct sockaddr);
599 new_sock
= accept(listen_io
->file_id
, /*(struct sockaddr *)sock_addr*/NULL
, /*&size*/NULL
);
600 //printf("win srv_accept(port=%d,new_sock=%d)\n", listen_io->server_port, new_sock);
601 int fh
= _open_osfhandle((intptr_t)new_sock
, _O_TEXT
);
602 //printf("Accept, got fh=%d for new_socket %p\n", fh, (void*)new_sock);
611 FILE *f
= fdopen(fh
, "r");
612 //printf("fdopened f=%p for fh=%d as input\n", f, fh);
613 io
->own_opened(f
, "r");
615 io
->server_port
= listen_io
->server_port
;
626 //int fh= _open_osfhandle((intptr_t)new_sock, _O_TEXT);
629 FILE *f
= fdopen(fh
, "w");
630 //printf("fdopened f=%p for fh=%d as output\n", f, fh);
631 io
->use_opened(f
, "w");
633 io
->server_port
= listen_io
->server_port
;
643 check_inputs(class cl_list
*active
, class cl_list
*avail
)
652 avail
->disconn_all();
654 for (i
= 0; i
< active
->count
; i
++)
656 class cl_f
*fio
= (class cl_f
*)active
->at(i
);
657 if (fio
->input_avail())
685 unsigned int cperiod_value() { return 10000; }
690 // Set output mode to handle virtual terminal sequences
691 HANDLE hOut
= GetStdHandle(STD_OUTPUT_HANDLE
);
692 if (hOut
== INVALID_HANDLE_VALUE
)
696 HANDLE hIn
= GetStdHandle(STD_INPUT_HANDLE
);
697 if (hIn
== INVALID_HANDLE_VALUE
)
702 DWORD dwOriginalOutMode
= 0;
703 DWORD dwOriginalInMode
= 0;
704 if (!GetConsoleMode(hOut
, &dwOriginalOutMode
))
708 if (!GetConsoleMode(hIn
, &dwOriginalInMode
))
713 DWORD dwRequestedOutModes
=
714 #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
715 ENABLE_VIRTUAL_TERMINAL_PROCESSING
720 #ifdef DISABLE_NEWLINE_AUTO_RETURN
721 DISABLE_NEWLINE_AUTO_RETURN
726 //DWORD dwRequestedInModes = ENABLE_VIRTUAL_TERMINAL_INPUT;
728 DWORD dwOutMode
= dwOriginalOutMode
| dwRequestedOutModes
;
729 if (!SetConsoleMode(hOut
, dwOutMode
))
731 // we failed to set both modes, try to step down mode gracefully.
732 dwRequestedOutModes
=
733 #ifdef ENABLE_VIRTUAL_TERMINAL_PROCESSING
734 ENABLE_VIRTUAL_TERMINAL_PROCESSING
739 dwOutMode
= dwOriginalOutMode
| dwRequestedOutModes
;
740 if (!SetConsoleMode(hOut
, dwOutMode
))
742 // Failed to set any VT mode, can't do anything here.
747 DWORD dwInMode
= dwOriginalInMode
|
748 #ifdef ENABLE_VIRTUAL_TERMINAL_INPUT
749 ENABLE_VIRTUAL_TERMINAL_INPUT
754 if (!SetConsoleMode(hIn
, dwInMode
))
756 // Failed to set VT input mode, can't do anything here.
768 gettimeofday(&tv
, NULL
);
769 return (double)tv
.tv_sec
+ ((double)tv
.tv_usec
/1000000.0);
779 restore_std_attribs()
784 /* End of utils.src/fwio.cc */