24 #if !defined(HAS_UARTMON_SUPPORT)
27 #warning "Platform does not support UMON"
49 char umon_write_buffer[UMON_WRITE_BUFFER_SIZE];
51 #define UNCONNECTED XS_INVALID_SOCKET
54 # define PRINTF_SOCK "%I64d"
56 # define PRINTF_SOCK "%d"
60 static xemusock_socket_t sock_server = UNCONNECTED;
61 static xemusock_socklen_t sock_len;
62 static xemusock_socket_t sock_client = UNCONNECTED;
64 static int umon_write_pos, umon_read_pos;
66 static char umon_read_buffer [0x1000];
72 static char *parse_hex_arg (
char *p,
int *val,
int min,
int max )
78 umon_printf(UMON_SYNTAX_ERROR
"unexpected end of command (no parameter)");
83 if (*p >=
'a' && *p <=
'f')
84 r = (
r << 4) | (*p -
'a' + 10);
85 else if (*p >=
'A' && *p <=
'F')
86 r = (
r << 4) | (*p -
'A' + 10);
87 else if (*p >=
'0' && *p <=
'9')
88 r = (
r << 4) | (*p -
'0');
89 else if (*p == 32 || *p == 0)
92 umon_printf(UMON_SYNTAX_ERROR
"invalid data as hex digit '%c'", *p);
98 if (r < min || r > max) {
99 umon_printf(UMON_SYNTAX_ERROR
"command parameter's value is outside of the allowed range for this command %X (%X...%X)",
r, min, max);
107 static int check_end_of_command (
char *p,
int error_out )
113 umon_printf(UMON_SYNTAX_ERROR
"unexpected command parameter");
120 static void setmem28 (
char *param,
int addr )
122 char *orig_param = param;
125 while (param && !check_end_of_command(param, 0)) {
127 param = parse_hex_arg(param, &val, 0, 0xFF);
131 for (
int idx = 0; idx < cnt; idx++) {
133 param = parse_hex_arg(param, &val, 0, 0xFF);
140 static void execute_command (
char *cmd )
146 if (p == cmd && (*cmd == 32 || *cmd ==
'\t' || *cmd == 8))
151 memmove(p - 1, p + 1, strlen(p + 1) + 1);
152 else if ((
unsigned char)*p > 127 || (
unsigned char)*p < 32) {
153 umon_printf(UMON_SYNTAX_ERROR
"invalid character in the command (ASCII=%d)", *p);
158 while (p >= cmd && *p <= 32)
160 DEBUG(
"UARTMON: command got \"%s\" (%d bytes)." NL, cmd, (
int)strlen(cmd));
165 if (check_end_of_command(cmd, 1))
166 umon_printf(
"Xemu/MEGA65 Serial Monitor\r\nWarning: not 100%% compatible with UART monitor of a *real* MEGA65 ...");
170 if (check_end_of_command(cmd, 1))
174 cmd = parse_hex_arg(cmd, &par1, 0, 0xFFFFFFF);
176 if (cmd && check_end_of_command(cmd, 1))
185 cmd = parse_hex_arg(cmd, &par1, 0, 0xFFFFFFF);
187 if (cmd && check_end_of_command(cmd, 1))
189 for (
int k = 0; k < 32; k++)
201 cmd = parse_hex_arg(cmd, &par1, 0, 0xFFFFFFF);
207 else if (*cmd ==
'c') {
208 if (check_end_of_command(cmd, 1))
211 cmd = parse_hex_arg(cmd, &par1, 0, 1);
212 if (cmd && check_end_of_command(cmd, 1))
217 cmd = parse_hex_arg(cmd, &par1, 0, 0xFFFF);
218 if (cmd && check_end_of_command(cmd, 1))
221 #ifdef TRACE_NEXT_SUPPORT
223 m65mon_next_command();
230 umon_printf(UMON_SYNTAX_ERROR
"unknown (or not implemented) command '%c'", cmd[-1]);
240 int uartmon_is_active (
void )
242 return sock_server != UNCONNECTED;
246 int uartmon_init (
const char *
fn )
248 static char fn_stored[PATH_MAX] =
"";
250 xemusock_socket_t sock;
252 ERROR_WINDOW(
"UARTMON: already activated on %s", fn_stored);
255 sock_server = UNCONNECTED;
256 sock_client = UNCONNECTED;
258 DEBUGPRINT(
"UARTMON: disabled, no name is specified to bind to." NL);
261 const char *init_status = xemusock_init();
263 ERROR_WINDOW(
"Cannot initialize network, uart_mon won't be availbale\n%s", init_status);
267 int port = atoi(
fn + 1);
268 if (port < 1024 || port > 65535) {
269 ERROR_WINDOW(
"uartmon: invalid port specification %d (1024-65535 is allowed) from string %s", port,
fn);
272 struct sockaddr_in sock_st;
273 sock_len =
sizeof(
struct sockaddr_in);
275 sock = xemusock_create_for_inet(XEMUSOCK_TCP, XEMUSOCK_BLOCKING, &xerr);
276 if (sock == XS_INVALID_SOCKET) {
277 ERROR_WINDOW(
"Cannot create TCP socket: %s", xemusock_strerror(xerr));
280 if (xemusock_setsockopt_reuseaddr(sock, &xerr)) {
281 ERROR_WINDOW(
"UARTMON: setsockopt for SO_REUSEADDR failed with %s", xemusock_strerror(xerr));
286 xemusock_fill_servaddr_for_inet_ip_native(&sock_st, 0, port);
287 if (xemusock_bind(sock, (
struct sockaddr*)&sock_st, sock_len, &xerr)) {
288 ERROR_WINDOW(
"Cannot bind TCP socket %d, UART monitor cannot be used: %s", port, xemusock_strerror(xerr));
289 xemusock_close(sock, NULL);
293 #if !defined(XEMU_ARCH_UNIX)
294 ERROR_WINDOW(
"On non-UNIX systems, you must use TCP/IP sockets, so uartmon parameter must be in form of :n (n=port number to bind to)\nUARTMON is not available because of bad syntax.");
299 struct sockaddr_un sock_st;
300 sock_len =
sizeof(
struct sockaddr_un);
301 sock = socket(AF_UNIX, SOCK_STREAM, 0);
303 ERROR_WINDOW(
"Cannot create named socket %s, UART monitor cannot be used: %s",
fn, strerror(errno));
306 sock_st.sun_family = AF_UNIX;
307 strcpy(sock_st.sun_path,
fn);
308 unlink(sock_st.sun_path);
309 if (bind(sock, (
struct sockaddr*)&sock_st, sock_len)) {
310 ERROR_WINDOW(
"Cannot bind named socket %s, UART monitor cannot be used: %s",
fn, strerror(errno));
311 xemusock_close(sock, NULL);
316 if (xemusock_listen(sock, 5, &xerr)) {
317 ERROR_WINDOW(
"Cannot listen socket %s, UART monitor cannot be used: %s",
fn, xemusock_strerror(xerr));
318 xemusock_close(sock, NULL);
321 if (xemusock_set_nonblocking(sock, XEMUSOCK_NONBLOCKING, &xerr)) {
322 ERROR_WINDOW(
"Cannot set socket %s into non-blocking mode, UART monitor cannot be used: %s",
fn, xemusock_strerror(xerr));
323 xemusock_close(sock, NULL);
326 DEBUG(
"UARTMON: monitor is listening on socket %s" NL,
fn);
327 sock_client = UNCONNECTED;
331 strcpy(fn_stored,
fn);
336 void uartmon_close (
void )
338 if (sock_server != UNCONNECTED) {
339 xemusock_close(sock_server, NULL);
340 sock_server = UNCONNECTED;
342 if (sock_client != UNCONNECTED) {
343 xemusock_close(sock_client, NULL);
344 sock_client = UNCONNECTED;
349 void uartmon_finish_command (
void )
352 if (umon_write_buffer[umon_write_size - 1] !=
'\n') {
354 umon_write_buffer[umon_write_size++] =
'\r';
355 umon_write_buffer[umon_write_size++] =
'\n';
358 umon_write_buffer[umon_write_size++] =
'.';
367 void uartmon_update (
void )
371 if (sock_server == UNCONNECTED)
374 if (sock_client == UNCONNECTED) {
376 xemusock_socklen_t len = sock_len;
378 #ifdef XEMU_ARCH_UNIX
379 struct sockaddr_un un;
381 struct sockaddr_in in;
383 xemusock_socket_t ret_sock = xemusock_accept(sock_server, (
struct sockaddr *)&sock_st, &len, &xerr);
384 if (ret_sock != XS_INVALID_SOCKET || (ret_sock == XS_INVALID_SOCKET && !xemusock_should_repeat_from_error(xerr)))
385 DEBUG(
"UARTMON: accept()=" PRINTF_SOCK
" error=%s" NL,
387 ret_sock != XS_INVALID_SOCKET ?
"OK" : xemusock_strerror(xerr)
389 if (ret_sock != XS_INVALID_SOCKET) {
390 if (xemusock_set_nonblocking(ret_sock, 1, &xerr)) {
391 DEBUGPRINT(
"UARTMON: error, cannot make socket non-blocking %s", xemusock_strerror(xerr));
392 xemusock_close(ret_sock, NULL);
395 sock_client = ret_sock;
399 DEBUGPRINT(
"UARTMON: new connection established on socket " PRINTF_SOCK
NL, sock_client);
404 if (sock_client == UNCONNECTED)
407 if (umon_write_size) {
410 ret = xemusock_send(sock_client, umon_write_buffer + umon_write_pos, umon_write_size, &xerr);
411 if (ret != XS_SOCKET_ERROR || (ret == XS_SOCKET_ERROR && !xemusock_should_repeat_from_error(xerr)))
412 DEBUG(
"UARTMON: write(" PRINTF_SOCK
",buffer+%d,%d)=%d (%s)" NL,
413 sock_client, umon_write_pos, umon_write_size,
414 ret, ret == XS_SOCKET_ERROR ? xemusock_strerror(xerr) :
"OK"
417 xemusock_close(sock_client, NULL);
418 sock_client = UNCONNECTED;
419 DEBUGPRINT(
"UARTMON: connection closed by peer while writing" NL);
424 umon_write_pos += ret;
425 umon_write_size -= ret;
426 if (umon_write_size < 0)
427 FATAL(
"FATAL: negative umon_write_size!");
434 ret = xemusock_recv(sock_client, umon_read_buffer + umon_read_pos,
sizeof(umon_read_buffer) - umon_read_pos - 1, &xerr);
435 if (ret != XS_SOCKET_ERROR || (ret == XS_SOCKET_ERROR && !xemusock_should_repeat_from_error(xerr)))
436 DEBUG(
"UARTMON: read(" PRINTF_SOCK
",buffer+%d,%d)=%d (%s)" NL,
437 sock_client, umon_read_pos, (
int)
sizeof(umon_read_buffer) - umon_read_pos - 1,
438 ret, ret == XS_SOCKET_ERROR ? xemusock_strerror(xerr) :
"OK"
441 xemusock_close(sock_client, NULL);
442 sock_client = UNCONNECTED;
443 DEBUGPRINT(
"UARTMON: connection closed by peer while reading" NL);
449 char*p = umon_read_buffer + umon_read_pos;
452 if (*p != 13 && *p != 10) {
453 umon_write_buffer[umon_write_size++] = *(p++);
461 umon_read_pos += ret;
462 umon_read_buffer[umon_read_pos] = 0;
464 if (!umon_echo ||
sizeof(umon_read_buffer) - umon_read_pos - 1 == 0) {
465 umon_read_buffer[
sizeof(umon_read_buffer) - 1] = 0;
466 umon_write_buffer[umon_write_size++] =
'\r';
467 umon_write_buffer[umon_write_size++] =
'\n';
469 execute_command(umon_read_buffer);
475 uartmon_finish_command();