From 0c20fb86633104744dbccf30ad732296694fff1b Mon Sep 17 00:00:00 2001 From: Dawid Rycerz Date: Sun, 8 Feb 2026 12:44:10 +0100 Subject: Initial pipewire --- src/usb/mod.rs | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/usb/mod.rs (limited to 'src/usb/mod.rs') diff --git a/src/usb/mod.rs b/src/usb/mod.rs new file mode 100644 index 0000000..38d9c7d --- /dev/null +++ b/src/usb/mod.rs @@ -0,0 +1,164 @@ +//! USB communication module for the Geek szitman supercamera + +mod device; +mod transfer; + +pub use device::UsbSupercamera; +pub use transfer::{UsbTransferConfig, UsbTransferError, UsbTransferResult, UsbTransferStats}; + +use rusb::{Direction, TransferType}; +use std::time::Duration; + +/// USB device constants +pub const USB_VENDOR_ID: u16 = 0x2ce3; +pub const USB_PRODUCT_ID: u16 = 0x3828; +pub const INTERFACE_A_NUMBER: u8 = 0; +pub const INTERFACE_B_NUMBER: u8 = 1; +pub const INTERFACE_B_ALTERNATE_SETTING: u8 = 1; +pub const ENDPOINT_1: u8 = 1; +pub const ENDPOINT_2: u8 = 2; +pub const USB_TIMEOUT: Duration = Duration::from_millis(1000); + +/// USB device information +#[derive(Debug, Clone)] +pub struct UsbDeviceInfo { + pub vendor_id: u16, + pub product_id: u16, + pub manufacturer: Option, + pub product: Option, + pub serial_number: Option, +} + +impl Default for UsbDeviceInfo { + fn default() -> Self { + Self { + vendor_id: USB_VENDOR_ID, + product_id: USB_PRODUCT_ID, + manufacturer: None, + product: None, + serial_number: None, + } + } +} + +/// USB endpoint configuration +#[derive(Debug, Clone)] +pub struct UsbEndpoint { + pub address: u8, + pub direction: Direction, + pub transfer_type: TransferType, + pub max_packet_size: u16, +} + +impl UsbEndpoint { + /// Create a new USB endpoint + pub fn new( + address: u8, + direction: Direction, + transfer_type: TransferType, + max_packet_size: u16, + ) -> Self { + Self { + address, + direction, + transfer_type, + max_packet_size, + } + } +} + +/// USB interface configuration +#[derive(Debug, Clone)] +pub struct UsbInterface { + pub number: u8, + pub alternate_setting: u8, + pub endpoints: Vec, +} + +impl UsbInterface { + /// Create a new USB interface + pub fn new(number: u8, alternate_setting: u8) -> Self { + Self { + number, + alternate_setting, + endpoints: Vec::new(), + } + } + + /// Add an endpoint to this interface + pub fn add_endpoint(&mut self, endpoint: UsbEndpoint) { + self.endpoints.push(endpoint); + } +} + +/// USB device configuration +#[derive(Debug, Clone)] +pub struct UsbConfig { + pub interfaces: Vec, + pub max_packet_size: u16, +} + +impl Default for UsbConfig { + fn default() -> Self { + let mut interface_a = UsbInterface::new(INTERFACE_A_NUMBER, 0); + interface_a.add_endpoint(UsbEndpoint::new( + ENDPOINT_1, + Direction::In, + TransferType::Bulk, + 0x1000, + )); + + let mut interface_b = UsbInterface::new(INTERFACE_B_NUMBER, INTERFACE_B_ALTERNATE_SETTING); + interface_b.add_endpoint(UsbEndpoint::new( + ENDPOINT_2, + Direction::Out, + TransferType::Bulk, + 64, + )); + + Self { + interfaces: vec![interface_a, interface_b], + max_packet_size: 0x1000, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_usb_device_info_default() { + let info = UsbDeviceInfo::default(); + assert_eq!(info.vendor_id, USB_VENDOR_ID); + assert_eq!(info.product_id, USB_PRODUCT_ID); + } + + #[test] + fn test_usb_endpoint_creation() { + let endpoint = UsbEndpoint::new(ENDPOINT_1, Direction::In, TransferType::Bulk, 0x1000); + assert_eq!(endpoint.address, ENDPOINT_1); + assert_eq!(endpoint.direction, Direction::In); + assert_eq!(endpoint.transfer_type, TransferType::Bulk); + assert_eq!(endpoint.max_packet_size, 0x1000); + } + + #[test] + fn test_usb_interface_management() { + let mut interface = UsbInterface::new(0, 0); + let endpoint = UsbEndpoint::new(1, Direction::In, TransferType::Bulk, 64); + + interface.add_endpoint(endpoint); + assert_eq!(interface.endpoints.len(), 1); + assert_eq!(interface.endpoints[0].address, 1); + } + + #[test] + fn test_usb_config_default() { + let config = UsbConfig::default(); + assert_eq!(config.interfaces.len(), 2); + assert_eq!(config.interfaces[0].number, INTERFACE_A_NUMBER); + assert_eq!(config.interfaces[1].number, INTERFACE_B_NUMBER); + assert_eq!(config.max_packet_size, 0x1000); + } +} -- cgit v1.2.3