Client

Struct Client 

Source
pub struct Client { /* private fields */ }
Expand description

The main entry point for interacting with the ViGEm bus driver.

A Client manages the connection to the driver and keeps track of all virtual controllers created by it. When the Client is dropped, it will automatically unplug all of its connected virtual controllers.

Use Client::builder() or Client::connect() to create a new client.

Implementations§

Source§

impl Client

Source

pub fn builder() -> ClientBuilder

Create a builder to configure and connect a new client.

This allows setting options like the maximum number of targets.

§Example
use vigem_rust::client::Client;
let client = Client::builder()
    .max_targets(32) // Allow up to 32 controllers
    .connect()
    .unwrap();
Source

pub fn connect() -> Result<Self, ClientError>

Creates a new client with default options and connects to the ViGEm bus.

This is a convenient shortcut for Client::builder().connect().

§Example
use vigem_rust::Client;

let client = Client::connect().unwrap();
Examples found in repository?
examples/x360.rs (line 8)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // Connect to the ViGEm bus
7    // This can fail if the ViGEm bus driver is not installed.
8    let client = Client::connect()?;
9    println!("Connected to ViGEm bus");
10
11    // Create and plugin the virtual controller
12    let x360 = client.new_x360_target().plugin()?;
13    println!("Plugged in virtual Xbox 360 controller");
14
15    // Wait for the controller to be ready
16    // The virtual controller needs a moment to be recognized
17    // by the system before it can receive updates.
18    x360.wait_for_ready()?;
19    println!("Controller is ready. You can test it at https://hardwaretester.com/gamepad");
20
21    // Set up a notification listener in a separate thread
22    // This allows us to react to feedback from the system, like rumble or LED changes.
23    let notifications = x360.register_notification()?;
24    thread::spawn(move || {
25        println!("Notification Thread Started. Waiting for feedback...");
26        while let Ok(Ok(notification)) = notifications.recv() {
27            println!("Notification Thread Received feedback:");
28            println!(
29                "  - Rumble: Large Motor = {}, Small Motor = {}",
30                notification.large_motor, notification.small_motor
31            );
32            println!("  - LED Number/Player Index: {}", notification.led_number);
33        }
34    });
35
36    // Here, we'll send reports to the controller to simulate input.
37    let mut report = X360Report::default();
38    let mut angle: f64 = 0.0;
39    let mut step = 0;
40
41    loop {
42        // Animate the left thumbstick in a circle
43        angle += 0.1;
44        let (sin, cos) = angle.sin_cos();
45        report.thumb_lx = (sin * 32767.0) as i16;
46        report.thumb_ly = (cos * 32767.0) as i16;
47
48        // Alternate pressing A and B buttons
49        if step % 2 == 0 {
50            report.buttons = X360Button::A;
51        } else {
52            report.buttons = X360Button::B;
53        }
54
55        // Send the updated report to the controller
56        x360.update(&report)?;
57
58        thread::sleep(Duration::from_millis(16));
59        step += 1;
60    }
61}
More examples
Hide additional examples
examples/ds4.rs (line 8)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // Connect to the ViGEm bus
7    // This can fail if the ViGEm bus driver is not installed.
8    let client = Client::connect()?;
9    println!("Connected to ViGEm bus");
10
11    // Create and plugin the virtual controller
12    let ds4 = client.new_ds4_target().plugin()?;
13    println!("Plugged in virtual DualShock 4 controller");
14
15    // Wait for the controller to be ready
16    ds4.wait_for_ready()?;
17    println!("Controller is ready. You can test it at https://hardwaretester.com/gamepad");
18
19    // Set up a notification listener in a separate thread
20    // This allows us to react to feedback from the system, like rumble or LED changes.
21    let notifications = ds4.register_notification()?;
22    thread::spawn(move || {
23        println!("Notification Thread Started. Waiting for feedback from the host...");
24        while let Ok(Ok(notification)) = notifications.recv() {
25            println!("Notification Thread Received feedback:");
26            println!(
27                "  - Rumble: Large Motor = {}, Small Motor = {}",
28                notification.large_motor, notification.small_motor
29            );
30            println!(
31                "  - Lightbar Color: R={}, G={}, B={}",
32                notification.lightbar.red, notification.lightbar.green, notification.lightbar.blue
33            );
34        }
35    });
36
37    // Here, we'll send reports to the controller to simulate input.
38
39    let mut report = Ds4Report::default();
40
41    // Hold the right D-pad button
42    report.set_dpad(Ds4Dpad::East);
43    // Hold the Cross button
44    report.buttons |= Ds4Button::CROSS.bits();
45    // Fully press the right trigger
46    report.trigger_r = 255;
47
48    let mut angle: f64 = 0.0;
49
50    loop {
51        // Animate the right thumbstick in a circle
52        let (sin, cos) = angle.sin_cos();
53
54        // DS4 thumbsticks are 0-255, with 128 as the center.
55        report.thumb_rx = (128.0 + sin * 127.0) as u8;
56        report.thumb_ry = (128.0 + cos * 127.0) as u8;
57
58        // Send the updated report to the controller
59        ds4.update(&report)?;
60
61        thread::sleep(Duration::from_millis(16));
62        angle += 0.05;
63    }
64}
examples/ds4_ex.rs (line 9)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // Connect to the ViGEm bus
8    // This can fail if the ViGEm bus driver is not installed.
9    let client = Client::connect()?;
10    println!("Connected to ViGEm bus");
11
12    // Create and plugin the virtual controller
13    let ds4 = client.new_ds4_target().plugin()?;
14    println!("Plugged in virtual DualShock 4 controller");
15
16    // Wait for the controller to be ready
17    ds4.wait_for_ready()?;
18    println!("Controller is ready. You can test it at https://hardwaretester.com/gamepad");
19
20    let notifications = ds4.register_notification()?;
21    thread::spawn(move || {
22        println!("Notification Thread Started. Waiting for feedback from the host...");
23        while let Ok(Ok(notification)) = notifications.recv() {
24            println!("Notification Thread Received feedback:");
25            println!(
26                "  - Rumble: Large Motor = {}, Small Motor = {}",
27                notification.large_motor, notification.small_motor
28            );
29            println!(
30                "  - Lightbar Color: R={}, G={}, B={}",
31                notification.lightbar.red, notification.lightbar.green, notification.lightbar.blue
32            );
33        }
34    });
35
36    // Main input loop for extended reports
37    let mut report_ex = Ds4ReportEx::default();
38
39    // Variables to animate the touch point
40    let mut packet_counter: u8 = 0;
41    let mut touch_x: i32 = 0;
42    let mut direction: i32 = 12;
43
44    loop {
45        // Move the touch point back and forth horizontally.
46        if touch_x <= 0 {
47            direction = 12;
48        }
49        if touch_x >= 1919 {
50            direction = -12;
51        }
52        touch_x += direction;
53
54        report_ex.touch_packets_n = 1;
55
56        // Get a mut reference to the touch data struct inside the report.
57        let touch = &mut report_ex.current_touch;
58
59        // This counter should increment for each new packet of touch data (not sure if necessary for functionality).
60        touch.packet_counter = packet_counter;
61        packet_counter = packet_counter.wrapping_add(1);
62
63        touch.set_touch_1(true, 1, touch_x as u16, 471); // Finger 1 is down, centered vertically.
64        touch.set_touch_2(false, 0, 0, 0); // Finger 2 is up (inactive).
65
66        // Send the updated report to the controller
67        ds4.update_ex(&report_ex)?;
68
69        thread::sleep(Duration::from_millis(16));
70    }
71}
Source

