source: asp3_tinet_ecnl_arm/trunk/ntshell/src/fdtable.c@ 374

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

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.8 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2017 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37#include "shellif.h"
38#include <stdint.h>
39#include <kernel.h>
40#include <t_syslog.h>
41#include <t_stdlib.h>
42#include <sil.h>
43#include "syssvc/serial.h"
44#include "syssvc/syslog.h"
45#include "target_syssvc.h"
46#ifndef NTSHELL_NO_SOCKET
47#include <tinet_defs.h>
48#include <tinet_config.h>
49#include <net/net.h>
50#include <net/net_endian.h>
51#include <netinet/in.h>
52#include <netinet/in_itron.h>
53#include <tinet_nic_defs.h>
54#include <tinet_cfg.h>
55#include <netinet/in_var.h>
56#include <net/ethernet.h>
57#include <net/if6_var.h>
58#include <net/net.h>
59#include <net/if_var.h>
60#include <netinet/udp.h>
61#include <netinet/udp_var.h>
62#include <netinet/tcp.h>
63#include <netinet/tcp_var.h>
64#include <net/net_buf.h>
65#endif
66#include "ff.h"
67#include "socket_stub.h"
68#include "kernel_cfg.h"
69#include <string.h>
70#include "util/ntstdio.h"
71#include "hal/serial_api.h"
72
73#ifdef _DEBUG
74static const char THIS_FILE[] = __FILE__;
75#endif
76
77static int stdio_close(struct SHELL_FILE *fp);
78static size_t stdio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
79static size_t stdio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
80static size_t stdin_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
81static size_t stdout_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
82static size_t stderr_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
83static void stdio_delete(struct SHELL_FILE *fp);
84
85static int sio_close(struct SHELL_FILE *fp);
86static size_t sio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
87static size_t sio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
88static off_t sio_seek(struct SHELL_FILE *fp, off_t ofs, int org);
89static int sio_ioctl(struct SHELL_FILE *fp, int req, void *arg);
90static bool_t sio_readable(struct SHELL_FILE *fp);
91static void sio_delete(struct SHELL_FILE *fp);
92
93IO_TYPE IO_TYPE_STDIN = { stdio_close, stdin_read, stdio_write, sio_seek, sio_ioctl, sio_readable, stdio_delete };
94IO_TYPE IO_TYPE_STDOUT = { stdio_close, stdio_read, stdout_write, sio_seek, sio_ioctl, sio_readable, stdio_delete };
95IO_TYPE IO_TYPE_STDERR = { stdio_close, stdio_read, stderr_write, sio_seek, sio_ioctl, sio_readable, stdio_delete };
96IO_TYPE IO_TYPE_SIO = { sio_close, sio_read, sio_write, sio_seek, sio_ioctl, sio_readable, sio_delete };
97ntstdio_t ntstdio;
98
99static struct SHELL_FILE fd_table[8 * sizeof(FLGPTN)] = {
100 { 0, &IO_TYPE_STDIN, 0, .exinf = &ntstdio },
101 { 1, &IO_TYPE_STDOUT, 0, .exinf = &ntstdio },
102 { 2, &IO_TYPE_STDERR, 0,.exinf = &ntstdio },
103};
104#define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
105
106extern ntstdio_t ntstdio;
107extern serial_t stdio_uart;
108
109unsigned char ntstdio_xi(struct ntstdio_t *handle)
110{
111 return serial_getc((serial_t *)handle->exinf);
112}
113
114void ntstdio_xo(struct ntstdio_t *handle, unsigned char c)
115{
116 serial_putc((serial_t *)handle->exinf, c);
117}
118
119void sys_init(intptr_t exinf)
120{
121 ntstdio_init(&ntstdio, NTSTDIO_OPTION_LINE_ECHO | NTSTDIO_OPTION_CANON | NTSTDIO_OPTION_LF_CRLF | NTSTDIO_OPTION_LF_CR, ntstdio_xi, ntstdio_xo);
122 ntstdio.exinf = (void *)&stdio_uart;
123}
124
125int stdio_close(struct SHELL_FILE *fp)
126{
127 return -EPERM;
128}
129
130size_t stdio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
131{
132 return -EPERM;
133}
134
135size_t stdio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
136{
137 return -EPERM;
138}
139
140size_t stdin_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
141{
142 int i = 0;
143 while (i < len) {
144 int c = ntstdio_getc((struct ntstdio_t *)fp->exinf);
145 data[i++] = c;
146 if ((c == EOF) || (c == '\n'))
147 break;
148 }
149 return i;
150}
151
152size_t stdout_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
153{
154 for (int i = 0; i < len; i++) {
155 ntstdio_putc((struct ntstdio_t *)fp->exinf, data[i]);
156 }
157 return len;
158}
159
160size_t stderr_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
161{
162 for (int i = 0; i < len; i++) {
163 ntstdio_putc((struct ntstdio_t *)fp->exinf, data[i]);
164 }
165 return len;
166}
167
168void stdio_delete(struct SHELL_FILE *fp)
169{
170}
171
172int sio_close(struct SHELL_FILE *fp)
173{
174 return -EPERM;
175}
176
177size_t sio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
178{
179 return -EPERM;
180}
181
182size_t sio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
183{
184 return -EPERM;
185}
186
187off_t sio_seek(struct SHELL_FILE *fp, off_t ofs, int org)
188{
189 return -EPERM;
190}
191
192int sio_ioctl(struct SHELL_FILE *fp, int request, void *arg)
193{
194 switch (request) {
195 case TIOCGWINSZ:
196 return 0;
197 case TCGETS:
198 return sio_tcgetattr(fp->fd, (struct termios *)arg);
199 case TCSETS + TCSANOW:
200 case TCSETS + TCSADRAIN:
201 case TCSETS + TCSAFLUSH:
202 return sio_tcsetattr(fp->fd, request - TCSETS, (const struct termios *)arg);
203 }
204
205 return -EINVAL;
206}
207
208bool_t sio_readable(struct SHELL_FILE *fp)
209{
210 return fp->readevt_w != fp->readevt_r;
211}
212
213void sio_delete(struct SHELL_FILE *fp)
214{
215 free((serial_t *)((struct ntstdio_t *)fp->exinf)->exinf);
216 ((struct ntstdio_t *)fp->exinf)->exinf = NULL;
217 free((struct ntstdio_t *)fp->exinf);
218 fp->exinf = NULL;
219}
220
221struct SHELL_FILE *new_fp(IO_TYPE *type, int id, int writable)
222{
223 struct SHELL_FILE *fp = NULL;
224 ER ret;
225
226 ret = wai_sem(SEM_FILEDESC);
227 if (ret < 0) {
228 syslog(LOG_ERROR, "wai_sem => %d", ret);
229 }
230
231 for (int fd = 3; fd < fd_table_count; fd++) {
232 fp = &fd_table[fd];
233 if (fp->type != NULL)
234 continue;
235
236 memset(fp, 0, sizeof(struct SHELL_FILE));
237 fp->fd = fd;
238 fp->type = type;
239 fp->handle = id;
240 fp->writable = writable;
241 break;
242 }
243
244 ret = sig_sem(SEM_FILEDESC);
245 if (ret < 0) {
246 syslog(LOG_ERROR, "sig_sem => %d", ret);
247 }
248
249 return fp;
250}
251
252struct SHELL_FILE *id_to_fd(IO_TYPE *type, int id)
253{
254 struct SHELL_FILE *fp = NULL;
255 ER ret;
256
257 ret = wai_sem(SEM_FILEDESC);
258 if (ret < 0) {
259 syslog(LOG_ERROR, "wai_sem => %d", ret);
260 }
261
262 for (int fd = 3; fd < fd_table_count; fd++) {
263 fp = &fd_table[fd];
264 if ((fp->type == type) && (fp->handle == id))
265 break;
266 }
267
268 ret = sig_sem(SEM_FILEDESC);
269 if (ret < 0) {
270 syslog(LOG_ERROR, "sig_sem => %d", ret);
271 }
272
273 return fp;
274}
275
276int delete_fd_by_id(IO_TYPE *type, int id)
277{
278 struct SHELL_FILE *fp = id_to_fd(type, id);
279 if (fp == NULL)
280 return -EBADF;
281
282 return delete_fp(fp);
283}
284
285int delete_fp(struct SHELL_FILE *fp)
286{
287 ER ret;
288
289 fp->type->delete(fp);
290
291 ret = wai_sem(SEM_FILEDESC);
292 if (ret < 0) {
293 syslog(LOG_ERROR, "wai_sem => %d", ret);
294 }
295
296 memset(fp, 0, sizeof(struct SHELL_FILE));
297
298 ret = sig_sem(SEM_FILEDESC);
299 if (ret < 0) {
300 syslog(LOG_ERROR, "sig_sem => %d", ret);
301 }
302
303 return 0;
304}
305
306struct SHELL_FILE *fd_to_fp(int fd)
307{
308 if ((fd < 0) || (fd >= fd_table_count))
309 return NULL;
310 return &fd_table[fd];
311}
312
313void memand(void *dst, void *src, size_t len)
314{
315 uint8_t *d = (uint8_t *)dst;
316 uint8_t *s = (uint8_t *)src;
317 uint8_t *e = &s[len];
318
319 while (s < e) {
320 *d++ &= *s++;
321 }
322}
323
324struct fd_events {
325 int count;
326 fd_set readfds;
327 fd_set writefds;
328 fd_set errorfds;
329};
330
331ER shell_get_evts(struct fd_events *evts, TMO tmout);
332
333#define TMO_MAX INT_MAX
334
335int shell_select(int n, fd_set *__restrict rfds, fd_set *__restrict wfds, fd_set *__restrict efds, struct timeval *__restrict tv)
336{
337 ER ret;
338 TMO tmout = TMO_FEVR;
339 struct fd_events evts;
340
341 if (tv != NULL) {
342 if (tv->tv_sec < (TMO_MAX / 1000000))
343 tmout = tv->tv_sec * 1000000 + tv->tv_usec;
344 else
345 tmout = TMO_MAX;
346 }
347
348 if (rfds != NULL)
349 memcpy(&evts.readfds, rfds, sizeof(fd_set));
350 else
351 memset(&evts.readfds, 0, sizeof(fd_set));
352 if (wfds != NULL)
353 memcpy(&evts.writefds, wfds, sizeof(fd_set));
354 else
355 memset(&evts.writefds, 0, sizeof(fd_set));
356 if (efds != NULL)
357 memcpy(&evts.errorfds, efds, sizeof(fd_set));
358 else
359 memset(&evts.errorfds, 0, sizeof(fd_set));
360 evts.count = 0;
361
362 ret = shell_get_evts(&evts, tmout);
363 if (ret == E_OK) {
364 if (rfds != NULL)
365 memand(rfds, &evts.readfds, sizeof(fd_set));
366 if (wfds != NULL)
367 memand(wfds, &evts.writefds, sizeof(fd_set));
368 if (efds != NULL)
369 memand(efds, &evts.errorfds, sizeof(fd_set));
370 return evts.count;
371 }
372 if (ret == E_TMOUT) {
373 if (rfds != NULL)
374 memset(rfds, 0, sizeof(fd_set));
375 if (wfds != NULL)
376 memset(wfds, 0, sizeof(fd_set));
377 if (efds != NULL)
378 memset(efds, 0, sizeof(fd_set));
379 return 0;
380 }
381
382 return -EBADF;
383}
384
385int shell_poll(struct pollfd *fds, nfds_t nfds, int timeout)
386{
387 ER ret;
388 TMO tmout;
389 struct fd_events evts;
390
391 if(timeout < 0)
392 tmout = TMO_FEVR;
393 else if (timeout < (TMO_MAX / 1000))
394 tmout = timeout * 1000;
395 else
396 tmout = TMO_MAX;
397
398 memset(&evts, 0, sizeof(evts));
399
400 for (int i = 0; i < nfds; i++) {
401 struct pollfd *pfd = &fds[i];
402 int fd = pfd->fd;
403 if ((fd < 0) || (fd >= fd_table_count))
404 continue;
405
406 if (pfd->events & POLLIN)
407 FD_SET(fd, &evts.readfds);
408 if (pfd->events & POLLOUT)
409 FD_SET(fd, &evts.writefds);
410 if (pfd->events & POLLERR)
411 FD_SET(fd, &evts.errorfds);
412 pfd->revents = 0;
413 }
414
415 ret = shell_get_evts(&evts, tmout);
416 if (ret == E_OK) {
417 int result = 0;
418 for (int i = 0; i < nfds; i++) {
419 struct pollfd *pfd = &fds[i];
420 int fd = pfd->fd;
421 if ((fd < 0) || (fd >= fd_table_count))
422 continue;
423
424 if (FD_ISSET(fd, &evts.readfds))
425 pfd->revents |= POLLIN;
426 if (FD_ISSET(fd, &evts.writefds))
427 pfd->revents |= POLLOUT;
428 if (FD_ISSET(fd, &evts.errorfds))
429 pfd->revents |= POLLERR;
430 if (pfd->revents != 0)
431 result++;
432 }
433 return result;
434 }
435 if (ret == E_TMOUT) {
436 return 0;
437 }
438
439 return -EBADF;
440}
441
442/* TODO:コールバック化したい */
443void stdio_update_evts()
444{
445 int fd = STDIN_FILENO;
446 struct SHELL_FILE *fp = &fd_table[fd];
447 FLGPTN flgptn = 0;
448
449 if (serial_readable((serial_t *)((struct ntstdio_t *)fp->exinf)->exinf)) {
450 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
451
452 FD_SET(fd, (fd_set *)&flgptn);
453 }
454 if (serial_writable((serial_t *)((struct ntstdio_t *)fp->exinf)->exinf)) {
455 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
456
457 FD_SET(fd, (fd_set *)&flgptn);
458 }
459
460 if (flgptn != 0) {
461 set_flg(FLG_SELECT_WAIT, flgptn);
462 }
463}
464
465/* TODO:コールバック化したい */
466void stdio_flgptn(FLGPTN *flgptn)
467{
468 int fd = STDIN_FILENO;
469 struct SHELL_FILE *fp = &fd_table[fd];
470 *flgptn = 0;
471
472 if (serial_readable((serial_t *)((struct ntstdio_t *)fp->exinf)->exinf)) {
473 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
474
475 FD_SET(fd, (fd_set *)flgptn);
476 }
477 if (serial_writable((serial_t *)((struct ntstdio_t *)fp->exinf)->exinf)) {
478 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
479
480 FD_SET(fd, (fd_set *)flgptn);
481 }
482}
483
484ER shell_get_evts(struct fd_events *evts, TMO tmout)
485{
486 int count = 0;
487 SYSTIM prev, now;
488
489 get_tim(&prev);
490
491 for (;;) {
492 ER ret;
493 FLGPTN waitptn, flgptn, readfds = 0, writefds = 0;
494 struct SHELL_FILE *fp = NULL;
495
496 stdio_update_evts();
497
498#ifndef NTSHELL_NO_SOCKET
499 waitptn = *((FLGPTN *)&evts->errorfds);
500#else
501 waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->errorfds);
502#endif
503 for (int fd = 0; fd < fd_table_count; fd++) {
504 fp = &fd_table[fd];
505
506#ifndef NTSHELL_NO_SOCKET
507 if (FD_ISSET(fd, &evts->readfds)) {
508 if (fp->type->readable(fp)) {
509 FD_SET(fd, (fd_set *)&readfds);
510 count++;
511 if (fp->readevt_w == fp->readevt_r) fp->readevt_r--;
512 }
513 else {
514 FD_SET(fd, (fd_set *)&waitptn);
515 }
516 }
517#endif
518 if (FD_ISSET(fd, &evts->writefds)) {
519 if (fp->writeevt_w == fp->writeevt_r) {
520 FD_SET(fd, (fd_set *)&writefds);
521 count++;
522 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_r--;
523 }
524 else {
525 FD_SET(fd, (fd_set *)&waitptn);
526 }
527 }
528 }
529 memset(evts, 0, sizeof(*evts));
530
531 if (waitptn == 0) {
532 memcpy(&evts->readfds, &readfds, sizeof(evts->readfds));
533 memcpy(&evts->writefds, &writefds, sizeof(evts->writefds));
534 evts->count = count;
535 return E_OK;
536 }
537 else if ((readfds | writefds) != 0) {
538 set_flg(FLG_SELECT_WAIT, (readfds | writefds));
539 }
540
541 /* イベント待ち */
542 flgptn = 0;
543 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, tmout);
544 if (ret != E_OK) {
545 if (ret != E_TMOUT) {
546 syslog(LOG_ERROR, "twai_flg => %d", ret);
547 return ret;
548 }
549
550 stdio_flgptn(&flgptn);
551
552 if (flgptn == 0)
553 return E_TMOUT;
554 }
555 flgptn &= waitptn;
556
557 /* 受け取ったフラグのみクリア */
558 ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
559 if (ret != E_OK) {
560 syslog(LOG_ERROR, "clr_flg => %d", ret);
561 }
562
563 count = 0;
564 for (int fd = 0; fd < fd_table_count; fd++) {
565 if (!FD_ISSET(fd, (fd_set *)&waitptn))
566 continue;
567
568 fp = &fd_table[fd];
569
570 if (fp->readevt_w != fp->readevt_r) {
571 fp->readevt_r++;
572 FD_SET(fd, &evts->readfds);
573 count++;
574 }
575 if (fp->writeevt_w != fp->writeevt_r) {
576 fp->writeevt_r++;
577 fp->writable = 1;
578 }
579 if (fp->writable) {
580 FD_SET(fd, &evts->writefds);
581 count++;
582 }
583 if (fp->errorevt_w != fp->errorevt_r) {
584 fp->errorevt_r++;
585 FD_SET(fd, &evts->errorfds);
586 count++;
587 }
588 }
589
590 if (count > 0)
591 break;
592
593 get_tim(&now);
594
595 SYSTIM elapse = now - prev;
596 if (elapse > tmout)
597 return E_TMOUT;
598
599 prev = now;
600 tmout -= elapse;
601 }
602
603 evts->count = count;
604
605 return E_OK;
606}
607
608void clean_fd()
609{
610 struct SHELL_FILE *fp = NULL;
611 for (int fd = 3; fd < fd_table_count; fd++) {
612 fp = &fd_table[fd];
613 if ((fp->type == 0) || (fp->fd == 0))
614 continue;
615
616 fp->type->close(fp);
617
618 delete_fp(fp);
619 }
620}
621
622int shell_ioctl(int fd, int request, void *arg)
623{
624 struct SHELL_FILE *fp = fd_to_fp(fd);
625 if (fp == NULL)
626 return -EBADF;
627
628 return fp->type->ioctl(fp, request, arg);
629}
630
631#ifdef NTSHELL_NO_SOCKET
632
633int shell_socket(int family, int type, int protocol)
634{
635 return -ENOMEM;
636}
637
638int shell_bind(int fd, const struct sockaddr *addr, socklen_t len)
639{
640 return -ENOMEM;
641}
642
643int shell_listen(int fd, int backlog)
644{
645 return -ENOMEM;
646}
647
648int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
649{
650 return -ENOMEM;
651}
652
653int shell_accept(int fd, struct sockaddr *__restrict addr, socklen_t *__restrict len)
654{
655 return -ENOMEM;
656}
657
658ssize_t shell_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
659{
660 return -ENOMEM;
661}
662
663ssize_t shell_sendmsg(int fd, const struct msghdr *msg, int flags)
664{
665 return -ENOMEM;
666}
667
668ssize_t shell_recvfrom(int fd, void *__restrict buf, size_t len, int flags, struct sockaddr *__restrict addr, socklen_t *__restrict alen)
669{
670 return -ENOMEM;
671}
672
673ssize_t shell_recvmsg(int fd, struct msghdr *msg, int flags)
674{
675 return -ENOMEM;
676}
677
678int shell_shutdown(int fd, int how)
679{
680 return -ENOMEM;
681}
682
683int shell_getsockopt(int fd, int level, int optname, void *optval, socklen_t *__restrict optlen)
684{
685 return -ENOMEM;
686}
687
688int shell_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
689{
690 return -ENOMEM;
691}
692
693int shell_getpeername(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
694{
695 return -ENOMEM;
696}
697
698int shell_getsockname(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
699{
700 return -ENOMEM;
701}
702#endif
Note: See TracBrowser for help on using the repository browser.