-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
usb_hid
: add start of very basic USB HID driver
This is the start of a driver for USB HID-class devices. It can detect devices it can potentially support from the Platform Bus, and then interrogate their configuration hierachies for HID-class interfaces. Also includes some definitions for HID descriptors for the future. Next steps will be actually parsing the HID descriptors (including the Report descriptors, which look potentially complex), and then working on Interrupt endpoints to be able to get data from a HID device! I think it would be worth getting some of the other parts of this infrastructure, including userspace interrupt delegation and potentially userspace async runtimes, working before we tackle this.
- Loading branch information
1 parent
17cf99d
commit 5f8bf94
Showing
10 changed files
with
166 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#[derive(Clone, Copy, Debug)] | ||
#[repr(C)] | ||
pub struct HidDescriptor { | ||
pub length: u8, | ||
pub typ: u8, | ||
pub bcd_hid: u16, | ||
pub country_code: CountryCode, | ||
/// The number of included class descriptors. Will be `>=1` as a `Report` descriptor will | ||
/// always be present. | ||
pub num_descriptors: u8, | ||
pub descriptor_typ: u8, | ||
pub descriptor_length: u16, | ||
} | ||
|
||
#[derive(Clone, Copy, Debug)] | ||
#[repr(u8)] | ||
pub enum CountryCode { | ||
NotSupported = 0, | ||
Arabic = 1, | ||
Belgian = 2, | ||
CanadianBilingual = 3, | ||
CanadianFrench = 4, | ||
Czech = 5, | ||
Danish = 6, | ||
Finnish = 7, | ||
French = 8, | ||
German = 9, | ||
Greek = 10, | ||
Hebrew = 11, | ||
Hungary = 12, | ||
International = 13, | ||
Italian = 14, | ||
Japan = 15, | ||
Korean = 16, | ||
LatinAmerican = 17, | ||
Dutch = 18, | ||
Norwegian = 19, | ||
Farsi = 20, | ||
Poland = 21, | ||
Portuguese = 22, | ||
Russia = 23, | ||
Slovakia = 24, | ||
Spanish = 25, | ||
Swedish = 26, | ||
SwissFrench = 27, | ||
SwissGerman = 28, | ||
Switzerland = 29, | ||
Taiwan = 30, | ||
Turkish = 31, | ||
// 36-255 are reserved | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#![no_std] | ||
|
||
pub mod descriptor; | ||
pub mod hid; | ||
pub mod setup; | ||
|
||
use core::mem; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ members = [ | |
"tests/test_syscalls", | ||
"hello_world", | ||
"usb_bus_ehci", | ||
"usb_hid", | ||
] | ||
resolver = "2" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "usb_hid" | ||
version = "0.1.0" | ||
authors = ["Isaac Woods"] | ||
edition = "2021" | ||
|
||
[dependencies] | ||
std = { path = "../../lib/std", features = ["ddk"] } | ||
log = "0.4" | ||
platform_bus = { path = "../platform_bus" } | ||
ptah = { path = "../../lib/ptah" } | ||
usb = { path = "../../lib/usb" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#![feature(never_type)] | ||
|
||
use log::info; | ||
use platform_bus::{BusDriverMessage, DeviceDriverMessage, DeviceDriverRequest, Filter, Property}; | ||
use std::poplar::{ | ||
caps::{CapabilitiesRepr, CAP_EARLY_LOGGING, CAP_PADDING, CAP_SERVICE_USER}, | ||
channel::Channel, | ||
early_logger::EarlyLogger, | ||
syscall, | ||
}; | ||
use usb::descriptor::InterfaceDescriptor; | ||
|
||
pub fn main() { | ||
log::set_logger(&EarlyLogger).unwrap(); | ||
log::set_max_level(log::LevelFilter::Trace); | ||
info!("USB HID Driver is running!"); | ||
|
||
// This allows us to talk to the PlatformBus as a bus driver (to register our abstract devices). | ||
let platform_bus_bus_channel: Channel<BusDriverMessage, !> = | ||
Channel::from_handle(syscall::subscribe_to_service("platform_bus.bus_driver").unwrap()); | ||
// This allows us to talk to the PlatformBus as a device driver (to find supported USB devices). | ||
let platform_bus_device_channel: Channel<DeviceDriverMessage, DeviceDriverRequest> = | ||
Channel::from_handle(syscall::subscribe_to_service("platform_bus.device_driver").unwrap()); | ||
|
||
// Tell PlatformBus that we're interested in USB devices that are specified per-interface | ||
// (we need to parse their configurations to tell if they're HID devices). A HID device is not | ||
// supposed to indicate its class at the device level so we don't need to test for that. | ||
platform_bus_device_channel | ||
.send(&DeviceDriverMessage::RegisterInterest(vec![ | ||
Filter::Matches(String::from("usb.device_class"), Property::Integer(0x00)), | ||
Filter::Matches(String::from("usb.device_subclass"), Property::Integer(0x00)), | ||
])) | ||
.unwrap(); | ||
|
||
// TODO: we need to be able to support multiple devices, so this needs to be spawned as a task | ||
// that loops round listening permanently | ||
let (_device_info, handoff_info) = loop { | ||
match platform_bus_device_channel.try_receive().unwrap() { | ||
Some(DeviceDriverRequest::QuerySupport(device_name, device_info)) => { | ||
info!("Platform bus asked if we can support device {} with info {:?}", device_name, device_info); | ||
// TODO: consider each config if multiple? | ||
let configuration = device_info.get_as_bytes("usb.config0").unwrap(); | ||
info!("USB config: {:x?}", configuration); | ||
|
||
struct Visitor(pub bool); | ||
impl usb::ConfigurationVisitor for Visitor { | ||
fn visit_interface(&mut self, descriptor: &InterfaceDescriptor) { | ||
// Check if this interface indicates a HID class device | ||
if descriptor.interface_class == 3 { | ||
info!("Found a HID class interface!"); | ||
self.0 = true; | ||
} | ||
} | ||
} | ||
|
||
let supported = { | ||
let mut visitor = Visitor(false); | ||
usb::walk_configuration(configuration, &mut visitor); | ||
visitor.0 | ||
}; | ||
platform_bus_device_channel | ||
.send(&DeviceDriverMessage::CanSupport(device_name, supported)) | ||
.unwrap(); | ||
} | ||
Some(DeviceDriverRequest::HandoffDevice(device_name, device_info, handoff_info)) => { | ||
break (device_info, handoff_info); | ||
} | ||
None => std::poplar::syscall::yield_to_kernel(), | ||
} | ||
}; | ||
|
||
loop { | ||
std::poplar::syscall::yield_to_kernel(); | ||
} | ||
} | ||
|
||
#[used] | ||
#[link_section = ".caps"] | ||
pub static mut CAPS: CapabilitiesRepr<4> = | ||
CapabilitiesRepr::new([CAP_EARLY_LOGGING, CAP_SERVICE_USER, CAP_PADDING, CAP_PADDING]); |