X-Git-Url: http://git.droids-corp.org/?p=aversive.git;a=blobdiff_plain;f=modules%2Fbase%2Fhostsim%2Fhostsim.c;h=87bbfc65298861e60db36fc92a9fdef3ca03584a;hp=850d23a59f7e1d7331f2599362d17e514da4b343;hb=87ccd3af8abb0da3e0fa98dc8e9216fc7b676f97;hpb=145b19e73ce5751b365bc53769189addeecee81b diff --git a/modules/base/hostsim/hostsim.c b/modules/base/hostsim/hostsim.c index 850d23a..87bbfc6 100644 --- a/modules/base/hostsim/hostsim.c +++ b/modules/base/hostsim/hostsim.c @@ -34,19 +34,41 @@ #include #include #include +#include #include #include #include #include #include +#include #ifdef CONFIG_MODULE_SCHEDULER #include #endif +#ifdef CONFIG_MODULE_UART +#include +#endif pthread_mutex_t mut; static volatile int cpt = 0; +static struct termios oldterm; +/* static */ int old_stdin, old_stdout; +static int stdin_pipe[2]; +static int stdout_pipe[2]; + +enum msg_type { + SCHED, + UART_RCV, + UART_SND, +}; + +struct message { + enum msg_type type; + char c; +}; +static struct message g_msg; + #ifdef SA_SIGINFO static void sigusr1(__attribute__((unused)) int sig, __attribute__((unused)) siginfo_t *info, @@ -55,10 +77,25 @@ static void sigusr1(__attribute__((unused)) int sig, void sigusr1(__attribute__((unused)) int sig) #endif { - pthread_mutex_unlock(&mut); + struct message m; + m = g_msg; #ifdef CONFIG_MODULE_SCHEDULER - scheduler_interrupt(); + if (m.type == SCHED) { + pthread_mutex_unlock(&mut); + scheduler_interrupt(); + } +#endif + +#ifdef CONFIG_MODULE_UART + if (m.type == UART_RCV) { + uart_host_rx_event(m.c); + pthread_mutex_unlock(&mut); + } + if (m.type == UART_SND) { + uart_host_tx_event(m.c); + pthread_mutex_unlock(&mut); + } #endif } @@ -82,7 +119,7 @@ void host_wait_ms(int ms) /* sends signal to child */ void *parent(void *arg) { - pthread_t *thread = arg; + pthread_t thread = (pthread_t)arg; struct timeval cur_tv, prev_tv, tv_millisec; int n; @@ -101,7 +138,8 @@ void *parent(void *arg) n = 0; } pthread_mutex_lock(&mut); - pthread_kill(*thread, SIGUSR1); + g_msg.type = SCHED; + pthread_kill(thread, SIGUSR1); /* signal was acked */ tv_millisec.tv_sec = 0; @@ -115,10 +153,96 @@ void *parent(void *arg) return NULL; } +void *hostsim_uart_stdin(void *arg) +{ + pthread_t thread = (pthread_t)arg; + int n; + char c; + + /* read on old stdin and put it in pipe */ + while (1) { + n = read(old_stdin, &c, 1); + if (n <= 0) + break; + + pthread_mutex_lock(&mut); + g_msg.type = UART_RCV; + g_msg.c = c; + pthread_kill(thread, SIGUSR1); + + write(stdin_pipe[1], &c, 1); + } + pthread_exit(NULL); + return NULL; +} + +void *hostsim_uart_stdout(void *arg) +{ + pthread_t thread = (pthread_t)arg; + int n; + char c; + + /* read on our pipe, and forward it to the old stdout */ + while (1) { + n = read(stdout_pipe[0], &c, 1); + if (n <= 0) + break; + + pthread_mutex_lock(&mut); + g_msg.type = UART_SND; + g_msg.c = c; + pthread_kill(thread, SIGUSR1); + + write(old_stdout, &c, 1); + } + pthread_exit(NULL); + return NULL; +} + +int hostsim_uart_init(void) +{ + struct termios term; + + tcgetattr(0, &oldterm); + memcpy(&term, &oldterm, sizeof(term)); + term.c_lflag &= ~(ICANON | ECHO | ISIG); + tcsetattr(0, TCSANOW, &term); + + /* duplicate stdin */ + old_stdin = dup(0); + if (old_stdin < 0) + return 1; + + /* duplicate stdout */ + old_stdout = dup(1); + if (old_stdout < 0) + return -1; + + /* create 2 pipes */ + if (pipe(stdin_pipe) < 0) + return -1; + if (pipe(stdout_pipe) < 0) + return -1; + + /* replace file desc 0 (stdin) by our pipe */ + if (dup2(stdin_pipe[0], 0) < 0) + return -1; + close(stdin_pipe[0]); + + /* replace file desc 1 (stdout) by our pipe */ + if (dup2(stdout_pipe[1], 1) < 0) + return -1; + close(stdout_pipe[1]); + setbuf(stdin, NULL); + setbuf(stdout, NULL); + + return 0; +} + int hostsim_init(void) { struct sigaction sigact; - pthread_t parent_id, child_id; + pthread_t parent_id, child_id, child2_id, child3_id; int ret; pthread_mutex_init(&mut, NULL); @@ -126,12 +250,30 @@ int hostsim_init(void) parent_id = pthread_self(); pthread_mutex_lock(&mut); - ret = pthread_create(&child_id, NULL, parent, (void *)&parent_id); + ret = pthread_create(&child_id, NULL, parent, (void *)parent_id); + if (ret) { + printf("pthread_create() returned %d\n", ret); + pthread_mutex_unlock(&mut); + return -1; + } + +#ifdef CONFIG_MODULE_UART + if (hostsim_uart_init()) + return -1; + + ret = pthread_create(&child2_id, NULL, hostsim_uart_stdin, (void *)parent_id); if (ret) { printf("pthread_create() returned %d\n", ret); pthread_mutex_unlock(&mut); return -1; } + ret = pthread_create(&child3_id, NULL, hostsim_uart_stdout, (void *)parent_id); + if (ret) { + printf("pthread_create() returned %d\n", ret); + pthread_mutex_unlock(&mut); + return -1; + } +#endif /* register a signal handler, which is interruptible */ memset(&sigact, 0, sizeof(sigact)); @@ -148,4 +290,11 @@ int hostsim_init(void) return 0; } + +void hostsim_exit(void) +{ +#ifdef CONFIG_MODULE_UART + tcsetattr(0, TCSANOW, &oldterm); +#endif +} #endif /* HOST_VERSION */