use anyhow::{bail, Result};
use std::rc::Rc;
use crate::io::gpio::{GpioPin, PinMode, PullMode};
use crate::transport::hyperdebug::{Flavor, Inner, StandardFlavor, VID_GOOGLE};
use crate::transport::{TransportError, TransportInterfaceType};
pub struct C2d2Flavor {}
impl C2d2Flavor {
const PID_C2D2: u16 = 0x5041;
}
impl Flavor for C2d2Flavor {
fn gpio_pin(inner: &Rc<Inner>, pinname: &str) -> Result<Rc<dyn GpioPin>> {
if pinname == "SPIVREF_RSVD_H1VREF_H1_RST_ODL" {
return Ok(Rc::new(C2d2ResetPin::open(inner)?));
}
StandardFlavor::gpio_pin(inner, pinname)
}
fn spi_index(_inner: &Rc<Inner>, instance: &str) -> Result<(u8, u8)> {
if instance == "0" {
return Ok((super::spi::USB_SPI_REQ_ENABLE, 0));
}
bail!(TransportError::InvalidInstance(
TransportInterfaceType::Spi,
instance.to_string()
))
}
fn get_default_usb_vid() -> u16 {
VID_GOOGLE
}
fn get_default_usb_pid() -> u16 {
Self::PID_C2D2
}
fn perform_initial_fw_check() -> bool {
false
}
}
pub struct C2d2ResetPin {
inner: Rc<Inner>,
}
impl C2d2ResetPin {
pub fn open(inner: &Rc<Inner>) -> Result<Self> {
Ok(Self {
inner: Rc::clone(inner),
})
}
}
impl GpioPin for C2d2ResetPin {
fn read(&self) -> Result<bool> {
let line = self
.inner
.cmd_one_line_output("gpioget SPIVREF_RSVD_H1VREF_H1_RST_ODL")
.map_err(|_| {
TransportError::CommunicationError("No output from gpioget".to_string())
})?;
Ok(line.trim_start().starts_with('1'))
}
fn write(&self, value: bool) -> Result<()> {
self.inner
.cmd_one_line_output(&format!("h1_reset {}", if value { 0 } else { 1 }))?;
Ok(())
}
fn set_mode(&self, _mode: PinMode) -> Result<()> {
bail!(TransportError::UnsupportedOperation)
}
fn set_pull_mode(&self, _mode: PullMode) -> Result<()> {
bail!(TransportError::UnsupportedOperation)
}
}