forked from stm32-rs/stm32h7xx-hal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
usb_passthrough.rs
138 lines (119 loc) · 3.92 KB
/
usb_passthrough.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Dual CDC-ACM serial port example using polling in a busy loop.
//!
//! Characters written to one serial port appear on both.
//!
//! This example uses both USB1 and USB2. This is only possible on devices that
//! have the USB2 peripheral.
#![no_std]
#![no_main]
use panic_itm as _;
use cortex_m_rt::entry;
use stm32h7xx_hal::rcc::rec::UsbClkSel;
use stm32h7xx_hal::usb_hs::{UsbBus, USB1, USB2};
use stm32h7xx_hal::{prelude::*, stm32};
use usb_device::prelude::*;
static mut EP_MEMORY_1: [u32; 1024] = [0; 1024];
static mut EP_MEMORY_2: [u32; 1024] = [0; 1024];
#[entry]
fn main() -> ! {
let dp = stm32::Peripherals::take().unwrap();
// Power
let pwr = dp.PWR.constrain();
let vos = pwr.freeze();
// RCC
let rcc = dp.RCC.constrain();
let mut ccdr = rcc.sys_ck(120.MHz()).freeze(vos, &dp.SYSCFG);
// 48MHz CLOCK
let _ = ccdr.clocks.hsi48_ck().expect("HSI48 must run");
ccdr.peripheral.kernel_usb_clk_mux(UsbClkSel::Hsi48);
// If your hardware uses the internal USB voltage regulator in ON mode, you
// should uncomment this block.
// unsafe {
// let pwr = &*stm32::PWR::ptr();
// pwr.cr3.modify(|_, w| w.usbregen().set_bit());
// while pwr.cr3.read().usb33rdy().bit_is_clear() {}
// }
// IO
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
let usb1 = USB1::new(
dp.OTG1_HS_GLOBAL,
dp.OTG1_HS_DEVICE,
dp.OTG1_HS_PWRCLK,
gpiob.pb14.into_alternate(),
gpiob.pb15.into_alternate(),
ccdr.peripheral.USB1OTG,
&ccdr.clocks,
);
let usb2 = USB2::new(
dp.OTG2_HS_GLOBAL,
dp.OTG2_HS_DEVICE,
dp.OTG2_HS_PWRCLK,
gpioa.pa11.into_alternate(),
gpioa.pa12.into_alternate(),
ccdr.peripheral.USB2OTG,
&ccdr.clocks,
);
// Port 1
let usb1_bus = UsbBus::new(usb1, unsafe { &mut EP_MEMORY_1 });
let mut serial1 = usbd_serial::SerialPort::new(&usb1_bus);
let mut usb1_dev =
UsbDeviceBuilder::new(&usb1_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST PORT 1")
.device_class(usbd_serial::USB_CLASS_CDC)
.build();
// Port 2
let usb2_bus = UsbBus::new(usb2, unsafe { &mut EP_MEMORY_2 });
let mut serial2 = usbd_serial::SerialPort::new(&usb2_bus);
let mut usb2_dev =
UsbDeviceBuilder::new(&usb2_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST PORT 2")
.device_class(usbd_serial::USB_CLASS_CDC)
.build();
loop {
let mut buf = [0u8; 64];
// Port 1
if usb1_dev.poll(&mut [&mut serial1]) {
match serial1.read(&mut buf) {
Ok(count) if count > 0 => {
// Write to both ports
write_serial(&mut serial1, &buf, count);
write_serial(&mut serial2, &buf, count);
}
_ => {}
}
}
// Port 2
if usb2_dev.poll(&mut [&mut serial2]) {
match serial2.read(&mut buf) {
Ok(count) if count > 0 => {
// Write to both ports
write_serial(&mut serial1, &buf, count);
write_serial(&mut serial2, &buf, count);
}
_ => {}
}
}
}
}
fn write_serial<P: usb_device::bus::UsbBus>(
serial: &mut usbd_serial::SerialPort<P>,
buf: &[u8],
count: usize,
) {
if serial.rts() {
let mut write_offset = 0;
while write_offset < count {
match serial.write(&buf[write_offset..count]) {
Ok(len) if len > 0 => {
write_offset += len;
}
_ => {}
}
}
}
}