pub fn new_x360_target(&self) -> TargetBuilder<'_, Xbox360>

Creates a builder for a new virtual Xbox 360 controller.

The returned builder can be used to set properties like vendor and product IDs before plugging the controller into the bus.

§Example
let x360 = client.new_x360_target()
    .with_vid(0xAAAA)
    .with_pid(0xBBBB)
    .plugin()
    .unwrap();
Examples found in repository?
examples/x360.rs (line 12)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // Connect to the ViGEm bus
7    // This can fail if the ViGEm bus driver is not installed.
8    let client = Client::connect()?;
9    println!("Connected to ViGEm bus");
10
11    // Create and plugin the virtual controller
12    let x360 = client.new_x360_target().plugin()?;
13    println!("Plugged in virtual Xbox 360 controller");
14
15    // Wait for the controller to be ready
16    // The virtual controller needs a moment to be recognized
17    // by the system before it can receive updates.
18    x360.wait_for_ready()?;
19    println!("Controller is ready. You can test it at https://hardwaretester.com/gamepad");
20
21    // Set up a notification listener in a separate thread
22    // This allows us to react to feedback from the system, like rumble or LED changes.
23    let notifications = x360.register_notification()?;
24    thread::spawn(move || {
25        println!("Notification Thread Started. Waiting for feedback...");
26        while let Ok(Ok(notification)) = notifications.recv() {
27            println!("Notification Thread Received feedback:");
28            println!(
29                "  - Rumble: Large Motor = {}, Small Motor = {}",
30                notification.large_motor, notification.small_motor
31            );
32            println!("  - LED Number/Player Index: {}", notification.led_number);
33        }
34    });
35
36    // Here, we'll send reports to the controller to simulate input.
37    let mut report = X360Report::default();
38    let mut angle: f64 = 0.0;
39    let mut step = 0;
40
41    loop {
42        // Animate the left thumbstick in a circle
43        angle += 0.1;
44        let (sin, cos) = angle.sin_cos();
45        report.thumb_lx = (sin * 32767.0) as i16;
46        report.thumb_ly = (cos * 32767.0) as i16;
47
48        // Alternate pressing A and B buttons
49        if step % 2 == 0 {
50            report.buttons = X360Button::A;
51        } else {
52            report.buttons = X360Button::B;
53        }
54
55        // Send the updated report to the controller
56        x360.update(&report)?;
57
58        thread::sleep(Duration::from_millis(16));
59        step += 1;
60    }
61}
Source

pub fn new_ds4_target(&self) -> TargetBuilder<'_, DualShock4>

Creates a builder for a new virtual DualShock 4 controller.

