@@ -70,7 +70,7 @@ fn update_status(f: impl FnOnce(&mut ConnectionStatus)) {
7070 // Drain after the commit so any producer racing past the mutex reads
7171 // the new state and routes to the new channel rather than the one
7272 // about to be cleared.
73- crate :: channel:: clear_report_channel ( prev_active) ;
73+ crate :: channel:: clear_and_release_report_channel ( prev_active) ;
7474 }
7575
7676 #[ cfg( feature = "_ble" ) ]
@@ -119,9 +119,9 @@ pub(crate) async fn load_preferred_connection() -> ConnectionType {
119119 #[ cfg( feature = "storage" ) ]
120120 let stored = crate :: storage:: read_connection_type ( ) . await ;
121121 #[ cfg( not( feature = "storage" ) ) ]
122- let stored: Option < u8 > = None ;
122+ let stored: Option < ConnectionType > = None ;
123123 match stored {
124- Some ( c) => c. into ( ) ,
124+ Some ( c) => c,
125125 #[ cfg( feature = "_no_usb" ) ]
126126 None => ConnectionType :: Ble ,
127127 #[ cfg( not( feature = "_no_usb" ) ) ]
@@ -160,6 +160,7 @@ mod tests {
160160 set_ble_state, set_preferred_connection, set_usb_state,
161161 } ;
162162 use crate :: event:: { ConnectionChangeEvent , EventSubscriber , SubscribableEvent } ;
163+ use crate :: hid:: { KeyboardReport , Report } ;
163164 use crate :: test_support:: test_block_on as block_on;
164165
165166 fn state_test_lock ( ) -> & ' static Mutex < ( ) > {
@@ -176,6 +177,27 @@ mod tests {
176177 crate :: channel:: BLE_REPORT_CHANNEL . clear ( ) ;
177178 }
178179
180+ fn pressed_keyboard_report ( ) -> Report {
181+ Report :: KeyboardReport ( KeyboardReport {
182+ modifier : 0x02 ,
183+ reserved : 0 ,
184+ leds : 0 ,
185+ keycodes : [ 4 , 0 , 0 , 0 , 0 , 0 ] ,
186+ } )
187+ }
188+
189+ fn assert_all_up_keyboard_report ( report : Report ) {
190+ match report {
191+ Report :: KeyboardReport ( r) => {
192+ assert_eq ! ( r. modifier, 0 ) ;
193+ assert_eq ! ( r. reserved, 0 ) ;
194+ assert_eq ! ( r. leds, 0 ) ;
195+ assert_eq ! ( r. keycodes, [ 0 ; 6 ] ) ;
196+ }
197+ _ => panic ! ( "expected keyboard all-up report" ) ,
198+ }
199+ }
200+
179201 #[ cfg( not( feature = "_no_usb" ) ) ]
180202 #[ test]
181203 fn usb_builds_keep_input_processing_active_without_transport ( ) {
@@ -223,9 +245,8 @@ mod tests {
223245
224246 #[ cfg( not( feature = "_no_usb" ) ) ]
225247 #[ test]
226- fn flipping_away_from_active_clears_its_report_channel ( ) {
248+ fn flipping_away_from_active_clears_stale_reports_and_queues_all_up ( ) {
227249 use crate :: channel:: USB_REPORT_CHANNEL ;
228- use crate :: hid:: { KeyboardReport , Report } ;
229250
230251 let _guard = state_test_lock ( ) . lock ( ) . unwrap ( ) ;
231252 reset_state ( ) ;
@@ -236,18 +257,23 @@ mod tests {
236257 // that would otherwise persist across a flip.
237258 USB_REPORT_CHANNEL . clear ( ) ;
238259 USB_REPORT_CHANNEL
239- . try_send ( Report :: KeyboardReport ( KeyboardReport :: default ( ) ) )
260+ . try_send ( pressed_keyboard_report ( ) )
240261 . expect ( "channel should have capacity for sentinel" ) ;
241262 assert ! ( USB_REPORT_CHANNEL . try_receive( ) . is_ok( ) ) ;
242263 USB_REPORT_CHANNEL
243- . try_send ( Report :: KeyboardReport ( KeyboardReport :: default ( ) ) )
264+ . try_send ( pressed_keyboard_report ( ) )
244265 . expect ( "channel should have capacity for sentinel" ) ;
245266
246267 set_usb_state ( UsbState :: Disabled ) ;
247268 assert ! ( super :: active_transport( ) . is_none( ) ) ;
269+ assert_all_up_keyboard_report (
270+ USB_REPORT_CHANNEL
271+ . try_receive ( )
272+ . expect ( "USB_REPORT_CHANNEL should contain keyboard all-up report" ) ,
273+ ) ;
248274 assert ! (
249275 USB_REPORT_CHANNEL . try_receive( ) . is_err( ) ,
250- "USB_REPORT_CHANNEL should be drained when USB stops being active "
276+ "USB_REPORT_CHANNEL should contain only the all-up report "
251277 ) ;
252278 }
253279
@@ -257,15 +283,14 @@ mod tests {
257283 use embassy_futures:: join:: join;
258284
259285 use crate :: channel:: { USB_REPORT_CHANNEL , send_hid_report} ;
260- use crate :: hid:: { KeyboardReport , Report } ;
261286
262287 let _guard = state_test_lock ( ) . lock ( ) . unwrap ( ) ;
263288 reset_state ( ) ;
264289 set_usb_state ( UsbState :: Configured ) ;
265290
266291 for _ in 0 ..crate :: REPORT_CHANNEL_SIZE {
267292 USB_REPORT_CHANNEL
268- . try_send ( Report :: KeyboardReport ( KeyboardReport :: default ( ) ) )
293+ . try_send ( pressed_keyboard_report ( ) )
269294 . expect ( "channel should have capacity while filling" ) ;
270295 }
271296
@@ -277,7 +302,43 @@ mod tests {
277302 } ,
278303 ) ) ;
279304
280- assert ! ( USB_REPORT_CHANNEL . try_receive( ) . is_err( ) ) ;
305+ assert_all_up_keyboard_report (
306+ USB_REPORT_CHANNEL
307+ . try_receive ( )
308+ . expect ( "USB_REPORT_CHANNEL should contain keyboard all-up report" ) ,
309+ ) ;
310+ assert ! (
311+ USB_REPORT_CHANNEL . try_receive( ) . is_err( ) ,
312+ "USB_REPORT_CHANNEL should contain only the all-up report"
313+ ) ;
314+ }
315+
316+ #[ cfg( all( not( feature = "_no_usb" ) , feature = "_ble" ) ) ]
317+ #[ test]
318+ fn usb_preference_flip_releases_previous_ble_transport ( ) {
319+ use crate :: channel:: BLE_REPORT_CHANNEL ;
320+
321+ let _guard = state_test_lock ( ) . lock ( ) . unwrap ( ) ;
322+ reset_state ( ) ;
323+ set_preferred_connection ( ConnectionType :: Usb ) ;
324+ set_ble_state ( BleState :: Connected ) ;
325+ assert_eq ! ( super :: active_transport( ) , Some ( ConnectionType :: Ble ) ) ;
326+
327+ BLE_REPORT_CHANNEL
328+ . try_send ( pressed_keyboard_report ( ) )
329+ . expect ( "BLE report channel should have capacity for sentinel" ) ;
330+
331+ set_usb_state ( UsbState :: Configured ) ;
332+ assert_eq ! ( super :: active_transport( ) , Some ( ConnectionType :: Usb ) ) ;
333+ assert_all_up_keyboard_report (
334+ BLE_REPORT_CHANNEL
335+ . try_receive ( )
336+ . expect ( "BLE_REPORT_CHANNEL should contain keyboard all-up report" ) ,
337+ ) ;
338+ assert ! (
339+ BLE_REPORT_CHANNEL . try_receive( ) . is_err( ) ,
340+ "BLE_REPORT_CHANNEL should contain only the all-up report"
341+ ) ;
281342 }
282343
283344 #[ test]
@@ -305,7 +366,6 @@ mod tests {
305366 use embassy_futures:: join:: join;
306367
307368 use crate :: channel:: { USB_REPORT_CHANNEL , send_hid_report} ;
308- use crate :: hid:: { KeyboardReport , Report } ;
309369
310370 let _guard = state_test_lock ( ) . lock ( ) . unwrap ( ) ;
311371 reset_state ( ) ;
0 commit comments