@@ -43,6 +43,7 @@ struct native_pty_status {
4343 int out_fd ; /* File descriptor used for output */
4444 int in_fd ; /* File descriptor used for input */
4545 bool on_stdinout ; /* This UART is connected to a PTY and not STDIN/OUT */
46+ bool stdin_disconnected ;
4647
4748 bool auto_attach ; /* For PTY, attach a terminal emulator automatically */
4849 char * auto_attach_cmd ; /* If auto_attach, which command to launch the terminal emulator */
@@ -64,6 +65,18 @@ struct native_pty_status {
6465 K_KERNEL_STACK_MEMBER (rx_stack , CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE );
6566 } async ;
6667#endif /* CONFIG_UART_ASYNC_API */
68+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
69+ struct {
70+ bool tx_enabled ;
71+ bool rx_enabled ;
72+ uart_irq_callback_user_data_t callback ;
73+ void * cb_data ;
74+ /* Instance-specific IRQ emulation thread. */
75+ struct k_thread poll_thread ;
76+ /* Stack for IRQ emulation thread */
77+ K_KERNEL_STACK_MEMBER (poll_stack , CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE );
78+ } irq ;
79+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
6780};
6881
6982static void np_uart_poll_out (const struct device * dev , unsigned char out_char );
@@ -81,6 +94,22 @@ static int np_uart_rx_enable(const struct device *dev, uint8_t *buf, size_t len,
8194static int np_uart_rx_disable (const struct device * dev );
8295#endif /* CONFIG_UART_ASYNC_API */
8396
97+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
98+ static int np_uart_fifo_fill (const struct device * dev , const uint8_t * tx_data , int size );
99+ static int np_uart_fifo_read (const struct device * dev , uint8_t * rx_data , const int size );
100+ static void np_uart_irq_tx_enable (const struct device * dev );
101+ static void np_uart_irq_tx_disable (const struct device * dev );
102+ static int np_uart_irq_tx_ready (const struct device * dev );
103+ static int np_uart_irq_tx_complete (const struct device * dev );
104+ static void np_uart_irq_rx_enable (const struct device * dev );
105+ static void np_uart_irq_rx_disable (const struct device * dev );
106+ static int np_uart_irq_rx_ready (const struct device * dev );
107+ static int np_uart_irq_is_pending (const struct device * dev );
108+ static int np_uart_irq_update (const struct device * dev );
109+ static void np_uart_irq_callback_set (const struct device * dev , uart_irq_callback_user_data_t cb ,
110+ void * cb_data );
111+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
112+
84113static DEVICE_API (uart , np_uart_driver_api ) = {
85114 .poll_out = np_uart_poll_out ,
86115 .poll_in = np_uart_poll_in ,
@@ -92,6 +121,20 @@ static DEVICE_API(uart, np_uart_driver_api) = {
92121 .rx_enable = np_uart_rx_enable ,
93122 .rx_disable = np_uart_rx_disable ,
94123#endif /* CONFIG_UART_ASYNC_API */
124+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
125+ .fifo_fill = np_uart_fifo_fill ,
126+ .fifo_read = np_uart_fifo_read ,
127+ .irq_tx_enable = np_uart_irq_tx_enable ,
128+ .irq_tx_disable = np_uart_irq_tx_disable ,
129+ .irq_tx_ready = np_uart_irq_tx_ready ,
130+ .irq_tx_complete = np_uart_irq_tx_complete ,
131+ .irq_rx_enable = np_uart_irq_rx_enable ,
132+ .irq_rx_disable = np_uart_irq_rx_disable ,
133+ .irq_rx_ready = np_uart_irq_rx_ready ,
134+ .irq_is_pending = np_uart_irq_is_pending ,
135+ .irq_update = np_uart_irq_update ,
136+ .irq_callback_set = np_uart_irq_callback_set ,
137+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
95138};
96139
97140#define NATIVE_PTY_INSTANCE (inst ) \
@@ -192,61 +235,49 @@ static void np_uart_poll_out(const struct device *dev, unsigned char out_char)
192235}
193236
194237/**
195- * @brief Poll the device for input.
238+ * @brief Poll the device for up to len input characters
196239 *
197240 * @param dev UART device structure.
198241 * @param p_char Pointer to character.
199242 *
200- * @retval 0 If a character arrived and was stored in p_char
243+ * @retval > 0 If a character arrived and was stored in p_char
244+ * @retval == 0 If a character arrived but len was 0
201245 * @retval -1 If no character was available to read
202246 */
203- static int np_uart_stdin_poll_in (const struct device * dev , unsigned char * p_char )
247+ static int np_uart_poll_in_n (const struct device * dev , unsigned char * p_char , int len )
204248{
205- int in_f = (( struct native_pty_status * ) dev -> data ) -> in_fd ;
206- static bool disconnected ;
207- int rc ;
249+ int rc = -1 ;
250+ struct native_pty_status * data = ( struct native_pty_status * ) dev -> data ;
251+ int in_f = data -> in_fd ;
208252
209- if (disconnected == true ) {
253+ if (data -> stdin_disconnected ) {
210254 return -1 ;
211255 }
212256
213- rc = np_uart_stdin_poll_in_bottom (in_f , p_char , 1 );
214- if (rc == -2 ) {
215- disconnected = true;
257+ if (data -> on_stdinout ) {
258+ rc = np_uart_stdin_poll_in_bottom (in_f , p_char , len );
259+
260+ if (rc == -2 ) {
261+ data -> stdin_disconnected = true;
262+ return -1 ;
263+ }
264+ } else {
265+ rc = np_uart_pty_poll_in_bottom (in_f , p_char , len );
216266 }
217- return rc == 1 ? 0 : -1 ;
267+
268+ return rc ;
218269}
219270
220- /**
221- * @brief Poll the device for input.
222- *
223- * @param dev UART device structure.
224- * @param p_char Pointer to character.
225- *
226- * @retval 0 If a character arrived and was stored in p_char
227- * @retval -1 If no character was available to read
228- */
229- static int np_uart_pty_poll_in (const struct device * dev , unsigned char * p_char )
271+ static int np_uart_poll_in (const struct device * dev , unsigned char * p_char )
230272{
231- int n = -1 ;
232- int in_f = ((struct native_pty_status * )dev -> data )-> in_fd ;
273+ int ret = np_uart_poll_in_n (dev , p_char , 1 );
233274
234- n = nsi_host_read (in_f , p_char , 1 );
235- if (n == -1 ) {
275+ if (ret == -1 ) {
236276 return -1 ;
237277 }
238278 return 0 ;
239279}
240280
241- static int np_uart_poll_in (const struct device * dev , unsigned char * p_char )
242- {
243- if (((struct native_pty_status * )dev -> data )-> on_stdinout ) {
244- return np_uart_stdin_poll_in (dev , p_char );
245- } else {
246- return np_uart_pty_poll_in (dev , p_char );
247- }
248- }
249-
250281#ifdef CONFIG_UART_ASYNC_API
251282
252283static int np_uart_callback_set (const struct device * dev , uart_callback_t callback , void * user_data )
@@ -337,8 +368,7 @@ static void native_pty_uart_async_poll_function(void *arg1, void *arg2, void *ar
337368 ARG_UNUSED (arg3 );
338369
339370 while (data -> async .rx_len ) {
340- rc = np_uart_stdin_poll_in_bottom (data -> in_fd , data -> async .rx_buf ,
341- data -> async .rx_len );
371+ rc = np_uart_poll_in_n (dev , data -> async .rx_buf , data -> async .rx_len );
342372 if (rc > 0 ) {
343373 /* Data received */
344374 evt .type = UART_RX_RDY ;
@@ -403,6 +433,179 @@ static int np_uart_rx_disable(const struct device *dev)
403433
404434#endif /* CONFIG_UART_ASYNC_API */
405435
436+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
437+ static void np_uart_irq_handler (const struct device * dev )
438+ {
439+ struct native_pty_status * data = dev -> data ;
440+
441+ if (data -> irq .callback ) {
442+ data -> irq .callback (dev , data -> irq .cb_data );
443+ } else {
444+ WARN ("No callback!\n" );
445+ }
446+ }
447+
448+ /*
449+ * Emulate uart interrupts using a polling thread
450+ */
451+ static void np_uart_irq_thread (void * arg1 , void * arg2 , void * arg3 )
452+ {
453+ ARG_UNUSED (arg2 );
454+ ARG_UNUSED (arg3 );
455+
456+ struct device * dev = (struct device * )arg1 ;
457+ struct native_pty_status * data = dev -> data ;
458+
459+ while (1 ) {
460+ if (data -> irq .rx_enabled ) {
461+ int ret = np_uart_poll_in_n (dev , NULL , 0 );
462+
463+ if (ret == 0 ) {
464+ np_uart_irq_handler (dev );
465+ } else if (ret == -1 ) {
466+ k_sleep (K_MSEC (1 ));
467+ } else {
468+ WARN ("Poll returned error %d\n" , ret );
469+ }
470+ }
471+ if (data -> irq .tx_enabled ) {
472+ np_uart_irq_handler (dev );
473+ }
474+ if (!data -> irq .tx_enabled && !data -> irq .rx_enabled ) {
475+ break ; /* No IRQs enabled, exit the thread */
476+ }
477+ }
478+ }
479+
480+ static void np_uart_irq_thread_start (const struct device * dev )
481+ {
482+ struct native_pty_status * data = dev -> data ;
483+
484+ /* Create a thread which will wait for data - replacement for IRQ */
485+ k_thread_create (& data -> irq .poll_thread , data -> irq .poll_stack ,
486+ K_KERNEL_STACK_SIZEOF (data -> irq .poll_stack ),
487+ np_uart_irq_thread ,
488+ (void * )dev , NULL , NULL ,
489+ K_HIGHEST_THREAD_PRIO , 0 , K_NO_WAIT );
490+ }
491+
492+ static void np_uart_irq_thread_stop (const struct device * dev )
493+ {
494+ struct native_pty_status * data = dev -> data ;
495+
496+ /* Wait for IRQ thread to terminate */
497+ k_thread_join (& data -> irq .poll_thread , K_FOREVER );
498+ }
499+
500+ static int np_uart_fifo_fill (const struct device * dev , const uint8_t * tx_data , int size )
501+ {
502+ for (int i = 0 ; i < size ; i ++ ) {
503+ np_uart_poll_out (dev , tx_data [i ]);
504+ }
505+
506+ return size ;
507+ }
508+
509+ static int np_uart_fifo_read (const struct device * dev , uint8_t * rx_data , const int size )
510+ {
511+ return np_uart_poll_in_n (dev , rx_data , size );
512+ }
513+
514+ static int np_uart_irq_tx_ready (const struct device * dev )
515+ {
516+ struct native_pty_status * data = dev -> data ;
517+
518+ return data -> irq .tx_enabled ? 1 : 0 ;
519+ }
520+
521+ static int np_uart_irq_tx_complete (const struct device * dev )
522+ {
523+ ARG_UNUSED (dev );
524+
525+ return 1 ;
526+ }
527+
528+ static void np_uart_irq_tx_enable (const struct device * dev )
529+ {
530+ struct native_pty_status * data = dev -> data ;
531+
532+ bool start_thread = !data -> irq .rx_enabled && !data -> irq .tx_enabled ;
533+
534+ data -> irq .tx_enabled = true;
535+
536+ if (start_thread ) {
537+ np_uart_irq_thread_start (dev );
538+ }
539+ }
540+
541+ static void np_uart_irq_tx_disable (const struct device * dev )
542+ {
543+ struct native_pty_status * data = dev -> data ;
544+
545+ data -> irq .tx_enabled = false;
546+
547+ if (!data -> irq .rx_enabled && !data -> irq .tx_enabled ) {
548+ np_uart_irq_thread_stop (dev );
549+ }
550+ }
551+
552+ static void np_uart_irq_rx_enable (const struct device * dev )
553+ {
554+ struct native_pty_status * data = dev -> data ;
555+
556+ bool start_thread = !data -> irq .rx_enabled && !data -> irq .tx_enabled ;
557+
558+ data -> irq .rx_enabled = true;
559+
560+ if (start_thread ) {
561+ np_uart_irq_thread_start (dev );
562+ }
563+ }
564+
565+ static void np_uart_irq_rx_disable (const struct device * dev )
566+ {
567+ struct native_pty_status * data = dev -> data ;
568+
569+ data -> irq .rx_enabled = false;
570+
571+ if (!data -> irq .rx_enabled && !data -> irq .tx_enabled ) {
572+ np_uart_irq_thread_stop (dev );
573+ }
574+ }
575+
576+ static int np_uart_irq_rx_ready (const struct device * dev )
577+ {
578+ struct native_pty_status * data = dev -> data ;
579+
580+ if (data -> irq .rx_enabled && np_uart_poll_in_n (dev , NULL , 0 ) == 0 ) {
581+ return 1 ;
582+ }
583+ return 0 ;
584+ }
585+
586+ static int np_uart_irq_is_pending (const struct device * dev )
587+ {
588+ return np_uart_irq_rx_ready (dev ) ||
589+ np_uart_irq_tx_ready (dev );
590+ }
591+
592+ static int np_uart_irq_update (const struct device * dev )
593+ {
594+ ARG_UNUSED (dev );
595+
596+ return 1 ;
597+ }
598+
599+ static void np_uart_irq_callback_set (const struct device * dev , uart_irq_callback_user_data_t cb ,
600+ void * cb_data )
601+ {
602+ struct native_pty_status * data = dev -> data ;
603+
604+ data -> irq .callback = cb ;
605+ data -> irq .cb_data = cb_data ;
606+ }
607+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
608+
406609
407610#define NATIVE_PTY_SET_AUTO_ATTACH_CMD (inst , cmd ) \
408611 native_pty_status_##inst.auto_attach_cmd = cmd;
0 commit comments