From e60e816927f2ac17f0a4b9c055f3620108ad1b78 Mon Sep 17 00:00:00 2001 From: Haobo Gu Date: Tue, 28 May 2024 21:28:07 +0800 Subject: [PATCH] feat(ble): update nrf ble tasks Signed-off-by: Haobo Gu --- rmk/src/ble.rs | 49 ++++++++++++++++++++++++++++---------------- rmk/src/ble/nrf.rs | 51 +++++++++++++++++++++++++++++----------------- 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/rmk/src/ble.rs b/rmk/src/ble.rs index e58de507..6020e2a1 100644 --- a/rmk/src/ble.rs +++ b/rmk/src/ble.rs @@ -6,27 +6,26 @@ pub mod esp; #[cfg(feature = "_nrf_ble")] pub mod nrf; +use defmt::error; +use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Receiver}; use embassy_time::Timer; -use embedded_hal::digital::{InputPin, OutputPin}; #[cfg(feature = "nrf52840_ble")] pub use nrf::SOFTWARE_VBUS; -use crate::{hid::HidWriterWrapper, Keyboard}; +use crate::{ + hid::HidWriterWrapper, keyboard::{write_other_report_to_host, KeyboardReportMessage}, + usb::descriptor::CompositeReportType, +}; -/// BLE keyboard task, run the keyboard with the ble server -pub(crate) async fn keyboard_ble_task< +/// BLE communication task, send reports to host via BLE. +pub(crate) async fn ble_task< 'a, W: HidWriterWrapper, W2: HidWriterWrapper, W3: HidWriterWrapper, W4: HidWriterWrapper, - In: InputPin, - Out: OutputPin, - const ROW: usize, - const COL: usize, - const NUM_LAYER: usize, >( - keyboard: &mut Keyboard<'a, In, Out, ROW, COL, NUM_LAYER>, + keyboard_report_receiver: &mut Receiver<'a, CriticalSectionRawMutex, KeyboardReportMessage, 8>, ble_keyboard_writer: &mut W, ble_media_writer: &mut W2, ble_system_control_writer: &mut W3, @@ -35,12 +34,28 @@ pub(crate) async fn keyboard_ble_task< // Wait 1 seconds, ensure that gatt server has been started Timer::after_secs(1).await; loop { - let _ = keyboard.scan_matrix().await; - keyboard.send_keyboard_report(ble_keyboard_writer).await; - keyboard.send_media_report(ble_media_writer).await; - keyboard - .send_system_control_report(ble_system_control_writer) - .await; - keyboard.send_mouse_report(ble_mouse_writer).await; + match keyboard_report_receiver.receive().await { + KeyboardReportMessage::KeyboardReport(report) => { + match ble_keyboard_writer.write_serialize(&report).await { + Ok(()) => {} + Err(e) => error!("Send keyboard report error: {}", e), + }; + } + KeyboardReportMessage::CompositeReport(report, report_type) => { + match report_type { + CompositeReportType::Media => { + write_other_report_to_host(report, report_type, ble_media_writer).await + } + CompositeReportType::Mouse => { + write_other_report_to_host(report, report_type, ble_mouse_writer).await + } + CompositeReportType::System => { + write_other_report_to_host(report, report_type, ble_system_control_writer) + .await + } + CompositeReportType::None => (), + }; + } + } } } diff --git a/rmk/src/ble/nrf.rs b/rmk/src/ble/nrf.rs index bc5ee927..03b87265 100644 --- a/rmk/src/ble/nrf.rs +++ b/rmk/src/ble/nrf.rs @@ -9,15 +9,12 @@ pub(crate) mod spec; // TODO: Conditional imports should be compatible with more nRF chip models use self::server::BleServer; use crate::{ - ble::{ - keyboard_ble_task, - nrf::{ - advertise::{create_advertisement_data, SCAN_DATA}, - bonder::{BondInfo, Bonder}, - server::BleHidWriter, - }, - }, - keyboard::Keyboard, + ble::{ble_task, nrf::{ + advertise::{create_advertisement_data, SCAN_DATA}, + bonder::{BondInfo, Bonder}, + server::BleHidWriter, + }}, + keyboard::{keyboard_task, Keyboard, KeyboardReportMessage}, storage::{get_bond_info_key, Storage, StorageData}, KeyAction, KeyMap, RmkConfig, }; @@ -33,10 +30,14 @@ use core::{cell::RefCell, mem}; use defmt::*; use embassy_executor::Spawner; #[cfg(not(feature = "nrf52832_ble"))] -use embassy_futures::select::{select, Either}; -use embassy_futures::select::{select4, Either4}; +use embassy_futures::select::Either; +use embassy_futures::select::{select, select4, Either4}; #[cfg(not(feature = "nrf52832_ble"))] use embassy_nrf::usb::vbus_detect::SoftwareVbusDetect; +use embassy_sync::{ + blocking_mutex::raw::CriticalSectionRawMutex, + channel::{Channel, Receiver, Sender}, +}; use embassy_time::Timer; #[cfg(not(feature = "nrf52832_ble"))] use embassy_usb::driver::Driver; @@ -44,7 +45,7 @@ use embedded_hal::digital::{InputPin, OutputPin}; use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash; use heapless::FnvIndexMap; use nrf_softdevice::{ - ble::{gatt_server, Connection, peripheral, security::SecurityHandler as _}, + ble::{gatt_server, peripheral, security::SecurityHandler as _, Connection}, raw, Config, Flash, Softdevice, }; #[cfg(not(feature = "nrf52832_ble"))] @@ -205,6 +206,11 @@ pub async fn initialize_nrf_ble_keyboard_with_config_and_run< LightService::from_config(keyboard_config.light_config), ); + static keyboard_channel: Channel = + Channel::new(); + let mut keyboard_report_sender = keyboard_channel.sender(); + let mut keyboard_report_receiver = keyboard_channel.receiver(); + // Main loop loop { // Init BLE advertising data @@ -228,6 +234,8 @@ pub async fn initialize_nrf_ble_keyboard_with_config_and_run< &mut storage, &mut light_service, &mut vial_service, + &mut keyboard_report_receiver, + &mut keyboard_report_sender, ); info!("Running USB keyboard!"); select(usb_fut, wait_for_usb_suspend()).await; @@ -243,10 +251,6 @@ pub async fn initialize_nrf_ble_keyboard_with_config_and_run< Either::First(re) => match re { Ok(conn) => { info!("Connected to BLE"); - // let mut buf = [0_u8; 64]; - // let l = get_sys_attrs(&conn, &mut buf).unwrap(); - // set_sys_attrs(&conn, Some(&buf[0..l])).unwrap(); - // bonder.save_sys_attrs(&conn); bonder.load_sys_attrs(&conn); let usb_configured = wait_for_usb_configured(); let usb_fut = usb_device.device.run(); @@ -257,6 +261,8 @@ pub async fn initialize_nrf_ble_keyboard_with_config_and_run< &mut keyboard, &mut storage, &mut keyboard_config.ble_battery_config, + &mut keyboard_report_receiver, + &mut keyboard_report_sender, ), select(usb_fut, usb_configured), ) @@ -287,6 +293,8 @@ pub async fn initialize_nrf_ble_keyboard_with_config_and_run< &mut keyboard, &mut storage, &mut keyboard_config.ble_battery_config, + &mut keyboard_report_receiver, + &mut keyboard_report_sender, ) .await } @@ -303,6 +311,8 @@ pub async fn initialize_nrf_ble_keyboard_with_config_and_run< &mut keyboard, &mut storage, &mut keyboard_config.ble_battery_config, + &mut keyboard_report_receiver, + &mut keyboard_report_sender, ) .await } @@ -329,6 +339,8 @@ async fn run_ble_keyboard< keyboard: &mut Keyboard<'a, In, Out, ROW, COL, NUM_LAYER>, storage: &mut Storage, battery_config: &mut BleBatteryConfig<'b>, + keyboard_report_receiver: &mut Receiver<'a, CriticalSectionRawMutex, KeyboardReportMessage, 8>, + keyboard_report_sender: &mut Sender<'a, CriticalSectionRawMutex, KeyboardReportMessage, 8>, ) { info!("Starting GATT server 200 ms later"); Timer::after_millis(200).await; @@ -342,8 +354,9 @@ async fn run_ble_keyboard< // Run the GATT server on the connection. This returns when the connection gets disconnected. let ble_fut = gatt_server::run(&conn, ble_server, |_| {}); - let keyboard_fut = keyboard_ble_task( - keyboard, + let keyboard_fut = keyboard_task(keyboard, keyboard_report_sender); + let ble_task = ble_task( + keyboard_report_receiver, &mut ble_keyboard_writer, &mut ble_media_writer, &mut ble_system_control_writer, @@ -352,7 +365,7 @@ async fn run_ble_keyboard< let storage_fut = storage.run::(); // Exit if anyone of three futures exits - match select4(ble_fut, keyboard_fut, battery_fut, storage_fut).await { + match select4(ble_fut, select(ble_task, keyboard_fut), battery_fut, storage_fut).await { Either4::First(disconnected_error) => error!( "BLE gatt_server run exited with error: {:?}", disconnected_error