Buttplug sex toy control library
at master 107 lines 3.2 kB view raw
1// Buttplug Rust Source Code File - See https://buttplug.io for more info. 2// 3// Copyright 2016-2024 Nonpolynomial Labs LLC. All rights reserved. 4// 5// Licensed under the BSD 3-Clause license. See LICENSE file in the project root 6// for full license information. 7 8use super::xinput_hardware::XInputHardwareConnector; 9use async_trait::async_trait; 10use buttplug_core::errors::ButtplugDeviceError; 11use buttplug_server::device::hardware::communication::{ 12 HardwareCommunicationManager, 13 HardwareCommunicationManagerBuilder, 14 HardwareCommunicationManagerEvent, 15 TimedRetryCommunicationManager, 16 TimedRetryCommunicationManagerImpl, 17}; 18use rusty_xinput::XInputHandle; 19use std::string::ToString; 20use tokio::sync::mpsc; 21 22// 1-index this because we use it elsewhere for showing which controller is which. 23#[derive(Debug, Display, Clone, Copy)] 24#[repr(u8)] 25pub enum XInputControllerIndex { 26 XInputController1 = 0, 27 XInputController2 = 1, 28 XInputController3 = 2, 29 XInputController4 = 3, 30} 31 32#[derive(Default, Clone)] 33pub struct XInputDeviceCommunicationManagerBuilder {} 34 35impl HardwareCommunicationManagerBuilder for XInputDeviceCommunicationManagerBuilder { 36 fn finish( 37 &mut self, 38 sender: mpsc::Sender<HardwareCommunicationManagerEvent>, 39 ) -> Box<dyn HardwareCommunicationManager> { 40 Box::new(TimedRetryCommunicationManager::new( 41 XInputDeviceCommunicationManager::new(sender), 42 )) 43 } 44} 45 46pub struct XInputDeviceCommunicationManager { 47 sender: mpsc::Sender<HardwareCommunicationManagerEvent>, 48 handle: XInputHandle, 49} 50 51impl XInputDeviceCommunicationManager { 52 fn new(sender: mpsc::Sender<HardwareCommunicationManagerEvent>) -> Self { 53 Self { 54 sender, 55 handle: rusty_xinput::XInputHandle::load_default() 56 .expect("Always loads in windows, this shouldn't run elsewhere."), 57 } 58 } 59} 60 61#[async_trait] 62impl TimedRetryCommunicationManagerImpl for XInputDeviceCommunicationManager { 63 fn name(&self) -> &'static str { 64 "XInputDeviceCommunicationManager" 65 } 66 67 async fn scan(&self) -> Result<(), ButtplugDeviceError> { 68 trace!("XInput manager scanning for devices"); 69 for i in &[ 70 XInputControllerIndex::XInputController1, 71 XInputControllerIndex::XInputController2, 72 XInputControllerIndex::XInputController3, 73 XInputControllerIndex::XInputController4, 74 ] { 75 match self.handle.get_state(*i as u32) { 76 Ok(_) => { 77 let index = *i as u32; 78 debug!("XInput manager found device {}", index); 79 let device_creator = Box::new(XInputHardwareConnector::new(*i)); 80 81 if self 82 .sender 83 .send(HardwareCommunicationManagerEvent::DeviceFound { 84 name: i.to_string(), 85 address: i.to_string(), 86 creator: device_creator, 87 }) 88 .await 89 .is_err() 90 { 91 error!("Error sending device found message from Xinput."); 92 break; 93 } 94 } 95 Err(_) => { 96 continue; 97 } 98 } 99 } 100 Ok(()) 101 } 102 103 // We should always be able to at least look at xinput if we're up on windows. 104 fn can_scan(&self) -> bool { 105 true 106 } 107}