11use super :: NegErr ;
22use crate :: device:: Device ;
33
4+ use std:: cmp;
5+ use std:: io;
6+ use std:: io:: { Read , Write , Error , ErrorKind } ;
7+
48pub trait UartSyscalls {
59 fn uart_poll_out ( device : & Device , out_char : char ) ;
610
@@ -13,6 +17,91 @@ pub trait UartSyscalls {
1317 fn uart_configure ( device : & Device , config : & UartConfig ) -> Result < ( ) , u32 > ;
1418}
1519
20+ type UartCallback = unsafe extern "C" fn ( * mut u8 , * mut usize ) -> * mut u8 ;
21+
22+ fn uart_pipe_register ( buf : & mut [ u8 ] , cb : UartCallback ) {
23+ unsafe {
24+ zephyr_sys:: raw:: uart_pipe_register ( buf. as_mut_ptr ( ) , buf. len ( ) , Some ( cb) )
25+ } ;
26+ }
27+
28+ pub struct UartDevice ;
29+
30+ const SERIAL_BUF_SIZE : usize = 4096 ;
31+ static mut SERIAL_BUF : [ u8 ; SERIAL_BUF_SIZE ] = [ 0 ; SERIAL_BUF_SIZE ] ;
32+ static mut SERIAL_WRITE_INDEX : usize = 0 ;
33+ static mut SERIAL_READ_INDEX : usize = 0 ;
34+
35+ /// Returns the amount of space that can be written into the serial buffer including wrapping.
36+ unsafe fn serial_buf_space ( ) -> usize {
37+ ( SERIAL_READ_INDEX - SERIAL_WRITE_INDEX - 1 ) & ( SERIAL_BUF_SIZE - 1 )
38+ }
39+
40+ /// Returns the amount of data available for reading in the serial buffer without wrapping.
41+ unsafe fn serial_buf_count_to_end ( ) -> usize {
42+ let end = SERIAL_BUF_SIZE - SERIAL_READ_INDEX ;
43+ let n = ( SERIAL_WRITE_INDEX + end) & ( SERIAL_BUF_SIZE - 1 ) ;
44+ if n < end { n } else { end }
45+ }
46+
47+ #[ no_mangle]
48+ unsafe extern "C" fn rust_uart_cb ( buf : * mut u8 , off : * mut usize ) -> * mut u8 {
49+ let array = std:: slice:: from_raw_parts ( buf, * off) ;
50+ let space = serial_buf_space ( ) ;
51+ let idx = SERIAL_WRITE_INDEX ;
52+ if space < * off {
53+ // XXX: do we need to handle this?
54+ panic ! ( "serial overflow" )
55+ }
56+ if idx + * off < SERIAL_BUF_SIZE {
57+ // easy case, copy in one chunk
58+ SERIAL_BUF [ idx..idx+* off] . copy_from_slice ( & array) ;
59+ } else {
60+ // wrap, copy in two chunks
61+ let len = SERIAL_BUF_SIZE - idx;
62+ SERIAL_BUF [ idx..SERIAL_BUF_SIZE ] . copy_from_slice ( & array[ ..len] ) ;
63+ SERIAL_BUF [ 0 ..* off-len] . copy_from_slice ( & array[ len..] ) ;
64+ }
65+ SERIAL_WRITE_INDEX = ( SERIAL_WRITE_INDEX + * off) & ( SERIAL_BUF_SIZE - 1 ) ;
66+ * off = 0 ;
67+ return buf;
68+ }
69+
70+ impl Read for UartDevice {
71+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
72+ unsafe {
73+ let avail = serial_buf_count_to_end ( ) ;
74+ let idx = SERIAL_READ_INDEX ;
75+ let amt = cmp:: min ( buf. len ( ) , avail) ;
76+ if amt == 0 {
77+ return Err ( Error :: new ( ErrorKind :: WouldBlock , "would block" ) ) ;
78+ }
79+ buf[ ..amt] . copy_from_slice ( & SERIAL_BUF [ idx..idx+amt] ) ;
80+ SERIAL_READ_INDEX = ( SERIAL_READ_INDEX + amt) & ( SERIAL_BUF_SIZE - 1 ) ;
81+ return Ok ( amt) ;
82+ }
83+ }
84+ }
85+
86+ impl Write for UartDevice {
87+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
88+ unsafe {
89+ zephyr_sys:: raw:: uart_pipe_send (
90+ buf. as_ptr ( ) ,
91+ buf. len ( ) as i32
92+ )
93+ } ;
94+
95+ // uart_pipe_send returns an int but it is always 0.
96+ Ok ( buf. len ( ) )
97+ }
98+
99+ fn flush ( & mut self ) -> io:: Result < ( ) > {
100+ Ok ( ( ) )
101+ }
102+ }
103+
104+
16105macro_rules! trait_impl {
17106 ( $context: ident, $context_struct: path) => {
18107 impl UartSyscalls for $context_struct {
0 commit comments