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(); +        }      }  }  | 
