use core::num::NonZeroU8;
use defmt::Format;
use usb_device::{
control::{Recipient, RequestType},
UsbDirection,
};
#[derive(Clone, Copy, PartialEq, Format)]
pub struct DeviceAddress(pub(crate) NonZeroU8);
impl From<DeviceAddress> for u16 {
fn from(value: DeviceAddress) -> Self {
u8::from(value.0) as u16
}
}
impl From<DeviceAddress> for u8 {
fn from(value: DeviceAddress) -> Self {
u8::from(value.0)
}
}
#[derive(Clone, Copy, PartialEq)]
pub struct Bcd16(pub(crate) u16);
impl Bcd16 {
pub fn to_digits(self) -> [u8; 4] {
[
((self.0 >> 12) & 0xF) as u8,
((self.0 >> 8) & 0xF) as u8,
((self.0 >> 4) & 0xF) as u8,
(self.0 & 0xF) as u8,
]
}
pub(crate) fn is_valid(value: u16) -> bool {
(value >> 12 & 0xF) < 10
&& (value >> 8 & 0xF) < 10
&& (value >> 4 & 0xF) < 10
&& (value & 0xF) < 10
}
}
impl Format for Bcd16 {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(
fmt,
"{}{}{}{}",
(self.0 >> 12) & 0xF,
(self.0 >> 8) & 0xF,
(self.0 >> 4) & 0xF,
self.0 & 0xF,
)
}
}
#[derive(Copy, Clone, PartialEq)]
pub enum ConnectionSpeed {
Low,
Full,
}
impl Format for ConnectionSpeed {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(
fmt,
"{}",
match self {
ConnectionSpeed::Low => "low",
ConnectionSpeed::Full => "full",
}
)
}
}
#[derive(Copy, Clone, PartialEq)]
#[repr(u8)]
pub enum TransferType {
Control = 0,
Isochronous = 1,
Bulk = 2,
Interrupt = 3,
}
pub struct SetupPacket {
pub request_type: u8,
pub request: u8,
pub value: u16,
pub index: u16,
pub length: u16,
}
impl SetupPacket {
pub fn new(
direction: UsbDirection,
request_type: RequestType,
recipient: Recipient,
request: u8,
value: u16,
index: u16,
length: u16,
) -> Self {
Self {
request_type: (recipient as u8) | ((request_type as u8) << 5) | (direction as u8),
request,
value,
index,
length,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use usb_device::control::Request;
#[test]
fn test_setup_new() {
let packet = SetupPacket::new(
UsbDirection::In,
RequestType::Standard,
Recipient::Device,
Request::GET_DESCRIPTOR,
0x1234,
0,
27,
);
assert_eq!(packet.request_type, 0x80);
assert_eq!(packet.request, 0x06);
assert_eq!(packet.value, 0x1234);
assert_eq!(packet.index, 0);
assert_eq!(packet.length, 27);
}
#[test]
fn test_bcd_digits() {
let bcd = Bcd16(0x1234);
assert_eq!(bcd.to_digits(), [1, 2, 3, 4]);
}
#[test]
fn test_bcd_is_valid() {
assert!(Bcd16::is_valid(0x1234));
assert!(Bcd16::is_valid(0x9999));
assert!(!Bcd16::is_valid(0xA000));
assert!(!Bcd16::is_valid(0x0F09));
}
}