source: asp3_tinet_ecnl_rx/trunk/ntshell/src/stdio_stub.c@ 387

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

ファイルディスクリプタ処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 15.9 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2017-2019 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#include "target_serial.h"
47#include "fdtable.h"
48#include "kernel_cfg.h"
49#include <string.h>
50#include <errno.h>
51#include "util/ntstdio.h"
52#include "hal/serial_api.h"
53#include "target_rename.h"
54#include "target_kernel_impl.h"
55#include "syssvc/siofd.h"
56
57#ifdef _DEBUG
58static const char THIS_FILE[] = __FILE__;
59#endif
60
61static unsigned char stdio_xi(struct ntstdio_t *handle);
62static void stdio_xo(struct ntstdio_t *handle, unsigned char c);
63static void stdio_serial_irq_handler(uint32_t id, SerialIrq event);
64
65static int stdio_close(struct SHELL_FILE *fp);
66static size_t stdio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
67static size_t stdio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
68static void stdio_delete(struct SHELL_FILE *fp);
69
70static unsigned char sio_xi(struct ntstdio_t *handle);
71static void sio_xo(struct ntstdio_t *handle, unsigned char c);
72static void sio_serial_irq_handler(uint32_t id, SerialIrq event);
73
74static int sio_close(struct SHELL_FILE *fp);
75static size_t sio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len);
76static size_t sio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len);
77static off_t sio_seek(struct SHELL_FILE *fp, off_t ofs, int org);
78static int sio_ioctl(struct SHELL_FILE *fp, int req, void *arg);
79static bool_t sio_readable(struct SHELL_FILE *fp);
80static bool_t sio_writable(struct SHELL_FILE *fp);
81static void sio_delete(struct SHELL_FILE *fp);
82
83IO_TYPE IO_TYPE_STDIN = { stdio_close, sio_read, stdio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, stdio_delete };
84IO_TYPE IO_TYPE_STDOUT = { stdio_close, stdio_read, sio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, stdio_delete };
85IO_TYPE IO_TYPE_STDERR = { stdio_close, stdio_read, sio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, stdio_delete };
86IO_TYPE IO_TYPE_SIO = { sio_close, sio_read, sio_write, sio_seek, sio_ioctl, sio_readable, sio_writable, sio_delete };
87
88#define STDIO_UART_BUF_SZ 256
89
90typedef struct stdio_sio_t {
91 serial_t serial;
92 ntstdio_t ntstdio;
93 struct SHELL_FILE *fp;
94 unsigned char tx_buf[STDIO_UART_BUF_SZ];
95 int tx_pos_w;
96 int tx_pos_r;
97 unsigned char rx_buf[STDIO_UART_BUF_SZ];
98 int rx_pos_w;
99 int rx_pos_r;
100} stdio_sio_t;
101
102stdio_sio_t stdio_sio;
103
104void sys_init(intptr_t exinf)
105{
106 serial_t *serial = &stdio_sio.serial;
107 ntstdio_t *ntstdio = &stdio_sio.ntstdio;
108
109 serial_init(serial, STDIO_UART_TX, STDIO_UART_RX);
110 serial_baud(serial, UART_BAUDRATE);
111 serial_format(serial, 8, ParityNone, 1);
112
113 ntstdio_init(ntstdio, NTSTDIO_OPTION_LINE_ECHO | NTSTDIO_OPTION_CANON | NTSTDIO_OPTION_LF_CRLF | NTSTDIO_OPTION_LF_CR, stdio_xi, stdio_xo);
114 ntstdio->exinf = (void *)&stdio_sio;
115
116 struct SHELL_FILE *fp;
117
118 fp = fd_to_fp(STDIN_FILENO);
119 fp->handle = SIO_PORTID;
120 fp->exinf = (void *)ntstdio;
121
122 fp = fd_to_fp(STDOUT_FILENO);
123 fp->handle = SIO_PORTID;
124 fp->exinf = (void *)ntstdio;
125
126 fp = fd_to_fp(STDERR_FILENO);
127 fp->handle = SIO_PORTID;
128 fp->exinf = (void *)ntstdio;
129
130 serial_irq_handler(&stdio_sio.serial, stdio_serial_irq_handler, 0);
131
132 serial_irq_set(serial, RxIrq, true);
133}
134
135ID serial_portid;
136
137void stdio_open(ID portid)
138{
139 struct SHELL_FILE *fp;
140
141 serial_portid = portid;
142 serial_ctl_por(portid, IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
143
144 fp = fd_to_fp(STDIN_FILENO);
145 fp->handle = portid;
146
147 fp = fd_to_fp(STDOUT_FILENO);
148 fp->handle = portid;
149
150 fp = fd_to_fp(STDERR_FILENO);
151 fp->handle = portid;
152}
153
154int stdio_close(struct SHELL_FILE *fp)
155{
156 return -EPERM;
157}
158
159size_t stdio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
160{
161 return -EPERM;
162}
163
164size_t stdio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
165{
166 return -EPERM;
167}
168
169void stdio_delete(struct SHELL_FILE *fp)
170{
171}
172
173int sio_close(struct SHELL_FILE *fp)
174{
175 return -EPERM;
176}
177
178size_t sio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
179{
180 int i = 0;
181 while (i < len) {
182 int c = ntstdio_getc((struct ntstdio_t *)fp->exinf);
183 data[i++] = c;
184 if ((c == EOF) || (c == '\n'))
185 break;
186 }
187 return i;
188}
189
190size_t sio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
191{
192 for (int i = 0; i < len; i++) {
193 ntstdio_putc((struct ntstdio_t *)fp->exinf, data[i]);
194 }
195 return len;
196}
197
198off_t sio_seek(struct SHELL_FILE *fp, off_t ofs, int org)
199{
200 return -EPERM;
201}
202
203int sio_tcgetattr(struct SHELL_FILE *fp, struct termios *termios)
204{
205 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
206
207 memset(termios, 0, sizeof(*termios));
208
209 if (ntstdio->option & NTSTDIO_OPTION_LINE_ECHO) {
210 termios->c_lflag |= ECHO;
211 }
212 else {
213 termios->c_lflag &= ~ECHO;
214 }
215 if (ntstdio->option & NTSTDIO_OPTION_CANON) {
216 termios->c_lflag |= ICANON;
217 }
218 else {
219 termios->c_lflag &= ~ICANON;
220 }
221 if (ntstdio->option & NTSTDIO_OPTION_LF_CR) {
222 termios->c_iflag |= INLCR;
223 }
224 else {
225 termios->c_iflag &= ~INLCR;
226 }
227 if (ntstdio->option & NTSTDIO_OPTION_LF_CRLF) {
228 termios->c_oflag |= ONLCR;
229 }
230 else {
231 termios->c_oflag &= ~ONLCR;
232 }
233
234 return 0;
235}
236
237int sio_tcsetattr(struct SHELL_FILE *fp, int optional_actions, const struct termios *termios)
238{
239 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
240
241 if (optional_actions == TCSANOW) {
242 if (termios->c_lflag & ECHO) {
243 ntstdio->option |= NTSTDIO_OPTION_LINE_ECHO;
244 }
245 else {
246 ntstdio->option &= ~NTSTDIO_OPTION_LINE_ECHO;
247 }
248 if (termios->c_lflag & ICANON) {
249 ntstdio->option |= NTSTDIO_OPTION_CANON;
250 }
251 else {
252 ntstdio->option &= ~NTSTDIO_OPTION_CANON;
253 }
254 if (termios->c_iflag & INLCR) {
255 ntstdio->option |= NTSTDIO_OPTION_LF_CR;
256 }
257 else {
258 ntstdio->option &= ~NTSTDIO_OPTION_LF_CR;
259 }
260 if (termios->c_oflag & ONLCR) {
261 ntstdio->option |= NTSTDIO_OPTION_LF_CRLF;
262 }
263 else {
264 ntstdio->option &= ~NTSTDIO_OPTION_LF_CRLF;
265 }
266 return 0;
267 }
268
269 //shell_abort();
270 return 0;
271}
272
273int sio_ioctl(struct SHELL_FILE *fp, int request, void *arg)
274{
275 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO))
276 return -EBADF;
277
278 switch (request) {
279 case TIOCGWINSZ:
280 return 0;
281 case TCGETS:
282 return sio_tcgetattr(fp, (struct termios *)arg);
283 case TCSETS + TCSANOW:
284 case TCSETS + TCSADRAIN:
285 case TCSETS + TCSAFLUSH:
286 return sio_tcsetattr(fp, request - TCSETS, (const struct termios *)arg);
287 }
288
289 return -EINVAL;
290}
291
292bool_t sio_readable(struct SHELL_FILE *fp)
293{
294 return fp->readevt_w != fp->readevt_r;
295}
296
297bool_t sio_writable(struct SHELL_FILE *fp)
298{
299 return fp->writable && (fp->writeevt_w == fp->writeevt_r);
300}
301
302void sio_delete(struct SHELL_FILE *fp)
303{
304 free((stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf);
305 ((struct ntstdio_t *)fp->exinf)->exinf = NULL;
306 free((struct ntstdio_t *)fp->exinf);
307 fp->exinf = NULL;
308}
309
310static unsigned char ntstdio_xi(struct ntstdio_t *handle, struct SHELL_FILE *fp)
311{
312 stdio_sio_t *uart = (stdio_sio_t *)handle->exinf;
313 ER ret;
314 unsigned char c;
315
316 bool_t lock = sense_lock();
317 if (lock)
318 unl_cpu();
319
320 while (uart->rx_pos_w == uart->rx_pos_r) {
321 FLGPTN flgptn = 0, waitptn = 0;
322 FD_SET(fp->fd, (fd_set *)&waitptn);
323
324 ret = wai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn);
325 if (ret != E_OK) {
326 if (lock)
327 loc_cpu();
328 syslog(LOG_ERROR, "wai_flg => %d", ret);
329 return 0;
330 }
331
332 ret = clr_flg(FLG_SELECT_WAIT, ~(flgptn & waitptn));
333 if (ret != E_OK) {
334 syslog(LOG_ERROR, "clr_flg => %d", ret);
335 }
336 }
337
338 if (lock)
339 unl_cpu();
340
341 if (fp->readevt_w != fp->readevt_r) fp->readevt_r++;
342
343 c = uart->rx_buf[uart->rx_pos_r++];
344 if (uart->rx_pos_r >= sizeof(uart->rx_buf))
345 uart->rx_pos_r = 0;
346
347 return c;
348}
349
350extern volatile int ntshell_state;
351extern ID serial_portid;
352
353static void serial_rx_irq_handler(int fd)
354{
355 struct SHELL_FILE *fp = fd_to_fp(fd);
356 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
357 serial_t *serial = (serial_t *)&uart->serial;
358
359 if (serial_readable(serial)) {
360 unsigned char c = (unsigned char)serial_getc(serial);
361
362 if (ntshell_state == 1) {
363 ER ret;
364 FLGPTN flgptn = 0;
365
366 uart->rx_buf[uart->rx_pos_w++] = c;
367 if (uart->rx_pos_w >= sizeof(uart->rx_buf))
368 uart->rx_pos_w = 0;
369
370 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
371
372 FD_SET(fd, (fd_set *)&flgptn);
373
374 ret = set_flg(FLG_SELECT_WAIT, flgptn);
375 if (ret != E_OK) {
376 syslog(LOG_ERROR, "set_flg => %d", ret);
377 }
378 }
379 else
380 sio_isr_rcv(fp->handle, c);
381 }
382}
383
384static void ntstdio_xo(struct ntstdio_t *handle, struct SHELL_FILE *fp, unsigned char c)
385{
386 stdio_sio_t *uart = (stdio_sio_t *)handle->exinf;
387 serial_t *serial = (serial_t *)&uart->serial;
388 ER ret;
389
390 // タスクコンテキストでない場合
391 if (sense_context()) {
392 // 送信可能になるまで待ち
393 while (!serial_writable(serial));
394 // 送信する
395 serial_putc(serial, c);
396 return;
397 }
398
399 // 送信バッファが空で
400 if (uart->tx_pos_w == uart->tx_pos_r) {
401 // 送信可能なら
402 if (serial_writable(serial)) {
403 // 送信する
404 serial_putc(serial, c);
405 return;
406 }
407 }
408
409 // 送信バッファに追加する
410 uart->tx_buf[uart->tx_pos_w++] = c;
411 if (uart->tx_pos_w >= sizeof(uart->tx_buf))
412 uart->tx_pos_w = 0;
413
414 // 送信可能になったら割り込みをもらうよう設定
415 serial_irq_set(serial, TxIrq, true);
416
417 bool_t lock = sense_lock();
418 if (lock)
419 unl_cpu();
420
421 do {
422 FLGPTN flgptn = 0, waitptn = 0;
423 FD_SET(fp->fd, (fd_set *)&waitptn);
424
425 ret = wai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn);
426 if (ret != E_OK) {
427 syslog(LOG_ERROR, "wai_flg => %d", ret);
428 break;
429 }
430
431 ret = clr_flg(FLG_SELECT_WAIT, ~(flgptn & waitptn));
432 if (ret != E_OK) {
433 syslog(LOG_ERROR, "clr_flg => %d", ret);
434 }
435 } while (fp->writeevt_w == fp->writeevt_r);
436
437 fp->writeevt_r++;
438
439 if (lock)
440 loc_cpu();
441}
442
443static void serial_tx_irq_handler(int fd)
444{
445 struct SHELL_FILE *fp = fd_to_fp(fd);
446 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
447 serial_t *serial = (serial_t *)&uart->serial;
448 ER ret;
449 unsigned char c;
450
451 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
452
453 FLGPTN flgptn = 0;
454 FD_SET(fd, (fd_set *)&flgptn);
455
456 ret = set_flg(FLG_SELECT_WAIT, flgptn);
457 if (ret != E_OK) {
458 syslog(LOG_ERROR, "set_flg => %d", ret);
459 }
460
461 // 送信バッファが空なら
462 if (uart->tx_pos_w == uart->tx_pos_r) {
463 // SIOドライバの送信
464 sio_isr_snd(fp->handle);
465 // やっぱり送信バッファが空なら
466 if (uart->tx_pos_w == uart->tx_pos_r) {
467 // 送信割り込み停止
468 serial_irq_set(serial, TxIrq, false);
469 return;
470 }
471 }
472
473 c = uart->tx_buf[uart->tx_pos_r++];
474 if (uart->tx_pos_r >= sizeof(uart->tx_buf))
475 uart->tx_pos_r = 0;
476
477 // 送信する
478 serial_putc(serial, c);
479}
480
481void stdio_serial_irq_handler(uint32_t id, SerialIrq event)
482{
483 switch (event) {
484 case RxIrq:
485 serial_rx_irq_handler(STDIN_FILENO);
486 break;
487 case TxIrq:
488 serial_tx_irq_handler(STDOUT_FILENO);
489 break;
490 }
491}
492
493void sio_serial_irq_handler(uint32_t id, SerialIrq event)
494{
495 struct SHELL_FILE *fp = fd_to_fp(id);
496 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO))
497 return;
498
499 switch (event) {
500 case RxIrq:
501 serial_rx_irq_handler(id);
502 break;
503 case TxIrq:
504 serial_tx_irq_handler(id);
505 break;
506 }
507}
508
509unsigned char stdio_xi(struct ntstdio_t *handle)
510{
511 return ntstdio_xi(handle, fd_to_fp(STDIN_FILENO));
512}
513
514void stdio_xo(struct ntstdio_t *handle, unsigned char c)
515{
516 ntstdio_xo(handle, fd_to_fp(STDOUT_FILENO), c);
517}
518
519unsigned char sio_xi(struct ntstdio_t *handle)
520{
521 return ntstdio_xi(handle, ((stdio_sio_t *)handle->exinf)->fp);
522}
523
524void sio_xo(struct ntstdio_t *handle, unsigned char c)
525{
526 ntstdio_xo(handle, ((stdio_sio_t *)handle->exinf)->fp, c);
527}
528
529int siofd_open(const char *path, int flags, ...)
530{
531 return -1;
532}
533
534int siofd_close(int fd)
535{
536 struct SHELL_FILE *fp = fd_to_fp(fd);
537 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO)) {
538 errno = EBADF;
539 return -1;
540 }
541
542 errno = sio_close(fp);
543 if (errno != 0)
544 return 1;
545 return 0;
546}
547
548ssize_t siofd_read(int fd, void *data, size_t len)
549{
550 struct SHELL_FILE *fp = fd_to_fp(fd);
551 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_SIO))) {
552 errno = EBADF;
553 return -1;
554 }
555 char *pos, *end;
556
557 for (pos = (char *)data, end = &pos[len]; pos < end; pos++) {
558 *pos = ntstdio_xi((struct ntstdio_t *)fp->exinf, fp);
559 }
560
561 return pos - (char *)data;
562}
563
564ssize_t siofd_write(int fd, const void *data, size_t len)
565{
566 struct SHELL_FILE *fp = fd_to_fp(fd);
567 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDOUT) && (fp->type != &IO_TYPE_STDERR)
568 && (fp->type != &IO_TYPE_SIO))) {
569 errno = EBADF;
570 return -1;
571 }
572 const char *pos, *end;
573
574 for (pos = (const char *)data, end = &pos[len]; pos < end; pos++) {
575 ntstdio_xo((struct ntstdio_t *)fp->exinf, fp, *pos);
576 }
577
578 return pos - (char *)data;
579}
580
581int siofd_tcsetattr(int fd, int act, const struct termios *tio)
582{
583 struct SHELL_FILE *fp = fd_to_fp(fd);
584 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
585 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
586 errno = EBADF;
587 return -1;
588 }
589
590 errno = sio_tcsetattr(fp, act, tio);
591 if (errno != 0)
592 return 1;
593 return 0;
594}
595
596int siofd_tcgetattr(int fd, struct termios *tio)
597{
598 struct SHELL_FILE *fp = fd_to_fp(fd);
599 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
600 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
601 errno = EBADF;
602 return -1;
603 }
604
605 errno = sio_tcgetattr(fp, tio);
606 if (errno != 0)
607 return 1;
608 return 0;
609}
610
611int siofd_fcntl(int fd, int cmd, ...)
612{
613 struct SHELL_FILE *fp = fd_to_fp(fd);
614 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
615 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
616 errno = EBADF;
617 return -1;
618 }
619 void *arg;
620 va_list ap;
621 va_start(ap, cmd);
622 arg = va_arg(ap, void *);
623 va_end(ap);
624
625 errno = sio_ioctl(fp, cmd, arg);
626 if (errno != 0)
627 return 1;
628 return 0;
629}
Note: See TracBrowser for help on using the repository browser.