use crate::bmrequesttype::{bmRequestType, Direction, Recipient, Type};
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Request {
pub interface: u8,
pub kind: Kind,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Kind {
GetLineCoding,
SetLineCoding,
SetControlLineState {
dtr: bool,
rts: bool,
},
}
const SET_LINE_CODING: u8 = 0x20;
const GET_LINE_CODING: u8 = 0x21;
const SET_CONTROL_LINE_STATE: u8 = 0x22;
pub struct SerialState {
pub interface: u8,
pub bOverRun: bool,
pub bParity: bool,
pub bFraming: bool,
pub bRingSignal: bool,
pub bBreak: bool,
pub bTxCarrier: bool,
pub bRxCarrier: bool,
}
impl SerialState {
pub const SIZE: u8 = 10;
pub fn bytes(&self) -> [u8; Self::SIZE as usize] {
const SERIAL_STATE: u8 = 0x20;
let mut bitmap = 0;
if self.bOverRun {
bitmap |= 1 << 6;
}
if self.bParity {
bitmap |= 1 << 5;
}
if self.bFraming {
bitmap |= 1 << 4;
}
if self.bRingSignal {
bitmap |= 1 << 3;
}
if self.bBreak {
bitmap |= 1 << 2;
}
if self.bTxCarrier {
bitmap |= 1 << 1;
}
if self.bRxCarrier {
bitmap |= 1 << 0;
}
[
0b1010_0001, SERIAL_STATE, 0,
0, self.interface,
0, 2,
0, bitmap,
0,
]
}
}
#[derive(Clone, Copy)]
pub struct LineCoding {
pub dwDTERate: u32,
pub bCharFormat: bCharFormat,
pub bParityType: bParityType,
pub bDataBits: bDataBits,
}
impl LineCoding {
pub const SIZE: u8 = 7;
pub fn bytes(&self) -> [u8; Self::SIZE as usize] {
[
self.dwDTERate as u8,
(self.dwDTERate >> 8) as u8,
(self.dwDTERate >> 16) as u8,
(self.dwDTERate >> 24) as u8,
self.bCharFormat as u8,
self.bParityType as u8,
self.bDataBits as u8,
]
}
}
#[derive(Clone, Copy)]
pub enum bCharFormat {
Stop1 = 0,
Stop1_5 = 1,
Stop2 = 2,
}
#[derive(Clone, Copy)]
pub enum bParityType {
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4,
}
#[derive(Clone, Copy)]
pub enum bDataBits {
_5 = 5,
_6 = 6,
_7 = 7,
_8 = 8,
_16 = 16,
}
impl Request {
pub fn parse(
bmrequesttype: u8,
brequest: u8,
wvalue: u16,
windex: u16,
wlength: u16,
) -> Result<Self, ()> {
let bmrequesttype = bmRequestType::parse(bmrequesttype)?;
if bmrequesttype.ty != Type::Class {
return Err(());
}
Self::parse2(bmrequesttype, brequest, wvalue, windex, wlength)
}
pub(crate) fn parse2(
bmRequestType {
direction,
recipient,
..
}: bmRequestType,
brequest: u8,
wvalue: u16,
windex: u16,
wlength: u16,
) -> Result<Self, ()> {
match (brequest, direction) {
(SET_LINE_CODING, Direction::HostToDevice)
if recipient == Recipient::Interface && wvalue == 0 && wlength == 7 =>
{
let interface = crate::windex2interface(windex)?;
Ok(Request {
interface,
kind: Kind::SetLineCoding,
})
}
(GET_LINE_CODING, Direction::DeviceToHost)
if recipient == Recipient::Interface && wvalue == 0 && wlength == 7 =>
{
let interface = crate::windex2interface(windex)?;
Ok(Request {
interface,
kind: Kind::GetLineCoding,
})
}
(SET_CONTROL_LINE_STATE, Direction::HostToDevice)
if recipient == Recipient::Interface && wlength == 0 =>
{
let interface = crate::windex2interface(windex)?;
if wvalue & !0b11 != 0 {
return Err(());
}
let dtr = wvalue & 1 != 0;
let rts = wvalue & (1 << 1) != 0;
Ok(Request {
interface,
kind: Kind::SetControlLineState { rts, dtr },
})
}
_ => Err(()),
}
}
}
#[allow(non_snake_case)]
#[derive(Clone, Copy)]
pub struct Descriptor {
pub bmCapabilities: Capabilities,
}
#[derive(Clone, Copy)]
pub struct Capabilities {
pub comm_features: bool,
pub line_serial: bool,
pub send_break: bool,
pub network_connection: bool,
}
impl Capabilities {
fn byte(&self) -> u8 {
let mut byte = 0;
if self.comm_features {
byte |= 1 << 0;
}
if self.line_serial {
byte |= 1 << 1;
}
if self.send_break {
byte |= 1 << 2;
}
if self.network_connection {
byte |= 1 << 3;
}
byte
}
}
impl Descriptor {
pub const SIZE: u8 = 4;
pub fn bytes(&self) -> [u8; Self::SIZE as usize] {
[
Self::SIZE,
super::CS_INTERFACE,
super::SUBTYPE_ACM,
self.bmCapabilities.byte(),
]
}
}