Skip to content

Commit 0226e80

Browse files
committed
Redesign transfer / endpoint API
1 parent c3ad79c commit 0226e80

File tree

26 files changed

+2012
-2158
lines changed

26 files changed

+2012
-2158
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ env_logger = "0.10.0"
2222
futures-lite = "1.13.0"
2323

2424
[target.'cfg(any(target_os="linux", target_os="android"))'.dependencies]
25-
rustix = { version = "0.38.17", features = ["fs", "event", "net"] }
25+
rustix = { version = "0.38.17", features = ["fs", "event", "net", "time"] }
2626
libc = "0.2.155"
2727

2828
[target.'cfg(target_os="windows")'.dependencies]

examples/blocking.rs

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

examples/bulk.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use futures_lite::future::block_on;
2-
use nusb::{transfer::RequestBuffer, MaybeFuture};
2+
use nusb::{
3+
transfer::{Bulk, In, Out},
4+
MaybeFuture,
5+
};
36

47
fn main() {
58
env_logger::init();
@@ -13,20 +16,22 @@ fn main() {
1316

1417
let device = di.open().wait().unwrap();
1518
let interface = device.claim_interface(0).wait().unwrap();
19+
let mut ep_out = interface.endpoint::<Bulk, Out>(0x02).unwrap();
20+
let mut ep_in = interface.endpoint::<Bulk, In>(0x81).unwrap();
1621

17-
block_on(interface.bulk_out(0x02, Vec::from([1, 2, 3, 4, 5])))
18-
.into_result()
19-
.unwrap();
20-
21-
let mut queue = interface.bulk_in_queue(0x81);
22+
let mut transfer = ep_out.allocate(64);
23+
transfer.extend_from_slice(&[1, 2, 3, 4, 5]);
24+
ep_out.submit(transfer);
25+
block_on(ep_out.next_complete()).status().unwrap();
2226

2327
loop {
24-
while queue.pending() < 8 {
25-
queue.submit(RequestBuffer::new(256));
28+
while ep_in.pending() < 8 {
29+
let transfer = ep_in.allocate(256);
30+
ep_in.submit(transfer);
2631
}
27-
let result = block_on(queue.next_complete());
32+
let result = block_on(ep_in.next_complete());
2833
println!("{result:?}");
29-
if result.status.is_err() {
34+
if result.status().is_err() {
3035
break;
3136
}
3237
}

examples/control.rs

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use futures_lite::future::block_on;
1+
use std::time::Duration;
2+
23
use nusb::{
34
transfer::{ControlIn, ControlOut, ControlType, Recipient},
45
MaybeFuture,
@@ -19,47 +20,67 @@ fn main() {
1920
// Linux can make control transfers without claiming an interface
2021
#[cfg(any(target_os = "linux", target_os = "macos"))]
2122
{
22-
let result = block_on(device.control_out(ControlOut {
23-
control_type: ControlType::Vendor,
24-
recipient: Recipient::Device,
25-
request: 0x81,
26-
value: 0x9999,
27-
index: 0x9999,
28-
data: &[1, 2, 3, 4],
29-
}));
23+
let result = device
24+
.control_out(
25+
ControlOut {
26+
control_type: ControlType::Vendor,
27+
recipient: Recipient::Device,
28+
request: 0x81,
29+
value: 0x9999,
30+
index: 0x9999,
31+
data: &[1, 2, 3, 4],
32+
},
33+
Duration::from_millis(100),
34+
)
35+
.wait();
3036
println!("{result:?}");
3137

32-
let result = block_on(device.control_in(ControlIn {
33-
control_type: ControlType::Vendor,
34-
recipient: Recipient::Device,
35-
request: 0x81,
36-
value: 0x9999,
37-
index: 0x9999,
38-
length: 256,
39-
}));
38+
let result = device
39+
.control_in(
40+
ControlIn {
41+
control_type: ControlType::Vendor,
42+
recipient: Recipient::Device,
43+
request: 0x81,
44+
value: 0x9999,
45+
index: 0x9999,
46+
length: 256,
47+
},
48+
Duration::from_millis(100),
49+
)
50+
.wait();
4051
println!("{result:?}");
4152
}
4253

4354
// but we also provide an API on the `Interface` to support Windows
4455
let interface = device.claim_interface(0).wait().unwrap();
4556

46-
let result = block_on(interface.control_out(ControlOut {
47-
control_type: ControlType::Vendor,
48-
recipient: Recipient::Device,
49-
request: 0x81,
50-
value: 0x9999,
51-
index: 0x9999,
52-
data: &[1, 2, 3, 4],
53-
}));
57+
let result = interface
58+
.control_out(
59+
ControlOut {
60+
control_type: ControlType::Vendor,
61+
recipient: Recipient::Device,
62+
request: 0x81,
63+
value: 0x9999,
64+
index: 0x9999,
65+
data: &[1, 2, 3, 4],
66+
},
67+
Duration::from_millis(100),
68+
)
69+
.wait();
5470
println!("{result:?}");
5571

56-
let result = block_on(interface.control_in(ControlIn {
57-
control_type: ControlType::Vendor,
58-
recipient: Recipient::Device,
59-
request: 0x81,
60-
value: 0x9999,
61-
index: 0x9999,
62-
length: 256,
63-
}));
72+
let result = interface
73+
.control_in(
74+
ControlIn {
75+
control_type: ControlType::Vendor,
76+
recipient: Recipient::Device,
77+
request: 0x81,
78+
value: 0x9999,
79+
index: 0x9999,
80+
length: 256,
81+
},
82+
Duration::from_millis(100),
83+
)
84+
.wait();
6485
println!("{result:?}");
6586
}

examples/string_descriptors.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,31 @@ fn inspect_device(dev: DeviceInfo) {
3333

3434
let languages: Vec<u16> = dev
3535
.get_string_descriptor_supported_languages(timeout)
36+
.wait()
3637
.map(|i| i.collect())
3738
.unwrap_or_default();
3839
println!(" Languages: {languages:02x?}");
3940

4041
let language = languages.first().copied().unwrap_or(US_ENGLISH);
4142

4243
if let Some(i_manufacturer) = dev_descriptor.manufacturer_string_index() {
43-
let s = dev.get_string_descriptor(i_manufacturer, language, timeout);
44+
let s = dev
45+
.get_string_descriptor(i_manufacturer, language, timeout)
46+
.wait();
4447
println!(" Manufacturer({i_manufacturer}): {s:?}");
4548
}
4649

4750
if let Some(i_product) = dev_descriptor.product_string_index() {
48-
let s = dev.get_string_descriptor(i_product, language, timeout);
51+
let s = dev
52+
.get_string_descriptor(i_product, language, timeout)
53+
.wait();
4954
println!(" Product({i_product}): {s:?}");
5055
}
5156

5257
if let Some(i_serial) = dev_descriptor.serial_number_string_index() {
53-
let s = dev.get_string_descriptor(i_serial, language, timeout);
58+
let s = dev
59+
.get_string_descriptor(i_serial, language, timeout)
60+
.wait();
5461
println!(" Serial({i_serial}): {s:?}");
5562
}
5663

src/bitset.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/// Bitset capable of storing 0x00..=0x0f and 0x80..=0x8f
2+
#[derive(Default, Clone, Copy)]
3+
pub struct EndpointBitSet(u32);
4+
5+
impl EndpointBitSet {
6+
pub fn mask(ep: u8) -> u32 {
7+
let bit = ((ep & 0x0f) << 1) | (ep >> 7);
8+
1 << bit
9+
}
10+
11+
pub fn is_set(&self, bit: u8) -> bool {
12+
self.0 & Self::mask(bit) != 0
13+
}
14+
15+
pub fn is_empty(&self) -> bool {
16+
self.0 == 0
17+
}
18+
19+
pub fn set(&mut self, bit: u8) {
20+
self.0 |= Self::mask(bit)
21+
}
22+
23+
pub fn clear(&mut self, bit: u8) {
24+
self.0 &= !Self::mask(bit)
25+
}
26+
}

src/descriptors.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ use std::{
1313

1414
use log::warn;
1515

16-
use crate::{
17-
transfer::{Direction, TransferType},
18-
Error,
19-
};
16+
use crate::{transfer::Direction, Error};
2017

2118
pub(crate) const DESCRIPTOR_TYPE_DEVICE: u8 = 0x01;
2219
pub(crate) const DESCRIPTOR_LEN_DEVICE: u8 = 18;
@@ -696,6 +693,23 @@ impl<'a> Debug for EndpointDescriptor<'a> {
696693
}
697694
}
698695

696+
/// Endpoint type.
697+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
698+
#[allow(dead_code)]
699+
pub enum TransferType {
700+
/// Control endpoint.
701+
Control = 0,
702+
703+
/// Isochronous endpoint.
704+
Isochronous = 1,
705+
706+
/// Bulk endpoint.
707+
Bulk = 2,
708+
709+
/// Interrupt endpoint.
710+
Interrupt = 3,
711+
}
712+
699713
/// Error from [`crate::Device::active_configuration`]
700714
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
701715
pub struct ActiveConfigurationError {

0 commit comments

Comments
 (0)