23
23
#include <zephyr/sys/speculation.h>
24
24
#include <zephyr/internal/syscall_handler.h>
25
25
#include <zephyr/sys/atomic.h>
26
+ #include <zephyr/device.h>
27
+ #include <zephyr/console/console.h>
28
+ #include <zephyr/console/tty.h>
29
+ #include <zephyr/drivers/uart.h>
26
30
27
31
struct stat ;
28
32
@@ -42,27 +46,42 @@ static const struct fd_op_vtable stdinout_fd_op_vtable;
42
46
BUILD_ASSERT (CONFIG_ZVFS_OPEN_MAX >= 3 , "CONFIG_ZVFS_OPEN_MAX >= 3 for CONFIG_POSIX_DEVICE_IO" );
43
47
#endif /* defined(CONFIG_POSIX_DEVICE_IO) */
44
48
49
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
50
+ static struct tty_serial tty ;
51
+ static uint8_t tty_rxbuf [CONFIG_POSIX_DEVICE_IO_STDIN_BUFSIZE ];
52
+ static uint8_t tty_txbuf [CONFIG_POSIX_DEVICE_IO_STDOUT_BUFSIZE ];
53
+ #endif
54
+
45
55
static struct fd_entry fdtable [CONFIG_ZVFS_OPEN_MAX ] = {
46
56
#if defined(CONFIG_POSIX_DEVICE_IO )
47
57
/*
48
58
* Predefine entries for stdin/stdout/stderr.
49
59
*/
50
60
{
51
61
/* STDIN */
62
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
63
+ .obj = & tty ,
64
+ #endif
52
65
.vtable = & stdinout_fd_op_vtable ,
53
66
.refcount = ATOMIC_INIT (1 ),
54
67
.lock = Z_MUTEX_INITIALIZER (fdtable [0 ].lock ),
55
68
.cond = Z_CONDVAR_INITIALIZER (fdtable [0 ].cond ),
56
69
},
57
70
{
58
71
/* STDOUT */
72
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
73
+ .obj = & tty ,
74
+ #endif
59
75
.vtable = & stdinout_fd_op_vtable ,
60
76
.refcount = ATOMIC_INIT (1 ),
61
77
.lock = Z_MUTEX_INITIALIZER (fdtable [1 ].lock ),
62
78
.cond = Z_CONDVAR_INITIALIZER (fdtable [1 ].cond ),
63
79
},
64
80
{
65
81
/* STDERR */
82
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
83
+ .obj = & tty ,
84
+ #endif
66
85
.vtable = & stdinout_fd_op_vtable ,
67
86
.refcount = ATOMIC_INIT (1 ),
68
87
.lock = Z_MUTEX_INITIALIZER (fdtable [2 ].lock ),
@@ -378,7 +397,7 @@ static ssize_t zvfs_rw(int fd, void *buf, size_t sz, bool is_write, const size_t
378
397
* Seekable file types should support pread() / pwrite() and per-fd offset passing.
379
398
* Otherwise, it's a bug.
380
399
*/
381
- errno = ENOTSUP ;
400
+ errno = ESPIPE ;
382
401
res = -1 ;
383
402
goto unlock ;
384
403
}
@@ -593,16 +612,66 @@ int zvfs_ioctl(int fd, unsigned long request, va_list args)
593
612
* fd operations for stdio/stdout/stderr
594
613
*/
595
614
615
+ int z_impl_zephyr_read_stdin (char * buf , int nbytes );
596
616
int z_impl_zephyr_write_stdout (const char * buf , int nbytes );
597
617
618
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
619
+ static int initialize_tty (struct tty_serial * obj )
620
+ {
621
+ static bool initialized ;
622
+ static int ret ;
623
+
624
+ if (initialized ) {
625
+ return ret ;
626
+ }
627
+ ret = tty_init (obj , DEVICE_DT_GET (DT_CHOSEN (zephyr_console )));
628
+ initialized = true;
629
+ if (ret ) {
630
+ errno = - ret ;
631
+ ret = -1 ;
632
+ return ret ;
633
+ }
634
+ tty_set_tx_buf (obj , tty_txbuf , sizeof (tty_txbuf ));
635
+ tty_set_rx_buf (obj , tty_rxbuf , sizeof (tty_rxbuf ));
636
+ return ret ;
637
+ }
638
+ #endif
639
+
598
640
static ssize_t stdinout_read_vmeth (void * obj , void * buffer , size_t count )
599
641
{
642
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
643
+ int ret = initialize_tty (obj );
644
+
645
+ if (ret ) {
646
+ return ret ;
647
+ }
648
+ ret = tty_read (obj , buffer , count );
649
+ if (ret < -1 ) { /* return no less than -1 as per POSIX; errno is already set */
650
+ return -1 ;
651
+ }
652
+ return ret ;
653
+ #elif defined(CONFIG_NEWLIB_LIBC )
654
+ return z_impl_zephyr_read_stdin (buffer , count );
655
+ #else
600
656
return 0 ;
657
+ #endif
601
658
}
602
659
603
660
static ssize_t stdinout_write_vmeth (void * obj , const void * buffer , size_t count )
604
661
{
605
- #if defined(CONFIG_NEWLIB_LIBC ) || defined(CONFIG_ARCMWDT_LIBC )
662
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
663
+ int ret = initialize_tty (obj );
664
+
665
+ if (ret ) {
666
+ return ret ;
667
+ }
668
+ ret = tty_write (obj , buffer , count );
669
+ if (ret < -1 ) { /* return no less than -1 as per POSIX; errno is already set */
670
+ return -1 ;
671
+ }
672
+ return ret ;
673
+ #elif defined(CONFIG_ARCMWDT_LIBC ) || defined(CONFIG_MINIMAL_LIBC ) || \
674
+ defined(CONFIG_NEWLIB_LIBC ) || defined(CONFIG_PICOLIBC )
606
675
return z_impl_zephyr_write_stdout (buffer , count );
607
676
#else
608
677
return 0 ;
@@ -611,10 +680,69 @@ static ssize_t stdinout_write_vmeth(void *obj, const void *buffer, size_t count)
611
680
612
681
static int stdinout_ioctl_vmeth (void * obj , unsigned int request , va_list args )
613
682
{
614
- errno = EINVAL ;
615
- return -1 ;
616
- }
683
+ #if defined(CONFIG_POSIX_DEVICE_IO_STDIO_CONSOLE )
684
+ struct tty_serial * cons = obj ;
617
685
686
+ if (initialize_tty (cons )) {
687
+ return -1 ;
688
+ }
689
+ #else
690
+ request = 0xffff ;
691
+ #endif
692
+ switch (request ) {
693
+ case ZFD_IOCTL_POLL_PREPARE : {
694
+ __maybe_unused struct zvfs_pollfd * pfd = va_arg (args , struct zvfs_pollfd * );
695
+ struct k_poll_event * * pev = va_arg (args , struct k_poll_event * * );
696
+ struct k_poll_event * pev_end = va_arg (args , struct k_poll_event * );
697
+
698
+ if (* pev == pev_end ) {
699
+ return - ENOMEM ;
700
+ }
701
+ #if CONFIG_POSIX_DEVICE_IO_STDIN_BUFSIZE + CONFIG_POSIX_DEVICE_IO_STDOUT_BUFSIZE > 0
702
+ if ((pfd -> fd == 0 ) && (pfd -> events & ZVFS_POLLIN )) {
703
+ (* pev )-> type = K_POLL_TYPE_SEM_AVAILABLE ;
704
+ (* pev )-> state = K_POLL_STATE_NOT_READY ;
705
+ (* pev )-> sem = & (cons -> rx_sem );
706
+ }
707
+ if (((pfd -> fd == 1 ) || (pfd -> fd == 2 )) && (pfd -> events & ZVFS_POLLOUT )) {
708
+ (* pev )-> type = K_POLL_TYPE_SEM_AVAILABLE ;
709
+ (* pev )-> state = K_POLL_STATE_NOT_READY ;
710
+ (* pev )-> sem = & (cons -> tx_sem );
711
+ }
712
+ #else
713
+ (* pev )-> type = K_POLL_TYPE_IGNORE ;
714
+ (* pev )-> state = K_POLL_STATE_NOT_READY ;
715
+ (* pev )-> obj = NULL ;
716
+ #endif
717
+ (* pev )++ ;
718
+ return 0 ;
719
+ }
720
+ case ZFD_IOCTL_POLL_UPDATE : {
721
+ struct zvfs_pollfd * pfd = va_arg (args , struct zvfs_pollfd * );
722
+ struct k_poll_event * * pev = va_arg (args , struct k_poll_event * * );
723
+
724
+ #if CONFIG_POSIX_DEVICE_IO_STDIN_BUFSIZE + CONFIG_POSIX_DEVICE_IO_STDOUT_BUFSIZE > 0
725
+ if ((* pev )-> state & K_POLL_STATE_SEM_AVAILABLE ) {
726
+ if ((pfd -> fd == 0 ) && (pfd -> events & ZVFS_POLLIN )) {
727
+ pfd -> revents |= ZVFS_POLLIN ;
728
+ }
729
+ if (((pfd -> fd == 1 ) || (pfd -> fd == 2 )) && (pfd -> events & ZVFS_POLLOUT )) {
730
+ pfd -> revents |= ZVFS_POLLOUT ;
731
+ }
732
+ }
733
+ #else
734
+ if (pfd -> events & (ZVFS_POLLIN | ZVFS_POLLPRI | ZVFS_POLLOUT )) {
735
+ pfd -> revents |= ZVFS_POLLNVAL ;
736
+ }
737
+ #endif
738
+ (* pev )++ ;
739
+ return 0 ;
740
+ }
741
+ default :
742
+ errno = EINVAL ;
743
+ return -1 ;
744
+ }
745
+ }
618
746
619
747
static const struct fd_op_vtable stdinout_fd_op_vtable = {
620
748
.read = stdinout_read_vmeth ,
0 commit comments