esp_idf_hal/
usb_serial.rs#![allow(non_camel_case_types)]
use crate::io::EspIOError;
use crate::peripheral::{Peripheral, PeripheralRef};
use crate::sys::{
esp, usb_serial_jtag_driver_config_t, usb_serial_jtag_driver_install,
usb_serial_jtag_driver_uninstall, usb_serial_jtag_is_connected, usb_serial_jtag_read_bytes,
usb_serial_jtag_write_bytes, EspError, TickType_t,
};
use crate::{delay, gpio};
pub type UsbSerialConfig = config::Config;
#[cfg(esp32c3)]
pub type UsbDMinGpio = gpio::Gpio18;
#[cfg(esp32c3)]
pub type UsbDPlusGpio = gpio::Gpio19;
#[cfg(esp32c5)]
pub type UsbDMinGpio = gpio::Gpio13;
#[cfg(esp32c5)]
pub type UsbDPlusGpio = gpio::Gpio14;
#[cfg(esp32c6)]
pub type UsbDMinGpio = gpio::Gpio12;
#[cfg(esp32c6)]
pub type UsbDPlusGpio = gpio::Gpio13;
#[cfg(esp32h2)]
pub type UsbDMinGpio = gpio::Gpio26;
#[cfg(esp32h2)]
pub type UsbDPlusGpio = gpio::Gpio27;
#[cfg(esp32p4)]
pub type UsbDMinGpio = gpio::Gpio24;
#[cfg(esp32p4)]
pub type UsbDPlusGpio = gpio::Gpio25;
#[cfg(esp32s3)]
pub type UsbDMinGpio = gpio::Gpio19;
#[cfg(esp32s3)]
pub type UsbDPlusGpio = gpio::Gpio20;
pub mod config {
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Config {
pub tx_buffer_size: usize,
pub rx_buffer_size: usize,
}
impl Config {
pub const fn new() -> Self {
Self {
tx_buffer_size: 256,
rx_buffer_size: 256,
}
}
#[must_use]
pub fn tx_buffer_size(mut self, tx_buffer_size: usize) -> Self {
self.tx_buffer_size = tx_buffer_size;
self
}
#[must_use]
pub fn rx_buffer_size(mut self, rx_buffer_size: usize) -> Self {
self.rx_buffer_size = rx_buffer_size;
self
}
}
impl Default for Config {
fn default() -> Self {
Self::new()
}
}
}
pub struct UsbSerialDriver<'d>(PeripheralRef<'d, USB_SERIAL>);
impl<'d> UsbSerialDriver<'d> {
pub fn new(
usb_serial: impl Peripheral<P = USB_SERIAL> + 'd,
_usb_d_min: impl Peripheral<P = UsbDMinGpio>,
_usb_d_plus: impl Peripheral<P = UsbDPlusGpio>,
config: &config::Config,
) -> Result<Self, EspError> {
crate::into_ref!(usb_serial);
let mut config = usb_serial_jtag_driver_config_t {
tx_buffer_size: config.tx_buffer_size as _,
rx_buffer_size: config.rx_buffer_size as _,
};
esp!(unsafe { usb_serial_jtag_driver_install(&mut config) })?;
Ok(Self(usb_serial))
}
pub fn is_connected(&self) -> bool {
unsafe { usb_serial_jtag_is_connected() }
}
pub fn read(&mut self, buf: &mut [u8], timeout: TickType_t) -> Result<usize, EspError> {
let len = unsafe {
usb_serial_jtag_read_bytes(buf.as_mut_ptr() as *mut _, buf.len() as _, timeout)
};
Ok(len as _)
}
pub fn write(&mut self, bytes: &[u8], timeout: TickType_t) -> Result<usize, EspError> {
let len = unsafe {
usb_serial_jtag_write_bytes(bytes.as_ptr() as *const _, bytes.len() as _, timeout)
};
Ok(len as _)
}
}
impl Drop for UsbSerialDriver<'_> {
fn drop(&mut self) {
esp!(unsafe { usb_serial_jtag_driver_uninstall() }).unwrap();
}
}
unsafe impl Send for UsbSerialDriver<'_> {}
impl embedded_io::ErrorType for UsbSerialDriver<'_> {
type Error = EspIOError;
}
impl embedded_io::Read for UsbSerialDriver<'_> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
UsbSerialDriver::read(self, buf, delay::BLOCK).map_err(EspIOError)
}
}
impl embedded_io::Write for UsbSerialDriver<'_> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
UsbSerialDriver::write(self, buf, delay::BLOCK).map_err(EspIOError)
}
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl embedded_hal_0_2::serial::Write<u8> for UsbSerialDriver<'_> {
type Error = EspError;
fn flush(&mut self) -> nb::Result<(), Self::Error> {
Ok(())
}
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
UsbSerialDriver::write(self, &[byte], delay::BLOCK)?;
Ok(())
}
}
impl core::fmt::Write for UsbSerialDriver<'_> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
let buf = s.as_bytes();
let mut offset = 0;
while offset < buf.len() {
offset += self
.write(buf, delay::BLOCK)
.map_err(|_| core::fmt::Error)?
}
Ok(())
}
}
crate::impl_peripheral!(USB_SERIAL);