Skip to content

Commit f95217b

Browse files
committed
Merge remote-tracking branch 'origin/master' into feature/alternate-settings
2 parents 136b00e + 46a354c commit f95217b

16 files changed

+475
-107
lines changed

.github/workflows/ci.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
on:
2+
push:
3+
branches: [ staging, trying, master ]
4+
pull_request:
5+
6+
name: CI
7+
8+
jobs:
9+
ci-linux:
10+
name: CI
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
rust: [stable]
16+
17+
include:
18+
# Test nightly but don't fail
19+
- rust: nightly
20+
experimental: true
21+
TARGET: x86_64-unknown-linux-gnu
22+
23+
steps:
24+
- uses: actions/checkout@v2
25+
26+
- uses: actions-rs/toolchain@v1
27+
with:
28+
profile: minimal
29+
toolchain: ${{ matrix.rust }}
30+
target: ${{ matrix.TARGET }}
31+
override: true
32+
33+
- name: Install libusb library
34+
run: sudo apt-get install -y libusb-1.0.0-dev
35+
36+
- uses: actions-rs/cargo@v1
37+
with:
38+
command: check
39+
args: --all-targets
40+
41+
- uses: actions-rs/cargo@v1
42+
with:
43+
command: check
44+
args: --features control-buffer-256
45+
46+
- uses: actions-rs/cargo@v1
47+
with:
48+
command: check
49+
args: --features defmt

.github/workflows/rustfmt.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
on:
2+
push:
3+
branches: [ staging, trying, master ]
4+
pull_request:
5+
6+
name: Code formatting check
7+
8+
jobs:
9+
fmt:
10+
name: Rustfmt
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
- uses: actions-rs/toolchain@v1
15+
with:
16+
profile: minimal
17+
toolchain: stable
18+
override: true
19+
components: rustfmt
20+
- uses: actions-rs/cargo@v1
21+
with:
22+
command: fmt
23+
args: --all -- --check

.travis.yml

Lines changed: 0 additions & 14 deletions
This file was deleted.

