Language: English🇬🇧 Русский🇷🇺
This project provides a comprehensive Linux kernel driver and toolset for the LG Magic Remote (MR20 and similar models). The driver enables full functionality of the remote including button mapping, gyroscopic airmouse control, and IMU data access. The package includes both a kernel module and Python utilities for calibration, testing, and visualization.
- kernel/dkms.conf - DKMS configuration file for automated kernel module building
- kernel/lg_magic_main.c - Main kernel driver implementation
- kernel/lg_magic_airmouse.h - Header file for airmouse calibration structures
- kernel/lg_magic_airmouse.c - Airmouse calibration and filtering implementation
- kernel/Makefile - Build system for the kernel module
- 51-lgimu.rules - Udev rule for non-root raw IMU access. Place to
/etc/udev/rules.d/if needed.
- scripts/lg_magic.py - HIDRAW-level packet analyzer and debug tool. Initial tool, kept for historical reasons
- scripts/calibrate.py - IMU calibration utility (accelerometer and gyroscope)
- scripts/convert_calib.py - Converts JSON calibration to binary format for kernel module
- scripts/display_imu.py - Real-time IMU data visualization and airmouse emulation
- Supports LG Magic Remote (HID Bluetooth device 000f:3412)
- Creates two input devices:
LG Magic Remote- Standard HID events (buttons, wheel, airmouse)LG Magic Remote IMU- Raw IMU data (accelerometer + gyroscope)
Comprehensive button support including:
- Power, number keys (0-9), navigation buttons (UP/DOWN/LEFT/RIGHT)
- Media controls (PLAY, PAUSE, VOLUME, MUTE)
- Color buttons (RED, GREEN, YELLOW, BLUE)
- Special function buttons (HOME, BACK, SETTINGS, GUIDE)
Needs calibration before usage
- Gyroscope-based pointer control
- Configurable sensitivity and threshold
- Low-pass filtering for smooth movement
- Automatic mode switching between navigation and pointer control
The airmouse feature is implemented in two ways:
- Kernel Module (Production): Built-in airmouse processing with minimal latency, running entirely in kernel space
- Python + Uinput (Debug): Raw IMU data processing in userspace via
display_imu.py --mousefor testing and calibration validation
- Raw accelerometer and gyroscope data via evdev
- 6-axis motion data (3-axis accel + 3-axis gyro)
- Hardware counter for timing synchronization
- Linux kernel headers
- DKMS (Dynamic Kernel Module Support)
- Build essentials (make, gcc)
make
sudo insmod lg_magic.kosudo mkdir /usr/src/lg-magic-1.0
sudo cp * /usr/src/lg-magic-1.0/
sudo dkms add -m lg-magic -v 1.0
sudo dkms build -m lg-magic -v 1.0
sudo dkms install -m lg-magic -v 1.0The driver supports several runtime parameters:
# Load with custom parameters
sudo modprobe lg_magic airmouse=1 airmouse_threshold=300 imu_evdev=1 debug=2
# Or set via sysfs after loading
echo 1 > /sys/module/lg_magic/parameters/airmouse
echo 500 > /sys/module/lg_magic/parameters/airmouse_threshold
echo 2 > /sys/module/lg_magic/parameters/debugParameters:
airmouse(0/1): Enable/disable airmouse functionalityairmouse_threshold(int): Gyro threshold for enabling airmouse (default: 300)imu_evdev(0/1): Expose raw IMU data as separate input devicedebug(0-2): Debug message level (0=quiet, 1=normal, 2=verbose)
The driver loads calibration data from binary files via Linux Firmware subsystem:
lg_magic_calib_XX_XX_XX_XX_XX_XX.bin- MAC address-specific individual calibrationlg_magic_calib.bin- Fallback calibration
- Collect IMU samples for both calibrations:
python3 display_imu.py --csv samples.csv- Calculate calibration values:
# Calibrate accelerometer (slowly rotate across all axes while collecting)
python3 calibrate.py --accel samples.csv calib_accel.json
# Calibrate gyroscope (keep remote stationary while collecting)
python3 calibrate.py --gyro samples.csv calib_gyro.json
# Combine Gyro/Accel JSONs
Combine gyro/accel sections. Adjust gyro scale. Out of scope of this project, recommended value about 0.07
- Convert to binary format:
python3 convert_calib.py calib.json lg_magic_calib.bin --alpha 0.2 --mouse_k 0.5alpha: Low-pass filter coefficient (0.0-1.0)mouse_k: Airmouse sensitivity multipliergyro_bias: Gyroscope zero-offset valuesgyro_scale: Gyroscope scaling factors
# Monitor HIDRAW packets
python3 lg_magic.py# Raw IMU data display
python3 display_imu.py
# AHRS
python3 display_imu.py --calib calib.json --ahrs
# 3D orientation cube
python3 display_imu.py --calib calib.json --cube
# Uinput airmouse
python3 display_imu.py --calib calib.json --mouseThe Python tools can create a virtual mouse device using uinput:
# Enable uinput module
sudo modprobe uinput
# Run airmouse with calibration
python3 display_imu.py --calib calib.json --mouseThe remote uses report ID 0xFD (30-byte total: 1 byte report ID + 29 bytes payload). The payload structure is:
| Offset | Size | Description | Format |
|---|---|---|---|
| 0 | 1 | Report ID (0xFD) | uint8_t |
| 1-2 | 2 | Packet counter | little-endian uint16 |
| 3-4 | 2 | Constant value (0xFD00) | little-endian uint16 |
| 5-6 | 2 | Gyro X | big-endian int16 |
| 7-8 | 2 | Gyro Y | big-endian int16 |
| 9-10 | 2 | Gyro Z | big-endian int16 |
| 11-12 | 2 | Accel X | big-endian int16 |
| 13-14 | 2 | Accel Y | big-endian int16 |
| 15-16 | 2 | Accel Z | big-endian int16 |
| 17-18 | 2 | Button code | big-endian uint16 |
| 19 | 1 | Wheel delta | int8 |
Other report types (0xF9, 0x01) were not observed, maybe used for other functions (like MIC)
- Sampling rate: ~50Hz (20ms intervals)
- Data format: Big-endian signed 16-bit values
- Coordinate system: Shown on image
- Gyro data is bias-corrected and scaled
- Low-pass filtering reduces high-frequency noise
- Angular velocity is converted to pointer movement
- Threshold detection switches between navigation and pointer modes. Pressing navigation buttons return to button mode.
- Module:
/lib/modules/$(uname -r)/kernel/drivers/input/misc/lg_magic.ko - Calibration:
/lib/firmware/lg_magic_calib.bin - DKMS source:
/usr/src/lg-magic-1.0/
- Tested with: LG Magic Remote MR20
- Kernel versions: 4.15+ (tested on 6.11)
- Python: 3.6+
- Dependencies: numpy, scipy, pyqtgraph, python-evdev
Please report issues and submit pull requests for:
- Additional device support
- Improved calibration algorithms
- Bug fixes and performance improvements
GPL v2 - Same as Linux kernel
Copyright © 2025 [Ilya Chelyadin]. This project is not affiliated with LG Electronics.
