use usb_if::{
descriptor::{ConfigurationDescriptor, DescriptorType, DeviceDescriptor},
endpoint::TransferRequest,
err::{TransferError, USBError},
host::ControlSetup,
transfer::{Recipient, Request, RequestType},
};
use super::EndpointHandle;
impl EndpointHandle {
pub async fn control_in(
&mut self,
param: usb_if::host::ControlSetup,
buff: &mut [u8],
) -> Result<usize, TransferError> {
let t = self.wait(TransferRequest::control_in(param, buff)).await?;
Ok(t.actual_length)
}
pub async fn control_out(
&mut self,
param: usb_if::host::ControlSetup,
buff: &[u8],
) -> Result<usize, TransferError> {
let t = self.wait(TransferRequest::control_out(param, buff)).await?;
Ok(t.actual_length)
}
pub async fn set_configuration(
&mut self,
configuration_value: u8,
) -> Result<(), TransferError> {
self.control_out(
ControlSetup {
request_type: RequestType::Standard,
recipient: Recipient::Device,
request: Request::SetConfiguration,
value: configuration_value as u16,
index: 0,
},
&[],
)
.await?;
Ok(())
}
pub async fn get_descriptor(
&mut self,
desc_type: DescriptorType,
desc_index: u8,
language_id: u16,
buff: &mut [u8],
) -> Result<usize, TransferError> {
self.control_in(
ControlSetup {
request_type: RequestType::Standard,
recipient: Recipient::Device,
request: Request::GetDescriptor,
value: ((desc_type.0 as u16) << 8) | desc_index as u16,
index: language_id,
},
buff,
)
.await
}
pub async fn get_device_descriptor(&mut self) -> Result<DeviceDescriptor, USBError> {
let mut buff = alloc::vec![0u8; DeviceDescriptor::LEN];
let actual = self
.get_descriptor(DescriptorType::DEVICE, 0, 0, &mut buff)
.await?;
if actual != buff.len() {
return Err(anyhow!(
"short device descriptor: expected {} bytes, got {actual}",
buff.len()
)
.into());
}
trace!("data: {buff:?}");
let desc = DeviceDescriptor::parse(&buff).ok_or(anyhow!("device descriptor parse err"))?;
Ok(desc)
}
pub async fn get_configuration(&mut self) -> Result<u8, TransferError> {
let mut buff = alloc::vec![0u8; 1];
self.control_in(
ControlSetup {
request_type: RequestType::Standard,
recipient: Recipient::Device,
request: Request::GetConfiguration,
value: 0,
index: 0,
},
&mut buff,
)
.await?;
Ok(buff[0])
}
pub async fn get_configuration_descriptor(
&mut self,
index: u8,
) -> Result<ConfigurationDescriptor, USBError> {
let mut header = alloc::vec![0u8; ConfigurationDescriptor::LEN];
self.get_descriptor(DescriptorType::CONFIGURATION, index, 0, &mut header)
.await?;
let total_length = u16::from_le_bytes(header[2..4].try_into().unwrap()) as usize;
let mut full_data = alloc::vec![0u8; total_length];
debug!("Reading configuration descriptor for index {index}, total length: {total_length}");
self.get_descriptor(DescriptorType::CONFIGURATION, index, 0, &mut full_data)
.await?;
ConfigurationDescriptor::parse(&full_data)
.ok_or_else(|| anyhow!("config descriptor parse err").into())
}
}