source: asp3_tinet_ecnl_arm/trunk/ntshell/src/stdio_stub.c@ 400

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