website logo
โŒ˜K
Hand Held Legend Wiki
Modding Tips
Sensitive Touch Sensors
Removing Adhered Screens
Restore Your Original Gameboy Bumper Buttons To Factory
IPS Comparison Info
Headphones Working But Speaker Is Not
Power Switch Cleaning Guide
IPS LCD Dry Test
GBA SP | IPS LCD Dry Test
Soldering Iron Guide
HHL Products
ProGCC V3
GC Pocket Adapter
Open Controller DevKit
Retro-C Cable Information
RetroGlow
ProGCC V2 and V1
Torx Screw Kits
Console Guides
Game Gear
Electrolytic Re-Cap Guide
Nintendo Switch
GameCube
Game Boy (DMG)
Game Boy Pocket
Game Boy Color
Game Boy Advance (AGB)
Game Boy Advance SP
Nintendo DS
Mod Install Guides
Nintendo Switch
Game Gear
GameCube
Game Boy (DMG)
Game Boy Pocket/Light
Game Boy Color
Game Boy Advance (AGB)
Game Boy Advance SP
Atari Lynx
WonderSwan
Product Usage Guides
EZ Flash Upgrade Guide
Writing A Rom To A Flash Cart
๐Ÿงƒ CleanJuice Modules
Game Boy Color
Troubleshooting
๐Ÿ”‰Audio
IPS Troubleshooting Guide
โšกEZ-Flash Omega Troubleshoot
๐Ÿ”‹ Power Switch Is Too Small
Developer Center
OpenJoyPad HID USB Specification
USB Product IDs Used
Nintendo Switch
Affiliate Guidelines
Docs powered by
Archbee
Developer Center
Nintendo Switch

Nintendo Switch Bluetooth Controller Protocol

10min

This page details all things Nintendo Switch controller protocol (Bluetooth only) related.

This article is still a work in progress! It was last updated June 24, 2022 and may have information that is missing or incomplete.

On top of this, specific details are given on how this looks implemented using the Bluedroid Bluetooth stack in the ESP-IDF development environment.

Sources

This work would not be possible without the following sources put together by community modding members.

  • ๏ปฟdekuNukem Nintendo Switch Reverse Engineering - GitHub๏ปฟ
  • ๏ปฟJoyConDroid Project - GitHub๏ปฟ
  • ๏ปฟNathanReeves BlueCubeMod - GitHub๏ปฟ

HID Reports and Sub-Commands

HID Reports from Nintendo Switch

Once a report comes in from the Nintendo Switch, it must be interpreted. The report type determines what type of data the Nintendo Switch will expect back from the controller. As far as I can tell, these reports are only sent through HID interrupt reports.

Obtaining Report Type

To obtain the report type, see the example below.

In this code example, we are acting on the callback event of a esp_hidd_cb_param_t type. The report type is specified by byte 0.

C++
|
// This is the callback event that's already registered
void hidd_cb(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
{
    switch(event)
    {
        case ESP_HIDD_INTR_DATA_EVT:
            // In this event case, we are handling an interrupt event
            // We'll grab the HID command type and set it as 'report_type'.
            uint8_t report_type = param->intr_data.data[0];
            break;
    }
}
๏ปฟ

HID report types and meanings

Report ID

Meaning

Details

0x01

Rumble data AND a Subcommand

The event data contains data to animate the linear actuators for HD rumble. This event data also contains a sub-command. Read on to learn more.

0x03

NFC and IR MCU firmware update packet

N/A

0x10

Rumble data

Only event data to animate the linear actuators for HD rumble.

0x11

Request NFC/IR MCU data

Read data from the IR sensor or NFC memory buffer from the controller.

Sub-Commands from Nintendo Switch

Sub-commands will interface with the various hardware built in to the controller to perform many functions. The Nintendo Switch controllers have SPI flash built in to hold firmware patches, controller colors, calibration data, and more.

Obtaining Sub-Command

In this code example, we are acting on the callback event of a esp_hidd_cb_param_t type. The sub-command is byte 10 of the incoming data.

C++
|
// This is the callback event that's already registered
void hidd_cb(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
{
    switch(event)
    {
        case ESP_HIDD_INTR_DATA_EVT:
            // This is the same as the previous example... we got report ID
            uint8_t report_type = param->intr_data.data[0];

            // We'll get the sub command as 'sub_cmd'
            uint8_t sub_cmd = param->intr_data.data[10]
            break;
    }
}
๏ปฟ

Sub-Command types and meanings

Sub-Command

Meaning

Details

0x00

Get ONLY Controller State

๏ปฟ

0x01

Bluetooth manual pairing

๏ปฟ

0x02

Request device info

๏ปฟ

0x03

Request input report mode

๏ปฟ

0x04

Trigger buttons time elapsed

๏ปฟ

0x05

Get page list state

๏ปฟ

0x06

Set HCI state

๏ปฟ

0x07

Reset pairing info

๏ปฟ

0x08

Set low power shipping state

๏ปฟ

0x10

SPI Flash read

๏ปฟ

0x11

SPI Flash write

๏ปฟ

0x12

SPI Sector erase

๏ปฟ

0x20

Reset NFC/IR MCU

๏ปฟ

0x21

Set NFC/IR MCU config

๏ปฟ

0x22

Set NFC/IR state

๏ปฟ

0x30

Set player number (lights)

๏ปฟ

0x31

Get player number (lights)

๏ปฟ

0x38

Set "Home" button LED

๏ปฟ

0x40

Enable 6-axis IMU

๏ปฟ

0x41

Set 6-axis sensitivity

๏ปฟ

0x42

Write IMU registers

๏ปฟ

0x43

Read IMU registers

๏ปฟ

0x48

Enable vibration

๏ปฟ

๏ปฟ

Updated 03 Mar 2023
Did this page help you?
PREVIOUS
Nintendo Switch
NEXT
Analog Stick Data
Docs powered by
Archbee
TABLE OF CONTENTS
Sources
HID Reports and Sub-Commands
HID Reports from Nintendo Switch
Obtaining Report Type
HID report types and meanings
Sub-Commands from Nintendo Switch
Obtaining Sub-Command
Sub-Command types and meanings
Docs powered by
Archbee