diff options
author | Robin Krahl <robin.krahl@ireas.org> | 2019-02-18 10:56:30 +0000 |
---|---|---|
committer | Robin Krahl <robin.krahl@ireas.org> | 2019-02-18 15:30:10 +0100 |
commit | 7da90438dd7851f66abfa81eba2eeb36ff9c9c25 (patch) | |
tree | 400bd0f6ab5e15899bd3fc1d8df55b57acfd1cf8 | |
parent | a3f0fb062048c52c3f04e907f0107e1db9b6141c (diff) | |
download | ntw-7da90438dd7851f66abfa81eba2eeb36ff9c9c25.tar.gz ntw-7da90438dd7851f66abfa81eba2eeb36ff9c9c25.tar.bz2 |
Add USB stack and simple HID implementation
This patch adds the usb-device and stm32f103xx-usb crates that provide a
USB stack. It introduces the HidClass struct, a basic implementation of
the Human Interface Device (HID) USB class. Devices with that class are
recognized as HID devices with the specified vendor and product ID, but
do not provide the endpoints required for interaction.
-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(); + } } } |