source: EcnlProtoTool/trunk/ntshell/src/stdio_stub.c@ 449

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

fdとidの扱いが間違っているのを修正

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.9 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 <kernel.h>
39#include <t_syslog.h>
40#include <t_stdlib.h>
41#include <sil.h>
42#include "syssvc/serial.h"
43#include "syssvc/syslog.h"
44#include "target_syssvc.h"
45#include "fdtable.h"
46#include "kernel_cfg.h"
47#include "util/ntstdio.h"
48#include "hal/serial_api.h"
49#include "target_rename.h"
50#include "target_kernel_impl.h"
51#include "syssvc/siofd.h"
52
53#ifdef _DEBUG
54static const char THIS_FILE[] = __FILE__;
55#endif
56
57#undef errno
58extern int errno;
59
60extern bool_t sio_isr_snd(ID siopid);
61extern bool_t sio_isr_rcv(ID siopid, char c);
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
137void stdio_open(ID portid)
138{
139 struct SHELL_FILE *fp;
140
141 serial_ctl_por(portid, IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV);
142
143 fp = fd_to_fp(STDIN_FILENO);
144 fp->handle = portid;
145
146 fp = fd_to_fp(STDOUT_FILENO);
147 fp->handle = portid;
148
149 fp = fd_to_fp(STDERR_FILENO);
150 fp->handle = portid;
151}
152
153int stdio_close(struct SHELL_FILE *fp)
154{
155 return -EPERM;
156}
157
158size_t stdio_read(struct SHELL_FILE *fp, unsigned char *data, size_t len)
159{
160 return -EPERM;
161}
162
163size_t stdio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
164{
165 return -EPERM;
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 int i = 0;
180 while (i < len) {
181 int c = ntstdio_getc((struct ntstdio_t *)fp->exinf);
182 data[i++] = c;
183 if ((c == EOF) || (c == '\n'))
184 break;
185 }
186 return i;
187}
188
189size_t sio_write(struct SHELL_FILE *fp, const unsigned char *data, size_t len)
190{
191 for (int i = 0; i < len; i++) {
192 ntstdio_putc((struct ntstdio_t *)fp->exinf, data[i]);
193 }
194 return len;
195}
196
197off_t sio_seek(struct SHELL_FILE *fp, off_t ofs, int org)
198{
199 return -EPERM;
200}
201
202int sio_tcgetattr(struct SHELL_FILE *fp, struct termios *termios)
203{
204 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
205
206 memset(termios, 0, sizeof(*termios));
207
208 if (ntstdio->option & NTSTDIO_OPTION_LINE_ECHO) {
209 termios->c_lflag |= ECHO;
210 }
211 else {
212 termios->c_lflag &= ~ECHO;
213 }
214 if (ntstdio->option & NTSTDIO_OPTION_CANON) {
215 termios->c_lflag |= ICANON;
216 }
217 else {
218 termios->c_lflag &= ~ICANON;
219 }
220 if (ntstdio->option & NTSTDIO_OPTION_LF_CR) {
221 termios->c_iflag |= INLCR;
222 }
223 else {
224 termios->c_iflag &= ~INLCR;
225 }
226 if (ntstdio->option & NTSTDIO_OPTION_LF_CRLF) {
227 termios->c_oflag |= ONLCR;
228 }
229 else {
230 termios->c_oflag &= ~ONLCR;
231 }
232
233 return 0;
234}
235
236int sio_tcsetattr(struct SHELL_FILE *fp, int optional_actions, const struct termios *termios)
237{
238 ntstdio_t *ntstdio = (ntstdio_t *)fp->exinf;
239
240 if (optional_actions == TCSANOW) {
241 if (termios->c_lflag & ECHO) {
242 ntstdio->option |= NTSTDIO_OPTION_LINE_ECHO;
243 }
244 else {
245 ntstdio->option &= ~NTSTDIO_OPTION_LINE_ECHO;
246 }
247 if (termios->c_lflag & ICANON) {
248 ntstdio->option |= NTSTDIO_OPTION_CANON;
249 }
250 else {
251 ntstdio->option &= ~NTSTDIO_OPTION_CANON;
252 }
253 if (termios->c_iflag & INLCR) {
254 ntstdio->option |= NTSTDIO_OPTION_LF_CR;
255 }
256 else {
257 ntstdio->option &= ~NTSTDIO_OPTION_LF_CR;
258 }
259 if (termios->c_oflag & ONLCR) {
260 ntstdio->option |= NTSTDIO_OPTION_LF_CRLF;
261 }
262 else {
263 ntstdio->option &= ~NTSTDIO_OPTION_LF_CRLF;
264 }
265 return 0;
266 }
267
268 //shell_abort();
269 return 0;
270}
271
272int sio_ioctl(struct SHELL_FILE *fp, int request, void *arg)
273{
274 switch (request) {
275 case TIOCGWINSZ:
276 return 0;
277 case TCGETS:
278 return sio_tcgetattr(fp, (struct termios *)arg);
279 case TCSETS + TCSANOW:
280 case TCSETS + TCSADRAIN:
281 case TCSETS + TCSAFLUSH:
282 return sio_tcsetattr(fp, request - TCSETS, (const struct termios *)arg);
283 }
284
285 return -EINVAL;
286}
287
288bool_t sio_readable(struct SHELL_FILE *fp)
289{
290 struct ntstdio_t *ntstdio = (struct ntstdio_t *)fp->exinf;
291 stdio_sio_t *uart = (stdio_sio_t *)ntstdio->exinf;
292
293 return uart->rx_pos_r != uart->rx_pos_w;
294}
295
296bool_t sio_writable(struct SHELL_FILE *fp)
297{
298 if (!fp->writable)
299 return false;
300
301 struct ntstdio_t *ntstdio = (struct ntstdio_t *)fp->exinf;
302 stdio_sio_t *uart = (stdio_sio_t *)ntstdio->exinf;
303
304 int tx_pos_w = uart->tx_pos_w + 1;
305 if (tx_pos_w >= sizeof(uart->tx_buf))
306 tx_pos_w = 0;
307 return uart->tx_pos_r != tx_pos_w;
308}
309
310void sio_delete(struct SHELL_FILE *fp)
311{
312 free((stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf);
313 ((struct ntstdio_t *)fp->exinf)->exinf = NULL;
314 free((struct ntstdio_t *)fp->exinf);
315 fp->exinf = NULL;
316}
317
318static unsigned char ntstdio_xi(struct ntstdio_t *handle, struct SHELL_FILE *fp)
319{
320 stdio_sio_t *uart = (stdio_sio_t *)handle->exinf;
321 ER ret;
322 unsigned char c;
323
324 bool_t lock = sense_lock();
325 if (lock)
326 unl_cpu();
327
328 while (uart->rx_pos_w == uart->rx_pos_r) {
329 FLGPTN flgptn = 0, waitptn = 0;
330 FD_SET(fp->fd, (fd_set *)&waitptn);
331
332 ret = wai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn);
333 if (ret != E_OK) {
334 if (lock)
335 loc_cpu();
336 syslog(LOG_ERROR, "wai_flg => %d", ret);
337 return 0;
338 }
339
340 ret = clr_flg(FLG_SELECT_WAIT, ~(flgptn & waitptn));
341 if (ret != E_OK) {
342 syslog(LOG_ERROR, "clr_flg => %d", ret);
343 }
344 }
345
346 if (lock)
347 unl_cpu();
348
349 c = uart->rx_buf[uart->rx_pos_r++];
350 if (uart->rx_pos_r >= sizeof(uart->rx_buf))
351 uart->rx_pos_r = 0;
352
353 if ((uart->rx_pos_r == uart->rx_pos_w)
354 && (fp->readevt_w != fp->readevt_r))
355 fp->readevt_r++;
356
357 return c;
358}
359
360void stdio_input(unsigned char c)
361{
362 struct SHELL_FILE *fp = fd_to_fp(STDIN_FILENO);
363 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
364 serial_t *serial = (serial_t *)&uart->serial;
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(STDIN_FILENO, (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
382static void serial_rx_irq_handler(struct SHELL_FILE *fp)
383{
384 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
385 serial_t *serial = (serial_t *)&uart->serial;
386
387 if (serial_readable(serial)) {
388 unsigned char c = (unsigned char)serial_getc(serial);
389
390 if (fp->fd != STDIN_FILENO) {
391 ER ret;
392 FLGPTN flgptn = 0;
393
394 uart->rx_buf[uart->rx_pos_w++] = c;
395 if (uart->rx_pos_w >= sizeof(uart->rx_buf))
396 uart->rx_pos_w = 0;
397
398 if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
399
400 FD_SET(fp->fd, (fd_set *)&flgptn);
401
402 ret = set_flg(FLG_SELECT_WAIT, flgptn);
403 if (ret != E_OK) {
404 syslog(LOG_ERROR, "set_flg => %d", ret);
405 }
406 }
407 else
408 sio_isr_rcv(fp->handle, c);
409 }
410}
411
412static void ntstdio_xo(struct ntstdio_t *handle, struct SHELL_FILE *fp, unsigned char c)
413{
414 stdio_sio_t *uart = (stdio_sio_t *)handle->exinf;
415 serial_t *serial = (serial_t *)&uart->serial;
416 ER ret;
417
418 // タスクコンテキストでない場合
419 if (sense_context()) {
420 // 送信可能になるまで待ち
421 while (!serial_writable(serial));
422 // 送信する
423 serial_putc(serial, c);
424 return;
425 }
426
427 // 送信バッファが空で
428 if (uart->tx_pos_w == uart->tx_pos_r) {
429 // 送信可能なら
430 if (serial_writable(serial)) {
431 // 送信する
432 serial_putc(serial, c);
433 return;
434 }
435 }
436
437 // 送信バッファに追加する
438 uart->tx_buf[uart->tx_pos_w++] = c;
439 if (uart->tx_pos_w >= sizeof(uart->tx_buf))
440 uart->tx_pos_w = 0;
441
442 // 送信可能になったら割り込みをもらうよう設定
443 serial_irq_set(serial, TxIrq, true);
444
445 bool_t lock = sense_lock();
446 if (lock)
447 unl_cpu();
448
449 // 送信バッファが一杯なら
450 int tx_pos_w = uart->tx_pos_w + 1;
451 if (tx_pos_w >= sizeof(uart->tx_buf))
452 tx_pos_w = 0;
453 while (tx_pos_w == uart->tx_pos_r) {
454 FLGPTN flgptn = 0, waitptn = 0;
455 FD_SET(fp->fd, (fd_set *)&waitptn);
456
457 // 送信完了割り込みまで待つ
458 ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, 1000);
459 if ((ret != E_OK) && (ret != E_TMOUT)) {
460 syslog(LOG_ERROR, "wai_flg => %d", ret);
461 break;
462 }
463
464 ret = clr_flg(FLG_SELECT_WAIT, ~(flgptn & waitptn));
465 if (ret != E_OK) {
466 syslog(LOG_ERROR, "clr_flg => %d", ret);
467 }
468 }
469
470 if (fp->writeevt_w != fp->writeevt_r) fp->writeevt_r++;
471
472 if (lock)
473 loc_cpu();
474}
475
476static void serial_tx_irq_handler(struct SHELL_FILE *fp)
477{
478 stdio_sio_t *uart = (stdio_sio_t *)((struct ntstdio_t *)fp->exinf)->exinf;
479 serial_t *serial = (serial_t *)&uart->serial;
480 ER ret;
481 unsigned char c;
482
483 if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
484
485 FLGPTN flgptn = 0;
486 FD_SET(fp->fd, (fd_set *)&flgptn);
487
488 ret = set_flg(FLG_SELECT_WAIT, flgptn);
489 if (ret != E_OK) {
490 syslog(LOG_ERROR, "set_flg => %d", ret);
491 }
492
493 // 送信バッファが空なら
494 if (uart->tx_pos_w == uart->tx_pos_r) {
495 // SIOドライバの送信
496 sio_isr_snd(fp->handle);
497 // やっぱり送信バッファが空なら
498 if (uart->tx_pos_w == uart->tx_pos_r) {
499 // 送信割り込み停止
500 serial_irq_set(serial, TxIrq, false);
501 return;
502 }
503 }
504
505 c = uart->tx_buf[uart->tx_pos_r++];
506 if (uart->tx_pos_r >= sizeof(uart->tx_buf))
507 uart->tx_pos_r = 0;
508
509 // 送信する
510 serial_putc(serial, c);
511}
512
513void stdio_serial_irq_handler(uint32_t id, SerialIrq event)
514{
515 switch (event) {
516 case RxIrq:
517 serial_rx_irq_handler(fd_to_fp(STDIN_FILENO));
518 break;
519 case TxIrq:
520 serial_tx_irq_handler(fd_to_fp(STDOUT_FILENO));
521 break;
522 }
523}
524
525void sio_serial_irq_handler(uint32_t id, SerialIrq event)
526{
527 struct SHELL_FILE *fp = id_to_fd(&IO_TYPE_SIO, id);
528 if (fp == NULL)
529 return;
530
531 switch (event) {
532 case RxIrq:
533 serial_rx_irq_handler(fp);
534 break;
535 case TxIrq:
536 serial_tx_irq_handler(fp);
537 break;
538 }
539}
540
541unsigned char stdio_xi(struct ntstdio_t *handle)
542{
543 return ntstdio_xi(handle, fd_to_fp(STDIN_FILENO));
544}
545
546void stdio_xo(struct ntstdio_t *handle, unsigned char c)
547{
548 ntstdio_xo(handle, fd_to_fp(STDOUT_FILENO), c);
549}
550
551unsigned char sio_xi(struct ntstdio_t *handle)
552{
553 return ntstdio_xi(handle, ((stdio_sio_t *)handle->exinf)->fp);
554}
555
556void sio_xo(struct ntstdio_t *handle, unsigned char c)
557{
558 ntstdio_xo(handle, ((stdio_sio_t *)handle->exinf)->fp, c);
559}
560
561int siofd_open(const char *path, int flags, ...)
562{
563 return -1;
564}
565
566int siofd_close(int fd)
567{
568 struct SHELL_FILE *fp = fd_to_fp(fd);
569 if ((fp == NULL) || (fp->type != &IO_TYPE_SIO)) {
570 errno = EBADF;
571 return -1;
572 }
573
574 errno = sio_close(fp);
575 if (errno != 0)
576 return 1;
577 return 0;
578}
579
580ssize_t siofd_read(int fd, void *data, size_t len)
581{
582 struct SHELL_FILE *fp = fd_to_fp(fd);
583 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_SIO))) {
584 errno = EBADF;
585 return -1;
586 }
587 char *pos, *end;
588
589 for (pos = (char *)data, end = &pos[len]; pos < end; pos++) {
590 *pos = ntstdio_xi((struct ntstdio_t *)fp->exinf, fp);
591 }
592
593 return pos - (char *)data;
594}
595
596ssize_t siofd_write(int fd, const void *data, size_t len)
597{
598 struct SHELL_FILE *fp = fd_to_fp(fd);
599 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDOUT) && (fp->type != &IO_TYPE_STDERR)
600 && (fp->type != &IO_TYPE_SIO))) {
601 errno = EBADF;
602 return -1;
603 }
604 const char *pos, *end;
605
606 for (pos = (const char *)data, end = &pos[len]; pos < end; pos++) {
607 ntstdio_xo((struct ntstdio_t *)fp->exinf, fp, *pos);
608 }
609
610 return pos - (char *)data;
611}
612
613int siofd_tcsetattr(int fd, int act, const struct termios *tio)
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
622 errno = sio_tcsetattr(fp, act, tio);
623 if (errno != 0)
624 return 1;
625 return 0;
626}
627
628int siofd_tcgetattr(int fd, struct termios *tio)
629{
630 struct SHELL_FILE *fp = fd_to_fp(fd);
631 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
632 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
633 errno = EBADF;
634 return -1;
635 }
636
637 errno = sio_tcgetattr(fp, tio);
638 if (errno != 0)
639 return 1;
640 return 0;
641}
642
643int siofd_fcntl(int fd, int cmd, ...)
644{
645 struct SHELL_FILE *fp = fd_to_fp(fd);
646 if ((fp == NULL) || ((fp->type != &IO_TYPE_STDIN) && (fp->type != &IO_TYPE_STDOUT)
647 && (fp->type != &IO_TYPE_STDERR) && (fp->type != &IO_TYPE_SIO))) {
648 errno = EBADF;
649 return -1;
650 }
651 void *arg;
652 va_list ap;
653 va_start(ap, cmd);
654 arg = va_arg(ap, void *);
655 va_end(ap);
656
657 errno = sio_ioctl(fp, cmd, arg);
658 if (errno != 0)
659 return 1;
660 return 0;
661}
Note: See TracBrowser for help on using the repository browser.