Skip to content

Commit 67d5e20

Browse files
committed
Merge remote-tracking branch 'rec/master' into rs/issue-82/short-data-stage
2 parents abdf004 + 10b4e12 commit 67d5e20

File tree

9 files changed

+197
-54
lines changed

9 files changed

+197
-54
lines changed

.github/workflows/ci.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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

.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: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
10+
...
11+
12+
## [0.2.8] - 2021-03-13
13+
14+
## [0.2.7] - 2020-10-03
15+
16+
## [0.2.6] - 2020-09-22
17+
18+
## [0.2.5] - 2020-02-10
19+
20+
## [0.2.4] - 2020-02-01
21+
22+
## [0.2.3] - 2019-08-28
23+
24+
## [0.2.2] - 2019-07-27
25+
26+
## [0.2.1] - 2019-06-07
27+
28+
## [0.2.0] - 2019-06-07
29+
30+
## 0.1.0 - 2019-06-07
31+
32+
This is the initial release to crates.io.
33+
34+
[Unreleased]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.8...HEAD
35+
[0.2.8]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.7...v0.2.8
36+
[0.2.7]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.6...v0.2.7
37+
[0.2.6]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.5...v0.2.6
38+
[0.2.5]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.4...v0.2.5
39+
[0.2.4]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.3...v0.2.4
40+
[0.2.3]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.2...v0.2.3
41+
[0.2.2]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.1...v0.2.2
42+
[0.2.1]: https://github.com/rust-embedded-community/usb-device/compare/v0.2.0...v0.2.1
43+
[0.2.0]: https://github.com/rust-embedded-community/usb-device/compare/v0.1.0...v0.2.0

src/control_pipe.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<B: UsbBus> ControlPipe<'_, B> {
122122
return Some(req);
123123
}
124124

125-
return None;
125+
None
126126
}
127127

128128
pub fn handle_out<'p>(&'p mut self) -> Option<Request> {
@@ -162,7 +162,7 @@ impl<B: UsbBus> ControlPipe<'_, B> {
162162
}
163163
}
164164

165-
return None;
165+
None
166166
}
167167

168168
pub fn handle_in_complete(&mut self) -> bool {
@@ -193,7 +193,7 @@ impl<B: UsbBus> ControlPipe<'_, B> {
193193
}
194194
};
195195

196-
return false;
196+
false
197197
}
198198

