Skip to content

Latest commit

 

History

History
192 lines (152 loc) · 8.41 KB

File metadata and controls

192 lines (152 loc) · 8.41 KB

VirtualDevice Documentation

The VirtualDevice interface provides a flexible way to define and control virtual input devices on Linux. Below is a detailed guide on how to use it for various operations.


Interface Definition

Configuration Methods

These methods allow you to configure the virtual device before registration.

Action Description
WithPath Sets the file path for the virtual device. Default is /dev/uinput.
WithMode Sets the file mode for the device file. Default is 0660.
WithQueueLen Configures the event queue length. Default is 1024.
WithBusType Sets the device bus type (e.g., linux.BUS_USB).
WithVendor Sets the vendor ID of the virtual device. (e.g. sdl.USB_VENDOR_MICROSOFT, 0x1234).
WithProduct Sets the product ID of the virtual device. (e.g. sdl.USB_PRODUCT_XBOX_ONE_S, 0x1234).
WithVersion Sets the version number for the virtual device. (e.g. 0x01).
WithName Sets the name of the virtual device.
WithKeys Specifies the keys supported by the device. (e.g. []linux.Key{linux.KEY_A, linux.KEY_B, linux.KEY_C}).
WithButtons Specifies the buttons supported by the device. (e.g. []linux.Button{linux.BTN_LEFT, linux.BTN_RIGHT}).
WithAbsAxes Configures the absolute axes for the device.
WithRelAxes Configures the relative axes for the device.
WithRepeat Configures key repeat delay and period.
WithLEDs Specifies the LEDs supported by the device. (e.g. []linux.Led{linux.LED_NUML, linux.LED_CAPSL).
WithProperties Sets device-specific properties (e.g., linux.INPUT_PROP_BUTTONPAD).
WithMiscEvents Specifies the miscellaneous events (e.g., linux.MSC_SCAN).

Lifecycle Methods

These methods manage the virtual device's lifecycle.

Action Description
Register Registers the virtual device with the system. Must be called before sending events.
Unregister Unregisters the virtual device, cleaning up resources.

Event Handling Methods

These methods send or manipulate input events.

Action Description
Send Sends a raw input event of the specified type, code, and value.
Sync Sends a synchronization event (e.g., linux.SYN_MT_REPORT).
SyncReport Sends a default synchronization event (linux.SYN_REPORT).
PressKey Simulates a key press event.
ReleaseKey Simulates a key release event.
PressButton Simulates a button press event.
ReleaseButton Simulates a button release event.
SendAbsoluteEvent Sends an absolute axis event with the specified axis and value.
SendRelativeEvent Sends a relative axis event with the specified axis and value.
SetLed Toggles the state of an LED on the virtual device.
SendMiscEvent Sends a miscellaneous event (e.g., linux.MSC_SCAN).

Usage

1. Configure a Virtual Device

Use the With... methods to configure your virtual device. These methods allow chaining for easy and clear initialization.

Example:

device := virtual_device.NewVirtualDevice().
   WithVendor(sdl.USB_VENDOR_LOGITECH).
   WithProduct(0xc22d).
   WithVersion(0x111).
   WithName("Logitech G510 Gaming Keyboard"),
   WithKeys([]linux.Key{linux.KEY_A, linux.KEY_B, linux.KEY_C}).
   WithLEDs([]linux.Led{linux.LED_CAPSL})

2. Register the Device

After configuration, call Register() to create the virtual device

err := device.Register()
if err != nil {
    log.Fatalf("Failed to register virtual device: %v", err)
}

3. Send Input Events

The VirtualDevice interface allows you to send various types of input events, simulating actions like key presses, mouse movements, and more.


Key Events

Simulate pressing and releasing keyboard keys:

device.PressKey(linux.KEY_A)  // Simulate pressing the "A" key
device.ReleaseKey(linux.KEY_A)  // Simulate releasing the "A" key

Button Events

Simulate pressing and releasing mouse or gamepad buttons:

device.PressButton(linux.BTN_LEFT)  // Simulate pressing the left mouse button
device.ReleaseButton(linux.BTN_LEFT)  // Simulate releasing the left mouse button

Absolute Axes Events

Used for devices like joysticks, touchpads, or drawing tablets. Send specific positions on an axis:

device.SendAbsoluteEvent(linux.ABS_X, 512)  // Move to the middle of the X-axis
device.SendAbsoluteEvent(linux.ABS_Y, 256)  // Move to a lower position on the Y-axis

Relative Axes Events

Used for devices like mice. Send relative movements instead of absolute positions:

device.SendRelativeEvent(linux.REL_X, 10)  // Move cursor 10 units to the right
device.SendRelativeEvent(linux.REL_Y, -5)  // Move cursor 5 units up

LED Events

Control the state of LEDs, such as Caps Lock or Num Lock:

device.SetLed(linux.LED_CAPSL, true)  // Turn on the Caps Lock LED
device.SetLed(linux.LED_CAPSL, false)  // Turn off the Caps Lock LED

Misc Events

Send miscellaneous events, including raw scan codes, to simulate hardware-level key events:

device.SendMiscEvent(linux.MSC_SCAN, 0x1E) // Send the scan code for the "A" key

4. Synchronize Events

After sending input events, it’s important to synchronize them to ensure the input subsystem processes them correctly. Synchronization informs the system that a complete input report has been sent.


Sync a Specific Event

Synchronize a specific event type (e.g., SYN_MT_REPORT) to signal that the current event sequence is complete:

device.Sync(linux.SYN_MT_REPORT)

Sync Report

Synchronize all pending input events. This is often used after sending a batch of input events to ensure they are processed together:

device.SyncReport()

Why Synchronization is Important?

Synchronization ensures that all input events sent to the system are properly interpreted and applied. Without synchronization, the system may ignore or misinterpret events, especially when sending multiple inputs in rapid succession.

5. Unregister the Device

When the device is no longer needed, unregister it to release system resources:

err := device.Unregister()
if err != nil {
    log.Fatalf("Failed to unregister virtual device: %v", err)
}

Example: Simulate Typing

Here’s how to simulate typing a string using a virtual keyboard:

package main

import (
	"fmt"
	virtual_device "github.com/jbdemonte/virtual-device"
	"github.com/jbdemonte/virtual-device/linux"
)

func main() {
	device := virtual_device.NewVirtualDevice().
		WithBusType(linux.BUS_USB).
		WithVendor(0xDEAD).
		WithProduct(0xBABE).
		WithVersion(0x01).
		WithName("Virtual Keyboard").
		WithKeys([]linux.Key{linux.KEY_A, linux.KEY_B, linux.KEY_C})

	device.Register()
	defer device.Unregister()

	device.PressKey(linux.KEY_B)
	device.ReleaseKey(linux.KEY_B)
}