teensy4_selfrebootor/
lib.rs1#![no_std]
2#![deny(missing_docs)]
3#![doc = include_str!("../README.md")]
4#![doc(issue_tracker_base_url = "https://github.com/Finomnis/teensy4-selfrebootor/issues")]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7use teensy4_bsp::hal::usbd::BusAdapter;
8use usb_device::{class_prelude::*, prelude::*};
9use usbd_hid::{descriptor::SerializedDescriptor, hid_class::HIDClass};
10
11mod hid_descriptor;
12mod reboot;
13
14pub use reboot::reboot_to_bootloader;
15
16pub struct Rebootor<'a> {
23 class: HIDClass<'a, BusAdapter>,
24 device: UsbDevice<'a, BusAdapter>,
25 configured: bool,
26}
27
28impl<'a> Rebootor<'a> {
29 pub fn new(bus_alloc: &'a UsbBusAllocator<BusAdapter>) -> Self {
36 let class = HIDClass::new(bus_alloc, crate::hid_descriptor::Rebootor::desc(), 10);
37 let device = UsbDeviceBuilder::new(bus_alloc, UsbVidPid(0x16C0, 0x0477))
38 .product("Self-Rebootor")
39 .manufacturer("PJRC")
40 .self_powered(true)
41 .max_packet_size_0(64)
42 .build();
43
44 device.bus().set_interrupts(true);
45
46 Self {
47 class,
48 device,
49 configured: false,
50 }
51 }
52
53 pub fn poll(&mut self) {
58 self.device.poll(&mut [&mut self.class]);
59
60 if self.device.state() == UsbDeviceState::Configured {
61 if !self.configured {
62 self.device.bus().configure();
63 }
64 self.configured = true;
65 } else {
66 self.configured = false;
67 }
68
69 if self.configured {
70 let mut buf = [0u8; 6];
71
72 let result = self.class.pull_raw_output(&mut buf);
73 match result {
74 Ok(info) => {
75 let buf = &buf[..info];
76 if buf == b"reboot" {
77 log::info!("Rebooting to HalfKay ...");
78 reboot::reboot_to_bootloader();
79 }
80 }
81 Err(usb_device::UsbError::WouldBlock) => (),
82 Err(_) => {}
83 }
84 }
85 }
86}