Skip to content

Commit ad79b33

Browse files
committed
Merge branch 'master' into polyfill
2 parents 8291ac0 + 4ad3f72 commit ad79b33

File tree

7 files changed

+99
-20
lines changed

7 files changed

+99
-20
lines changed

CHANGELOG.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
9+
910
### Added
10-
* New enums and allocators for Isochronous endpoints
11+
* New enums and allocators for Isochronous endpoints ([#60](https://github.com/rust-embedded-community/usb-device/pull/60)).
12+
* Ability to select USB revision ([#116](https://github.com/rust-embedded-community/usb-device/pull/116)).
13+
* Added support for alternate settings on interfaces ([#114](https://github.com/rust-embedded-community/usb-device/pull/114)).
1114

1215
### Changed
13-
* `EndpointType` enum now has fields for isochronous synchronization and usage.
16+
* `EndpointType` enum now has fields for isochronous synchronization and usage ([#60](https://github.com/rust-embedded-community/usb-device/pull/60)).
1417

1518
## [0.2.9] - 2022-08-02
1619

20+
### Added
21+
* Optional support for defmt ([#76](https://github.com/rust-embedded-community/usb-device/pull/76)).
22+
1723
### Fixed
1824
* Fixed an issue where USB devices were not enumerating on Windows ([#32](https://github.com/rust-embedded-community/usb-device/issues/82))
19-
* Add optional support for defmt ([#76](https://github.com/rust-embedded-community/usb-device/pull/76))
2025
* Fixed Suspend state transition so it goes back to the previous state, not just Default ([#97](https://github.com/rust-embedded-community/usb-device/pull/97))
2126

2227
## [0.2.8] - 2021-03-13

src/bus.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ impl<B: UsbBus> UsbBusAllocator<B> {
321321
/// A handle for a USB interface that contains its number.
322322
#[derive(Copy, Clone, Eq, PartialEq)]
323323
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
324-
pub struct InterfaceNumber(u8);
324+
pub struct InterfaceNumber(pub(crate) u8);
325325

326326
impl From<InterfaceNumber> for u8 {
327327
fn from(n: InterfaceNumber) -> u8 {

src/class.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::bus::{StringIndex, UsbBus};
1+
use crate::bus::{InterfaceNumber, StringIndex, UsbBus};
22
use crate::control;
33
use crate::control_pipe::ControlPipe;
44
use crate::descriptor::{BosWriter, DescriptorWriter};
@@ -116,6 +116,24 @@ pub trait UsbClass<B: UsbBus> {
116116
fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
117117
let _ = addr;
118118
}
119+
120+
/// Called when the interfaces alternate setting state is requested.
121+
///
122+
/// Note: This method may be called on interfaces, that are not relevant to this class.
123+
/// You should return `None, if `interface` belongs to an interface you don't know.
124+
fn get_alt_setting(&mut self, interface: InterfaceNumber) -> Option<u8> {
125+
let _ = interface;
126+
None
127+
}
128+
129+
/// Called when the interfaces alternate setting state is altered.
130+
///
131+
/// Note: This method may be called on interfaces, that are not relevant to this class.
132+
/// You should return `false`, if `interface` belongs to an interface you don't know.
133+
fn set_alt_setting(&mut self, interface: InterfaceNumber, alternative: u8) -> bool {
134+
let _ = (interface, alternative);
135+
false
136+
}
119137
}
120138

121139
/// Handle for a control IN transfer. When implementing a class, use the methods of this object to

src/descriptor.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ impl DescriptorWriter<'_> {
110110
self.write(
111111
descriptor_type::DEVICE,
112112
&[
113-
0x10,
114-
0x02, // bcdUSB 2.1
115-
config.device_class, // bDeviceClass
116-
config.device_sub_class, // bDeviceSubClass
117-
config.device_protocol, // bDeviceProtocol
118-
config.max_packet_size_0, // bMaxPacketSize0
113+
(config.usb_rev as u16) as u8,
114+
(config.usb_rev as u16 >> 8) as u8, // bcdUSB
115+
config.device_class, // bDeviceClass
116+
config.device_sub_class, // bDeviceSubClass
117+
config.device_protocol, // bDeviceProtocol
118+
config.max_packet_size_0, // bMaxPacketSize0
119119
config.vendor_id as u8,
120120
(config.vendor_id >> 8) as u8, // idVendor
121121
config.product_id as u8,

src/device.rs

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::bus::{PollResult, StringIndex, UsbBus, UsbBusAllocator};
1+
use crate::bus::{InterfaceNumber, PollResult, StringIndex, UsbBus, UsbBusAllocator};
22
use crate::class::{ControlIn, ControlOut, UsbClass};
33
use crate::control;
44
use crate::control_pipe::ControlPipe;
@@ -30,6 +30,18 @@ pub enum UsbDeviceState {
3030
// Maximum number of endpoints in one direction. Specified by the USB specification.
3131
const MAX_ENDPOINTS: usize = 16;
3232

33+
/// Usb spec revision.
34+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
35+
#[repr(u16)]
36+
pub enum UsbRev {
37+
/// USB 2.0 compliance
38+
Usb200 = 0x200,
39+
/// USB 2.1 compliance.
40+
///
41+
/// Typically adds support for BOS requests.
42+
Usb210 = 0x210,
43+
}
44+
3345
/// A USB device consisting of one or more device classes.
3446
pub struct UsbDevice<'a, B: UsbBus> {
3547
bus: &'a B,
@@ -49,6 +61,7 @@ pub(crate) struct Config<'a> {
4961
pub max_packet_size_0: u8,
5062
pub vendor_id: u16,
5163
pub product_id: u16,
64+
pub usb_rev: UsbRev,
5265
pub device_release: u16,
5366
pub manufacturer: Option<&'a str>,
5467
pub product: Option<&'a str>,
@@ -344,7 +357,25 @@ impl<B: UsbBus> UsbDevice<'_, B> {
344357
}
345358

346359
(Recipient::Interface, Request::GET_INTERFACE) => {
347-
// TODO: change when alternate settings are implemented
360+
// Reject interface numbers bigger than 255
361+
if req.index > core::u8::MAX.into() {
362+
xfer.reject().ok();
363+
return;
364+
}
365+
366+
// Ask class implementations, whether they know the alternate setting
367+
// of the interface in question
368+
for cls in classes {
369+
match cls.get_alt_setting(InterfaceNumber(req.index as u8)) {
370+
Some(setting) => {
371+
xfer.accept_with(&setting.to_le_bytes()).ok();
372+
return;
373+
}
374+
None => (),
375+
}
376+
}
377+
378+
// If no class returned an alternate setting, return the default value
348379
xfer.accept_with(&DEFAULT_ALTERNATE_SETTING.to_le_bytes())
349380
.ok();
350381
}
@@ -361,7 +392,7 @@ impl<B: UsbBus> UsbDevice<'_, B> {
361392
fn control_out(&mut self, classes: &mut ClassList<'_, B>, req: control::Request) {
362393
use crate::control::{Recipient, Request};
363394

364-
for cls in classes {
395+
for cls in classes.iter_mut() {
365396
cls.control_out(ControlOut::new(&mut self.control, &req));
366397

367398
if !self.control.waiting_for_response() {
@@ -434,9 +465,28 @@ impl<B: UsbBus> UsbDevice<'_, B> {
434465
}
435466
}
436467

437-
(Recipient::Interface, Request::SET_INTERFACE, DEFAULT_ALTERNATE_SETTING_U16) => {
438-
// TODO: do something when alternate settings are implemented
439-
xfer.accept().ok();
468+
(Recipient::Interface, Request::SET_INTERFACE, alt_setting) => {
469+
// Reject interface numbers and alt settings bigger than 255
470+
if req.index > core::u8::MAX.into() || alt_setting > core::u8::MAX.into() {
471+
xfer.reject().ok();
472+
return;
473+
}
474+
475+
// Ask class implementations, whether they accept the alternate interface setting.
476+
for cls in classes {
477+
if cls.set_alt_setting(InterfaceNumber(req.index as u8), alt_setting as u8)
478+
{
479+
xfer.accept().ok();
480+
return;
481+
}
482+
}
483+
484+
// Default behaviour, if no class implementation accepted the alternate setting.
485+
if alt_setting == DEFAULT_ALTERNATE_SETTING_U16 {
486+
xfer.accept().ok();
487+
} else {
488+
xfer.reject().ok();
489+
}
440490
}
441491

442492
_ => {
@@ -469,7 +519,7 @@ impl<B: UsbBus> UsbDevice<'_, B> {
469519
}
470520

471521
match dtype {
472-
descriptor_type::BOS => accept_writer(xfer, |w| {
522+
descriptor_type::BOS if config.usb_rev > UsbRev::Usb200 => accept_writer(xfer, |w| {
473523
let mut bw = BosWriter::new(w);
474524
bw.bos()?;
475525

src/device_builder.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::bus::{UsbBus, UsbBusAllocator};
2-
use crate::device::{Config, UsbDevice};
2+
use crate::device::{Config, UsbDevice, UsbRev};
33

44
/// A USB vendor ID and product ID pair.
55
pub struct UsbVidPid(pub u16, pub u16);
@@ -34,6 +34,7 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
3434
max_packet_size_0: 8,
3535
vendor_id: vid_pid.0,
3636
product_id: vid_pid.1,
37+
usb_rev: UsbRev::Usb210,
3738
device_release: 0x0010,
3839
manufacturer: None,
3940
product: None,
@@ -87,6 +88,11 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
8788
///
8889
/// Default: `false`
8990
supports_remote_wakeup: bool,
91+
92+
/// Sets which Usb 2 revision to comply to.
93+
///
94+
/// Default: `UsbRev::Usb210`
95+
usb_rev: UsbRev,
9096
}
9197

9298
/// Configures the device as a composite device with interface association descriptors.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pub mod class_prelude {
198198
}
199199

200200
fn _ensure_sync() {
201-
use crate::bus::{PollResult, UsbBus, UsbBusAllocator};
201+
use crate::bus::PollResult;
202202
use crate::class_prelude::*;
203203

204204
struct DummyBus<'a> {

0 commit comments

Comments
 (0)