use embassy_executor::Spawner; use embassy_rp::{peripherals::USB, usb::Driver}; use embassy_usb::{Builder, Config, UsbDevice}; use static_cell::StaticCell; use crate::{interrupts::Irqs, keyboard::KbEvents}; pub mod keyboard; pub mod logger; pub const MAX_PACKET_SIZE: u8 = 64; struct State { device_descriptor: [u8; 256], config_descriptor: [u8; 256], bos_descriptor: [u8; 256], control_buf: [u8; 64], } static STATE: StaticCell = StaticCell::new(); pub async fn setup_logger_and_keyboard(usb: USB, events: KbEvents) { let mut builder = builder(usb); //logger::setup(&mut builder).await; keyboard::setup(&mut builder, events).await; log::info!("building usb device"); let usb = builder.build(); log::info!("spawning usb task"); Spawner::for_current_executor().await.must_spawn(run(usb)); } pub fn builder(usb: USB) -> Builder<'static, Driver<'static, USB>> { // calling init here can't panic because this function can't be called // twice since we are taking ownership of the only USB peripheral. let state = STATE.init_with(|| State { device_descriptor: [0; 256], config_descriptor: [0; 256], bos_descriptor: [0; 256], control_buf: [0; 64], }); // Create embassy-usb Config let mut config = Config::new(0xb00b, 0x1355); config.manufacturer = Some("Tux"); config.product = Some("Tangentbord1"); config.serial_number = Some("42069"); config.max_power = 100; config.max_packet_size_0 = MAX_PACKET_SIZE; // Required for windows compatiblity. // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help config.device_class = 0xEF; config.device_sub_class = 0x02; config.device_protocol = 0x01; config.composite_with_iads = true; let driver = Driver::new(usb, Irqs); Builder::new( driver, config, &mut state.device_descriptor, &mut state.config_descriptor, &mut state.bos_descriptor, &mut state.control_buf, ) } #[embassy_executor::task] pub async fn run(mut device: UsbDevice<'static, Driver<'static, USB>>) { log::info!("running usb device"); device.run().await }