use core::future::poll_fn;
use embassy_sync::channel::{Channel, TrySendError};
#[cfg(feature = "_ble")]
use embassy_sync::signal::Signal;
pub use embassy_sync::{blocking_mutex, channel, pubsub, zerocopy_channel};
use rmk_types::connection::ConnectionType;
#[cfg(feature = "_ble")]
use {crate::ble::profile::BleProfileAction, rmk_types::led_indicator::LedIndicator};
#[cfg(all(feature = "vial", feature = "_ble"))]
use crate::VIAL_CHANNEL_SIZE;
use crate::event::KeyboardEvent;
use crate::hid::{KeyboardReport, Report};
#[cfg(feature = "storage")]
use crate::{FLASH_CHANNEL_SIZE, storage::FlashOperationMessage};
use crate::{REPORT_CHANNEL_SIZE, RawMutex};
type ReportChannel = Channel<RawMutex, Report, REPORT_CHANNEL_SIZE>;
#[cfg(feature = "_ble")]
pub(crate) static LED_SIGNAL: Signal<RawMutex, LedIndicator> = Signal::new();
#[cfg(not(feature = "_no_usb"))]
pub static USB_REPORT_CHANNEL: ReportChannel = Channel::new();
#[cfg(feature = "_ble")]
pub static BLE_REPORT_CHANNEL: ReportChannel = Channel::new();
fn report_channel(transport: ConnectionType) -> Option<&'static ReportChannel> {
match transport {
#[cfg(not(feature = "_no_usb"))]
ConnectionType::Usb => Some(&USB_REPORT_CHANNEL),
#[cfg(feature = "_ble")]
ConnectionType::Ble => Some(&BLE_REPORT_CHANNEL),
#[allow(unreachable_patterns)]
_ => None,
}
}
fn active_report_channel() -> Option<(ConnectionType, &'static ReportChannel)> {
let transport = crate::state::active_transport()?;
report_channel(transport).map(|ch| (transport, ch))
}
pub(crate) async fn send_hid_report(mut report: Report) {
let Some((transport, ch)) = active_report_channel() else {
return;
};
loop {
match ch.try_send(report) {
Ok(()) => return,
Err(TrySendError::Full(r)) => report = r,
}
poll_fn(|cx| ch.poll_ready_to_send(cx)).await;
if crate::state::active_transport() != Some(transport) {
return;
}
}
}
pub(crate) fn try_send_hid_report(report: Report) {
if let Some((_, ch)) = active_report_channel() {
let _ = ch.try_send(report);
}
}
pub(crate) fn clear_and_release_report_channel(transport: ConnectionType) {
if let Some(ch) = report_channel(transport) {
ch.clear();
let _ = ch.try_send(Report::KeyboardReport(KeyboardReport::default()));
}
}
#[cfg(feature = "storage")]
pub(crate) static FLASH_CHANNEL: Channel<RawMutex, FlashOperationMessage, FLASH_CHANNEL_SIZE> = Channel::new();
#[cfg(feature = "std")]
#[doc(hidden)]
pub async fn drain_flash_channel_for_test() {
#[cfg(feature = "storage")]
loop {
FLASH_CHANNEL.receive().await;
}
#[cfg(not(feature = "storage"))]
core::future::pending::<()>().await
}
#[cfg(feature = "_ble")]
pub(crate) static BLE_PROFILE_CHANNEL: Channel<RawMutex, BleProfileAction, 1> = Channel::new();
#[cfg(all(feature = "vial", feature = "_ble"))]
pub(crate) static VIAL_BLE_RX_CHANNEL: Channel<RawMutex, [u8; 32], VIAL_CHANNEL_SIZE> = Channel::new();
#[cfg(all(feature = "rynk", feature = "_ble"))]
pub(crate) static RYNK_BLE_RX_PIPE: embassy_sync::pipe::Pipe<RawMutex, 512> = embassy_sync::pipe::Pipe::new();
pub(crate) static MACRO_TRIGGER_CHANNEL: Channel<RawMutex, (u8, KeyboardEvent), 4> = Channel::new();