aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/device.rs16
-rw-r--r--src/hid.rs88
-rw-r--r--src/main.rs35
3 files changed, 136 insertions, 3 deletions
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();
+ }
}
}