diff --git a/Cargo.toml b/Cargo.toml index 0e15d93..cfc3239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "sixaxis_go" -version = "0.1.0" +version = "1.0.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -futures-lite = "2.2.0" -hidapi = "2.4.1" +futures-lite = "2.3.0" macaddr = "1.0.1" +nusb = "0.1.7" diff --git a/src/hidapi.rs b/src/hidapi.rs index c98a11f..9814ab7 100644 --- a/src/hidapi.rs +++ b/src/hidapi.rs @@ -1,72 +1,64 @@ use std::error::Error; use futures_lite::future::block_on; -use nusb::list_devices; -use nusb::{Device, DeviceInfo, Interface, InterfaceInfo}; -use nusb::transfer::{ControlType, ControlIn, Recipient, Control}; +use nusb::{Interface, list_devices, transfer::{ControlIn, ControlType, Recipient, ControlOut}}; -pub struct HidApi { +pub struct SixaxisApi; -} - -pub struct HidDevice { - device: Device, +pub struct SixaxisDevice { interface: Interface, } -impl HidApi { +impl SixaxisApi { pub fn new() -> Self { Self {} } - pub fn open(&self, vendor_id: u16, product_id: u16) -> Result> { - let device; - for dev_info in list_devices()? { - if dev_info.vendor_id() == vendor_id - && dev_info.product_id() == product_id - { - let temp_dev = dev_info.open()?; + pub fn open(&self, vendor_id: u16, product_id: u16) -> Result> { + let device = list_devices() + .unwrap() + .find(|dev| dev.vendor_id() == vendor_id && dev.product_id() == product_id) + .expect("Unable to find SixAxis device!") + .open()?; - device = HidDevice::new(temp_dev, dev_info)?; - return Ok(device) - } - } + let interface = device.detach_and_claim_interface(0)?; - Err("Could not find requested device".into()) + Ok(SixaxisDevice { + interface, + }) } } -impl HidDevice { - fn new(device: Device, device_info: DeviceInfo) -> Result> { - let interface; - for int_info in device_info.interfaces() { - if int_info.class() == 3 { // Ensure it's an HID interface - interface = device.detach_and_claim_interface(0)?; - - return Ok(Self { - device, - interface - }) - } - } - - Err("Could not find valid interface".into()) - } - +impl SixaxisDevice { pub fn get_feature_report(&self, report_number: u8) -> Result, Box> { let result = block_on(self.interface.control_in( ControlIn { control_type: ControlType::Class, recipient: Recipient::Interface, - request: 0x01, - value: (3 << 8) | report_number as u16, + request: 1, + value: 0x300 | report_number as u16, index: 0, length: 8 } )).into_result()?; - dbg!(result.clone()); + let result = result[2..].to_vec(); Ok(result) } + + pub fn set_feature_report(&self, report_number: u8, out_buffer: &Vec) -> Result<(), Box> { + block_on(self.interface.control_out( + ControlOut { + control_type: ControlType::Class, + recipient: Recipient::Interface, + request: 9, + value: 0x300 | report_number as u16, + index: 0, + data: out_buffer, + } + )).into_result()?; + + Ok(()) + } } diff --git a/src/main.rs b/src/main.rs index d982b1e..e19054c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ -use hidapi::{HidApi, HidDevice}; +mod hidapi; + +use crate::hidapi::{SixaxisApi, SixaxisDevice}; use macaddr::MacAddr6; -use std::str::FromStr; -use std::{env, error::Error, process::exit}; +use std::{env, error::Error, process::exit, str::FromStr}; const VENDOR: u16 = 0x054c; const PRODUCT: u16 = 0x0268; @@ -11,10 +12,7 @@ fn main() { let args: Vec = env::args().collect(); // Get HIDAPI context - let api = match HidApi::new() { - Ok(api) => api, - Err(_) => panic!(), - }; + let api = SixaxisApi::new(); // Try to get the first sixaxis controller let device = match api.open(VENDOR, PRODUCT) { @@ -40,29 +38,26 @@ fn main() { } else if args.len() == 2 { // If mac address provided, set it set_pairing(device, args[1].as_str()).unwrap(); + println!("New Device: {}", args[1]); } else { println!("Usage:\n\n{} [mac]", args[0]); } } /// Get the current pairing of a SixAxis controller -fn pairing(device: HidDevice) -> Result, Box> { - let mut buffer = [0u8; 8]; - buffer[0] = MAC_REPORT_ID; - - device.get_feature_report(&mut buffer)?; - let result = &buffer[2..]; +fn pairing(device: SixaxisDevice) -> Result, Box> { + let result = device.get_feature_report(MAC_REPORT_ID)?; Ok(result.into()) } /// Set the new pairing of a SixAxis controller -fn set_pairing(device: HidDevice, address: &str) -> Result<(), Box> { +fn set_pairing(device: SixaxisDevice, address: &str) -> Result<(), Box> { let mut buffer = vec![MAC_REPORT_ID, 0x0]; let mut address = MacAddr6::from_str(address)?.as_bytes().to_vec(); buffer.append(&mut address); - device.send_feature_report(&buffer)?; + device.set_feature_report(MAC_REPORT_ID, &buffer)?; Ok(()) }