Skip to main content

device/
device.rs

1//! Device-side example.
2
3use std::time::{Duration, Instant};
4use tokio::time::sleep;
5use usb_gadget::{default_udc, Config, Gadget, Id, OsDescriptor, Strings};
6use uuid::uuid;
7
8use upc::{
9    device::{InterfaceId, UpcFunction},
10    Class,
11};
12
13mod common;
14use common::*;
15
16const DEVICE_CLASS: Class = Class::vendor_specific(0xff, 0);
17
18#[tokio::main(flavor = "current_thread")]
19async fn main() {
20    init_log();
21
22    usb_gadget::remove_all().expect("cannot remove all USB gadgets");
23    sleep(Duration::from_secs(1)).await;
24
25    println!("Creating UPC function...");
26    let (mut upc, hnd) = UpcFunction::new(
27        InterfaceId::new(CLASS)
28            .with_name("USB PACKET TEST")
29            .with_guid(uuid!("3bf77270-42d2-42c6-a475-490227a9cc89")),
30    );
31    upc.set_info(INFO.to_vec()).await;
32
33    println!("Registering gadget...");
34    let udc = default_udc().expect("cannot get UDC");
35    let mut gadget = Gadget::new(DEVICE_CLASS.into(), Id::new(VID, PID), Strings::new("usb-packet", "test", "0"))
36        .with_config(Config::new("config").with_function(hnd))
37        .with_os_descriptor(OsDescriptor::microsoft());
38    gadget.device_release = 0x0110;
39    let reg = gadget.bind(&udc).expect("cannot bind to UDC");
40    assert!(reg.is_attached());
41
42    println!("Waiting for connection...");
43    let (tx, mut rx) = upc.accept().await.expect("accept failed");
44    assert_eq!(rx.topic(), TOPIC, "wrong topic");
45
46    let overall_start = Instant::now();
47
48    let rx_task = tokio::spawn(async move {
49        let mut rx_testdata = TestData::new(HOST_SEED, TEST_PACKET_MAX_SIZE);
50        let mut rx_delay = TestDelayer::new(HOST_SEED);
51
52        let start = Instant::now();
53        let mut total = 0usize;
54
55        println!("Receiving...");
56        for n in 0..TEST_PACKETS {
57            let data = rx.recv().await.expect("receive failed").expect("unexpected EOF");
58            eprintln!("Recv {n}: {} bytes", data.len());
59            total += data.len();
60            rx_testdata.validate(&data);
61            rx_delay.delay().await;
62        }
63
64        let elapsed = start.elapsed().as_secs_f32();
65        println!("Received {total} bytes in {elapsed:.2} seconds: {} MB/s", total as f32 / elapsed / 1_048_576.);
66
67        println!("Waiting for receiver close");
68        assert_eq!(rx.recv().await.unwrap(), None, "receiver not closed");
69        println!("Receiver closed");
70
71        total
72    });
73
74    let mut tx_testdata = TestData::new(DEVICE_SEED, TEST_PACKET_MAX_SIZE);
75    let mut tx_delay = TestDelayer::new(DEVICE_SEED);
76
77    let start = Instant::now();
78    let mut tx_total = 0;
79
80    println!("Sending");
81    for n in 0..TEST_PACKETS {
82        let data = tx_testdata.generate();
83        let len = data.len();
84        tx.send(data.into()).await.expect("send failed");
85        tx_total += len;
86        tx_delay.delay().await;
87
88        eprintln!("Send {n}: {len} bytes");
89    }
90
91    let elapsed = start.elapsed().as_secs_f32();
92    println!("Sent {tx_total} bytes in {elapsed:.2} seconds: {} MB/s", tx_total as f32 / elapsed / 1_048_576.);
93
94    sleep(Duration::from_secs(3)).await;
95
96    println!("Waiting for receiver...");
97    let rx_total = rx_task.await.unwrap();
98    drop(tx);
99
100    let overall_elapsed = overall_start.elapsed().as_secs_f32();
101    let total_bytes = tx_total + rx_total;
102    println!(
103        "Total throughput: {} bytes in {overall_elapsed:.2} seconds: {:.2} MB/s",
104        total_bytes,
105        total_bytes as f32 / overall_elapsed / 1_048_576.
106    );
107    println!("Disconnected");
108
109    sleep(Duration::from_secs(3)).await;
110}