The returned builder can be used to set properties like vendor and product IDs before plugging the controller into the bus.

§Example
let ds4 = client.new_ds4_target()
    .with_vid(0xAAAA)
    .with_pid(0xBBBB)
    .plugin()
    .unwrap();
Examples found in repository?
examples/ds4.rs (line 12)
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    // Connect to the ViGEm bus
7    // This can fail if the ViGEm bus driver is not installed.
8    let client = Client::connect()?;
9    println!("Connected to ViGEm bus");
10
11    // Create and plugin the virtual controller
12    let ds4 = client.new_ds4_target().plugin()?;
13    println!("Plugged in virtual DualShock 4 controller");
14
15    // Wait for the controller to be ready
16    ds4.wait_for_ready()?;
17    println!("Controller is ready. You can test it at https://hardwaretester.com/gamepad");
18
19    // Set up a notification listener in a separate thread
20    // This allows us to react to feedback from the system, like rumble or LED changes.
21    let notifications = ds4.register_notification()?;
22    thread::spawn(move || {
23        println!("Notification Thread Started. Waiting for feedback from the host...");
24        while let Ok(Ok(notification)) = notifications.recv() {
25            println!("Notification Thread Received feedback:");
26            println!(
27                "  - Rumble: Large Motor = {}, Small Motor = {}",
28                notification.large_motor, notification.small_motor
29            );
30            println!(
31                "  - Lightbar Color: R={}, G={}, B={}",
32                notification.lightbar.red, notification.lightbar.green, notification.lightbar.blue
33            );
34        }
35    });
36
37    // Here, we'll send reports to the controller to simulate input.
38
39    let mut report = Ds4Report::default();
40
41    // Hold the right D-pad button
42    report.set_dpad(Ds4Dpad::East);
43    // Hold the Cross button
44    report.buttons |= Ds4Button::CROSS.bits();
45    // Fully press the right trigger
46    report.trigger_r = 255;
47
48    let mut angle: f64 = 0.0;
49
50    loop {
51        // Animate the right thumbstick in a circle
52        let (sin, cos) = angle.sin_cos();
53
54        // DS4 thumbsticks are 0-255, with 128 as the center.
55        report.thumb_rx = (128.0 + sin * 127.0) as u8;
56        report.thumb_ry = (128.0 + cos * 127.0) as u8;
57
58        // Send the updated report to the controller
59        ds4.update(&report)?;
60
61        thread::sleep(Duration::from_millis(16));
62        angle += 0.05;
63    }
64}
More examples
Hide additional examples
examples/ds4_ex.rs (line 13)
6fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // Connect to the ViGEm bus
8    // This can fail if the ViGEm bus driver is not installed.
9    let client = Client::connect()?;
10    println!("Connected to ViGEm bus");
11
12    // Create and plugin the virtual controller
13    let ds4 = client.new_ds4_target().plugin()?;
14    println!("Plugged in virtual DualShock 4 controller");
15
16    // Wait for the controller to be ready
17    ds4.wait_for_ready()?;
18    println!("Controller is ready. You can test it at https://hardwaretester.com/gamepad");
19
20    let notifications = ds4.register_notification()?;
21    thread::spawn(move || {
22        println!("Notification Thread Started. Waiting for feedback from the host...");
23        while let Ok(Ok(notification)) = notifications.recv() {
24            println!("Notification Thread Received feedback:");
25            println!(
26                "  - Rumble: Large Motor = {}, Small Motor = {}",
27                notification.large_motor, notification.small_motor
28            );
29            println!(
30                "  - Lightbar Color: R={}, G={}, B={}",
31                notification.lightbar.red, notification.lightbar.green, notification.lightbar.blue
32            );
33        }
34    });
35
36    // Main input loop for extended reports
37    let mut report_ex = Ds4ReportEx::default();
38
39    // Variables to animate the touch point
40    let mut packet_counter: u8 = 0;
41    let mut touch_x: i32 = 0;
42    let mut direction: i32 = 12;
43
44    loop {
45        // Move the touch point back and forth horizontally.
46        if touch_x <= 0 {
47            direction = 12;
48        }
49        if touch_x >= 1919 {
50            direction = -12;
51        }
52        touch_x += direction;
53
54        report_ex.touch_packets_n = 1;
55
56        // Get a mut reference to the touch data struct inside the report.
57        let touch = &mut report_ex.current_touch;
58
59        // This counter should increment for each new packet of touch data (not sure if necessary for functionality).
60        touch.packet_counter = packet_counter;
61        packet_counter = packet_counter.wrapping_add(1);
62
63        touch.set_touch_1(true, 1, touch_x as u16, 471); // Finger 1 is down, centered vertically.
64        touch.set_touch_2(false, 0, 0, 0); // Finger 2 is up (inactive).
65
66        // Send the updated report to the controller
67        ds4.update_ex(&report_ex)?;
68
69        thread::sleep(Duration::from_millis(16));
70    }
71}

Auto Trait Implementations§

§

impl Freeze for Client

§

impl RefUnwindSafe for Client

§

impl Send for Client

§

impl Sync for Client

§

impl Unpin for Client

§

impl UnwindSafe for Client

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.