use clap::ValueEnum;
use crate::{
ProtocolType, Stk500v1Params,
error::{AvrError, AvrResult},
interface::DeviceInterfaceType,
};
#[derive(Debug, Clone, ValueEnum)]
pub enum Microcontroller {
ArduinoUno,
Atmega328p,
}
pub fn protocol_for_mcu(
mcu: Microcontroller,
interface_type: Option<DeviceInterfaceType>,
) -> AvrResult<ProtocolType> {
match mcu {
Microcontroller::ArduinoUno | Microcontroller::Atmega328p => {
let default_baud_rate = 115200;
let signature = vec![0x1e, 0x95, 0x0f];
let page_size = 128;
let num_pages = 256;
let product_id = vec![0x0043, 0x7523, 0x0001, 0xea60, 0x6015];
let (port, baud) = match interface_type {
Some(interface) => {
let DeviceInterfaceType::Serial(params) = interface;
let port = params
.port
.unwrap_or(serial_port_from_product_id(&product_id)?);
(port, params.baud.unwrap_or(default_baud_rate))
}
None => {
let baud = default_baud_rate;
let port = serial_port_from_product_id(&product_id)?;
(port, baud)
}
};
Ok(ProtocolType::Stk500v1(Stk500v1Params {
port,
baud,
device_signature: signature,
page_size,
num_pages,
product_id,
}))
}
}
}
pub(crate) fn serial_port_from_product_id(product_ids: &Vec<u16>) -> AvrResult<String> {
match serialport::available_ports() {
Ok(ports) => {
for port in ports {
if let serialport::SerialPortType::UsbPort(info) = port.port_type {
for pid in product_ids {
if *pid == info.pid {
return Ok(port.port_name);
}
}
}
}
}
Err(e) => {
return Err(AvrError::ConfigurationError(format!(
"Could not get available ports. Err {:?}",
e
)));
}
};
Err(AvrError::ConfigurationError(format!(
"Looked at all available serial ports; could not find one that matches one of
product IDs {:?}. Try specifying a serial port for the given MCU?",
product_ids
)))
}