diff --git a/services/usb-device-xous/Cargo.toml b/services/usb-device-xous/Cargo.toml index dd341319b..b39628e5b 100644 --- a/services/usb-device-xous/Cargo.toml +++ b/services/usb-device-xous/Cargo.toml @@ -21,17 +21,23 @@ rkyv = { version = "0.4.3", default-features = false, features = [ ] } susres = { package = "xous-api-susres", version = "0.9.57" } modals = { path = "../modals" } -keyboard = { path = "../keyboard", features = ["inject-api"] } +keyboard = { path = "../keyboard", features = ["inject-api"], optional = true } bitfield = "0.13.2" vcell = "0.1.3" xous-semver = "0.1.2" utralib = { version = "0.1.24", optional = true, default-features = false } trng = { path = "../trng" } -xous-usb-hid = { git = "https://github.com/betrusted-io/xous-usb-hid.git", branch="main" } -embedded-time = "0.12.1" # required by the keyboard interface -packed_struct = { version = "0.10", default-features = false } # used by the xous-usb-hid crate -num_enum = { version = "0.5", default-features = false } # used by the xous-usb-hid crate +xous-usb-hid = { git = "https://github.com/betrusted-io/xous-usb-hid.git", branch = "main" } +embedded-time = "0.12.1" # required by the keyboard interface +packed_struct = { version = "0.10", default-features = false } # used by the xous-usb-hid crate +num_enum = { version = "0.5", default-features = false } # used by the xous-usb-hid crate + +cramium-hal = { path = "../../libs/cramium-hal", features = [ + "std", +], optional = true } +cram-hal-service = { path = "../cram-hal-service", optional = true } + # Mass storage support usbd_scsi = { path = "../../libs/mass-storage/usbd_scsi", optional = true } @@ -54,9 +60,15 @@ rand = "0.8.5" rand_chacha = "0.3.1" [features] -precursor = ["utralib/precursor", "utralib/std"] -hosted = ["utralib/hosted", "utralib/std"] -renode = ["utralib/renode", "utralib/std"] +precursor = ["utralib/precursor", "utralib/std", "keyboard"] +hosted = ["utralib/hosted", "utralib/std", "keyboard"] +renode = ["utralib/renode", "utralib/std", "keyboard"] +cramium-soc = [ + "utralib/cramium-soc", + "utralib/std", + "cramium-hal", + "cram-hal-service", +] minimal = ["mass-storage"] mass-storage = ["usbd_scsi", "usbd_mass_storage"] mjolnir = [ diff --git a/services/usb-device-xous/src/api.rs b/services/usb-device-xous/src/api.rs index f5c7d218f..effcc879e 100644 --- a/services/usb-device-xous/src/api.rs +++ b/services/usb-device-xous/src/api.rs @@ -78,6 +78,7 @@ pub(crate) enum Opcode { /// Handle the USB interrupt UsbIrqHandler = 2048, /// Suspend/resume callback + #[cfg(any(feature = "renode", feature = "precursor", feature = "hosted"))] SuspendResume = 2049, /// Exits the server Quit = 4096, diff --git a/services/usb-device-xous/src/main.rs b/services/usb-device-xous/src/main.rs index 9c3f4faa8..04a7e2ecb 100644 --- a/services/usb-device-xous/src/main.rs +++ b/services/usb-device-xous/src/main.rs @@ -3,7 +3,7 @@ #[cfg(not(target_os = "xous"))] mod main_hosted; -#[cfg(any(feature = "precursor", feature = "renode"))] +#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))] mod main_hw; mod api; @@ -21,10 +21,10 @@ mod spinal_udc; use packed_struct::PackedStructSlice; #[cfg(any(feature = "precursor", feature = "renode"))] use spinal_udc::*; -#[cfg(all(any(feature = "precursor", feature = "renode"), feature = "mass-storage"))] +#[cfg(all(any(feature = "precursor", feature = "renode", feature = "corigine"), feature = "mass-storage"))] mod apps_block_device; -#[cfg(any(feature = "precursor", feature = "renode"))] +#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))] mod hid; #[cfg(not(target_os = "xous"))] mod hosted; @@ -36,7 +36,7 @@ use hosted::*; use num_traits::*; fn main() -> ! { - #[cfg(any(feature = "precursor", feature = "renode"))] + #[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))] main_hw::main_hw(); #[cfg(not(target_os = "xous"))] main_hosted::main_hosted(); diff --git a/services/usb-device-xous/src/main_hw.rs b/services/usb-device-xous/src/main_hw.rs index 7192de0b9..dfdd9ce99 100644 --- a/services/usb-device-xous/src/main_hw.rs +++ b/services/usb-device-xous/src/main_hw.rs @@ -4,18 +4,27 @@ use std::collections::VecDeque; use std::convert::TryInto; use std::sync::Arc; -#[cfg(not(feature = "minimal"))] +#[cfg(all(not(feature = "minimal"), any(feature = "cramium-soc")))] +use cram_hal_service::api::KeyMap; +#[cfg(feature = "cramium-soc")] +use cram_hal_service::keyboard; +use cramium_hal::usb::driver::CorigineUsb; +#[cfg(all(not(feature = "minimal"), any(feature = "renode", feature = "precursor")))] use keyboard::KeyMap; use num_traits::*; +#[cfg(feature = "cramium-soc")] +use packed_struct::PackedStructSlice; use usb_device::class_prelude::*; use usb_device::prelude::*; use usb_device_xous::KeyboardLedsReport; use usb_device_xous::UsbDeviceType; use usbd_serial::SerialPort; +#[cfg(any(feature = "precursor", feature = "renode"))] use utralib::generated::*; +use utralib::AtomicCsr; use xous::{msg_blocking_scalar_unpack, msg_scalar_unpack}; use xous_ipc::Buffer; -#[cfg(not(feature = "minimal"))] +#[cfg(all(not(feature = "minimal"), any(feature = "precursor", feature = "renode")))] use xous_semver::SemVer; use xous_usb_hid::device::fido::RawFido; use xous_usb_hid::device::fido::RawFidoConfig; @@ -79,16 +88,21 @@ pub(crate) fn main_hw() -> ! { let xns = xous_names::XousNames::new().unwrap(); let usbdev_sid = xns.register_name(api::SERVER_NAME_USB_DEVICE, None).expect("can't register server"); + let cid = xous::connect(usbdev_sid).expect("couldn't create suspend callback connection"); log::trace!("registered with NS -- {:?}", usbdev_sid); #[cfg(not(feature = "minimal"))] + #[cfg(any(feature = "precursor", feature = "renode"))] let llio = llio::Llio::new(&xns); let tt = ticktimer_server::Ticktimer::new().unwrap(); #[cfg(not(feature = "minimal"))] let native_kbd = keyboard::Keyboard::new(&xns).unwrap(); - #[cfg(not(feature = "minimal"))] + #[cfg(all(not(feature = "minimal"), any(feature = "precursor", feature = "renode")))] let serial_number = format!("{:x}", llio.soc_dna().unwrap()); - #[cfg(not(feature = "minimal"))] + #[cfg(all(not(feature = "minimal"), any(feature = "cramium-soc")))] + let serial_number = format!("TODO!!"); // implement in cramium-hal once we have a serial number API + + #[cfg(all(not(feature = "minimal"), any(feature = "precursor", feature = "renode")))] { let minimum_ver = SemVer { maj: 0, min: 9, rev: 8, extra: 20, commit: None }; let soc_ver = llio.soc_gitrev().unwrap(); @@ -161,6 +175,7 @@ pub(crate) fn main_hw() -> ! { } // Allocate memory range and CSR for sharing between all the views. + #[cfg(any(feature = "precursor", feature = "renode"))] let usb = xous::syscall::map_memory( xous::MemoryAddress::new(utralib::HW_USBDEV_MEM), None, @@ -168,6 +183,7 @@ pub(crate) fn main_hw() -> ! { xous::MemoryFlags::R | xous::MemoryFlags::W, ) .expect("couldn't map USB device memory range"); + #[cfg(any(feature = "precursor", feature = "renode"))] let csr = xous::syscall::map_memory( xous::MemoryAddress::new(utra::usbdev::HW_USBDEV_BASE), None, @@ -176,33 +192,78 @@ pub(crate) fn main_hw() -> ! { ) .expect("couldn't map USB CSR range"); + #[cfg(feature = "cramium-soc")] + let usb_mapping = xous::syscall::map_memory( + xous::MemoryAddress::new(cramium_hal::usb::utra::CORIGINE_USB_BASE), + None, + cramium_hal::usb::utra::CORIGINE_USB_LEN, + xous::MemoryFlags::R | xous::MemoryFlags::W, + ) + .expect("couldn't reserve register pages"); + #[cfg(feature = "cramium-soc")] + let ifram_range = xous::syscall::map_memory( + xous::MemoryAddress::new(cramium_hal::usb::driver::CRG_UDC_MEMBASE), + xous::MemoryAddress::new(cramium_hal::usb::driver::CRG_UDC_MEMBASE), // make P & V addresses line up + cramium_hal::usb::driver::CRG_IFRAM_PAGES * 0x1000, + xous::MemoryFlags::R | xous::MemoryFlags::W, + ) + .expect("couldn't allocate IFRAM pages"); + #[cfg(feature = "cramium-soc")] + let usb = AtomicCsr::new(usb_mapping.as_ptr() as *mut u32); + // Notes: // - Most drivers would `Box()` the hardware management structure to make sure the compiler doesn't move // its location. However, we can't do this here because we are trying to maintain compatibility with // another crate that implements the USB stack which can't handle Box'd structures. // - It is safe to call `.init()` repeatedly because within `init()` we have an atomic bool that tracks // if the interrupt handler has been hooked, and ignores further requests to hook it. + #[cfg(any(feature = "renode", feature = "precursor"))] let usb_fidokbd_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone()); + #[cfg(feature = "cramium-soc")] + // safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses + let usb_fidokbd_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) }; + #[cfg(any(feature = "renode", feature = "precursor"))] usb_fidokbd_dev.init(); + #[cfg(any(feature = "renode", feature = "precursor"))] let mut usbmgmt = usb_fidokbd_dev.get_iface(); + #[cfg(feature = "cramium-soc")] + // safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses + let mut usbmgmt = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) }; // before doing any allocs, clone a copy of the hardware access structure so we can build a second // view into the hardware with only FIDO descriptors + #[cfg(any(feature = "renode", feature = "precursor"))] let usb_fido_dev: SpinalUsbDevice = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone()); + #[cfg(feature = "cramium-soc")] + // safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses + let usb_fido_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) }; + #[cfg(any(feature = "renode", feature = "precursor"))] usb_fido_dev.init(); // do the same thing for mass storage - #[cfg(feature = "mass-storage")] + #[cfg(all(feature = "mass-storage", any(feature = "precursor", feature = "renode")))] let ums_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone()); + #[cfg(all(feature = "mass-storage", any(feature = "cramium-soc")))] + // safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses + let ums_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) }; #[cfg(feature = "mass-storage")] + #[cfg(any(feature = "renode", feature = "precursor"))] ums_dev.init(); + #[cfg(any(feature = "renode", feature = "precursor"))] let serial_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone()); + #[cfg(feature = "cramium-soc")] + // safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses + let serial_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) }; + #[cfg(any(feature = "renode", feature = "precursor"))] serial_dev.init(); + #[cfg(feature = "cramium-soc")] + usbmgmt.init(); // for the cramium target, call init only once via management structure + // track which view is visible on the device core #[cfg(not(feature = "minimal"))] let mut view = Views::FidoWithKbd; // register a suspend/resume listener - let cid = xous::connect(usbdev_sid).expect("couldn't create suspend callback connection"); + #[cfg(any(feature = "renode", feature = "precursor", feature = "hosted"))] let mut susres = susres::Susres::new(None, &xns, api::Opcode::SuspendResume as u32, cid) .expect("couldn't create suspend/resume object"); @@ -282,7 +343,12 @@ pub(crate) fn main_hw() -> ! { const TRNG_BACKOFF_MS: u32 = 1; const TRNG_BACKOFF_MAX_MS: u32 = 1000; // cap on how far we backoff the polling rate + #[cfg(any(feature = "renode", feature = "precursor"))] let usb_hidv2_dev = SpinalUsbDevice::new(usbdev_sid, usb.clone(), csr.clone()); + #[cfg(feature = "cramium-soc")] + // safety: this is safe because we allocated ifram_range to have the same physical and virtual addresses + let usb_hidv2_dev = unsafe { CorigineUsb::new(cid, ifram_range.as_ptr() as usize, usb.clone()) }; + let hidv2_alloc = UsbBusAllocator::new(usb_hidv2_dev); let mut hidv2 = hid::AppHID::new( @@ -468,6 +534,7 @@ pub(crate) fn main_hw() -> ! { .unwrap(); xous::return_scalar(msg.sender, 0).unwrap(); }), + #[cfg(any(feature = "renode", feature = "precursor", feature = "hosted"))] Some(Opcode::SuspendResume) => msg_scalar_unpack!(msg, token, _, _, _, { usbmgmt.xous_suspend(); susres.suspend_until_resume(token).expect("couldn't execute suspend/resume"); diff --git a/services/usb-device-xous/src/mappings.rs b/services/usb-device-xous/src/mappings.rs index a7cf62cf8..6a565948d 100644 --- a/services/usb-device-xous/src/mappings.rs +++ b/services/usb-device-xous/src/mappings.rs @@ -1,7 +1,7 @@ #![allow(unused_imports)] pub use xous_usb_hid::page::Keyboard as UsbKeyCode; -#[cfg(any(feature="precursor", feature="renode"))] +#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))] #[rustfmt::skip] pub fn char_to_hid_code_us101(key: char) -> Vec { let mut code = vec![]; @@ -120,7 +120,7 @@ pub fn char_to_hid_code_us101(key: char) -> Vec { } /// auto-generated using tools/kbd_layout.py + `usb kbdtest` on device for dvorak layout on US101 -#[cfg(any(feature="precursor", feature="renode"))] +#[cfg(any(feature = "precursor", feature = "renode", feature = "cramium-soc"))] #[rustfmt::skip] pub fn char_to_hid_code_dvorak(key: char) -> Vec { let mut code = vec![];