source: EcnlProtoTool/trunk/prototool/src/main.c@ 279

Last change on this file since 279 was 279, checked in by coas-nagasima, 7 years ago

ファイルを追加、更新。

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 15.1 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2014-2016 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者
7は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再é…
10å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
11 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
12 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
13 * スコード中に含まれていること.
14 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
15 * 用できる形で再é…
16å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
17å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
18 * 者
19マニュアルなど)に,上記の著作権表示,この利用条件および下記
20 * の無保証規定を掲載すること.
21 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22 * 用できない形で再é…
23å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
24 * と.
25 * (a) 再é…
26å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
27マニュアルなど)に,上記の著
28 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
29 * (b) 再é…
30å¸ƒã®å½¢æ…
31‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
32 * 報告すること.
33 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
34 * 害からも,上記著作権者
35およびTOPPERSプロジェクトをå…
36è²¬ã™ã‚‹ã“と.
37 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
38 * 由に基づく請求からも,上記著作権者
39およびTOPPERSプロジェクトを
40 * å…
41è²¬ã™ã‚‹ã“と.
42 *
43 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
44お
45 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
46 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
47 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
48 * の責任を負わない.
49 *
50 * @(#) $Id: main.c 279 2017-04-29 07:33:37Z coas-nagasima $
51 */
52
53 /*
54 * サンプルプログラム(1)の本体
55 */
56
57#include <sys/types.h>
58#include <sys/socket.h>
59#include <sys/un.h>
60#include <netinet/in.h>
61#include <netinet/tcp.h>
62#include <arpa/inet.h>
63#include <fcntl.h>
64#include <netdb.h>
65#include <unistd.h>
66#include <setjmp.h>
67#include <signal.h>
68#include <time.h>
69#include <sys/time.h>
70#include <sys/unistd.h>
71#include <errno.h>
72
73#include <string.h>
74#include <mruby.h>
75#include <mruby/compile.h>
76#include <mruby/proc.h>
77#include <mruby/array.h>
78#include <mruby/data.h>
79#include <mruby/class.h>
80#include <mruby/dump.h>
81#include <mruby/string.h>
82#include <usrcmd.h>
83
84#define ETHER_MAX_LEN 1518
85#define IF_FLAG_UP 1
86#define IF_FLAG_LINK_UP 2
87#define MAKE_IPV4_ADDR(a,b,c,d) htonl(((uint32_t)(a)<<24)|((uint32_t)(b)<<16)|((uint32_t)(c)<<8)|(d))
88
89struct udp_msg
90{
91 struct sockaddr_in dst;
92 int len;
93 uint8_t buffer[ETHER_MAX_LEN];
94};
95
96typedef struct
97{
98 cmd_table_t *table;
99 cmd_table_t *count;
100} cmd_table_info_t;
101
102extern int mrbc_main(int argc, char **argv);
103extern int mrdb_main(int argc, char **argv);
104extern int mruby_main(int argc, char **argv);
105extern int mirb_main(int argc, char **argv);
106extern int tcc_main(int argc, char **argv);
107extern int vi_main(int argc, char **argv);
108extern int onitest_main(int argc, char **argv);
109extern int tcp_echo_main(int argc, char **argv);
110extern int echo_client_main(int argc, char **argv);
111extern int mrdb_break(void);
112
113static const cmd_table_t cmdlist[] = {
114 {"mrbc", "mruby compiler executable", mrbc_main},
115 {"mrdb","mruby debugger command", mrdb_main},
116 {"mruby","mruby command", mruby_main},
117 {"mirb", "Embeddable Interactive Ruby Shell", mirb_main},
118 {"tcc", "Tiny C compiler", tcc_main},
119 {"vi", "Text editor", vi_main},
120 {"cd", "change directory", usrcmd_cd },
121 {"ls", "list files", usrcmd_ls },
122 {"cp", "copy file", usrcmd_cp },
123 {"rm", "remove file", usrcmd_rm },
124 {"mv", "move file", usrcmd_mv },
125 {"mkdir", "Make directory", usrcmd_mkdir},
126 {"hexdump", "Hex dump", usrcmd_hexdump},
127 {"onitest", "Onigumo Test", onitest_main},
128 {"tcp_echo", "TCP echo server/client", tcp_echo_main},
129 {"help", "This is a description text string for help command.", usrcmd_help},
130 {"info", "This is a description text string for info command.", usrcmd_info},
131 {"exit", "Exit Natural Tyny Shell", usrcmd_exit},
132};
133cmd_table_info_t cmd_table_info = { &cmdlist, sizeof(cmdlist) / sizeof(cmdlist[0]) };
134
135int echonet = 1;
136struct timeval main_time;
137struct RClass *_module_target_board;
138int sock;
139
140int main(int argc, char **argv)
141{
142 if (argc == 0) {
143 return 0;
144 }
145 const cmd_table_t *p = cmd_table_info.table;
146 for (int i = 0; i < cmd_table_info.count; i++) {
147 if (strcmp((const char *)argv[0], p->cmd) == 0) {
148 return p->func(argc, argv);
149 }
150 p++;
151 }
152 printf("Unknown command found.\n");
153 return 0;
154}
155
156int run_mruby_code(int argc, char **argv, const uint8_t *code, const char *cmdline)
157{
158 mrb_state *mrb;
159 struct RProc* n;
160 struct mrb_irep *irep;
161 mrb_value ARGV;
162 mrbc_context *c;
163 mrb_value v;
164 mrb_sym zero_sym;
165
166 echonet = 0;
167
168 /* mrubyの初期化 */
169 mrb = mrb_open();
170 if (mrb == NULL)
171 return -1;
172
173 int ai = mrb_gc_arena_save(mrb);
174 ARGV = mrb_ary_new_capa(mrb, argc);
175 for (int i = 0; i < argc; i++) {
176 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, argv[i]));
177 }
178 mrb_define_global_const(mrb, "ARGV", ARGV);
179
180 c = mrbc_context_new(mrb);
181 c->dump_result = TRUE;
182
183 /* Set $0 */
184 zero_sym = mrb_intern_lit(mrb, "$0");
185 mrbc_filename(mrb, c, cmdline);
186 mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
187
188 irep = mrb_read_irep(mrb, code);
189 n = mrb_proc_new(mrb, irep);
190 mrb_run(mrb, n, mrb_nil_value());
191
192 mrb_gc_arena_restore(mrb, ai);
193 mrbc_context_free(mrb, c);
194 if (mrb->exc) {
195 if (!mrb_undef_p(v)) {
196 mrb_print_error(mrb);
197 }
198 n = -1;
199 }
200
201 mrb_close(mrb);
202 return 0;
203}
204
205int tcp_echo_main(int argc, char **argv)
206{
207 extern const uint8_t echo_server_code[];
208 extern const uint8_t echo_client_code[];
209
210 if (argc >= 2) {
211 if (strcmp(argv[1], "-s") == 0) {
212 return run_mruby_code(argc - 2, &argv[2], echo_server_code, "echo_server");
213 }
214 else if (strcmp(argv[1], "-c") == 0) {
215 return run_mruby_code(argc - 2, &argv[2], echo_client_code, "echo_client");
216 }
217 }
218
219 printf("tcp_echo -s port\n");
220 printf("tcp_echo -c ipaddr port\n");
221
222 return 0;
223}
224
225int usrcmd_help(int argc, char **argv)
226{
227 const cmd_table_t *p = cmd_table_info.table;
228 for (int i = 0; i < cmd_table_info.count; i++) {
229 printf(p->cmd);
230 printf("\t:");
231 printf(p->desc);
232 printf("\n");
233 p++;
234 }
235 return 0;
236}
237
238void sigusr1_handler(int sig)
239{
240 printf("signal called\n");
241}
242
243void mrb_target_board_init()
244{
245 int ret;
246 struct sockaddr_in ep;
247 struct ip_mreq mreq;
248
249 signal(SIGUSR1, sigusr1_handler);
250
251 sock = socket(AF_INET, SOCK_DGRAM, 0);
252
253 memset(&ep, 0, sizeof(ep));
254 ep.sin_family = AF_INET;
255 ep.sin_port = htons(3610);
256 ep.sin_addr.s_addr = INADDR_ANY;
257 //ep.sin_addr.s_addr = MAKE_IPV4_ADDR(192,168,137,200);
258
259 ret = bind(sock, &ep, sizeof(ep));
260 if (ret != 0) {
261 printf("bind %d", ret);
262 return;
263 }
264
265 mreq.imr_interface.s_addr = INADDR_ANY;
266 mreq.imr_multiaddr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
267
268 ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
269 if (ret != 0) {
270 printf("setsockopt %d", ret);
271 return;
272 }
273
274 ret = gettimeofday(&main_time, NULL);
275 if (ret != 0) {
276 printf("gettimeofday");
277 return;
278 }
279}
280
281void mrb_target_board_final()
282{
283 close(sock);
284}
285
286void mrb_target_board_break()
287{
288 raise(SIGUSR1);
289}
290
291/*
292 * アプリケーションタスクの登録
293 */
294static mrb_value mrb_target_board_wait_msg(mrb_state *mrb, mrb_value self)
295{
296 int tmr;
297 struct timeval timer, *ptimer;
298 struct timeval now, elps;
299 int ret, ret2;
300 struct udp_msg _msg;
301 struct udp_msg *msg = &_msg;
302 mrb_value arv[3];
303 fd_set readfds, writefds, errorfds;
304
305 mrb_get_args(mrb, "i", &tmr);
306
307 if (tmr < 0)
308 ptimer = NULL;
309 else {
310 timer.tv_sec = tmr / 1000;
311 timer.tv_usec = (tmr % 1000) * 1000;
312 ptimer = &timer;
313 }
314
315 FD_ZERO(&readfds);
316 FD_ZERO(&writefds);
317 FD_ZERO(&errorfds);
318 FD_SET(sock, &readfds);
319 FD_SET(sock, &writefds);
320 FD_SET(sock, &errorfds);
321
322 /* メッセージ待
323ち */
324 memset(msg, 0, sizeof(*msg));
325 ret = select(sock + 1, &readfds, &writefds, &errorfds, ptimer);
326 if (ret < 0)
327 mrb_raise(mrb, E_RUNTIME_ERROR, "socket select error");
328 if (FD_ISSET(sock, &readfds)) {
329 int fromlen = sizeof(msg->dst);
330 msg->len = recvfrom(sock, msg->buffer, sizeof(msg->buffer), 0, &msg->dst, &fromlen);
331 if (msg->len < 0) {
332 printf("recvfrom %d", msg->len);
333 return mrb_nil_value();
334 }
335 }
336
337 ret2 = gettimeofday(&now, NULL);
338 if (ret2 != 0) {
339 printf("gettimeofday");
340 return mrb_nil_value();
341 }
342
343 timersub(&now, &main_time, &elps);
344 arv[0] = mrb_fixnum_value(elps.tv_sec);
345 main_time = now;
346
347 /* タイムアウトの場合 */
348 if (ret == 0) {
349 return mrb_ary_new_from_values(mrb, 1, arv);
350 }
351
352 /* 内
353部イベントの場合 */
354 if (msg->dst.sin_addr.s_addr == 0) {
355 /* Ethernet Link up */
356 if (msg->buffer[0] & IF_FLAG_LINK_UP) {
357 arv[1] = mrb_fixnum_value(1);
358 }
359 /* EP Link up */
360 else if (msg->buffer[0] & IF_FLAG_UP) {
361 arv[1] = mrb_fixnum_value(2);
362 }
363
364 return mrb_ary_new_from_values(mrb, 2, arv);
365 }
366 /* Echonet電文受信の場合 */
367 else {
368 /* 通信端点 */
369 arv[1] = mrb_str_new(mrb, (char *)&msg->dst, sizeof(msg->dst));
370
371 /* 受信データ */
372 arv[2] = mrb_str_new(mrb, (char *)msg->buffer, msg->len);
373
374 return mrb_ary_new_from_values(mrb, 3, arv);
375 }
376}
377
378/*
379 * アプリケーションタスクの登録
380 */
381static mrb_value mrb_target_board_restart(mrb_state *mrb, mrb_value self)
382{
383 /* DHCP開始 */
384
385 return self;
386}
387
388/*
389 * 通信レイヤーへの送信
390 */
391static mrb_value mrb_target_board_snd_msg(mrb_state *mrb, mrb_value self)
392{
393 mrb_value rep;
394 mrb_value rdat;
395 struct sockaddr_in *ep;
396 int ret;
397
398 mrb_get_args(mrb, "SS", &rep, &rdat);
399
400 if (RSTRING_LEN(rep) != sizeof(struct sockaddr_in)) {
401 mrb_raise(mrb, E_RUNTIME_ERROR, "snd_msg");
402 return mrb_nil_value();
403 }
404
405 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
406
407 ret = sendto(sock, RSTRING_PTR(rdat), RSTRING_LEN(rdat), 0, (struct sockaddr *)ep, sizeof(*ep));
408 if (ret < 0) {
409 mrb_raise(mrb, E_RUNTIME_ERROR, "sendto");
410 return mrb_nil_value();
411 }
412
413 return mrb_nil_value();
414}
415
416/*
417 * ローカルアドレスか確認
418 */
419static mrb_value mrb_target_board_is_local_addr(mrb_state *mrb, mrb_value self)
420{
421 mrb_value rep;
422 struct sockaddr_in *ep;
423
424 mrb_get_args(mrb, "S", &rep);
425
426 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
427 mrb_raise(mrb, E_RUNTIME_ERROR, "is_local_addr");
428 return mrb_nil_value();
429 }
430
431 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
432
433 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(127, 0, 0, 1)) ? mrb_true_value() : mrb_false_value();
434}
435
436/*
437 * マルチキャストアドレスか確認
438 */
439static mrb_value mrb_target_board_is_multicast_addr(mrb_state *mrb, mrb_value self)
440{
441 mrb_value rep;
442 struct sockaddr_in *ep;
443
444 mrb_get_args(mrb, "S", &rep);
445
446 if (RSTRING_LEN(rep) < sizeof(struct sockaddr_in)) {
447 mrb_raise(mrb, E_RUNTIME_ERROR, "is_multicast_addr");
448 return mrb_nil_value();
449 }
450
451 ep = (struct sockaddr_in *)RSTRING_PTR(rep);
452
453 return (ep->sin_addr.s_addr == MAKE_IPV4_ADDR(224, 0, 23, 0)) ? mrb_true_value() : mrb_false_value();
454}
455
456/*
457 * 同一アドレスか確認
458 */
459static mrb_value mrb_target_board_equals_addr(mrb_state *mrb, mrb_value self)
460{
461 mrb_value rep1, rep2;
462 struct sockaddr_in *ep1, *ep2;
463
464 mrb_get_args(mrb, "SS", &rep1, &rep2);
465
466 if ((RSTRING_LEN(rep1) != sizeof(struct sockaddr_in)) || (RSTRING_LEN(rep2) != sizeof(struct sockaddr_in))) {
467 mrb_raise(mrb, E_RUNTIME_ERROR, "equals_addr");
468 return mrb_nil_value();
469 }
470
471 ep1 = (struct sockaddr_in *)RSTRING_PTR(rep1);
472 ep2 = (struct sockaddr_in *)RSTRING_PTR(rep2);
473
474 return (ep1->sin_addr.s_addr == ep2->sin_addr.s_addr) ? mrb_true_value() : mrb_false_value();
475}
476
477/*
478 * ローカルアドレスの取得
479 */
480static mrb_value mrb_target_board_get_local_addr(mrb_state *mrb, mrb_value self)
481{
482 struct sockaddr_in ep;
483 mrb_value rep;
484
485 memset(&ep, 0, sizeof(ep));
486 ep.sin_family = AF_INET;
487 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(127, 0, 0, 1);
488 ep.sin_port = htons(3610);
489
490 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
491
492 return rep;
493}
494
495/*
496 * マルチキャストアドレスの取得
497 */
498static mrb_value mrb_target_board_get_multicast_addr(mrb_state *mrb, mrb_value self)
499{
500 struct sockaddr_in ep;
501 mrb_value rep;
502
503 memset(&ep, 0, sizeof(ep));
504 ep.sin_family = AF_INET;
505 ep.sin_addr.s_addr = MAKE_IPV4_ADDR(224, 0, 23, 0);
506 ep.sin_port = htons(3610);
507
508 rep = mrb_str_new(mrb, (char *)&ep, sizeof(ep));
509
510 return rep;
511}
512
513void mrb_mruby_others_gem_init(mrb_state* mrb)
514{
515 if (!echonet)
516 return;
517
518 _module_target_board = mrb_define_module(mrb, "TargetBoard");
519
520 mrb_define_class_method(mrb, _module_target_board, "wait_msg", mrb_target_board_wait_msg, MRB_ARGS_REQ(1));
521 mrb_define_class_method(mrb, _module_target_board, "restart", mrb_target_board_restart, MRB_ARGS_NONE());
522 mrb_define_class_method(mrb, _module_target_board, "snd_msg", mrb_target_board_snd_msg, MRB_ARGS_REQ(2));
523 mrb_define_class_method(mrb, _module_target_board, "is_local_addr", mrb_target_board_is_local_addr, MRB_ARGS_REQ(1));
524 mrb_define_class_method(mrb, _module_target_board, "is_multicast_addr", mrb_target_board_is_multicast_addr, MRB_ARGS_REQ(1));
525 mrb_define_class_method(mrb, _module_target_board, "equals_addr", mrb_target_board_equals_addr, MRB_ARGS_REQ(2));
526 mrb_define_class_method(mrb, _module_target_board, "get_local_addr", mrb_target_board_get_local_addr, MRB_ARGS_NONE());
527 mrb_define_class_method(mrb, _module_target_board, "get_multicast_addr", mrb_target_board_get_multicast_addr, MRB_ARGS_NONE());
528
529 mrb_target_board_init();
530}
531
532void mrb_mruby_others_gem_final(mrb_state* mrb)
533{
534 if (!echonet)
535 return;
536
537 mrb_target_board_final();
538}
539
540// Provide implementation of _sbrk (low-level dynamic memory allocation
541// routine) for GCC_ARM which compares new heap pointer with MSP instead of
542// SP. This make it compatible with RTX RTOS thread stacks.
543
544// Linker defined symbol used by _sbrk to indicate where heap should start.
545int _end;
546uint32_t _stack;
547
548// Turn off the errno macro and use actual global variable instead.
549#undef errno
550int errno;
551
552static unsigned char* heap = (unsigned char*)&_end;
553
554// Dynamic memory allocation related syscall.
555caddr_t _sbrk(int incr) {
556 unsigned char* prev_heap = heap;
557 unsigned char* new_heap = heap + incr;
558
559 if (new_heap >= (unsigned char*)&_stack) { /* _stack is end of heap section */
560 errno = ENOMEM;
561 return (caddr_t)-1;
562 }
563
564 heap = new_heap;
565 return (caddr_t) prev_heap;
566}
567
568char *optarg;
569int _data, _mdata, _edata;
570int _bss, _ebss;
571
572int _PowerON_Reset(int argc, char **argv)
573{
574 memcpy(&_data, &_mdata, (size_t)&_edata - (size_t)&_data);
575 memset(&_bss, 0, (size_t)&_ebss - (size_t)&_bss);
576
577 optarg = *argv;
578 return main(argc, argv);
579}
580
581#define FVECT_SECT __attribute__ ((section (".fvectors")))
582const void *HardwareVectors[] FVECT_SECT = {
583 _PowerON_Reset,
584 mrdb_break,
585};
586
587char stack_space[0x100000] __attribute__ ((section (".stack")));
Note: See TracBrowser for help on using the repository browser.