@@ -51,7 +51,7 @@ use super::{InputError, OutputError, TargetInputDevice, TargetOutputDevice};
51
51
const MIN_FRAME_TIME : Duration = Duration :: from_millis ( 80 ) ;
52
52
53
53
pub struct SteamDeckDevice {
54
- device : VirtualUSBDevice ,
54
+ device : Option < VirtualUSBDevice > ,
55
55
state : PackedInputDataReport ,
56
56
/// Steam will send 'SetReport' commands with a report type, so it can fetch
57
57
/// a particular result with 'GetReport'
@@ -70,12 +70,8 @@ impl SteamDeckDevice {
70
70
return Err ( e. to_string ( ) . into ( ) ) ;
71
71
}
72
72
73
- // Create and start the virtual USB device
74
- let mut device = SteamDeckDevice :: create_virtual_device ( ) ?;
75
- device. start ( ) ?;
76
-
77
73
Ok ( Self {
78
- device,
74
+ device : None ,
79
75
state : PackedInputDataReport :: default ( ) ,
80
76
current_report : ReportType :: InputData ,
81
77
lizard_mode_enabled : false ,
@@ -86,9 +82,9 @@ impl SteamDeckDevice {
86
82
}
87
83
88
84
/// Create the virtual device to emulate
89
- fn create_virtual_device ( ) -> Result < VirtualUSBDevice , Box < dyn Error > > {
85
+ fn create_virtual_device ( product_id : u16 ) -> Result < VirtualUSBDevice , Box < dyn Error > > {
90
86
// Configuration values can be obtained from a real device with "sudo lsusb -v"
91
- let virtual_device = VirtualUSBDeviceBuilder :: new ( VID , PID )
87
+ let virtual_device = VirtualUSBDeviceBuilder :: new ( VID , product_id )
92
88
. class ( DeviceClass :: UseInterface )
93
89
. supported_langs ( vec ! [ LangId :: EnglishUnitedStates ] )
94
90
. manufacturer ( "Valve Software" )
@@ -673,6 +669,44 @@ impl SteamDeckDevice {
673
669
}
674
670
675
671
impl TargetInputDevice for SteamDeckDevice {
672
+ /// Start the driver when attached to a composite device.
673
+ fn on_composite_device_attached (
674
+ & mut self ,
675
+ composite_device : CompositeDeviceClient ,
676
+ ) -> Result < ( ) , InputError > {
677
+ // Get the configuration from the composite device
678
+ let config = composite_device. blocking_get_config ( ) ?;
679
+
680
+ // Set the product id based on the composite device configuration
681
+ let pid = match config. name . as_str ( ) {
682
+ "Lenovo Legion Go" => PID ,
683
+ "ASUS ROG Ally" => PID ,
684
+ "ASUS ROG Ally X" => PID ,
685
+ _ => PID ,
686
+ } ;
687
+
688
+ // TODO:
689
+ // Get the device node paths to the source devices to query for additional
690
+ // information like serial number, etc.
691
+ //let source_device_paths = composite_device.blocking_get_source_device_paths()?;
692
+ //let mut source_device_info = Vec::with_capacity(source_device_paths.len());
693
+ //for source_path in source_device_paths {
694
+ // let path = Path::new(source_path.as_str());
695
+ // let name = path.file_name().unwrap_or_default();
696
+ // let base_path = path.parent().unwrap().as_os_str();
697
+ // let device =
698
+ // UdevDevice::from_devnode(base_path.to_str().unwrap(), name.to_str().unwrap());
699
+ // source_device_info.push(device);
700
+ //}
701
+
702
+ // Create and start the virtual USB device
703
+ let mut device = SteamDeckDevice :: create_virtual_device ( pid) ?;
704
+ device. start ( ) ?;
705
+ self . device = Some ( device) ;
706
+
707
+ Ok ( ( ) )
708
+ }
709
+
676
710
fn write_event ( & mut self , event : NativeEvent ) -> Result < ( ) , InputError > {
677
711
log:: trace!( "Received event: {event:?}" ) ;
678
712
@@ -768,18 +802,28 @@ impl TargetInputDevice for SteamDeckDevice {
768
802
/// Stop the virtual USB read/write threads
769
803
fn stop ( & mut self ) -> Result < ( ) , InputError > {
770
804
log:: debug!( "Stopping virtual Deck controller" ) ;
771
- self . device . stop ( ) ;
772
-
773
- // Read from the device
774
- let xfer = self . device . blocking_read ( ) ?;
805
+ let xfer = {
806
+ let Some ( device) = self . device . as_mut ( ) else {
807
+ log:: trace!( "Deck controller was never started" ) ;
808
+ return Ok ( ( ) ) ;
809
+ } ;
810
+ device. stop ( ) ;
811
+
812
+ // Read from the device
813
+ device. blocking_read ( ) ?
814
+ } ;
775
815
776
816
// Handle any non-standard transfers
777
817
if let Some ( xfer) = xfer {
778
818
let reply = self . handle_xfer ( xfer) ;
779
819
780
820
// Write to the device if a reply is necessary
781
821
if let Some ( reply) = reply {
782
- self . device . write ( reply) ?;
822
+ let Some ( device) = self . device . as_mut ( ) else {
823
+ log:: trace!( "Deck controller was never started" ) ;
824
+ return Ok ( ( ) ) ;
825
+ } ;
826
+ device. write ( reply) ?;
783
827
}
784
828
}
785
829
@@ -797,15 +841,25 @@ impl TargetOutputDevice for SteamDeckDevice {
797
841
self . state . frame = Integer :: from_primitive ( frame. wrapping_add ( 1 ) ) ;
798
842
799
843
// Read from the device
800
- let xfer = self . device . blocking_read ( ) ?;
844
+ let xfer = {
845
+ let Some ( device) = self . device . as_mut ( ) else {
846
+ log:: trace!( "Device not started yet" ) ;
847
+ return Ok ( vec ! [ ] ) ;
848
+ } ;
849
+ device. blocking_read ( ) ?
850
+ } ;
801
851
802
852
// Handle any non-standard transfers
803
853
if let Some ( xfer) = xfer {
804
854
let reply = self . handle_xfer ( xfer) ;
805
855
806
856
// Write to the device if a reply is necessary
807
857
if let Some ( reply) = reply {
808
- self . device . write ( reply) ?;
858
+ let Some ( device) = self . device . as_mut ( ) else {
859
+ log:: trace!( "Device not started yet" ) ;
860
+ return Ok ( vec ! [ ] ) ;
861
+ } ;
862
+ device. write ( reply) ?;
809
863
}
810
864
}
811
865
0 commit comments