CHANGELOG.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
### Added
10+
* New enums and allocators for Isochronous endpoints
11+
* Added support for alternate settings on interfaces
12+
13+
### Changed
14+
* `EndpointType` enum now has fields for isochronous synchronization and usage.
15+
16+
## [0.2.9] - 2022-08-02
17+
18+
### Fixed
19+
* Fixed an issue where USB devices were not enumerating on Windows ([#32](https://github.com/rust-embedded-community/usb-device/issues/82))
20+
* Add optional support for defmt ([#76](https://github.com/rust-embedded-community/usb-device/pull/76))
21+
* 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))
22+
23+
## [0.2.8] - 2021-03-13
24+
25+
## [0.2.7] - 2020-10-03
26+
27+
## [0.2.6] - 2020-09-22
28+
29+
## [0.2.5] - 2020-02-10
30+
31+
## [0.2.4] - 2020-02-01
32+
33+
## [0.2.3] - 2019-08-28
34+
35+
## [0.2.2] - 2019-07-27
36+
37+
## [0.2.1] - 2019-06-07
38+
39+
## [0.2.0] - 2019-06-07
40+
41+
## 0.1.0 - 2019-06-07
42+
43+
This is the initial release to crates.io.
44+
45+
[Unreleased]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.9...HEAD
46+
[0.2.9]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.8...v0.2.9
47+
[0.2.8]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.7...v0.2.8
48+
[0.2.7]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.6...v0.2.7
49+
[0.2.6]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.5...v0.2.6
50+
[0.2.5]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.4...v0.2.5
51+
[0.2.4]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.3...v0.2.4
52+
[0.2.3]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.2...v0.2.3
53+
[0.2.2]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.1...v0.2.2
54+
[0.2.1]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.0...v0.2.1
55+
[0.2.0]: https://github.com/rust-embedded-community/usb-device/compare/v0.1.0...v0.2.0

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ license = "MIT"
99
authors = ["Matti Virkkunen <[email protected]>"]
1010
repository = "https://github.com/mvirkkunen/usb-device"
1111

12+
[dependencies]
13+
defmt = { version = "0.3", optional = true }
14+
1215
[dev-dependencies]
13-
rusb = "0.8.0"
14-
rand = "0.6.1"
16+
rusb = "0.9.1"
17+
rand = "0.8.5"
1518

1619
[features]
1720
# Use a 256 byte buffer for control transfers instead of 128.

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,26 @@ each device's USB peripheral.
2020
Hardware driver crates
2121
----------------------
2222

23-
* [stm32-usbd](https://github.com/stm32-rs/stm32-usbd) - device-driver implementation for multiple STM32 microcontroller families.
24-
Examples can be found in each individual HAL crate that implements the USB peripheral.
23+
* [atsam4](https://github.com/atsam-rs/atsam4-hal) - device-driver implementation for atsam4e & atsam4s microcontrollers (UDP). Examples can be found [here](https://github.com/atsam-rs/sam_xplained). While not expressly supported with this crate, atsam3s and atsam55g could also be supported with a similar code-base.
2524

2625
* [atsamd](https://github.com/atsamd-rs/atsamd) - device-driver implementation for samd21 & samd51 microcontrollers. An example for the
2726
itsybitsy_m4 board from Adafruit can be found [here](https://github.com/atsamd-rs/atsamd/blob/master/boards/itsybitsy_m4/examples/usb_serial.rs).
2827

2928
* [imxrt-usbd](https://github.com/imxrt-rs/imxrt-usbd) - device-driver implementation for NXP i.MX RT microcontrollers. Examples for
3029
i.MX RT boards, like the Teensy 4, are maintained with the driver.
3130

31+
* [stm32-usbd](https://github.com/stm32-rs/stm32-usbd) - device-driver implementation for multiple STM32 microcontroller families.
32+
Examples can be found in each individual HAL crate that implements the USB peripheral.
33+
3234
Class crates
3335
------------
3436

35-
* [usbd-serial](https://github.com/mvirkkunen/usbd-serial) [![Crates.io](https://img.shields.io/crates/v/usbd-serial.svg)](https://crates.io/crates/usbd-serial) - CDC-ACM serial port class
3637
* [usbd-hid](https://github.com/twitchyliquid64/usbd-hid) [![Crates.io](https://img.shields.io/crates/v/usbd-hid.svg)](https://crates.io/crates/usbd-hid) - HID class
38+
* [usbd-serial](https://github.com/mvirkkunen/usbd-serial) [![Crates.io](https://img.shields.io/crates/v/usbd-serial.svg)](https://crates.io/crates/usbd-serial) - CDC-ACM serial port class
39+
40+
41+
Others
42+
------
43+
44+
Other implementations for USB in Rust
45+
* The [Embassy](https://github.com/embassy-rs/embassy) project has an async USB stack, embassy-usb.

src/bus.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::endpoint::{Endpoint, EndpointAddress, EndpointDirection, EndpointType};
1+
use crate::endpoint::{
2+
Endpoint, EndpointAddress, EndpointDirection, EndpointType, IsochronousSynchronizationType,
3+
IsochronousUsageType,
4+
};
25
use crate::{Result, UsbDirection, UsbError};
36
use core::cell::RefCell;
47
use core::mem;
@@ -211,7 +214,7 @@ impl<B: UsbBus> UsbBusAllocator<B> {
211214
///
212215
/// This directly delegates to [`UsbBus::alloc_ep`], so see that method for details. In most
213216
/// cases classes should call the endpoint type specific methods instead.
214-
pub fn alloc<'a, D: EndpointDirection>(
217+
pub fn alloc<D: EndpointDirection>(
215218
&self,
216219
ep_addr: Option<EndpointAddress>,
217220
ep_type: EndpointType,
@@ -244,6 +247,41 @@ impl<B: UsbBus> UsbBusAllocator<B> {
244247
.expect("alloc_ep failed")
245248
}
246249

250+
/// Allocates an isochronous endpoint.
251+
///
252+
/// # Arguments
253+
///
254+
/// * `synchronization` - Type of synchronization used by the endpoint
255+
/// * `usage` - Whether the endpoint is data, explicit feedback, or data+implicit feedback
256+
/// * `payload_size` - Payload size in bytes.
257+
/// * `interval` - Interval for polling, expressed in frames/microframes.
258+
///
259+
/// See USB 2.0 section 9.6.6.
260+
///
261+
/// # Panics
262+
///
263+
/// Panics if endpoint allocation fails, because running out of endpoints or memory is not
264+
/// feasibly recoverable.
265+
#[inline]
266+
pub fn isochronous<D: EndpointDirection>(
267+
&self,
268+
synchronization: IsochronousSynchronizationType,
269+
usage: IsochronousUsageType,
270+
payload_size: u16,
271+
interval: u8,
272+
) -> Endpoint<'_, B, D> {
273+
self.alloc(
274+
None,
275+
EndpointType::Isochronous {
276+
synchronization,
277+
usage,
278+
},
279+
payload_size,
280+
interval,
281+
)
282+
.expect("alloc_ep failed")
283+
}
284+
247285
/// Allocates a bulk endpoint.
248286
///
249287
/// # Arguments
@@ -263,6 +301,7 @@ impl<B: UsbBus> UsbBusAllocator<B> {
263301
/// Allocates an interrupt endpoint.
264302
///
265303
/// * `max_packet_size` - Maximum packet size in bytes. Cannot exceed 64 bytes.
304+
/// * `interval` - Polling interval.
266305
///
267306
/// # Panics
268307
///
@@ -281,6 +320,7 @@ impl<B: UsbBus> UsbBusAllocator<B> {
281320

282321
/// A handle for a USB interface that contains its number.
283322
#[derive(Copy, Clone, Eq, PartialEq)]
323+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
284324
pub struct InterfaceNumber(pub(crate) u8);
285325

286326
impl From<InterfaceNumber> for u8 {
@@ -291,6 +331,7 @@ impl From<InterfaceNumber> for u8 {
291331

292332
/// A handle for a USB string descriptor that contains its index.
293333
#[derive(Copy, Clone, Eq, PartialEq)]
334+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
294335
pub struct StringIndex(u8);
295336

296337
impl StringIndex {

src/control.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::mem;
44
/// Control request type.
55
#[repr(u8)]
66
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
7+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
78
pub enum RequestType {
89
/// Request is a USB standard request. Usually handled by
910
/// [`UsbDevice`](crate::device::UsbDevice).
@@ -18,6 +19,7 @@ pub enum RequestType {
1819

1920
/// Control request recipient.
2021
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
22+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2123
pub enum Recipient {
2224
/// Request is intended for the entire device.
2325
Device = 0,
@@ -35,6 +37,7 @@ pub enum Recipient {
3537

3638
/// A control request read from a SETUP packet.
3739
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
40+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3841
pub struct Request {
3942
/// Direction of the request.
4043
pub direction: UsbDirection,

src/control_pipe.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{Result, UsbDirection, UsbError};
55
use core::cmp::min;
66

77
#[derive(Debug)]
8+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
89
#[allow(unused)]
910
enum ControlState {
1011
Idle,
@@ -51,10 +52,10 @@ impl<B: UsbBus> ControlPipe<'_, B> {
5152
}
5253

5354
pub fn waiting_for_response(&self) -> bool {
54-
match self.state {
55-
ControlState::CompleteOut | ControlState::CompleteIn(_) => true,
56-
_ => false,
57-
}
55+
matches!(
56+
self.state,
57+
ControlState::CompleteOut | ControlState::CompleteIn(_)
58+
)
5859
}
5960

6061
pub fn data(&self) -> &[u8] {
@@ -65,7 +66,7 @@ impl<B: UsbBus> ControlPipe<'_, B> {
6566
self.state = ControlState::Idle;
6667
}
6768

68-
pub fn handle_setup<'p>(&'p mut self) -> Option<Request> {
69+
pub fn handle_setup(&mut self) -> Option<Request> {
6970
let count = match self.ep_out.read(&mut self.buf[..]) {
7071
Ok(count) => count,
7172
Err(UsbError::WouldBlock) => return None,
@@ -122,10 +123,10 @@ impl<B: UsbBus> ControlPipe<'_, B> {
122123
return Some(req);
123124
}
124125

125-
return None;
126+
None
126127
}
127128

128-
pub fn handle_out<'p>(&'p mut self) -> Option<Request> {
129+
pub fn handle_out(&mut self) -> Option<Request> {
129130
match self.state {
130131
ControlState::DataOut(req) => {
131132
let i = self.i;
@@ -147,7 +148,12 @@ impl<B: UsbBus> ControlPipe<'_, B> {
147148
return Some(req);
148149
}
149150
}
150-
ControlState::StatusOut => {
151+
// The host may terminate a DATA stage early by sending a zero-length status packet
152+
// acknowledging the data we sent it.
153+
ControlState::DataIn
154+
| ControlState::DataInLast
155+
| ControlState::DataInZlp
156+
| ControlState::StatusOut => {
151157
self.ep_out.read(&mut []).ok();
152158
self.state = ControlState::Idle;
153159
}
@@ -160,7 +166,7 @@ impl<B: UsbBus> ControlPipe<'_, B> {
160166
}
161167
}
162168

163-
return None;
169+
None
164170
}
165171

166172
pub fn handle_in_complete(&mut self) -> bool {
@@ -191,7 +197,7 @@ impl<B: UsbBus> ControlPipe<'_, B> {
191197
}
192198
};
193199

194-
return false;
200+
false
195201
}
196202

197203
fn write_in_chunk(&mut self) {

0 commit comments

Comments
 (0)