Skip to content

Commit 3eb79b6

Browse files
redpfiremvirkkunen
authored andcommitted
Change USB version to 2.1 and add BOS functionality
1 parent 0a55ee7 commit 3eb79b6

File tree

5 files changed

+104
-7
lines changed

5 files changed

+104
-7
lines changed

src/class.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{Result, UsbError};
22
use crate::bus::{UsbBus, StringIndex};
3-
use crate::descriptor::DescriptorWriter;
3+
use crate::descriptor::{DescriptorWriter, BosWriter};
44
use crate::control;
55
use crate::control_pipe::ControlPipe;
66
use crate::endpoint::EndpointAddress;
@@ -24,6 +24,15 @@ pub trait UsbClass<B: UsbBus> {
2424
Ok (())
2525
}
2626

27+
/// Called when a GET_DESCRIPTOR request is received for a BOS descriptor.
28+
/// When called, the implementation should write its blobs such as capability
29+
/// descriptors into `writer`. The BOS descriptor itself will be written by
30+
/// [UsbDevice](crate::device::UsbDevice) and shouldn't be written by classes.
31+
fn get_bos_descriptors(&self, writer: &mut BosWriter) -> Result<()> {
32+
let _ = writer;
33+
Ok (())
34+
}
35+
2736
/// Gets a class-specific string descriptor.
2837
///
2938
/// Note: All string descriptor requests are passed to all classes in turn, so implementations
@@ -190,4 +199,4 @@ impl<'a, 'p, 'r, B: UsbBus> ControlOut<'a, 'p, 'r, B> {
190199
pub fn reject(self) -> Result<()> {
191200
self.pipe.reject()
192201
}
193-
}
202+
}

src/descriptor.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub mod descriptor_type {
1111
pub const STRING: u8 = 3;
1212
pub const INTERFACE: u8 = 4;
1313
pub const ENDPOINT: u8 = 5;
14+
pub const BOS: u8 = 0x0f;
15+
pub const CAPABILITY: u8 = 0x10;
1416
}
1517

1618
/// String descriptor language IDs.
@@ -21,6 +23,16 @@ pub mod lang_id {
2123
pub const ENGLISH_US: u16 = 0x0409;
2224
}
2325

26+
/// Standard capability descriptor types
27+
#[allow(missing_docs)]
28+
pub mod capability_type {
29+
pub const WIRELESS_USB: u8 = 1;
30+
pub const USB_2_0_EXTENSION: u8 = 2;
31+
pub const SS_USB_DEVICE: u8 = 3;
32+
pub const CONTAINER_ID: u8 = 4;
33+
pub const PLATFORM: u8 = 5;
34+
}
35+
2436
/// A writer for USB descriptors.
2537
pub struct DescriptorWriter<'a> {
2638
buf: &'a mut [u8],
@@ -29,6 +41,68 @@ pub struct DescriptorWriter<'a> {
2941
num_endpoints_mark: Option<usize>,
3042
}
3143