199199
fn write_in_chunk(&mut self) {

src/descriptor.rs

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::cmp::min;
2+
13
use crate::bus::{InterfaceNumber, StringIndex, UsbBus};
24
use crate::device;
35
use crate::endpoint::{Endpoint, EndpointDirection};
@@ -61,20 +63,45 @@ impl DescriptorWriter<'_> {
6163

6264
/// Writes an arbitrary (usually class-specific) descriptor.
6365
pub fn write(&mut self, descriptor_type: u8, descriptor: &[u8]) -> Result<()> {
64-
let length = descriptor.len();
66+
self.write_with(descriptor_type, |buf| {
67+
if descriptor.len() > buf.len() {
68+
return Err(UsbError::BufferOverflow);
69+
}
6570

66-
if (self.position + 2 + length) > self.buf.len() || (length + 2) > 255 {
71+
buf[..descriptor.len()].copy_from_slice(descriptor);
72+
73+
Ok(descriptor.len())
74+
})
75+
}
76+
77+
/// Writes an arbitrary (usually class-specific) descriptor by using a callback function.
78+
///
79+
/// The callback function gets a reference to the remaining buffer space, and it should write
80+
/// the descriptor into it and return the number of bytes written. If the descriptor doesn't
81+
/// fit, the function should return `Err(UsbError::BufferOverflow)`. That and any error returned
82+
/// by it will be propagated up.
83+
pub fn write_with(
84+
&mut self,
85+
descriptor_type: u8,
86+
f: impl FnOnce(&mut [u8]) -> Result<usize>,
87+
) -> Result<()> {
88+
if self.position + 2 > self.buf.len() {
6789
return Err(UsbError::BufferOverflow);
6890
}
6991

70-
self.buf[self.position] = (length + 2) as u8;
71-
self.buf[self.position + 1] = descriptor_type;
92+
let data_end = min(self.buf.len(), self.position + 256);
93+
let data_buf = &mut self.buf[self.position + 2..data_end];
94+
95+
let total_len = f(data_buf)? + 2;
7296

73-
let start = self.position + 2;
97+
if self.position + total_len > self.buf.len() {
98+
return Err(UsbError::BufferOverflow);
99+
}
74100

75-
self.buf[start..start + length].copy_from_slice(descriptor);
101+
self.buf[self.position] = total_len as u8;
102+
self.buf[self.position + 1] = descriptor_type;
76103

77-
self.position = start + length;
104+
self.position += total_len;
78105

79106
Ok(())
80107
}
@@ -264,26 +291,46 @@ impl DescriptorWriter<'_> {
264291
pub fn endpoint<'e, B: UsbBus, D: EndpointDirection>(
265292
&mut self,
266293
endpoint: &Endpoint<'e, B, D>,
294+
) -> Result<()> {
295+
self.endpoint_ex(endpoint, |_| Ok(0))
296+
}
297+
298+
/// Writes an endpoint descriptor with extra trailing data.
299+
///
300+
/// This is rarely needed and shouldn't be used except for compatibility with standard USB
301+
/// classes that require it. Extra data is normally written in a separate class specific
302+
/// descriptor.
303+
///
304+
/// # Arguments
305+
///
306+
/// * `endpoint` - Endpoint previously allocated with
307+
/// [`UsbBusAllocator`](crate::bus::UsbBusAllocator).
308+
/// * `f` - Callback for the extra data. See `write_with` for more information.
309+
pub fn endpoint_ex<'e, B: UsbBus, D: EndpointDirection>(
310+
&mut self,
311+
endpoint: &Endpoint<'e, B, D>,
312+
f: impl FnOnce(&mut [u8]) -> Result<usize>,
267313
) -> Result<()> {
268314
match self.num_endpoints_mark {
269315
Some(mark) => self.buf[mark] += 1,
270316
None => return Err(UsbError::InvalidState),
271317
};
272318

273-
let mps = endpoint.max_packet_size();
319+
self.write_with(descriptor_type::ENDPOINT, |buf| {
320+
if buf.len() < 5 {
321+
return Err(UsbError::BufferOverflow);
322+
}
274323

275-
self.write(
276-
descriptor_type::ENDPOINT,
277-
&[
278-
endpoint.address().into(), // bEndpointAddress
279-
endpoint.ep_type() as u8, // bmAttributes
280-
mps as u8,
281-
(mps >> 8) as u8, // wMaxPacketSize
282-
endpoint.interval(), // bInterval
283-
],
284-
)?;
324+
let mps = endpoint.max_packet_size();
285325

286-
Ok(())
326+
buf[0] = endpoint.address().into();
327+
buf[1] = endpoint.ep_type() as u8;
328+
buf[2] = mps as u8;
329+
buf[3] = (mps >> 8) as u8;
330+
buf[4] = endpoint.interval();
331+
332+
Ok(f(&mut buf[5..])? + 5)
333+
})
287334
}
288335

289336
/// Writes a string descriptor.
@@ -325,7 +372,7 @@ pub struct BosWriter<'w, 'a: 'w> {
325372
impl<'w, 'a: 'w> BosWriter<'w, 'a> {
326373
pub(crate) fn new(writer: &'w mut DescriptorWriter<'a>) -> Self {
327374
Self {
328-
writer: writer,
375+
writer,
329376
num_caps_mark: None,
330377
}
331378
}

