diff options
-rw-r--r-- | Cargo.lock | 22 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | README.md | 13 | ||||
-rw-r--r-- | src/device.rs | 16 | ||||
-rw-r--r-- | src/hid.rs | 88 | ||||
-rw-r--r-- | src/main.rs | 35 |
6 files changed, 172 insertions, 4 deletions
@@ -72,7 +72,9 @@ dependencies = [ "cortex-m-rt 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "embedded-hal 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "panic-halt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stm32f103xx-usb 0.1.0 (git+https://github.com/mvirkkunen/stm32f103xx-usb?rev=57d23751367461bec5f39322727bdd65e5c2aa30)", "stm32f1xx-hal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "usb-device 0.2.0 (git+https://github.com/mvirkkunen/usb-device?rev=e58e30f3b9c9bf4aab00ea039d129b964a3fd2d3)", ] [[package]] @@ -150,6 +152,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cortex-m-rt 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stm32f103xx-usb" +version = "0.1.0" +source = "git+https://github.com/mvirkkunen/stm32f103xx-usb?rev=57d23751367461bec5f39322727bdd65e5c2aa30#57d23751367461bec5f39322727bdd65e5c2aa30" +dependencies = [ + "bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cortex-m 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "stm32f1xx-hal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "usb-device 0.2.0 (git+https://github.com/mvirkkunen/usb-device?rev=e58e30f3b9c9bf4aab00ea039d129b964a3fd2d3)", "vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -183,6 +198,11 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "usb-device" +version = "0.2.0" +source = "git+https://github.com/mvirkkunen/usb-device?rev=e58e30f3b9c9bf4aab00ea039d129b964a3fd2d3#e58e30f3b9c9bf4aab00ea039d129b964a3fd2d3" + +[[package]] name = "vcell" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -220,9 +240,11 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum stm32f1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48763f6f093674476399efbd8d2e52349dc32c3bbf57657234cbb15d309cd8a3" +"checksum stm32f103xx-usb 0.1.0 (git+https://github.com/mvirkkunen/stm32f103xx-usb?rev=57d23751367461bec5f39322727bdd65e5c2aa30)" = "<none>" "checksum stm32f1xx-hal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f410543fc282d51e181e3cf5c8adff303d9e5ae8b9eb731e6a07f58a4cec4265" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum usb-device 0.2.0 (git+https://github.com/mvirkkunen/usb-device?rev=e58e30f3b9c9bf4aab00ea039d129b964a3fd2d3)" = "<none>" "checksum vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45c297f0afb6928cd08ab1ff9d95e99392595ea25ae1b5ecf822ff8764e57a0d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286" @@ -14,6 +14,8 @@ cortex-m = "0.5.8" cortex-m-rt = "0.6.7" embedded-hal = "0.2.2" panic-halt = "0.2.0" +stm32f103xx-usb = { git = "https://github.com/mvirkkunen/stm32f103xx-usb", rev = "57d23751367461bec5f39322727bdd65e5c2aa30" } +usb-device = { git = "https://github.com/mvirkkunen/usb-device", rev = "e58e30f3b9c9bf4aab00ea039d129b964a3fd2d3" } [dependencies.hal] package = "stm32f1xx-hal" @@ -6,7 +6,9 @@ SPDX-License-Identifier: CC0-1.0 # ntw `ntw` is an experimental firmware for the Nitrokey Pro. It is in very early -development and currently does not support any commands. +development and supports: + +- connecting as a USB device with the Nitrokey Pro’s product and vendor ID ## Resources @@ -21,6 +23,15 @@ development and currently does not support any commands. [STM32F103RB-ds]: https://www.st.com/resource/en/datasheet/stm32f103rb.pdf [STM32F103RB-rm]: https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf +### Protocols + +- [Universal Serial Bus Specification][usb], Revision 1.1 +- [Universal Serial Bus: Device Class Definition for Human Interface Devices + (HID)][hid], Firmware Specification, Version 1.11 + +[usb]: http://esd.cs.ucr.edu/webres/usb11.pdf +[hid]: https://www.usb.org/sites/default/files/documents/hid1_11.pdf + ## Contact For bug reports, patches, feature requests or other messages, please send a diff --git a/src/device.rs b/src/device.rs new file mode 100644 index 0000000..ea732e6 --- /dev/null +++ b/src/device.rs @@ -0,0 +1,16 @@ +// Copyright 2019 Robin Krahl <robin.krahl@ireas.org> +// SPDX-License-Identifier: GPL-3.0-or-later + +use usb_device::bus::{UsbBus, UsbBusAllocator}; +use usb_device::device::{UsbDevice, UsbDeviceBuilder, UsbVidPid}; + +const VID_CLAY_LOGIC: u16 = 0x20a0; +const PID_NITROKEY_PRO: u16 = 0x4108; + +pub fn create_usb_device<B: UsbBus>(alloc: &UsbBusAllocator<B>) -> UsbDevice<'_, B> { + UsbDeviceBuilder::new(alloc, UsbVidPid(VID_CLAY_LOGIC, PID_NITROKEY_PRO)) + .manufacturer("Nitrokey/ntw") + .product("Nitrokey Pro/ntw") + .serial_number("?") + .build() +} diff --git a/src/hid.rs b/src/hid.rs new file mode 100644 index 0000000..4f1d506 --- /dev/null +++ b/src/hid.rs @@ -0,0 +1,88 @@ +// Copyright 2019 Robin Krahl <robin.krahl@ireas.org> +// SPDX-License-Identifier: GPL-3.0-or-later + +use core::marker::PhantomData; + +use usb_device::bus::{InterfaceNumber, StringIndex, UsbBus, UsbBusAllocator}; +use usb_device::class::{ControlIn, ControlOut, UsbClass}; +use usb_device::descriptor::DescriptorWriter; +use usb_device::endpoint::EndpointAddress; +use usb_device::Result; + +const INTERFACE_CLASS_HID: u8 = 0x03; + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(u8)] +pub enum Subclass { + None = 0x00, + BootInterface = 0x01, +} + +impl From<Subclass> for u8 { + fn from(subclass: Subclass) -> u8 { + subclass as u8 + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(u8)] +pub enum Protocol { + None = 0x00, + Keyboard = 0x01, + Mouse = 0x02, +} + +impl From<Protocol> for u8 { + fn from(protocol: Protocol) -> u8 { + protocol as u8 + } +} + +pub struct HidClass<'a, B: UsbBus> { + interface: InterfaceNumber, + subclass: Subclass, + protocol: Protocol, + marker: PhantomData<&'a B>, +} + +impl<B: UsbBus> HidClass<'_, B> { + pub fn new( + alloc: &UsbBusAllocator<B>, + subclass: Subclass, + protocol: Protocol, + ) -> HidClass<'_, B> { + HidClass { + interface: alloc.interface(), + subclass, + protocol, + marker: PhantomData, + } + } +} + +impl<B: UsbBus> UsbClass<B> for HidClass<'_, B> { + fn poll(&mut self) {} + + fn reset(&mut self) {} + + fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> { + writer.interface( + self.interface, + INTERFACE_CLASS_HID, + self.subclass.into(), + self.protocol.into(), + ) + } + + fn get_string(&self, _index: StringIndex, _lang_id: u16) -> Option<&str> { + None + } + + fn endpoint_in_complete(&mut self, _addr: EndpointAddress) {} + + fn endpoint_out(&mut self, _addr: EndpointAddress) {} + + fn control_in(&mut self, _xfer: ControlIn<B>) {} + + fn control_out(&mut self, _xfer: ControlOut<B>) {} +} diff --git a/src/main.rs b/src/main.rs index d76cf33..b0ecafd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,14 +5,43 @@ #![no_main] extern crate panic_halt; -extern crate hal; -use cortex_m::asm; +mod device; +mod hid; + use cortex_m_rt::entry; +use hal::prelude::*; +use stm32f103xx_usb::UsbBus; +use usb_device::class::UsbClass; + +use crate::hid::{HidClass, Protocol, Subclass}; #[entry] fn main() -> ! { + let p = hal::stm32::Peripherals::take().unwrap(); + + let mut flash = p.FLASH.constrain(); + let mut rcc = p.RCC.constrain(); + + let clocks = rcc + .cfgr + .use_hse(8.mhz()) + .sysclk(48.mhz()) + .pclk1(24.mhz()) + .freeze(&mut flash.acr); + + assert!(clocks.usbclk_valid(), "USB clocks not valid"); + + let mut gpioa = p.GPIOA.split(&mut rcc.apb2); + + let usb_bus = UsbBus::usb_with_reset(p.USB, &mut rcc.apb1, &clocks, &mut gpioa.crh, gpioa.pa12); + let mut usb_class = HidClass::new(&usb_bus, Subclass::BootInterface, Protocol::Keyboard); + let mut usb_dev = device::create_usb_device(&usb_bus); + usb_dev.force_reset().expect("USB reset failed"); + loop { - asm::nop(); + if usb_dev.poll(&mut [&mut usb_class]) { + usb_class.poll(); + } } } |