rktk/task/mod.rs
1//! Program entrypoint.
2
3use crate::{
4 config::Hand,
5 drivers::interface::{
6 debounce::DebounceDriver, display::DisplayDriver, encoder::EncoderDriver,
7 keyscan::KeyscanDriver, mouse::MouseDriver, rgb::RgbDriver, split::SplitDriver,
8 storage::StorageDriver, usb::UsbReporterDriverBuilder,
9 wireless::WirelessReporterDriverBuilder,
10 },
11 hooks::Hooks,
12};
13use crate::{
14 drivers::{Drivers, interface::system::SystemDriver},
15 hooks::interface::*,
16 utils::sjoin,
17};
18use display::DisplayConfig;
19use embassy_futures::join::{join, join5};
20use embassy_time::Duration;
21use rktk_log::{debug, info};
22
23pub(crate) mod channels;
24// `display` module is public as internally used by macros
25pub mod display;
26mod initializers;
27#[cfg(feature = "rrp-log")]
28mod logger;
29mod master;
30mod rgb;
31mod slave;
32mod split_handler;
33
34/// Runs rktk with the given drivers and key configuration.
35///
36/// # Parameters
37/// - `drivers`: Drivers for the keyboard.
38/// - `hooks`: Hooks for the keyboard. See [`Hooks`] for detail.
39/// - `opts`: Other options such as keymap. See [`crate::config`] for detail.
40#[allow(clippy::type_complexity)]
41pub async fn start<
42 System: SystemDriver,
43 KeyScan: KeyscanDriver,
44 Debounce: DebounceDriver,
45 Encoder: EncoderDriver,
46 Rgb: RgbDriver,
47 Storage: StorageDriver,
48 Split: SplitDriver,
49 Ble: WirelessReporterDriverBuilder,
50 Usb: UsbReporterDriverBuilder,
51 Display: DisplayDriver,
52 Mouse: MouseDriver,
53 //
54 CH: CommonHooks,
55 MH: MasterHooks,
56 SH: SlaveHooks,
57 BH: RgbHooks,
58 //
59 DC: DisplayConfig + 'static,
60 RL: blinksy::layout::Layout2d + 'static,
61>(
62 mut drivers: Drivers<
63 System,
64 KeyScan,
65 Debounce,
66 Encoder,
67 Rgb,
68 Storage,
69 Split,
70 Ble,
71 Usb,
72 Display,
73 Mouse,
74 >,
75 mut hooks: Hooks<CH, MH, SH, BH>,
76 mut opts: crate::config::RktkOpts<DC, RL>,
77) {
78 #[cfg(feature = "rrp-log")]
79 {
80 debug!("log init");
81 critical_section::with(|_| unsafe {
82 let _ = log::set_logger_racy(&logger::RRP_LOGGER);
83 log::set_max_level_racy(log::LevelFilter::Info);
84 });
85 }
86
87 info!("Booting rktk",);
88
89 drivers
90 .system
91 .double_reset_usb_boot(Duration::from_millis(opts.config.rktk.split_usb_timeout))
92 .await;
93
94 sjoin::join!(
95 async {
96 initializers::init_mouse(&mut drivers.mouse, opts.config).await;
97 let ((wireless, wireless_task), (usb, usb_task)) =
98 initializers::init_reporters(drivers.ble_builder, drivers.usb_builder).await;
99
100 sjoin::join!(
101 async {
102 let hand = opts.hand.unwrap_or(Hand::Left);
103 crate::utils::display_state!(Hand, Some(hand));
104
105 let role =
106 initializers::init_split(opts.config, drivers.split, &usb, &wireless).await;
107
108 hooks
109 .common
110 .on_init(
111 hand,
112 &mut drivers.keyscan,
113 drivers.mouse.as_mut(),
114 drivers.storage.as_mut(),
115 )
116 .await;
117
118 crate::utils::display_state!(Master, Some(role.is_master()));
119
120 match role {
121 initializers::KeyboardRoleRes::Master {
122 sender,
123 receiver,
124 task,
125 } => {
126 info!("Master start");
127 sjoin::join!(
128 async {
129 let config_store =
130 master::utils::init_storage(drivers.storage).await;
131 let state = master::utils::load_state(
132 &opts.config.key_manager,
133 &config_store,
134 opts.keymap,
135 )
136 .await;
137
138 hooks
139 .master
140 .on_master_init(
141 &mut drivers.keyscan,
142 drivers.mouse.as_mut(),
143 )
144 .await;
145
146 join(
147 join5(
148 master::report::report_task(
149 opts.config,
150 &drivers.system,
151 &state,
152 &config_store,
153 &wireless,
154 &usb,
155 hooks.master,
156 ),
157 master::handle_slave::start(
158 opts.config,
159 hand,
160 receiver,
161 ),
162 master::handle_keyboard::start(
163 opts.config,
164 hand,
165 drivers.keyscan,
166 &mut drivers.debounce,
167 ),
168 master::handle_mouse::start(opts.config, drivers.mouse),
169 master::handle_encoder::start(&mut drivers.encoder),
170 ),
171 async {
172 #[cfg(feature = "rrp")]
173 master::rrp_server::start(
174 opts.config,
175 &usb,
176 &wireless,
177 &state,
178 &config_store,
179 )
180 .await;
181 },
182 )
183 .await;
184 },
185 rgb::start::<RL, _>(
186 opts.config,
187 drivers.rgb,
188 hooks.rgb,
189 Some(sender)
190 ),
191 async move {
192 if let Some(task) = task {
193 task.await;
194 }
195 }
196 );
197 }
198 initializers::KeyboardRoleRes::Slave {
199 sender,
200 receiver,
201 task,
202 } => {
203 debug!("Slave start");
204 sjoin::join!(
205 async move {
206 slave::start(
207 opts.config,
208 sender,
209 receiver,
210 drivers.keyscan,
211 &mut drivers.debounce,
212 drivers.mouse,
213 hooks.slave,
214 )
215 .await
216 },
217 rgb::start::<RL, _>(opts.config, drivers.rgb, hooks.rgb, None),
218 async move {
219 if let Some(task) = task {
220 task.await;
221 }
222 }
223 );
224 }
225 }
226 },
227 async {
228 if let Some(usb_task) = usb_task {
229 usb_task.await
230 }
231 },
232 async {
233 if let Some(wireless_task) = wireless_task {
234 wireless_task.await
235 }
236 }
237 );
238 },
239 async move {
240 if let Some(mut display) = drivers.display {
241 display::start(&mut display, &mut opts.display).await;
242 }
243 }
244 );
245}