/* * TOPPERS PROJECT Home Network Working Group Software * * Copyright (C) 2014-2019 Cores Co., Ltd. Japan * * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー * スコード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 * の無保証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ * と. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 * 作権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに * 報告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを * 免責すること. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * * @(#) $Id$ */ /* * サンプルプログラム(1)の本体 */ #include "shellif.h" #include #include #include #include #include #include "syssvc/serial.h" #include "syssvc/syslog.h" #include "kernel_cfg.h" #include "main.h" #include "rza1.h" #include #include #include #include #include #include #include #include #include #include #include #include "ffarch.h" #include "ff.h" #include "websocket_fbs.h" #include "core/ntshell.h" #include "core/ntlibc.h" #include "util/ntstdio.h" #include "usrcmd.h" #include "util/ntopt.h" #include "fdtable.h" #include "target_syssvc.h" ID ws_api_mailboxid = MAIN_DATAQUEUE; ID ws_mempoolid = MPF_NET_BUF_256; char command[NTOPT_TEXT_MAXLEN]; ntstdio_t ntstdio; unsigned char ntstdio_xi(struct ntstdio_t *handle) { char buf[1]; if(serial_rea_dat(SIO_PORTID, buf, 1) != 1) return -EIO; return buf[0]; } void ntstdio_xo(struct ntstdio_t *handle, unsigned char c) { char buf[1]; buf[0] = c; serial_wri_dat(SIO_PORTID, buf, 1); } const uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; const struct utsname host_name = { "TOPPERS/ASP3", TARGET_NAME, "3.5.0", "3.5.0", TARGET_NAME, "toppers.jp" }; int shell_uname(struct utsname *uts) { memcpy(uts, &host_name, sizeof(host_name)); return 0; } enum main_state_t { main_state_start, main_state_idle, }; struct main_obj_t { ntshell_t ntshell; TMO timer; enum main_state_t state; SYSTIM prev, now; WS_FBS_ID rcvmsg; T_WS_FBS_QUEUE wbs_queue; WS_FBS_ID sndmsg; }; struct main_obj_t main_obj; static void main_change_netif_link(T_IFNET *ether); static void main_initialize(struct main_obj_t *obj); static TMO main_get_timer(struct main_obj_t *obj); static void main_progress(struct main_obj_t *obj, TMO elapse); static void main_timeout(struct main_obj_t *obj); extern int execute_command(int wait); static int usrcmd_ntopt_callback(long *args, void *extobj); int shellcmd_exit_code; volatile int shellcmd_state; typedef void (*PowerOn_Reset_t)(long *args); jmp_buf shellcmd_exit; int uart_read(char *buf, int cnt, void *extobj) { return serial_rea_dat(SIO_PORTID, (char *)buf, cnt); } int uart_write(const char *buf, int cnt, void *extobj) { return serial_wri_dat(SIO_PORTID, buf, cnt); } int cmd_execute(const char *text, void *extobj) { if (text != NULL) { ntlibc_strlcpy(command, text, sizeof(command)); } ER ret; ID tskid = 0; ret = get_tid(&tskid); if (ret != E_OK) { syslog(LOG_ERROR, "get_tid %d", ret); } return execute_command(tskid == MAIN_TASK); } /* * メインタスク */ void main_task(intptr_t exinf) { struct main_obj_t *obj = (struct main_obj_t *)&main_obj; main_initialize(obj); ntshell_init(&obj->ntshell, uart_read, uart_write, cmd_execute, obj); ntshell_set_prompt(&obj->ntshell, "NTShell>"); ntshell_execute(&obj->ntshell); } /* * 初期化 */ static void main_initialize(struct main_obj_t *obj) { FILINFO fno; #if FF_USE_LFN char lfn[FF_MAX_LFN + 1]; fno.lfname = lfn; fno.lfsize = FF_MAX_LFN + 1; #endif ER ret; ntstdio_init(&ntstdio, NTSTDIO_OPTION_LINE_ECHO | NTSTDIO_OPTION_CANON | NTSTDIO_OPTION_LF_CRLF | NTSTDIO_OPTION_LF_CR, ntstdio_xi, ntstdio_xo); obj->timer = TMO_FEVR; obj->state = main_state_start; gpio_t led_blue, led_green, led_red, sw; gpio_init_out(&led_blue, LED_BLUE); gpio_init_out(&led_green, LED_GREEN); gpio_init_out(&led_red, LED_RED); gpio_init_in(&sw, USER_BUTTON0); bool_t exec = gpio_read(&sw) == 1; gpio_write(&led_blue, 1); gpio_write(&led_green, exec ? 1 : 0); gpio_write(&led_red, 0); ether_set_link_callback(main_change_netif_link); /* 初期化 */ if (mruby_arduino_init() == 0) { gpio_write(&led_blue, 0); } else { gpio_write(&led_blue, 0); gpio_write(&led_red, 1); } gpio_write(&led_green, 0); act_tsk(HTTPD1_TASK); act_tsk(HTTPD2_TASK); if (f_stat("1:/upload/main.mrb", &fno) != FR_OK) { exec = false; } if (exec) { ntlibc_strlcpy(command, "mruby -b 1:/upload/main.mrb", sizeof(command)); execute_command(1); } ret = get_tim(&obj->now); if (ret != E_OK) { syslog(LOG_ERROR, "get_tim"); ext_tsk(); return; } } /* * タイマー取得 */ static TMO main_get_timer(struct main_obj_t *obj) { TMO timer = obj->timer; return timer; } /* * 時間経過 */ static void main_progress(struct main_obj_t *obj, TMO elapse) { if (obj->timer != TMO_FEVR) { obj->timer -= elapse; if (obj->timer < 0) { obj->timer = 0; } } } /* * タイムアウト処理 */ static void main_timeout(struct main_obj_t *obj) { //if (obj->timer == 0) { //} } /* MACアドレスの設定時に呼ばれる */ void mbed_mac_address(char *mac) { memcpy(mac, mac_addr, 6); } static void main_change_netif_link(T_IFNET *ether) { FLGPTN flgptn; T_RTSK rtsk; ER ret; ret = ref_tsk(SHELLCMD_TASK, &rtsk); if ((ret != E_OK) || (rtsk.tskstat == TTS_DMT)) return; FD_SET(0, (fd_set *)&flgptn); set_flg(FLG_SELECT_WAIT, flgptn); } /* * shellcmdタスク */ void shellcmd_task(intptr_t exinf) { shellcmd_state = 1; shellcmd_exit_code = ntopt_parse(command, usrcmd_ntopt_callback, NULL); shellcmd_state = 2; } static const cmd_table_t cmdlist[] = { {"cd", "change directory", usrcmd_cd }, {"ls", "list files", usrcmd_ls }, {"cp", "copy file", usrcmd_cp }, {"rm", "remove file", usrcmd_rm }, {"mv", "move file", usrcmd_mv }, {"mkdir", "Make directory", usrcmd_mkdir}, {"hexdump", "Hex dump", usrcmd_hexdump}, {"date", "print date and time", usrcmd_date}, {"info", "This is a description text string for info command.", usrcmd_info}, {"exit", "Exit Natural Tiny Shell", usrcmd_exit}, }; cmd_table_info_t cmd_table_info = { cmdlist, sizeof(cmdlist) / sizeof(cmdlist[0]) }; static int usrcmd_ntopt_callback(long *args, void *extobj) { const cmd_table_t *p = cmd_table_info.table; int result = 0; int found = 0; if (*args == 0) return result; if (ntlibc_strcmp((const char *)args[1], "help") == 0) { usrcmd_help(args[0], (char **)&args[1]); } else for (int i = 0; i < cmd_table_info.count; i++) { if (ntlibc_strcmp((const char *)args[1], p->cmd) == 0) { return p->func(args[0], (char **)&args[1]); } p++; } if (setjmp(shellcmd_exit) == 0) { (*((PowerOn_Reset_t *)0x18220000))(args); } clean_fd(); return 0; } int usrcmd_help(int argc, char **argv) { const cmd_table_t *p = cmd_table_info.table; for (int i = 0; i < cmd_table_info.count; i++) { ntstdio_puts(&ntstdio, p->cmd); ntstdio_puts(&ntstdio, "\t:"); ntstdio_puts(&ntstdio, p->desc); ntstdio_puts(&ntstdio, "\n"); p++; } return 0; } void shellif_into() { /* メインタスクの優先度より高くする */ chg_pri(SHELLCMD_PRIORITY, MAIN_PRIORITY + 1); } void shellif_outof() { /* shellcmdタスクの優先度に戻す */ chg_pri(SHELLCMD_PRIORITY, SHELLCMD_PRIORITY); } void shell_abort() { asm("bkpt #0"); shellcmd_exit_code = -1; longjmp(shellcmd_exit, 1); } void shell_exit(int exitcd) { shellcmd_exit_code = exitcd; longjmp(shellcmd_exit, 1); } void shell_exit_group(int exitcd) { shellcmd_exit_code = exitcd; longjmp(shellcmd_exit, 1); } int execute_command(int wait) { ER ret; ret = ter_tsk(SHELLCMD_TASK); if ((ret != E_OK) && (ret != E_OBJ)) { syslog(LOG_ERROR, "ter_tsk => %d", ret); } tslp_tsk(100000); clean_fd(); shellcmd_state = 0; ret = act_tsk(SHELLCMD_TASK); if (ret != E_OK) { syslog(LOG_ERROR, "act_tsk => %d", ret); } if (wait == 0) return 0; do { tslp_tsk(100000); } while(shellcmd_state == 1); return shellcmd_exit_code; } int shell_clock_getres(clockid_t clk_id, struct timespec *res) { if (clk_id != CLOCK_REALTIME) return -EINVAL; memset(&res->tv_sec, 0xFF, sizeof(res->tv_sec)); res->tv_nsec = 0; return 0; } int shell_clock_gettime(clockid_t clk_id, struct timespec *tp) { SYSTIM now = 0; if (clk_id != CLOCK_REALTIME) return -EINVAL; get_tim(&now); tp->tv_sec = now / 1000000; tp->tv_nsec = (now % 1000000) * 1000; return 0; } int shell_clock_settime(clockid_t clk_id, const struct timespec *tp) { if (clk_id != CLOCK_REALTIME) return -EINVAL; rtc_write(tp->tv_sec); return 0; } sigset_t g_sigmask; int shell_sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict old) { if (old != NULL) memcpy(old, &g_sigmask, sizeof(sigset_t)); switch (how) { case SIG_BLOCK: for (int i = 0; i < sizeof(g_sigmask.__bits) / sizeof(g_sigmask.__bits[0]); i++) { g_sigmask.__bits[i] |= set->__bits[i]; } break; case SIG_UNBLOCK: for (int i = 0; i < sizeof(g_sigmask.__bits) / sizeof(g_sigmask.__bits[0]); i++) { g_sigmask.__bits[i] &= ~set->__bits[i]; } break; case SIG_SETMASK: memcpy(&g_sigmask, set, sizeof(sigset_t)); break; default: return -EINVAL; } return 0; } struct sigaction sigtable[6]; int shell_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old) { struct sigaction *sat; switch(sig){ case SIGALRM: sat = &sigtable[0]; break; case SIGFPE: sat = &sigtable[1]; break; case SIGILL: sat = &sigtable[2]; break; case SIGSEGV: sat = &sigtable[3]; break; case SIGBUS: sat = &sigtable[4]; break; case SIGABRT: sat = &sigtable[5]; break; default: return -EINVAL; } if (old != NULL) memcpy(old, sat, sizeof(struct sigaction)); memcpy(sat, sa, sizeof(struct sigaction)); return 0; } int shell_madvise(void *a, size_t b, int c) { return 0; } int stdio_close(struct _IO_FILE *fp) { return -EPERM; } size_t stdio_read(struct _IO_FILE *fp, unsigned char *data, size_t len) { return -EPERM; } size_t stdio_write(struct _IO_FILE *fp, const unsigned char *data, size_t len) { return -EPERM; } size_t stdin_read(struct _IO_FILE *fp, unsigned char *data, size_t len) { int i = 0; while (i < len) { int c = ntstdio_getc(&ntstdio); data[i++] = c; if ((c == EOF) || (c == '\n')) break; } return i; } size_t stdout_write(struct _IO_FILE *fp, const unsigned char *data, size_t len) { for (int i = 0; i < len; i++) { ntstdio_putc(&ntstdio, data[i]); } return len; } size_t stderr_write(struct _IO_FILE *fp, const unsigned char *data, size_t len) { for (int i = 0; i < len; i++) { ntstdio_putc(&ntstdio, data[i]); } return len; } int sio_close(struct _IO_FILE *fp) { return -EPERM; } size_t sio_read(struct _IO_FILE *fp, unsigned char *data, size_t len) { return -EPERM; } size_t sio_write(struct _IO_FILE *fp, const unsigned char *data, size_t len) { return -EPERM; } off_t sio_seek(struct _IO_FILE *fp, off_t ofs, int org) { return -EPERM; } int sio_ioctl(struct _IO_FILE *fp, int request, void *arg) { switch (request) { case TIOCGWINSZ: return 0; case TCGETS: return sio_tcgetattr(fp->fd, (struct termios *)arg); case TCSETS + TCSANOW: case TCSETS + TCSADRAIN: case TCSETS + TCSAFLUSH: return sio_tcsetattr(fp->fd, request - TCSETS, (const struct termios *)arg); } return -EINVAL; }