X-Git-Url: http://git.droids-corp.org/?p=aversive.git;a=blobdiff_plain;f=modules%2Fbase%2Fhostsim%2Fhostsim.c;fp=modules%2Fbase%2Fhostsim%2Fhostsim.c;h=bb77ad9e3f894444ac0a991dac52037ec057a33d;hp=e8a02f342093578e3e29c70bb635a07ca7cca84a;hb=a16ba178c7ef15fb408593b0e7c666ed2ed1d253;hpb=7d6a4a1f99a11437d608cbe61f07fac0e3d70ad1 diff --git a/modules/base/hostsim/hostsim.c b/modules/base/hostsim/hostsim.c index e8a02f3..bb77ad9 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 static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 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 } @@ -102,7 +139,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; @@ -121,7 +158,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; @@ -135,10 +173,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; parent_id = pthread_self(); @@ -151,6 +275,24 @@ int hostsim_init(void) 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)); sigemptyset(&sigact.sa_mask); @@ -162,9 +304,16 @@ int hostsim_init(void) if (siginterrupt (SIGUSR1, 0) != 0) return -1; - printf("hostsim_init()\n", ret); pthread_mutex_unlock(&mut); return 0; } + +int hostsim_exit(void) +{ +#ifdef CONFIG_MODULE_UART + tcsetattr(0, TCSANOW, &oldterm); +#endif + return 0; +} #endif /* HOST_VERSION */