Use your Android phone as a racing game controller for PC.
DriveLink Mobile is the Android client for the DriveLink PC Application. It transforms your device's motion sensors into a steering wheel and provides responsive touch controls for throttle, brake, and clutch. By communicating with a companion desktop application, it emulates a virtual gamepad on your Windows PC, providing a much more immersive racing experience compared to using a keyboard.
- Precise Steering: Uses the device gyroscope and accelerometer sensor with a complementary filter for smooth and accurate steering input.
- Three Pedal System: 3 vertical sliders to control throttle, brake, and clutch.
- Customizable buttons: 6 digital buttons for gear shifts, handbrake, or other vital racing functions.
- Adjustable Layout: Toggle between standard and alternate pedal layouts.
- Low Latency Input: High frequency (~100Hz) UDP transmission for quick response.
The DriveLink system consists of two primary components working in tandem:
- DriveLink Mobile (Android): Captures sensor and touch data, normalizes it, and streams it over the local network via UDP.
- DriveLink Desktop: Receives the UDP stream and maps the data to a virtual gamepad using the vJoy driver.
- Minimum OS: Android 7.0 (API 24) or higher.
- Hardware: Gyroscope and Accelerometer (required for motion steering).
- Network: Stable Wi-Fi connection on the same local network as the PC.
- OS: Windows 10/11.
- Driver: vJoy installed and configured.
- Companion App: DriveLink Desktop bridge running.
- Clone this repository:
git clone https://github.com/DevBoiAgru/DriveLinkMobile.git
- Open the project in Android Studio (Ladybug or newer).
- Sync Gradle and build the project.
- Install the APK on your device or run directly from Android Studio.
- Preparation: Ensure your phone and PC are on the same Wi-Fi network.
- Setup vJoy: Ensure vJoy is installed and a virtual device is enabled on your PC.
- Start Desktop Bridge: Launch the DriveLink Desktop application on your PC.
- Connect Mobile:
- Launch DriveLink Mobile on your phone.
- Go to Settings and enter your PC's local IP address.
- Check the connection status on the Navbar.
- Calibrate:
- In Settings, place your phone in landscape against a flat vertical surface and tap Calibrate Steering.
- Play:
- Launch your racing game of choice.
- Map the virtual controls in the game's input settings.
Tested games:
- BeamNG.drive (Very fun on manual transmission mode with clutch assist disabled)
Try it out and let me know more games that work with it!
Note
These are not exclusive mappings. You can map whichever slider you want to whichever function you want in the game's input settings.
- Throttle (Green): Controlled by the right-most slider.
- Brake (Red): Controlled by the slider next to throttle (standard) or in the left cluster (alternate).
- Clutch (Blue): Controlled by the left-most slider.
- Gear Up/Down: Arrow buttons in the right cluster.
- Auxiliary Buttons: 4 circular buttons in the left cluster for custom mappings (Handbrake, DRS, Look Back, etc.).
DriveLink uses a Complementary Filter for the steering data to combine high-speed gyroscope rotation with gravity-based accelerometer data. This eliminates "drift" while maintaining instantaneous response.
- Steering: Normalized to a radian-based value ranging from -π to +π.
- Pedals: Vertically normalized from 0.0 (released) to 1.0 (fully pressed).
To ensure the lowest possible "input lag," the app uses UDP (User Datagram Protocol) on port 7001. Unlike TCP, UDP does not wait for packet retransmissions, ensuring the game always receives the most current state of your controller.
app/
├─ data/ # Persistence (SettingsRepository) and State (InputRepository)
├─ network/ # UDP Socket handling (InputSender)
├─ sensors/ # Motion sensor logic and SteeringCalculator
├─ ui/ # Compose UI components and Screens
└─ viewmodel/ # MainViewModel - Central logic and state bridge
The app sends a 29-byte payload every 10ms (100Hz) in Little Endian format:
Type(1 byte): Packet identifier.Steering(4 bytes, Float): Steering angle in radians.Throttle(4 bytes, Float): 0.0 - 1.0.Brake(4 bytes, Float): 0.0 - 1.0.Clutch(4 bytes, Float): 0.0 - 1.0.Buttons(4 bytes, Int): Bitmask of button states.Timestamp(8 bytes, Long): Transmission time.
- Target SDK: 36
- Language: Kotlin
- UI Framework: Jetpack Compose
- Serialization: GSON
Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.
- Steering curve customisability: Adjustable steering curves with deadzones and sensitivity.
- Haptic Feedback: Force feedback using haptics.
- Dynamic UI: Support for different dashboard styles.

