@@ -49,7 +49,7 @@ fn with_usb_stdio_global<T>(f: impl FnOnce(&mut UsbStdioGlobal, &mut WriteBufDeq
49
49
}
50
50
51
51
/// The options for the USB serial device configured by [`configure`].
52
- pub trait Options {
52
+ pub trait Options : ' static + Send + Sync {
53
53
/// Handle incoming data.
54
54
///
55
55
/// This method may be called with interrupts disabled. It's safe to write
@@ -60,6 +60,15 @@ pub trait Options {
60
60
fn product_name ( ) -> & ' static str {
61
61
"R3 Example Application Port"
62
62
}
63
+
64
+ /// Return a flag indicating whether the output data should be withheld
65
+ /// from transmission.
66
+ ///
67
+ /// If this flag is changed to `false`, [`poll`] must be called to flush
68
+ /// the data in the transmission buffer.
69
+ fn should_pause_output ( ) -> bool {
70
+ false
71
+ }
63
72
}
64
73
65
74
/// Add a USB serial device to the system and register it as the destination of
@@ -98,7 +107,7 @@ pub const fn configure<System: Kernel, TOptions: Options>(b: &mut CfgBuilder<Sys
98
107
} ) ;
99
108
100
109
// Register the standard output
101
- crate :: stdout:: set_stdout ( NbWriter ) ;
110
+ crate :: stdout:: set_stdout ( NbWriter :: < TOptions > ( core :: marker :: PhantomData ) ) ;
102
111
} )
103
112
. finish ( b) ;
104
113
@@ -114,29 +123,33 @@ pub const fn configure<System: Kernel, TOptions: Options>(b: &mut CfgBuilder<Sys
114
123
InterruptHandler :: build ( )
115
124
. line ( int_num)
116
125
. start ( |_| {
117
- let mut buf = [ 0 ; 64 ] ;
118
- let mut read_len = 0 ;
126
+ poll :: < TOptions > ( ) ;
127
+ } )
128
+ . finish ( b) ;
129
+ }
119
130
120
- // Get the global `UsbStdioGlobal` instance, which should
121
- // have been created by the startup hook above
122
- with_usb_stdio_global ( |g, write_buf| {
123
- g. usb_device . poll ( & mut [ & mut g. serial ] ) ;
131
+ pub fn poll < TOptions : Options > ( ) {
132
+ let mut buf = [ 0 ; 64 ] ;
133
+ let mut read_len = 0 ;
124
134
125
- if let Ok ( len) = g. serial . read ( & mut buf) {
126
- read_len = len;
127
- }
135
+ // Get the global `UsbStdioGlobal` instance, which should
136
+ // have been created by the startup hook above
137
+ with_usb_stdio_global ( |g, write_buf| {
138
+ g. usb_device . poll ( & mut [ & mut g. serial ] ) ;
128
139
129
- g. try_flush ( write_buf) ;
130
- } ) ;
140
+ if let Ok ( len) = g. serial . read ( & mut buf) {
141
+ read_len = len;
142
+ }
131
143
132
- if read_len > 0 {
133
- TOptions :: handle_input ( & buf[ ..read_len] ) ;
134
- }
135
- } )
136
- . finish ( b) ;
144
+ g. try_flush :: < TOptions > ( write_buf) ;
145
+ } ) ;
146
+
147
+ if read_len > 0 {
148
+ TOptions :: handle_input ( & buf[ ..read_len] ) ;
149
+ }
137
150
}
138
151
139
- struct NbWriter ;
152
+ struct NbWriter < TOptions > ( core :: marker :: PhantomData < fn ( ) -> TOptions > ) ;
140
153
141
154
fn map_usb_error_to_nb_error ( e : usb_device:: UsbError ) -> nb:: Error < core:: convert:: Infallible > {
142
155
match e {
@@ -158,22 +171,22 @@ fn map_usb_error_to_nb_error(e: usb_device::UsbError) -> nb::Error<core::convert
158
171
}
159
172
}
160
173
161
- impl embedded_hal:: serial:: Write < u8 > for NbWriter {
174
+ impl < TOptions : Options > embedded_hal:: serial:: Write < u8 > for NbWriter < TOptions > {
162
175
type Error = core:: convert:: Infallible ;
163
176
164
177
fn write ( & mut self , word : u8 ) -> nb:: Result < ( ) , Self :: Error > {
165
178
with_usb_stdio_global ( |g, write_buf| {
166
179
// Push the given byte to the write buffer. Return `WouldBlock` if
167
180
// the buffer is full.
168
181
write_buf. push ( word) . map_err ( |_| nb:: Error :: WouldBlock ) ?;
169
- g. try_flush ( write_buf) ;
182
+ g. try_flush :: < TOptions > ( write_buf) ;
170
183
Ok ( ( ) )
171
184
} )
172
185
}
173
186
174
187
fn flush ( & mut self ) -> nb:: Result < ( ) , Self :: Error > {
175
188
with_usb_stdio_global ( |g, write_buf| {
176
- g. try_flush ( write_buf) ;
189
+ g. try_flush :: < TOptions > ( write_buf) ;
177
190
g. serial . flush ( ) . map_err ( map_usb_error_to_nb_error) ?;
178
191
if !write_buf. is_empty ( ) {
179
192
return Err ( nb:: Error :: WouldBlock ) ;
@@ -184,9 +197,9 @@ impl embedded_hal::serial::Write<u8> for NbWriter {
184
197
}
185
198
186
199
impl UsbStdioGlobal {
187
- fn try_flush ( & mut self , write_buf : & mut WriteBufDeque ) {
188
- // Withhold the data until DTR is asserted and RTS is cleared
189
- if !self . serial . dtr ( ) {
200
+ fn try_flush < TOptions : Options > ( & mut self , write_buf : & mut WriteBufDeque ) {
201
+ // Withhold the data until DTR is asserted
202
+ if !self . serial . dtr ( ) || TOptions :: should_pause_output ( ) {
190
203
return ;
191
204
}
192
205
0 commit comments