src/device.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,14 @@ impl<B: UsbBus> UsbDevice<'_, B> {
193193
if (ep_in_complete & 1) != 0 {
194194
let completed = self.control.handle_in_complete();
195195

196-
if !B::QUIRK_SET_ADDRESS_BEFORE_STATUS {
197-
if completed && self.pending_address != 0 {
198-
self.bus.set_device_address(self.pending_address);
199-
self.pending_address = 0;
196+
if !B::QUIRK_SET_ADDRESS_BEFORE_STATUS
197+
&& completed
198+
&& self.pending_address != 0
199+
{
200+
self.bus.set_device_address(self.pending_address);
201+
self.pending_address = 0;
200202

201-
self.device_state = UsbDeviceState::Addressed;
202-
}
203+
self.device_state = UsbDeviceState::Addressed;
203204
}
204205
}
205206

@@ -275,7 +276,7 @@ impl<B: UsbBus> UsbDevice<'_, B> {
275276
}
276277
}
277278

278-
return false;
279+
false
279280
}
280281

281282
fn control_in(&mut self, classes: &mut ClassList<'_, B>, req: control::Request) {
@@ -508,7 +509,7 @@ impl<B: UsbBus> UsbDevice<'_, B> {
508509
classes
509510
.iter()
510511
.filter_map(|cls| cls.get_string(index, lang_id))
511-
.nth(0)
512+
.next()
512513
}
513514
};
514515

src/endpoint.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::bus::UsbBus;
22
use crate::{Result, UsbDirection};
33
use core::marker::PhantomData;
4-
use core::ptr;
54
use core::sync::atomic::{AtomicPtr, Ordering};
65

76
/// Trait for endpoint type markers.
@@ -77,7 +76,7 @@ impl<B: UsbBus, D: EndpointDirection> Endpoint<'_, B, D> {
7776

7877
fn bus(&self) -> &B {
7978
let bus_ptr = self.bus_ptr.load(Ordering::SeqCst);
80-
if bus_ptr == ptr::null_mut() {
79+
if bus_ptr.is_null() {
8180
panic!("UsbBus initialization not complete");
8281
}
8382

src/test_class.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ pub struct TestClass<'a, B: UsbBus> {
4646

4747
pub const VID: u16 = 0x16c0;
4848
pub const PID: u16 = 0x05dc;
49-
pub const MANUFACTURER: &'static str = "TestClass Manufacturer";
50-
pub const PRODUCT: &'static str = "virkkunen.net usb-device TestClass";
51-
pub const SERIAL_NUMBER: &'static str = "TestClass Serial";
52-
pub const CUSTOM_STRING: &'static str = "TestClass Custom String";
53-
pub const INTERFACE_STRING: &'static str = "TestClass Interface";
49+
pub const MANUFACTURER: &str = "TestClass Manufacturer";
50+
pub const PRODUCT: &str = "virkkunen.net usb-device TestClass";
51+
pub const SERIAL_NUMBER: &str = "TestClass Serial";
52+
pub const CUSTOM_STRING: &str = "TestClass Custom String";
53+
pub const INTERFACE_STRING: &str = "TestClass Interface";
5454

5555
pub const REQ_STORE_REQUEST: u8 = 1;
5656
pub const REQ_READ_BUFFER: u8 = 2;
@@ -59,7 +59,7 @@ pub const REQ_SET_BENCH_ENABLED: u8 = 4;
5959
pub const REQ_READ_LONG_DATA: u8 = 5;
6060
pub const REQ_UNKNOWN: u8 = 42;
6161

62-
pub const LONG_DATA: &'static [u8] = &[0x17; 257];
62+
pub const LONG_DATA: &[u8] = &[0x17; 257];
6363

6464
impl<B: UsbBus> TestClass<'_, B> {
6565
/// Creates a new TestClass.
@@ -105,7 +105,7 @@ impl<B: UsbBus> TestClass<'_, B> {
105105
&'a self,
106106
usb_bus: &'b UsbBusAllocator<B>,
107107
) -> UsbDeviceBuilder<'b, B> {
108-
UsbDeviceBuilder::new(&usb_bus, UsbVidPid(VID, PID))
108+
UsbDeviceBuilder::new(usb_bus, UsbVidPid(VID, PID))
109109
.manufacturer(MANUFACTURER)
110110
.product(PRODUCT)
111111
.serial_number(SERIAL_NUMBER)

0 commit comments

Comments
 (0)