forked from stm32-rs/stm32h7xx-hal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
usb_passthrough.rs
162 lines (141 loc) · 4.76 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! 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.
#![deny(warnings)]
#![no_std]
#![no_main]
use panic_itm as _;
use core::mem::MaybeUninit;
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: MaybeUninit<[u32; 1024]> = MaybeUninit::uninit();
static mut EP_MEMORY_2: MaybeUninit<[u32; 1024]> = MaybeUninit::uninit();
#[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,
);
// Initialise EP_MEMORY_1 to zero
unsafe {
let buf: &mut [MaybeUninit<u32>; 1024] =
&mut *(core::ptr::addr_of_mut!(EP_MEMORY_1) as *mut _);
for value in buf.iter_mut() {
value.as_mut_ptr().write(0);
}
}
// Initialise EP_MEMORY_2 to zero
unsafe {
let buf: &mut [MaybeUninit<u32>; 1024] =
&mut *(core::ptr::addr_of_mut!(EP_MEMORY_2) as *mut _);
for value in buf.iter_mut() {
value.as_mut_ptr().write(0);
}
}
// Port 1
let usb1_bus = UsbBus::new(usb1, unsafe { EP_MEMORY_1.assume_init_mut() });
let mut serial1 = usbd_serial::SerialPort::new(&usb1_bus);
let mut usb1_dev =
UsbDeviceBuilder::new(&usb1_bus, UsbVidPid(0x16c0, 0x27dd))
.strings(&[usb_device::device::StringDescriptors::default()
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST PORT 1")])
.unwrap()
.device_class(usbd_serial::USB_CLASS_CDC)
.build();
// Port 2
let usb2_bus = UsbBus::new(usb2, unsafe { EP_MEMORY_2.assume_init_mut() });
let mut serial2 = usbd_serial::SerialPort::new(&usb2_bus);
let mut usb2_dev =
UsbDeviceBuilder::new(&usb2_bus, UsbVidPid(0x16c0, 0x27dd))
.strings(&[usb_device::device::StringDescriptors::default()
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST PORT 1")])
.unwrap()
.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;
}
_ => {}
}
}
}
}