Skip to content

Commit

Permalink
Merge branch 'master' into polyfill
Browse files Browse the repository at this point in the history
  • Loading branch information
ia0 committed Apr 24, 2023
2 parents 8291ac0 + 4ad3f72 commit ad79b33
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 20 deletions.
11 changes: 8 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
* New enums and allocators for Isochronous endpoints
* 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.
* `EndpointType` enum now has fields for isochronous synchronization and usage ([#60](https://github.com/rust-embedded-community/usb-device/pull/60)).

## [0.2.9] - 2022-08-02

### Added
* Optional support for defmt ([#76](https://github.com/rust-embedded-community/usb-device/pull/76)).

### Fixed
* Fixed an issue where USB devices were not enumerating on Windows ([#32](https://github.com/rust-embedded-community/usb-device/issues/82))
* Add optional support for defmt ([#76](https://github.com/rust-embedded-community/usb-device/pull/76))
* 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))

## [0.2.8] - 2021-03-13
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
12 changes: 6 additions & 6 deletions src/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ impl DescriptorWriter<'_> {
self.write(
descriptor_type::DEVICE,
&[
0x10,
0x02, // bcdUSB 2.1
config.device_class, // bDeviceClass
config.device_sub_class, // bDeviceSubClass
config.device_protocol, // bDeviceProtocol
config.max_packet_size_0, // bMaxPacketSize0
(config.usb_rev as u16) as u8,
(config.usb_rev as u16 >> 8) as u8, // bcdUSB
config.device_class, // bDeviceClass
config.device_sub_class, // bDeviceSubClass
config.device_protocol, // bDeviceProtocol
config.max_packet_size_0, // bMaxPacketSize0
config.vendor_id as u8,
(config.vendor_id >> 8) as u8, // idVendor
config.product_id as u8,
Expand Down
64 changes: 57 additions & 7 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 @@ -30,6 +30,18 @@ pub enum UsbDeviceState {
// Maximum number of endpoints in one direction. Specified by the USB specification.
const MAX_ENDPOINTS: usize = 16;

/// Usb spec revision.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u16)]
pub enum UsbRev {
/// USB 2.0 compliance
Usb200 = 0x200,
/// USB 2.1 compliance.
///
/// Typically adds support for BOS requests.
Usb210 = 0x210,
}

/// A USB device consisting of one or more device classes.
pub struct UsbDevice<'a, B: UsbBus> {
bus: &'a B,
Expand All @@ -49,6 +61,7 @@ pub(crate) struct Config<'a> {
pub max_packet_size_0: u8,
pub vendor_id: u16,
pub product_id: u16,
pub usb_rev: UsbRev,
pub device_release: u16,
pub manufacturer: Option<&'a str>,
pub product: Option<&'a str>,
Expand Down Expand Up @@ -344,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 @@ -361,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 @@ -434,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 Expand Up @@ -469,7 +519,7 @@ impl<B: UsbBus> UsbDevice<'_, B> {
}

match dtype {
descriptor_type::BOS => accept_writer(xfer, |w| {
descriptor_type::BOS if config.usb_rev > UsbRev::Usb200 => accept_writer(xfer, |w| {
let mut bw = BosWriter::new(w);
bw.bos()?;

Expand Down
8 changes: 7 additions & 1 deletion src/device_builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::bus::{UsbBus, UsbBusAllocator};
use crate::device::{Config, UsbDevice};
use crate::device::{Config, UsbDevice, UsbRev};

/// A USB vendor ID and product ID pair.
pub struct UsbVidPid(pub u16, pub u16);
Expand Down Expand Up @@ -34,6 +34,7 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
max_packet_size_0: 8,
vendor_id: vid_pid.0,
product_id: vid_pid.1,
usb_rev: UsbRev::Usb210,
device_release: 0x0010,
manufacturer: None,
product: None,
Expand Down Expand Up @@ -87,6 +88,11 @@ impl<'a, B: UsbBus> UsbDeviceBuilder<'a, B> {
///
/// Default: `false`
supports_remote_wakeup: bool,

/// Sets which Usb 2 revision to comply to.
///
/// Default: `UsbRev::Usb210`
usb_rev: UsbRev,
}

/// Configures the device as a composite device with interface association descriptors.
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ pub mod class_prelude {
}

fn _ensure_sync() {
use crate::bus::{PollResult, UsbBus, UsbBusAllocator};
use crate::bus::PollResult;
use crate::class_prelude::*;

struct DummyBus<'a> {
Expand Down

0 comments on commit ad79b33

Please sign in to comment.