44+
/// A writer for Binary Object Store descriptor.
45+
pub struct BosWriter<'w, 'a: 'w> {
46+
writer: &'w mut DescriptorWriter<'a>,
47+
num_caps_mark: Option<usize>,
48+
}
49+
50+
impl<'w, 'a: 'w> BosWriter<'w, 'a> {
51+
pub(crate) fn new(writer: &'w mut DescriptorWriter<'a>) -> Self {
52+
Self {
53+
writer: writer,
54+
num_caps_mark: None,
55+
}
56+
}
57+
58+
pub(crate) fn bos(&mut self) -> Result<()> {
59+
self.num_caps_mark= Some(self.writer.position + 4);
60+
self.writer.write(
61+
descriptor_type::BOS,
62+
&[
63+
0x00, 0x00, // wTotalLength
64+
0x00, // bNumDeviceCaps
65+
])
66+
}
67+
68+
/// Writes capability descriptor to a BOS
69+
///
70+
/// # Arguments
71+
///
72+
/// * `capability_type` - Type of a capability
73+
/// * `data` - Binary data of the descriptor
74+
pub fn capability(&mut self, capability_type: u8, data: &[u8]) -> Result<()> {
75+
match self.num_caps_mark{
76+
Some(mark) => self.writer.buf[mark] += 1,
77+
None => return Err(UsbError::InvalidState),
78+
}
79+
80+
let mut start = self.writer.position;
81+
let blen = data.len();
82+
83+
if start + blen + 3 > self.writer.buf.len()
84+
|| (blen + 3) > 255 {
85+
return Err(UsbError::BufferOverflow);
86+
}
87+
88+
self.writer.buf[start] = (blen + 3) as u8;
89+
self.writer.buf[start+1] = descriptor_type::CAPABILITY;
90+
self.writer.buf[start+2] = capability_type;
91+
92+
start += 3;
93+
self.writer.buf[start..start+blen].copy_from_slice(data);
94+
self.writer.position = start + blen;
95+
96+
Ok(())
97+
}
98+
99+
pub(crate) fn end_bos(&mut self) {
100+
self.num_caps_mark= None;
101+
let position = self.writer.position as u16;
102+
self.writer.buf[2..4].copy_from_slice(&position.to_le_bytes());
103+
}
104+
}
105+
32106
impl DescriptorWriter<'_> {
33107
pub(crate) fn new(buf: &mut [u8]) -> DescriptorWriter<'_> {
34108
DescriptorWriter {
@@ -64,11 +138,12 @@ impl DescriptorWriter<'_> {
64138
Ok(())
65139
}
66140

141+
67142
pub(crate) fn device(&mut self, config: &device::Config) -> Result<()> {
68143
self.write(
69144
descriptor_type::DEVICE,
70145
&[
71-
0x00, 0x02, // bcdUSB
146+
0x10, 0x02, // bcdUSB 2.1
72147
config.device_class, // bDeviceClass
73148
config.device_sub_class, // bDeviceSubClass
74149
config.device_protocol, // bDeviceProtocol

src/device.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::bus::{UsbBusAllocator, UsbBus, PollResult, StringIndex};
33
use crate::class::{UsbClass, ControlIn, ControlOut};
44
use crate::control;
55
use crate::control_pipe::ControlPipe;
6-
use crate::descriptor::{DescriptorWriter, descriptor_type, lang_id};
6+
use crate::descriptor::{DescriptorWriter, BosWriter, descriptor_type, lang_id};
77
use crate::endpoint::{EndpointType, EndpointAddress};
88
pub use crate::device_builder::{UsbDeviceBuilder, UsbVidPid};
99

@@ -413,6 +413,19 @@ impl<B: UsbBus> UsbDevice<'_, B> {
413413
}
414414

415415
match dtype {
416+
descriptor_type::BOS => accept_writer(xfer, |w| {
417+
let mut bw = BosWriter::new(w);
418+
bw.bos()?;
419+
420+
for cls in classes {
421+
cls.get_bos_descriptors(&mut bw)?;
422+
}
423+
424+
bw.end_bos();
425+
426+
Ok(())
427+
}),
428+
416429
descriptor_type::DEVICE => accept_writer(xfer, |w| w.device(config)),
417430

418431
descriptor_type::CONFIGURATION => accept_writer(xfer, |w| {

src/device_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,4 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
148148
self.config.max_power = (max_power_ma / 2) as u8;
149149
self
150150
}
151-
}
151+
}

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ pub mod prelude {
185185
pub mod class_prelude {
186186
pub use crate::UsbError;
187187
pub use crate::bus::{UsbBus, UsbBusAllocator, InterfaceNumber, StringIndex};
188-
pub use crate::descriptor::DescriptorWriter;
188+
pub use crate::descriptor::{DescriptorWriter, BosWriter};
189189
pub use crate::endpoint::{EndpointType, EndpointIn, EndpointOut, EndpointAddress};
190190
pub use crate::class::{UsbClass, ControlIn, ControlOut};
191191
pub use crate::control;
@@ -253,4 +253,4 @@ fn _ensure_sync() {
253253
ensure_sync::<crate::endpoint::EndpointIn<DummyBus>>();
254254
ensure_sync::<crate::endpoint::EndpointOut<DummyBus>>();
255255
ensure_sync::<DummyClass<'_, DummyBus>>();
256-
}
256+
}

0 commit comments

Comments
 (0)