Joy-Con is the name for the Switch's primary game controllers. The controllers communicate to the console through bluetooth and can be disconnected from the main unit.
Hardware
The controllers themselves are simple to disassemble and identify.
Error creating thumbnail: File with dimensions greater than 12.5 MP
The front of the Joy-Con internal
[1]
Error creating thumbnail: File with dimensions greater than 12.5 MP
The rear of the Joy-Con internal
[2]
Color |
Item
|
Red |
Broadcom BCM20734 Bluetooth 4.1/2.4 GHz Transceiver
|
Orange |
STMicroelectronics NFCBEA 812006 33 (Likely NFC reader IC)
|
Yellow |
Macronix International MX25U4033E 4 Mb CMOS Flash
|
Firmware
See also: Joy-Con Firmware
The firmware of the Joy-Cons seems to be generic across all instances. Details such as the handedness of the controller and the color is just indicated in a configuration part of the flash. Judging by quick glance at the firmware, it's probably identical to that used on the Pro Controller as well.
The flash is in a patch-ram format. Tools for dealing with it are available [3].
A dump of the ROM region (taken while firmware was running) can be found here. Note this is the same SoC used on the other controller models, as well.
Protocol
The Joy-Con can communicate wirelessly over Bluetooth or through the rails over UART. This uses a Nintendo proprietary protocol called "Nwcp".
NwcpPacket
This is a 5-byte packet header used by Broadcom's HCI Control Protocol.
Offset
|
Size
|
Description
|
0x0
|
0x1
|
PacketType (always 0x19)
|
0x1
|
0x1
|
CommandCode
|
0x2
|
0x1
|
GroupCode (always 0x03)
|
0x3
|
0x2
|
PacketLength
|
CommandCode
Value
|
Description
|
0x1 |
SendToDevice
|
0x81 |
ReceiveFromDevice
|
Offset
|
Size
|
Description
|
0x0
|
0x1
|
CommandType
|
0x1
|
0x1
|
DeviceCommand
|
0x2
|
0x2
|
DataSize
|
0x4
|
0x1
|
CommandResult
|
0x5
|
0x1
|
DataCrc (CRC8 over Data for DataSize bytes)
|
0x6
|
0x1
|
HeaderCrc (CRC8 over the previous 6 bytes)
|
CommandType
Value
|
Description
|
0x91 |
DeviceCommandToDevice
|
0x92 |
Hid
|
0x94 |
DeviceCommandFromDevice
|
0x9A |
|
0xA3 |
|
0xA5 |
Handshake
|
DeviceCommand
Value
|
Description
|
0x01 |
Inquiry
|
0x02 |
WriteChargerSettings
|
0x03 |
|
0x04 |
|
0x05 |
|
0x06 |
|
0x07 |
ReadWakeUpReason
|
0x10 |
CreateHidConnection
|
0x11 |
DisconnectHid
|
0x12 |
SetHidInterval
|
0x13 |
|
0x18 |
Pairing
|
0x20 |
UpdateUartBaudRate
|
0x40 |
|
HidCommand
Value
|
Description
|
0x00 |
|
0x01 |
PairingOut
|
0x02 |
GetDeviceInfo
|
0x03 |
SetDataFormat
|
0x04 |
LRButtonDetection
|
0x05 |
Page
|
0x06 |
Reset
|
0x07 |
ClearPairingInfo
|
0x08 |
Shipment
|
0x10 |
SerialFlashRead
|
0x11 |
SerialFlashWrite
|
0x12 |
SerialFlashSectorErase
|
0x20 |
McuReset
|
0x21 |
McuWrite
|
0x22 |
McuResume
|
0x23 |
|
0x24 |
McuPollingEnable
|
0x25 |
McuPollingDisable
|
0x28 |
AttachmentWrite
|
0x29 |
AttachmentRead
|
0x2A |
AttachmentEnable
|
0x2B |
|
0x30 |
SetIndicatorLed
|
0x31 |
GetIndicatorLed
|
0x38 |
SetNotificationLed
|
0x40 |
SensorSleep
|
0x41 |
SensorConfig
|
0x42 |
SensorWrite
|
0x43 |
SensorRead
|
0x48 |
MotorEnable
|
0x50 |
GetBatteryVoltage
|
0x51 |
WriteChargeSetting
|
0x52 |
ReadChargeSetting
|
0x58 |
ExtDevWrite
|
0x59 |
GetExtDevInfo
|
0x5A |
ExtDevPollingEnable
|
0x5B |
ExtDevPollingDisable
|
0x5C |
ExtDevInFormatConfig
|
0x5D |
|
0x60 |
InternalAttachmentWrite
|
0x61 |
InternalAttachmentReadOld
|
0x62 |
InternalAttachmentEnable
|
0x63 |
InternalAttachmentPollingEnable
|
0x64 |
InternalAttachmentPollingDisable
|
0x7A |
AddButtonPlayData
|
0x7B |
StartStopButtonPlayData
|
0x80 |
Ack
|
0x81 |
PairingIn
|
0x82 |
DeviceInfo
|
0x83 |
LRButtonElapsedTime
|
0x90 |
SerialFlashData
|
0xA0 |
McuData
|
0xA8 |
AttachmentData
|
0xA9 |
|
0xAA |
InternalAttachmentRead
|
0xB0 |
IndicatorLed
|
0xC0 |
SensorData
|
0xD0 |
BatteryVoltage
|
0xD8 |
ExtDevRead
|
0xD9 |
ExtDevInfo
|
Left & Right Separate Joy-con
When paired directly to a computer over bluetooth, the joy-con both provide identical HID input report descriptor. This does not appear to include motion controls, IR data, or NFC. They both behave as detached single-player controllers.
HID Input Report Descriptor (Hexadecimal):
00000000: 05010905 A1010601 FF852109 21750895 ....¡...ÿ…!.!u.•
00000010: 30810285 30093075 08953081 02853109 0..…0.0u.•0..…1.
00000020: 31750896 69018102 85320932 75089669 1u.–i...…2.2u.–i
00000030: 01810285 33093375 08966901 8102853F ...…3.3u.–i...…?
00000040: 05091901 29101500 25017501 95108102 ....)...%.u.•...
00000050: 05010939 15002507 75049501 81420509 ...9..%.u.•..B..
00000060: 75049501 81010501 09300931 09330934 u.•......0.1.3.4
00000070: 16000027 FFFF0000 75109504 81020601 ...'ÿÿ..u.•.....
00000080: FF850109 01750895 30910285 10091075 ÿ…...u.•0‘.…...u
00000090: 08953091 02851109 11750895 30910285 .•0‘.…...u.•0‘.…
000000A0: 12091275 08953091 02C0 ...u.•0‘.À
Parsed Bytes |
Description
|
0x05, 0x01, |
Usage Page (Generic Desktop Ctrls)
|
0x09, 0x05, |
Usage (Game Pad)
|
0xA1, 0x01, |
Collection (Application)
|
0x06, 0x01, 0xFF, |
Usage Page (Vendor Defined 0xFF01)
|
0x85, 0x21, |
Report ID (33)
|
0x09, 0x21, |
Usage (0x21)
|
0x75, 0x08, |
Report Size (8)
|
0x95, 0x30, |
Report Count (48)
|
0x81, 0x02, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x85, 0x30, |
Report ID (48)
|
0x09, 0x30, |
Usage (0x30)
|
0x75, 0x08, |
Report Size (8)
|
0x95, 0x30, |
Report Count (48)
|
0x81, 0x02, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x85, 0x31, |
Report ID (49)
|
0x09, 0x31, |
Usage (0x31)
|
0x75, 0x08, |
Report Size (8)
|
0x96, 0x69, 0x01, |
Report Count (361)
|
0x81, 0x02, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x85, 0x32, |
Report ID (50)
|
0x09, 0x32, |
Usage (0x32)
|
0x75, 0x08, |
Report Size (8)
|
0x96, 0x69, 0x01, |
Report Count (361)
|
0x81, 0x02, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x85, 0x33, |
Report ID (51)
|
0x09, 0x33, |
Usage (0x33)
|
0x75, 0x08, |
Report Size (8)
|
0x96, 0x69, 0x01, |
Report Count (361)
|
0x81, 0x02, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x85, 0x3F, |
Report ID (63)
|
0x05, 0x09, |
Usage Page (Button)
|
0x19, 0x01, |
Usage Minimum (0x01)
|
0x29, 0x10, |
Usage Maximum (0x10)
|
0x15, 0x00, |
Logical Minimum (0)
|
0x25, 0x01, |
Logical Maximum (1)
|
0x75, 0x01, |
Report Size (1)
|
0x95, 0x10, |
Report Count (16)
|
0x81, 0x02, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x05, 0x01, |
Usage Page (Generic Desktop Ctrls)
|
0x09, 0x39, |
Usage (Hat switch)
|
0x15, 0x00, |
Logical Minimum (0)
|
0x25, 0x07, |
Logical Maximum (7)
|
0x75, 0x04, |
Report Size (4)
|
0x95, 0x01, |
Report Count (1)
|
0x81, 0x42, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
|
0x05, 0x09, |
Usage Page (Button)
|
0x75, 0x04, |
Report Size (4)
|
0x95, 0x01, |
Report Count (1)
|
0x81, 0x01, |
Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x05, 0x01, |
Usage Page (Generic Desktop Ctrls)
|
0x09, 0x30, |
Usage (X)
|
0x09, 0x31, |
Usage (Y)
|
0x09, 0x33, |
Usage (Rx)
|
0x09, 0x34, |
Usage (Ry)
|
0x16, 0x00, 0x00, |
Logical Minimum (0)
|
0x27, 0xFF, 0xFF, 0x00, 0x00, |
Logical Maximum (65534)
|
0x75, 0x10, |
Report Size (16)
|
0x95, 0x04, |
Report Count (4)
|
0x81, 0x02, |
Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
0x06, 0x01, 0xFF, |
Usage Page (Vendor Defined 0xFF01)
|
0x85, 0x01, |
Report ID (1)
|
0x09, 0x01, |
Usage (0x01)
|
0x75, 0x08, |
Report Size (8)
|
0x95, 0x30, |
Report Count (48)
|
0x91, 0x02, |
Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
0x85, 0x10, |
Report ID (16)
|
0x09, 0x10, |
Usage (0x10)
|
0x75, 0x08, |
Report Size (8)
|
0x95, 0x30, |
Report Count (48)
|
0x91, 0x02, |
Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
0x85, 0x11, |
Report ID (17)
|
0x09, 0x11, |
Usage (0x11)
|
0x75, 0x08, |
Report Size (8)
|
0x95, 0x30, |
Report Count (48)
|
0x91, 0x02, |
Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
0x85, 0x12, |
Report ID (18)
|
0x09, 0x12, |
Usage (0x12)
|
0x75, 0x08, |
Report Size (8)
|
0x95, 0x30, |
Report Count (48)
|
0x91, 0x02, |
Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
|
0xC0, |
End Collection
|
Colors
HEX codes for the colors shown in the "Controllers" menu of the Switch UI can be found in a Joy-con SPI dump starting at offset 0x6050. Body color is first followed by button color and each is 3 bytes long. These values are able to be re-written with any HEX color value to make the Joy-cons show up as different colors in the UI. The following is a list of official HEX colors recovered from SPI dumps.
Developer Kit Joy-Con |
Release |
Body HEX |
Button HEX
|
Black / ブラック |
2015.10.16 |
#313131 |
#0F0F0F
|
Standard Retail Joy-Con Color |
Release |
Body HEX |
Button HEX
|
Gray / グレー |
2017.03.03 |
#828282 |
#0F0F0F
|
Neon Red / ネオンレッド |
2017.03.03 |
#FF3C28 |
#1E0A0A
|
Neon Blue / ネオンブルー |
2017.03.03 |
#0AB9E6 |
#001E1E
|
Neon Yellow / ネオンイエロー |
2017.06.16 |
#E6FF00 |
#142800
|
Neon Green / ネオングリーン |
2017.07.21 |
#1EDC00 |
#002800
|
Neon Pink / ネオンピンク |
2017.07.21 |
#FF3278 |
#28001E
|
Red / レッド |
2017.10.27 |
#E10F00 |
#280A0A
|
Blue / ブルー |
2019.10.04 |
#4655F5 |
#00000A
|
Neon Purple / ネオンパープル |
2019.10.04 |
#B400E6 |
#140014
|
Neon Orange / ネオンオレンジ |
2019.10.04 |
#FAA005 |
#0F0A00
|
White / ホワイト |
2021.10.08 |
#E6E6E6 |
#323232
|
Special Edition Joy-Con Color |
Release |
Body HEX |
Button HEX
|
Splatoon 2 Edition Neon-Green Left Joy-Con / スプラトゥーン2 |
2017.07.21 |
#1EDC00 |
#002800
|
Splatoon 2 Edition Neon-Pink Right Joy-Con / スプラトゥーン2 |
2017.07.21 |
#FF3278 |
#28001E
|
Super Mario Odyssey Edition Red Joy-Con / スーパーマリオ オデッセイ |
2017.10.27 |
#E10F00 |
#280A0A
|
Super Smash Bros. Ultimate Edition Gray Joy-Con / 大乱闘スマッシュブラザーズ |
2018.11.02 |
#828282 |
#0F0F0F
|
Pokemon: Let's Go! Eevee-Brown Left Joy-Con / ポケットモンスター Let's Go! イーブイ |
2018.11.16 |
#C88C32 |
#281900
|
Pokemon: Let's Go! Pikachu-Yellow Right Joy-Con / ポケットモンスター Let's Go! ピカチュウ |
2018.11.16 |
#FFDC00 |
#322800
|
*Nintendo Labo Creators Contest Edition "Cardboard"-Colored Joy-Con |
2018. (...?) |
#D7AA73 |
#1E1914
|
**Dragon Quest XI S Lotto Edition Royal-Blue Joy-Con / ドラゴン クエスト XI S (ロト版) |
2019.09.27 |
#1473FA |
#00000F
|
**Disney Tsum Tsum Festival Neon-Purple Left Joy-Con / ディズニー ツムツム フェスティバル |
2019.10.10 |
#B400E6 |
#140014
|
**Disney Tsum Tsum Festival Neon-Pink Right Joy-Con / ディズニー ツムツム フェスティバル |
2019.10.10 |
#FF3278 |
#28001E
|
Animal Crossing: New Horizons Pastel-Green Left Joy-Con / あつまれ どうぶつの森 |
2020.03.13 |
#82FF96 |
#0A1E0A
|
Animal Crossing: New Horizons Pastel-Blue Right Joy-Con / あつまれ どうぶつの森 |
2020.03.13 |
#96F5F5 |
#0A1E28
|
Fortnite Wildcat Edition Yellow Left Joy-Con / フォートナイト ワイルドキャット(山猫) |
2020.10.30 |
#FFCC00 |
#1A1100
|
Fortnite Wildcat Edition Dark-Blue Right Joy-Con / フォートナイト ワイルドキャット(山猫) |
2020.10.30 |
#0084FF |
#000F1E
|
Mario Red & Blue Edition Red Joy-Con / マリオ レッド × ブルー |
2021.02.12 |
#F04614 |
#1E1914
|
Monster Hunter Rise Edition Gray Joy-Con / モンスターハンターライズ |
2021.03.26 |
#818282 |
#0E0F0F
|
Fortnite Fleet Force Edition Dark-Blue Left Joy-Con / フォートナイト フリート フォース(力の艦隊) |
2021.06.04 |
#0084FF |
#000F1E
|
Fortnite Fleet Force Edition Yellow Right Joy-Con / フォートナイト フリート フォース(力の艦隊) |
2021.06.04 |
#FFCC00 |
#1A1100
|
Legend of Zelda: Skyward Sword Dark-Blue Left Joy-Con / ゼルダの伝説 スカイウォードソード |
2021.07.16 |
#2D50F0 |
#1E0F46
|
Legend of Zelda: Skyward Sword Dark-Purple Right Joy-Con / ゼルダの伝説 スカイウォードソード |
2021.07.16 |
#500FC8 |
#00051E
|
Nintendo Switch OLED Edition White Joy-Con / Nintendo Switch(有機ELモデル) ホワイト |
2021.10.08 |
#E6E6E6 |
#323232
|
Splatoon 3 OLED Edition Blue-Gradient Left Joy-Con / (有機ELモデル) スプラトゥーン3 |
2022.08.26 |
#4655F5 |
#00000A
|
Splatoon 3 OLED Edition Neon-Yellow-Gradient Right Joy-Con / (有機ELモデル) スプラトゥーン3 |
2022.08.26 |
#E6FF00 |
#142800
|
// *(Prize Awarded for Labo Contest - No Retail) // **(Available Japan Only)
|
Additional Links
Reverse Engineering of the Joy-Con by Github user dekuNukem