usbvfiod 0.2.0

A vfio-user server for USB pass-through.
Documentation
pub mod meta;
pub mod packet;

pub use meta::EndpointPcapMeta;
pub use packet::{UsbDirection, UsbEventType, UsbPcapManager};

use crate::device::xhci::{
    real_endpoint_handle::{
        ControlRequestProcessingResult, InTrbProcessingResult, OutTrbProcessingResult,
    },
    usbrequest::UsbRequest,
};

pub fn control_submission(base: EndpointPcapMeta, req: &UsbRequest) {
    let control_direction = if req.request_type & 0x80 == 0 {
        UsbDirection::HostToDevice
    } else {
        UsbDirection::DeviceToHost
    };
    packet::log_control_submission(
        base,
        control_direction,
        req,
        req.data.as_deref().unwrap_or(&[]),
    );
}

pub fn control_completion_in(base: EndpointPcapMeta, urb_id: u64, data: &[u8]) {
    packet::log_control_completion(
        base,
        UsbDirection::DeviceToHost,
        urb_id,
        0,
        data.len() as u32,
        data,
    );
}

pub fn control_completion_out(base: EndpointPcapMeta, urb_id: u64, len: u32) {
    packet::log_control_completion(base, UsbDirection::HostToDevice, urb_id, 0, len, &[]);
}

pub fn control_in_error(
    base: EndpointPcapMeta,
    req: &UsbRequest,
    error: &ControlRequestProcessingResult,
) {
    packet::log_error(
        base,
        Some(UsbDirection::DeviceToHost),
        req.address,
        UsbEventType::Error,
        meta::control_error_status(error),
        Some(packet::build_setup_bytes(req)),
        req.data.as_deref().unwrap_or(&[]),
    );
}

pub fn control_out_error(
    base: EndpointPcapMeta,
    req: &UsbRequest,
    error: &ControlRequestProcessingResult,
) {
    packet::log_error(
        base,
        Some(UsbDirection::HostToDevice),
        req.address,
        UsbEventType::Error,
        meta::control_error_status(error),
        Some(packet::build_setup_bytes(req)),
        req.data.as_deref().unwrap_or(&[]),
    );
}

pub fn in_submission(base: EndpointPcapMeta, urb_id: u64, expected_len: u32) {
    packet::log_submission(base, None, urb_id, expected_len, None, &[]);
}

pub fn in_completion(base: EndpointPcapMeta, urb_id: u64, data: &[u8]) {
    packet::log_completion(base, None, urb_id, 0, data.len() as u32, data);
}

pub fn in_error(meta: EndpointPcapMeta, urb_id: u64, error: &InTrbProcessingResult) {
    packet::log_error(
        meta,
        None,
        urb_id,
        UsbEventType::Error,
        meta::in_error_status(error),
        None,
        &[],
    );
}

pub fn out_submission(meta: EndpointPcapMeta, urb_id: u64, payload: &[u8], expected_len: u32) {
    packet::log_submission(meta, None, urb_id, expected_len, None, payload);
}

pub fn out_completion(meta: EndpointPcapMeta, urb_id: u64, len: u32) {
    packet::log_completion(meta, None, urb_id, 0, len, &[]);
}

pub fn out_error(
    meta: EndpointPcapMeta,
    urb_id: u64,
    error: &OutTrbProcessingResult,
    payload: &[u8],
) {
    packet::log_error(
        meta,
        None,
        urb_id,
        UsbEventType::Error,
        meta::out_error_status(error),
        None,
        payload,
    );
}

pub fn trb_error(meta: EndpointPcapMeta, urb_id: u64) {
    packet::log_error(
        meta,
        None,
        urb_id,
        UsbEventType::Error,
        meta::trb_error_status(),
        None,
        &[],
    );
}