usbvfiod 0.2.0

A vfio-user server for USB pass-through.
Documentation
use super::packet::UsbTransferType;
use crate::device::xhci::real_endpoint_handle::{
    ControlRequestProcessingResult, InTrbProcessingResult, OutTrbProcessingResult,
};

const LINUX_ENODEV: i32 = 19;
const LINUX_EINVAL: i32 = 22;
const LINUX_EPIPE: i32 = 32;
const LINUX_EPROTO: i32 = 71;

pub const fn errno_status(errno: i32) -> i32 {
    -errno
}

/// Context passed from endpoint handlers to PCAP logging, describing
/// which USB endpoint a record belongs to.
#[derive(Clone, Copy, Debug)]
pub struct EndpointPcapMeta {
    pub bus_number: u16,
    pub device_address: u8,
    pub endpoint_id: u8,
    pub transfer_type: UsbTransferType,
}

impl EndpointPcapMeta {
    pub const fn control(bus: u16, dev: u8, ep: u8) -> Self {
        Self {
            bus_number: bus,
            device_address: dev,
            endpoint_id: ep,
            transfer_type: UsbTransferType::Control,
        }
    }

    pub const fn bulk(bus: u16, dev: u8, ep: u8) -> Self {
        Self {
            bus_number: bus,
            device_address: dev,
            endpoint_id: ep,
            transfer_type: UsbTransferType::Bulk,
        }
    }

    pub const fn interrupt(bus: u16, dev: u8, ep: u8) -> Self {
        Self {
            bus_number: bus,
            device_address: dev,
            endpoint_id: ep,
            transfer_type: UsbTransferType::Interrupt,
        }
    }
}

pub const fn control_error_status(error: &ControlRequestProcessingResult) -> i32 {
    match error {
        ControlRequestProcessingResult::Disconnect => errno_status(LINUX_ENODEV),
        ControlRequestProcessingResult::Stall => errno_status(LINUX_EPIPE),
        ControlRequestProcessingResult::TransactionError => errno_status(LINUX_EPROTO),
        ControlRequestProcessingResult::SuccessfulControlIn(_)
        | ControlRequestProcessingResult::SuccessfulControlOut => 0,
    }
}

pub const fn trb_error_status() -> i32 {
    errno_status(LINUX_EINVAL)
}

pub const fn in_error_status(error: &InTrbProcessingResult) -> i32 {
    match error {
        InTrbProcessingResult::Disconnect => errno_status(LINUX_ENODEV),
        InTrbProcessingResult::Stall => errno_status(LINUX_EPIPE),
        InTrbProcessingResult::TransactionError => errno_status(LINUX_EPROTO),
        InTrbProcessingResult::Success(_) => 0,
    }
}

pub const fn out_error_status(error: &OutTrbProcessingResult) -> i32 {
    match error {
        OutTrbProcessingResult::Disconnect => errno_status(LINUX_ENODEV),
        OutTrbProcessingResult::Stall => errno_status(LINUX_EPIPE),
        OutTrbProcessingResult::TransactionError => errno_status(LINUX_EPROTO),
        OutTrbProcessingResult::Success => 0,
    }
}