diff --git a/Cargo.lock b/Cargo.lock index 43c8424..0865d9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "allocator-api2" version = "0.3.1" @@ -20,6 +32,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + [[package]] name = "bitfield" version = "0.19.4" @@ -331,6 +349,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "embassy-net-driver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524eb3c489760508f71360112bca70f6e53173e6fe48fc5f0efd0f5ab217751d" + +[[package]] +name = "embassy-net-driver-channel" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07d2eb9f05a6fc876500949856ea1be40773d866d8cb99384f72d0ae4568c16" +dependencies = [ + "embassy-futures", + "embassy-net-driver", + "embassy-sync 0.8.0", +] + [[package]] name = "embassy-sync" version = "0.6.2" @@ -410,12 +445,32 @@ dependencies = [ "heapless 0.9.2", ] +[[package]] +name = "embassy-usb" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25746d8b152b72fbf2a217f489a083dbbe243f281f09184a1f2cfbe9bbb245f" +dependencies = [ + "bitflags 2.11.1", + "defmt 1.1.0", + "embassy-futures", + "embassy-net-driver-channel", + "embassy-sync 0.8.0", + "embassy-time", + "embassy-usb-driver", + "embedded-io-async 0.7.0", + "heapless 0.9.2", + "ssmarshal", + "usbd-hid", +] + [[package]] name = "embassy-usb-driver" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17119855ccc2d1f7470a39756b12068454ae27a3eabb037d940b5c03d9c77b7a" dependencies = [ + "defmt 1.1.0", "embedded-io-async 0.6.1", ] @@ -517,6 +572,12 @@ dependencies = [ "embedded-storage", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "enumset" version = "1.1.10" @@ -599,7 +660,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54786287c0a61ca0f78cb0c338a39427551d1be229103b4444591796c579e093" dependencies = [ - "bitfield", + "bitfield 0.19.4", "bitflags 2.11.1", "bytemuck", "cfg-if", @@ -944,6 +1005,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.17.0" @@ -989,7 +1059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.17.0", ] [[package]] @@ -1107,6 +1177,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + [[package]] name = "padmapper" version = "0.1.0" @@ -1115,12 +1191,14 @@ dependencies = [ "defmt 1.1.0", "embassy-executor", "embassy-time", + "embassy-usb", "esp-alloc", "esp-bootloader-esp-idf", "esp-hal", "esp-println", "esp-rtos", "static_cell", + "usbd-hid", "ws2812-rs", ] @@ -1361,6 +1439,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0f368519fc6c85fc1afdb769fb5a51123f6158013e143656e25a3485a0d401c" +[[package]] +name = "ssmarshal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850" +dependencies = [ + "encode_unicode", + "serde", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -1537,6 +1625,41 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "usbd-hid" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68beab087e4971a2fe76f631478b0e91d39593f58efd2775026ce6dc07a7bac6" +dependencies = [ + "usb-device", + "usbd-hid-macros", +] + +[[package]] +name = "usbd-hid-descriptors" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b297f021719c4308d5d0c61b6c1e7c6b3ba383deba774b49aa5484f996bdb8f1" +dependencies = [ + "bitfield 0.14.0", +] + +[[package]] +name = "usbd-hid-macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "011a3219e0933f5b3ad7dc90d9a66541a967d084c98c067deed1cd608e557ed7" +dependencies = [ + "byteorder", + "hashbrown 0.13.2", + "log", + "proc-macro2", + "quote", + "serde", + "syn 2.0.117", + "usbd-hid-descriptors", +] + [[package]] name = "vcell" version = "0.1.3" @@ -1629,3 +1752,23 @@ dependencies = [ "quote", "syn 2.0.117", ] + +[[package]] +name = "zerocopy" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] diff --git a/Cargo.toml b/Cargo.toml index 0a2a495..c6289dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,25 +9,29 @@ name = "padmapper" path = "./src/bin/main.rs" [dependencies] -esp-hal = { version = "~1.0", features = ["defmt", "esp32s3", "unstable"] } - -esp-rtos = { version = "0.2.0", features = [ - "defmt", - "embassy", - "esp-alloc", - "esp32s3", -] } - -defmt = "1.1.0" -esp-bootloader-esp-idf = { version = "0.4.0", features = ["defmt", "esp32s3"] } +critical-section = "1.2.0" +defmt = "1.1.0" +static_cell = "2.1.1" embassy-executor = { version = "0.9.1", features = ["defmt"] } embassy-time = { version = "0.5.0", features = ["defmt"] } -esp-alloc = { version = "0.9.0", features = ["defmt"] } -esp-println = { version = "0.17.0", features = ["colors", "defmt-espflash", "esp32s3", "uart"], default-features = false } +embassy-usb = { version = "0.6.0", features = ["defmt"] } +usbd-hid = "0.10.0" + +esp-alloc = { version = "0.9.0", features = ["defmt"] } +esp-bootloader-esp-idf = { version = "0.4.0", features = ["defmt", "esp32s3"] } +esp-hal = { version = "~1.0", features = ["defmt", "esp32s3", "unstable"] } +esp-println = { version = "0.17.0", features = ["colors", + "defmt-espflash", + "esp32s3", + "uart"], default-features = false + } +esp-rtos = { version = "0.2.0", features = ["defmt", + "embassy", + "esp-alloc", + "esp32s3", + ] } -critical-section = "1.2.0" -static_cell = "2.1.1" ws2812-rs = "0.3.1" diff --git a/src/bin/main.rs b/src/bin/main.rs index cfbbbf4..3d78636 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -10,12 +10,15 @@ use defmt::info; use embassy_executor::Spawner; use embassy_time::Timer; +use embassy_usb::{Builder, Config as UsbConfig}; use esp_hal::Blocking; use esp_hal::clock::CpuClock; +use esp_hal::otg_fs::{asynch::{Driver as UsbDriver, Config as UsbDriverConfig}, Usb}; use esp_hal::spi::master::{Spi, Config as SpiConfig}; use esp_hal::time::Rate; use esp_hal::timer::timg::TimerGroup; #[allow(unused_imports)] use esp_println; // Needed to link global logger +use static_cell::StaticCell; use ws2812_rs::{WS2812SPI, SendColorBySPI, Color}; #[panic_handler] @@ -31,6 +34,16 @@ esp_bootloader_esp_idf::esp_app_desc!(); const LED_SPI_HZ: u32 = 3_200_000; +const VENDOR_ID: u16 = 0x2341; +const PRODUCT_ID: u16 = 0x8037; +const MANUFACTURER_NAME: &str = "Padmapper"; +const PRODUCT_NAME: &str = "StepManiaX"; // AI suggests "StepManiaX Stage" or "StepManiaX Controller" + +static EP_STATE: StaticCell<[u8; 1024]> = StaticCell::new(); +static CONFIG_DESCRIPTOR: StaticCell<[u8; 256]> = StaticCell::new(); +static BOS_DESCRIPTOR: StaticCell<[u8; 256]> = StaticCell::new(); // Do I actually need this? +static CONTROL_BUF: StaticCell<[u8; 64]> = StaticCell::new(); + #[allow( clippy::large_stack_frames, reason = "it's not unusual to allocate larger buffers etc. in main" @@ -52,6 +65,26 @@ async fn main(spawner: Spawner) -> ! { let led = WS2812SPI::new(spi); spawner.spawn(heartbeat_task(led)).unwrap(); + let usb_dev = Usb::new(peripherals.USB0, + peripherals.GPIO20, // USB D+ + peripherals.GPIO19); // USB D- + let usb_driver = UsbDriver::new(usb_dev, + EP_STATE.init([0; 1024]), + UsbDriverConfig::default()); + + let mut usb_config = UsbConfig::new(VENDOR_ID, PRODUCT_ID); + usb_config.manufacturer = Some(MANUFACTURER_NAME); + usb_config.product = Some(PRODUCT_NAME); + let usb_builder = Builder::new(usb_driver, + usb_config, + CONFIG_DESCRIPTOR.init([0; 256]), + BOS_DESCRIPTOR.init([0; 256]), // Don't think I need this? + &mut [], // no msos descriptors + CONTROL_BUF.init([0; 64])); + + let usb = usb_builder.build(); + spawner.spawn(usb_task(usb)).unwrap(); + info!("Padmapper initialized!"); // Idle forever @@ -76,3 +109,8 @@ async fn heartbeat_task(mut led: WS2812SPI>) { Timer::after_millis(700).await; } } + +#[embassy_executor::task] +async fn usb_task(mut usb: embassy_usb::UsbDevice<'static, UsbDriver<'static>>) { + usb.run().await; +}