Skip to content

sirfragles/lg-magic

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LG Magic Remote (MR20) Linux Kernel Driver and Tools

Language: English🇬🇧 Русский🇷🇺

LG Magic Remote

Overview

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.

Project Structure

Kernel Module Files

  • 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.

Python Tools

  • 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

Kernel Module Features

Device Support

  • 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)

Button Mapping

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)

Airmouse Functionality

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 --mouse for testing and calibration validation

IMU Data Access

  • Raw accelerometer and gyroscope data via evdev
  • 6-axis motion data (3-axis accel + 3-axis gyro)
  • Hardware counter for timing synchronization

Building and Installation

Prerequisites

  • Linux kernel headers
  • DKMS (Dynamic Kernel Module Support)
  • Build essentials (make, gcc)

Manual Build

make
sudo insmod lg_magic.ko

DKMS Installation

sudo 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.0

Module Parameters

The 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/debug

Parameters:

  • airmouse (0/1): Enable/disable airmouse functionality
  • airmouse_threshold (int): Gyro threshold for enabling airmouse (default: 300)
  • imu_evdev (0/1): Expose raw IMU data as separate input device
  • debug (0-2): Debug message level (0=quiet, 1=normal, 2=verbose)

Calibration System

Calibration File Format

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 calibration
  • lg_magic_calib.bin - Fallback calibration

Creating Calibration Files

  1. Collect IMU samples for both calibrations:
python3 display_imu.py --csv samples.csv
  1. 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
  1. Convert to binary format:
python3 convert_calib.py calib.json lg_magic_calib.bin --alpha 0.2 --mouse_k 0.5

Calibration Parameters

  • alpha: Low-pass filter coefficient (0.0-1.0)
  • mouse_k: Airmouse sensitivity multiplier
  • gyro_bias: Gyroscope zero-offset values
  • gyro_scale: Gyroscope scaling factors

Python Tools Usage

lg_magic.py - Packet Analyzer

# Monitor HIDRAW packets
python3 lg_magic.py

display_imu.py - IMU Visualization

# 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 --mouse

Airmouse debug

The 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 --mouse

Technical Details

HID Protocol Structure

The 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)

IMU Data Processing

  • Sampling rate: ~50Hz (20ms intervals)
  • Data format: Big-endian signed 16-bit values
  • Coordinate system: Shown on image

Airmouse Algorithm

  1. Gyro data is bias-corrected and scaled
  2. Low-pass filtering reduces high-frequency noise
  3. Angular velocity is converted to pointer movement
  4. Threshold detection switches between navigation and pointer modes. Pressing navigation buttons return to button mode.

Filesystem Locations

  • 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/

Compatibility

  • Tested with: LG Magic Remote MR20
  • Kernel versions: 4.15+ (tested on 6.11)
  • Python: 3.6+
  • Dependencies: numpy, scipy, pyqtgraph, python-evdev

Contributing

Please report issues and submit pull requests for:

  • Additional device support
  • Improved calibration algorithms
  • Bug fixes and performance improvements

License

GPL v2 - Same as Linux kernel

Copyright © 2025 [Ilya Chelyadin]. This project is not affiliated with LG Electronics.

About

LG Magic Remote Linux driver

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 58.2%
  • C 40.8%
  • Makefile 1.0%