Skip to content

Commit

Permalink
Merge pull request #114 from rust-embedded-community/feature/alternat…
Browse files Browse the repository at this point in the history
…e-settings

Feature/alternate settings
  • Loading branch information
eldruin committed Apr 24, 2023
2 parents c9e28ff + b7cf238 commit 4ad3f72
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
* New enums and allocators for Isochronous endpoints ([#60](https://github.com/rust-embedded-community/usb-device/pull/60)).
* Ability to select USB revision ([#116](https://github.com/rust-embedded-community/usb-device/pull/116)).
* Added support for alternate settings on interfaces ([#114](https://github.com/rust-embedded-community/usb-device/pull/114)).

### Changed
* `EndpointType` enum now has fields for isochronous synchronization and usage ([#60](https://github.com/rust-embedded-community/usb-device/pull/60)).
Expand Down
2 changes: 1 addition & 1 deletion src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ impl<B: UsbBus> UsbBusAllocator<B> {
/// A handle for a USB interface that contains its number.
#[derive(Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct InterfaceNumber(u8);
pub struct InterfaceNumber(pub(crate) u8);

impl From<InterfaceNumber> for u8 {
fn from(n: InterfaceNumber) -> u8 {
Expand Down
20 changes: 19 additions & 1 deletion src/class.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::bus::{StringIndex, UsbBus};
use crate::bus::{InterfaceNumber, StringIndex, UsbBus};
use crate::control;
use crate::control_pipe::ControlPipe;
use crate::descriptor::{BosWriter, DescriptorWriter};
Expand Down Expand Up @@ -116,6 +116,24 @@ pub trait UsbClass<B: UsbBus> {
fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
let _ = addr;
}

/// Called when the interfaces alternate setting state is requested.
///
/// Note: This method may be called on interfaces, that are not relevant to this class.
/// You should return `None, if `interface` belongs to an interface you don't know.
fn get_alt_setting(&mut self, interface: InterfaceNumber) -> Option<u8> {
let _ = interface;
None
}

/// Called when the interfaces alternate setting state is altered.
///
/// Note: This method may be called on interfaces, that are not relevant to this class.
/// You should return `false`, if `interface` belongs to an interface you don't know.
fn set_alt_setting(&mut self, interface: InterfaceNumber, alternative: u8) -> bool {
let _ = (interface, alternative);
false
}
}

/// Handle for a control IN transfer. When implementing a class, use the methods of this object to
Expand Down
49 changes: 43 additions & 6 deletions src/device.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::bus::{PollResult, StringIndex, UsbBus, UsbBusAllocator};
use crate::bus::{InterfaceNumber, PollResult, StringIndex, UsbBus, UsbBusAllocator};
use crate::class::{ControlIn, ControlOut, UsbClass};
use crate::control;
use crate::control_pipe::ControlPipe;
Expand Down Expand Up @@ -357,7 +357,25 @@ impl<B: UsbBus> UsbDevice<'_, B> {
}

(Recipient::Interface, Request::GET_INTERFACE) => {
// TODO: change when alternate settings are implemented
// Reject interface numbers bigger than 255
if req.index > core::u8::MAX.into() {
xfer.reject().ok();
return;
}

// Ask class implementations, whether they know the alternate setting
// of the interface in question
for cls in classes {
match cls.get_alt_setting(InterfaceNumber(req.index as u8)) {
Some(setting) => {
xfer.accept_with(&setting.to_le_bytes()).ok();
return;
}
None => (),
}
}

// If no class returned an alternate setting, return the default value
xfer.accept_with(&DEFAULT_ALTERNATE_SETTING.to_le_bytes())
.ok();
}
Expand All @@ -374,7 +392,7 @@ impl<B: UsbBus> UsbDevice<'_, B> {
fn control_out(&mut self, classes: &mut ClassList<'_, B>, req: control::Request) {
use crate::control::{Recipient, Request};

for cls in classes {
for cls in classes.iter_mut() {
cls.control_out(ControlOut::new(&mut self.control, &req));

if !self.control.waiting_for_response() {
Expand Down Expand Up @@ -447,9 +465,28 @@ impl<B: UsbBus> UsbDevice<'_, B> {
}
}

(Recipient::Interface, Request::SET_INTERFACE, DEFAULT_ALTERNATE_SETTING_U16) => {
// TODO: do something when alternate settings are implemented
xfer.accept().ok();
(Recipient::Interface, Request::SET_INTERFACE, alt_setting) => {
// Reject interface numbers and alt settings bigger than 255
if req.index > core::u8::MAX.into() || alt_setting > core::u8::MAX.into() {
xfer.reject().ok();
return;
}

// Ask class implementations, whether they accept the alternate interface setting.
for cls in classes {
if cls.set_alt_setting(InterfaceNumber(req.index as u8), alt_setting as u8)
{
xfer.accept().ok();
return;
}
}

// Default behaviour, if no class implementation accepted the alternate setting.
if alt_setting == DEFAULT_ALTERNATE_SETTING_U16 {
xfer.accept().ok();
} else {
xfer.reject().ok();
}
}

_ => {
Expand Down

0 comments on commit 4ad3f72

Please sign in to comment.