Using AI/Claude to write a macOS driver for the Mario Kart Racing Wheel Pro Mini for Nintendo Switch™
A complete DriverKit-based driver for the HORI Racing Wheel Switch (USB ID: 0x0F0D:0x013E) with full button and axis mapping discovered through interactive testing.
- Vendor ID: 0x0F0D (HORI CO.,LTD.)
- Product ID: 0x013E
- Product Name: HORI Racing Wheel Switch
- Serial Number: 12340000
- ✅ Complete DriverKit driver implementation
- ✅ 16-bit steering wheel support (65,536 positions!)
- ✅ All 20 physical controls mapped (3 analog axes, 17 digital buttons)
- ✅ Interactive mapping tool to discover button/axis positions
- ✅ Real-time testing dashboard
- ✅ Comprehensive documentation
All physical controls have been successfully mapped:
- Byte 2 (8 controls): D-pad (4 directions) + L/R shoulder buttons + Plus/Minus buttons
- Byte 3 (7 controls): Paddle shifters (2) + Face buttons (A/B/X/Y/Home)
- Bytes 4-5 (5 controls): Brake/Accelerator pedals + ZL/ZR button overlays
- Bytes 6-7 (1 control): 16-bit steering wheel (signed-style encoding, 0x0000 = center)
See DISCOVERED_MAPPING.md for complete protocol documentation.
This driver uses Apple's DriverKit framework (modern replacement for kernel extensions) and implements:
- IOUSBHostDevice: USB device communication
- IOUserHIDEventService: HID event generation for game compatibility
- Asynchronous interrupt endpoint reading
- HID report descriptor translation
Before building the driver, test all inputs work:
sudo python3 test_wheel.pyThis displays a live dashboard showing all controls in real-time.
See BUILD_INSTRUCTIONS.md for complete build instructions.
# Quick build with Xcode
xcodebuild -project HORIRacingWheelDriver.xcodeproj -scheme HORIRacingWheelDriversudo cp -r HORIRacingWheelDriver.dext /Library/SystemExtensions/
sudo systemextensionsctl developer on
systemextensionsctl submit com.yourname.HORIRacingWheelDriverHORIRacingWheelDriver.iig- Driver interface definitionHORIRacingWheelDriver.cpp- Driver implementationInfo.plist- Driver bundle configuration and USB device matchingHORIRacingWheelDriver.entitlements- Required DriverKit entitlements
test_wheel.py- Real-time input testing dashboardmap_controls.py- Interactive control mapping toolcapture_hid_descriptor.py- USB HID descriptor capture tool
START_HERE.txt- Quick orientation guideBUILD_INSTRUCTIONS.md- How to build and installDISCOVERED_MAPPING.md- Complete protocol documentation (all 20 controls!)TESTING_GUIDE.md- How to test the wheelMAPPING_GUIDE.md- How to use the mapping toolQUICK_REFERENCE.md- Command reference
- Xcode 12 or later with Command Line Tools
- macOS 11.0 SDK or later
- Apple Developer Account (for code signing)
- System Integrity Protection (SIP) must be disabled for testing:
# Reboot into Recovery Mode (Command+R during boot) csrutil disable csrutil authenticated-root disable # Reboot normally
-
Create an Xcode project:
- File → New → Project
- Choose DriverKit → Driver template
- Set Product Name to "HORIRacingWheelDriver"
- Set Bundle Identifier (e.g.,
com.yourname.HORIRacingWheelDriver)
OR create a macOS App and add a DriverKit Driver target to it (recommended for deployment)
-
Add the files to your project:
- Replace template files with:
.iig,.cpp,.plist, and.entitlementsfiles
- Replace template files with:
-
Configure build settings:
- Set deployment target to macOS 11.0+
- Enable "Hardened Runtime"
- Set code signing identity
- Add the entitlements file to the target
-
Build the driver:
xcodebuild -project HORIRacingWheelDriver.xcodeproj -scheme HORIRacingWheelDriver
See BUILD_INSTRUCTIONS.md for detailed instructions.
-
Build the driver extension (.dext bundle)
-
Copy to system extensions directory:
sudo cp -r HORIRacingWheelDriver.dext /Library/SystemExtensions/
-
Activate the extension:
sudo systemextensionsctl developer on systemextensionsctl submit com.yourname.HORIRacingWheelDriver
-
Load the driver:
sudo kmutil load -p /Library/SystemExtensions/HORIRacingWheelDriver.dext
-
Verify driver is loaded:
sudo kmutil showloaded | grep HORI
Test all wheel inputs without installing the driver:
sudo python3 test_wheel.pyThis displays a live dashboard showing:
- Steering wheel position with visual indicator (16-bit precision!)
- Accelerator and brake pedal bars
- All 17 buttons (lights up when pressed)
- Paddle shifters
- D-pad direction with arrow
- Raw hex values for debugging
See TESTING_GUIDE.md for complete testing instructions.
-
Check driver attachment:
ioreg -p IOUSB -w0 -l | grep -i hori -A 20 -
Monitor driver logs:
log stream --predicate 'eventMessage contains "HORIRacingWheelDriver"' --level debug -
Test with a game: The wheel should appear as a standard HID game controller
If you get this error when running test tools:
# Install pyusb for system Python
sudo python3 -m pip install --break-system-packages pyusbSee FIX_PYUSB.md for detailed troubleshooting.
# Real-time logging
log stream --predicate 'eventMessage contains "HORIRacingWheelDriver"' --level debug
# View system log
log show --last 10m | grep HORIRacingWheelDriversudo python3 capture_hid_descriptor.pysudo python3 map_controls.pyUnlike typical 8-bit wheels (256 positions), this wheel uses 16-bit steering:
- 65,536 unique positions
- Signed-style encoding: 0x0000 = center, 0x0001-0x7FFF = right, 0x8000-0xFFFF = left
- Professional racing simulator grade precision
The protocol uses highly efficient bit-packing:
- Byte 2: All 8 bits used (D-pad + shoulders + system buttons)
- Byte 3: 7 buttons (paddles + face buttons)
- Overlays: ZL/ZR buttons overlay on analog pedal axes
All 20 physical controls have been mapped through interactive testing:
- 3 analog axes (steering, brake, accelerator)
- 17 digital buttons (including D-pad as 4 buttons)
- DriverKit extensions run in user space (safer than kernel extensions)
- Code must be signed with a Developer ID
- Requires entitlements for USB and HID access
- SIP must be disabled for development/testing
MIT License - Modify and use as needed
Contributions welcome, especially:
- Force feedback implementation
- Better error handling
- Multi-device support
- Testing on different macOS versions
Generated with Claude Code