use core::mem::MaybeUninit;
use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
use crate::types::StringIndex;
use crate::{Builder, Handler, msos};
pub struct State {
control: MaybeUninit<Control>,
}
struct Control {
iface_string: StringIndex,
}
impl Handler for Control {
fn get_string(&mut self, index: StringIndex, _lang_id: u16) -> Option<&str> {
if index == self.iface_string {
Some("CMSIS-DAP v2 Interface")
} else {
warn!("unknown string index requested");
None
}
}
}
impl State {
pub const fn new() -> Self {
Self {
control: MaybeUninit::uninit(),
}
}
}
pub struct CmsisDapV2Class<'d, D: Driver<'d>> {
read_ep: D::EndpointOut,
write_ep: D::EndpointIn,
trace_ep: Option<D::EndpointIn>,
max_packet_size: u16,
}
impl<'d, D: Driver<'d>> CmsisDapV2Class<'d, D> {
pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State, max_packet_size: u16, trace: bool) -> Self {
let iface_string = builder.string();
let mut function = builder.function(0xFF, 0, 0);
function.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
function.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
"DeviceInterfaceGUIDs",
msos::PropertyData::RegMultiSz(&["{CDB3B5AD-293B-4663-AA36-1AAE46463776}"]),
));
let mut interface = function.interface();
let mut alt = interface.alt_setting(0xFF, 0, 0, Some(iface_string));
let read_ep = alt.endpoint_bulk_out(None, max_packet_size);
let write_ep = alt.endpoint_bulk_in(None, max_packet_size);
let trace_ep = if trace {
Some(alt.endpoint_bulk_in(None, max_packet_size))
} else {
None
};
drop(function);
builder.handler(state.control.write(Control { iface_string }));
CmsisDapV2Class {
read_ep,
write_ep,
trace_ep,
max_packet_size,
}
}
pub async fn wait_connection(&mut self) {
self.read_ep.wait_enabled().await;
}
pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
for chunk in data.chunks(self.max_packet_size as usize) {
self.write_ep.write(chunk).await?;
}
if data.len() % self.max_packet_size as usize == 0 {
self.write_ep.write(&[]).await?;
}
Ok(())
}
pub async fn write_trace(&mut self, data: &[u8]) -> Result<(), EndpointError> {
let Some(ep) = self.trace_ep.as_mut() else {
return Err(EndpointError::Disabled);
};
for chunk in data.chunks(self.max_packet_size as usize) {
ep.write(chunk).await?;
}
if data.len() % self.max_packet_size as usize == 0 {
ep.write(&[]).await?;
}
Ok(())
}
pub async fn read_packet(&mut self, data: &mut [u8]) -> Result<usize, EndpointError> {
let mut n = 0;
loop {
let i = self.read_ep.read(&mut data[n..]).await?;
n += i;
if i < self.max_packet_size as usize {
return Ok(n);
}
}
}
}