commit b7e0bc374d935a50b7e60e741ba7c99efcf123dd from: Benjamins Stürz date: Fri Feb 07 17:21:46 2025 UTC Initial commit commit - /dev/null commit + b7e0bc374d935a50b7e60e741ba7c99efcf123dd blob - /dev/null blob + ea8c4bf7f35f6f77f75d92ad8ce8349f6e81ddba (mode 644) --- /dev/null +++ .gitignore @@ -0,0 +1 @@ +/target blob - /dev/null blob + 2e341f9de998c7131836438f524b1cc63195adbd (mode 644) --- /dev/null +++ Cargo.lock @@ -0,0 +1,72 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "cc" +version = "1.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" +dependencies = [ + "shlex", +] + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libusb1-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da050ade7ac4ff1ba5379af847a10a10a8e284181e060105bf8d86960ce9ce0f" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "ppa6" +version = "0.1.0" +dependencies = [ + "anyhow", + "rusb", +] + +[[package]] +name = "rusb" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab9f9ff05b63a786553a4c02943b74b34a988448671001e9a27e2f0565cc05a4" +dependencies = [ + "libc", + "libusb1-sys", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" blob - /dev/null blob + da9c3648d53ff4cc6cfe7806fe8bc889b6ce54ce (mode 644) --- /dev/null +++ Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ppa6" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.95" +rusb = "0.9.4" blob - /dev/null blob + e950f4221ea673013612454faad769ce61e482a6 (mode 644) --- /dev/null +++ src/main.rs @@ -0,0 +1,80 @@ +// Very helpful doc for USB: https://www.beyondlogic.org/usbnutshell/usb1.shtml +use rusb::{Direction, TransferType, UsbContext}; + +const VENDOR_ID: u16 = 0x09c5; +const PRODUCT_ID: u16 = 0x0200; + +fn main() { + println!("libusb version: {:?}", rusb::version()); + println!("Kernel supports detaching driver: {}", rusb::supports_detach_kernel_driver()); + + + let ctx = rusb::Context::new().expect("cannot connect to libusb"); + + // Find Peripage A6 + let dev = ctx + .devices() + .expect("cannot read list of devices") + .iter() + .find(|dev| { + let Ok(desc) = dev.device_descriptor() else { + eprintln!("cannot get device descriptor for Bus {dev:?}"); + return false + }; + + desc.vendor_id() == VENDOR_ID && desc.product_id() == PRODUCT_ID + }) + .expect("No Peripage A6 found") + ; + + let handle = dev.open().expect("cannot open usb device"); + + let dd = dev.device_descriptor().unwrap(); + println!("Device Descriptor = {dd:#?}"); + assert_eq!(dd.vendor_id(), VENDOR_ID); + assert_eq!(dd.product_id(), PRODUCT_ID); + if let Ok(s) = handle.read_manufacturer_string_ascii(&dd) { + println!("Vendor: {s}"); + } + if let Ok(s) = handle.read_product_string_ascii(&dd) { + println!("Product: {s}"); + } + if let Ok(s) = handle.read_serial_number_string_ascii(&dd) { + println!("Serial: {s}"); + } + + assert_eq!(dd.num_configurations(), 1); + let cd = dev.config_descriptor(0).unwrap(); + println!("Config Descriptor = {cd:#?}"); + + assert_eq!(cd.num_interfaces(), 1); + let int = cd.interfaces().next().unwrap(); + let id = int.descriptors().next().unwrap(); + println!("Interface Descriptor = {id:#?}"); + if let Some(sid) = id.description_string_index() { + println!("Interface: {}", handle.read_string_descriptor_ascii(sid).unwrap()); + } + println!("Is kernel driver attached: {:?}", handle.kernel_driver_active(0)); + + assert_eq!(id.class_code(), 7); + assert_eq!(id.sub_class_code(), 1); + assert_eq!(id.protocol_code(), 2); + assert_eq!(id.num_endpoints(), 2); + + let mut epds = id.endpoint_descriptors(); + let epd0 = epds.next().unwrap(); + let epd1 = epds.next().unwrap(); + println!("Endpoint Descriptor 0: {epd0:#?}"); + println!("Endpoint Descriptor 1: {epd1:#?}"); + + assert_eq!(epd0.address(), 129); // IN (128) + 1 + assert_eq!(epd0.direction(), Direction::In); + assert_eq!(epd0.transfer_type(), TransferType::Bulk); + + assert_eq!(epd1.address(), 2); // OUT (0) + 2 + assert_eq!(epd1.direction(), Direction::Out); + assert_eq!(epd1.transfer_type(), TransferType::Bulk); + + handle.claim_interface(0).expect("failed to claim interface 0"); + handle.release_interface(0).expect("failed to release interface 0"); +}