Line 1: |
Line 1: |
− | 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. | + | Joy-Con is the name for the Switch's primary game controllers. The Joy-Con are internally called Sakyo (Left) and Ukyo (Right). |
| | | |
− | == Hardware == | + | = Hardware = |
− | The controllers themselves are simple to disassemble and identify.
| + | == Sakyo == |
− | [[File:JoyconFront.jpg|400px|thumb|The front of the Joy-Con internal[https://www.ifixit.com/Teardown/Nintendo+Switch+Teardown/78263]]]
| |
− | [[File:JoyconRear.jpg|400px|thumb|The rear of the Joy-Con internal[https://www.ifixit.com/Teardown/Nintendo+Switch+Teardown/78263]]]
| |
| {| class="wikitable" | | {| class="wikitable" |
− | ! Color || Item | + | ! Component || Description |
| |- | | |- |
− | | Red || Broadcom BCM20734 Bluetooth 4.1/2.4 GHz Transceiver | + | | SoC || Broadcom BCM20734 |
| |- | | |- |
− | | Orange || STMicroelectronics NFCBEA 812006 33 (Likely NFC reader IC) | + | | IMU || STMicroelectronics LSM6DS3H |
| |- | | |- |
− | | Yellow|| Macronix International MX25U4033E 4 Mb CMOS Flash | + | | PMIC || Texas Instruments BQ24072 |
| + | |- |
| + | | Storage || Macronix International MX25U4033E 4 Mb CMOS Flash |
| + | |} |
| + | |
| + | == Ukyo == |
| + | {| class="wikitable" |
| + | ! Component || Description |
| + | |- |
| + | | SoC || Broadcom BCM20734 |
| + | |- |
| + | | MCU || STMicroelectronics STM32P411 |
| + | |- |
| + | | NFC || STMicroelectronics ST21NFCB |
| + | |- |
| + | | IMU || STMicroelectronics LSM6DS3H |
| + | |- |
| + | | PMIC || Texas Instruments BQ24072 |
| + | |- |
| + | | Storage || Macronix International MX25U4033E 4 Mb CMOS Flash |
| + | |} |
| + | |
| + | = Protocol = |
| + | The Joy-Con can communicate wirelessly over Bluetooth or through the rails over UART. The latter uses a Nintendo proprietary protocol called "Nwcp". |
| + | |
| + | == NwcpPacket == |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x5 |
| + | | [[#HciHeader|HciHeader]] |
| + | |- |
| + | | 0x5 |
| + | | 0x7 |
| + | | [[#NwcpHeader|NwcpHeader]] |
| + | |- |
| + | | 0xC |
| + | | Variable |
| + | | Data |
| + | |} |
| + | |
| + | === HciHeader === |
| + | This is a 5-byte packet header used by Broadcom's HCI Control Protocol. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | PacketType (always 0x19) |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | [[#CommandCode|CommandCode]] |
| + | |- |
| + | | 0x2 |
| + | | 0x1 |
| + | | GroupCode (always 0x03) |
| + | |- |
| + | | 0x3 |
| + | | 0x2 |
| + | | PacketLength |
| + | |} |
| + | |
| + | ==== CommandCode ==== |
| + | {| class="wikitable" border="1" |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0x1 || SendToDevice |
| + | |- |
| + | | 0x81 || ReceiveFromDevice |
| + | |} |
| + | |
| + | === NwcpHeader === |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#CommandType|CommandType]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | [[#DeviceCommand|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 ==== |
| + | {| class="wikitable" border="1" |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0x43 || ReportOut |
| + | |- |
| + | | 0x53 || ReportIn |
| + | |- |
| + | | 0x91 || DeviceCommandIn |
| + | |- |
| + | | 0x92 || Hid |
| + | |- |
| + | | 0x93 || |
| + | |- |
| + | | 0x94 || DeviceCommandOut |
| + | |- |
| + | | 0x95 || |
| + | |- |
| + | | 0x9A || Fifty |
| + | |- |
| + | | 0xA3 || ReportComplete |
| + | |- |
| + | | 0xA5 || Handshake |
| + | |} |
| + | |
| + | == HidCommandInputReport == |
| + | This is a 0x31-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | LatencyTimer |
| + | |- |
| + | | 0x2 |
| + | | 0x1 |
| + | | PowerInfo |
| + | |- |
| + | | 0x3 |
| + | | 0x1 |
| + | | RightPadButtonStatus |
| + | |- |
| + | | 0x4 |
| + | | 0x1 |
| + | | SharedButtonStatus |
| + | |- |
| + | | 0x5 |
| + | | 0x1 |
| + | | LeftPadButtonStatus |
| + | |- |
| + | | 0x6 |
| + | | 0x3 |
| + | | LeftAnalogStickData |
| + | |- |
| + | | 0x9 |
| + | | 0x3 |
| + | | RightAnalogStickData |
| + | |- |
| + | | 0xC |
| + | | 0x1 |
| + | | MotorStatus |
| + | |- |
| + | | 0xD |
| + | | 0x1 |
| + | | CommandAck |
| + | |- |
| + | | 0xE |
| + | | 0x1 |
| + | | [[#HidCommand|CommandId]] |
| + | |- |
| + | | 0xF |
| + | | 0x22 |
| + | | CommandReply |
| + | |} |
| + | |
| + | == HidMcuUpdateInputReport == |
| + | This is a 0x30-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | LatencyTimer |
| + | |- |
| + | | 0x2 |
| + | | 0x1 |
| + | | PowerInfo |
| + | |- |
| + | | 0x3 |
| + | | 0x1 |
| + | | RightPadButtonStatus |
| + | |- |
| + | | 0x4 |
| + | | 0x1 |
| + | | SharedButtonStatus |
| + | |- |
| + | | 0x5 |
| + | | 0x1 |
| + | | LeftPadButtonStatus |
| + | |- |
| + | | 0x6 |
| + | | 0x3 |
| + | | LeftAnalogStickData |
| + | |- |
| + | | 0x9 |
| + | | 0x3 |
| + | | RightAnalogStickData |
| + | |- |
| + | | 0xC |
| + | | 0x1 |
| + | | MotorStatus |
| + | |- |
| + | | 0xD |
| + | | 0x23 |
| + | | McuUpdateData |
| + | |} |
| + | |
| + | == HidBasicInputReport == |
| + | This is a 0x31-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | LatencyTimer |
| + | |- |
| + | | 0x2 |
| + | | 0x1 |
| + | | PowerInfo |
| + | |- |
| + | | 0x3 |
| + | | 0x1 |
| + | | RightPadButtonStatus |
| + | |- |
| + | | 0x4 |
| + | | 0x1 |
| + | | SharedButtonStatus |
| + | |- |
| + | | 0x5 |
| + | | 0x1 |
| + | | LeftPadButtonStatus |
| + | |- |
| + | | 0x6 |
| + | | 0x3 |
| + | | LeftAnalogStickData |
| + | |- |
| + | | 0x9 |
| + | | 0x3 |
| + | | RightAnalogStickData |
| + | |- |
| + | | 0xC |
| + | | 0x1 |
| + | | MotorStatus |
| + | |- |
| + | | 0xD |
| + | | 0x24 |
| + | | BasicData |
| + | |} |
| + | |
| + | == HidMcuInputReport == |
| + | This is a 0x16A-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | LatencyTimer |
| + | |- |
| + | | 0x2 |
| + | | 0x1 |
| + | | PowerInfo |
| + | |- |
| + | | 0x3 |
| + | | 0x1 |
| + | | RightPadButtonStatus |
| + | |- |
| + | | 0x4 |
| + | | 0x1 |
| + | | SharedButtonStatus |
| + | |- |
| + | | 0x5 |
| + | | 0x1 |
| + | | LeftPadButtonStatus |
| + | |- |
| + | | 0x6 |
| + | | 0x3 |
| + | | LeftAnalogStickData |
| + | |- |
| + | | 0x9 |
| + | | 0x3 |
| + | | RightAnalogStickData |
| + | |- |
| + | | 0xC |
| + | | 0x1 |
| + | | MotorStatus |
| + | |- |
| + | | 0xD |
| + | | 0x6 |
| + | | SensorAccelSample0 |
| + | |- |
| + | | 0x13 |
| + | | 0x6 |
| + | | SensorGyroSample0 |
| + | |- |
| + | | 0x19 |
| + | | 0x6 |
| + | | SensorAccelSample1 |
| + | |- |
| + | | 0x1F |
| + | | 0x6 |
| + | | SensorGyroSample1 |
| + | |- |
| + | | 0x25 |
| + | | 0x6 |
| + | | SensorAccelSample2 |
| + | |- |
| + | | 0x2B |
| + | | 0x6 |
| + | | SensorGyroSample2 |
| + | |- |
| + | | 0x31 |
| + | | 0x139 |
| + | | McuData |
| + | |} |
| + | |
| + | == HidAttachmentInputReport == |
| + | This is a 0x16A-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | LatencyTimer |
| + | |- |
| + | | 0x2 |
| + | | 0x1 |
| + | | PowerInfo |
| + | |- |
| + | | 0x3 |
| + | | 0x1 |
| + | | RightPadButtonStatus |
| + | |- |
| + | | 0x4 |
| + | | 0x1 |
| + | | SharedButtonStatus |
| + | |- |
| + | | 0x5 |
| + | | 0x1 |
| + | | LeftPadButtonStatus |
| + | |- |
| + | | 0x6 |
| + | | 0x3 |
| + | | LeftAnalogStickData |
| + | |- |
| + | | 0x9 |
| + | | 0x3 |
| + | | RightAnalogStickData |
| + | |- |
| + | | 0xC |
| + | | 0x1 |
| + | | MotorStatus |
| + | |- |
| + | | 0xD |
| + | | 0x6 |
| + | | SensorAccelSample0 |
| + | |- |
| + | | 0x13 |
| + | | 0x6 |
| + | | SensorGyroSample0 |
| + | |- |
| + | | 0x19 |
| + | | 0x6 |
| + | | SensorAccelSample1 |
| + | |- |
| + | | 0x1F |
| + | | 0x6 |
| + | | SensorGyroSample1 |
| + | |- |
| + | | 0x25 |
| + | | 0x6 |
| + | | SensorAccelSample2 |
| + | |- |
| + | | 0x2B |
| + | | 0x6 |
| + | | SensorGyroSample2 |
| + | |- |
| + | | 0x31 |
| + | | 0x139 |
| + | | AttachmentData |
| + | |} |
| + | |
| + | == HidGenericInputReport == |
| + | This is a 0xC-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x2 |
| + | | ButtonStatus |
| + | |- |
| + | | 0x3 |
| + | | 0x1 |
| + | | StickHatData |
| + | |- |
| + | | 0x4 |
| + | | 0x4 |
| + | | LeftAnalogStickData |
| + | |- |
| + | | 0x8 |
| + | | 0x4 |
| + | | RightAnalogStickData |
| + | |} |
| + | |
| + | == HidCommandOutputReport == |
| + | This is a 0x31-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | PacketNumber |
| + | |- |
| + | | 0x2 |
| + | | 0x8 |
| + | | [[#HidMotorData|MotorData]] |
| + | |- |
| + | | 0xA |
| + | | 0x1 |
| + | | [[#HidCommand|CommandId]] |
| + | |- |
| + | | 0xB |
| + | | 0x26 |
| + | | CommandData |
| + | |} |
| + | |
| + | == HidMcuUpdateOutputReport == |
| + | This is a 0x13E-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | PacketNumber |
| + | |- |
| + | | 0x2 |
| + | | 0x8 |
| + | | [[#HidMotorData|MotorData]] |
| + | |- |
| + | | 0xA |
| + | | 0x134 |
| + | | McuUpdateData |
| + | |} |
| + | |
| + | == HidBasicOutputReport == |
| + | This is a 0xA-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | PacketNumber |
| + | |- |
| + | | 0x2 |
| + | | 0x8 |
| + | | [[#HidMotorData|MotorData]] |
| + | |} |
| + | |
| + | == HidMcuOutputReport == |
| + | This is a 0x30-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | PacketNumber |
| + | |- |
| + | | 0x2 |
| + | | 0x8 |
| + | | [[#HidMotorData|MotorData]] |
| + | |- |
| + | | 0xA |
| + | | 0x26 |
| + | | McuData |
| + | |} |
| + | |
| + | == HidAttachmentOutputReport == |
| + | This is a 0x30-byte struct. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x1 |
| + | | [[#HidReportId|ReportId]] |
| + | |- |
| + | | 0x1 |
| + | | 0x1 |
| + | | PacketNumber |
| + | |- |
| + | | 0x2 |
| + | | 0x8 |
| + | | [[#HidMotorData|MotorData]] |
| + | |- |
| + | | 0xA |
| + | | 0x26 |
| + | | AttachmentData |
| |} | | |} |
| | | |
− | == Firmware == | + | == HidReportId == |
− | ''See also: [[Joy-Con Firmware]]''
| + | {| class="wikitable" border="1" |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0x01 || CommandOutputReport |
| + | |- |
| + | | 0x03 || McuUpdateOutputReport |
| + | |- |
| + | | 0x10 || BasicOutputReport |
| + | |- |
| + | | 0x11 || McuOutputReport |
| + | |- |
| + | | 0x12 || AttachmentOutputReport |
| + | |- |
| + | | 0x21 || CommandInputReport |
| + | |- |
| + | | 0x23 || McuUpdateInputReport |
| + | |- |
| + | | 0x30 || BasicInputReport |
| + | |- |
| + | | 0x31 || McuInputReport |
| + | |- |
| + | | 0x32 || AttachmentInputReport |
| + | |- |
| + | | 0x33 || |
| + | |- |
| + | | 0x3F || GenericInputReport |
| + | |- |
| + | | 0x70 || OtaEnableFwuReport |
| + | |- |
| + | | 0x71 || OtaSetupReadReport |
| + | |- |
| + | | 0x72 || OtaReadReport |
| + | |- |
| + | | 0x73 || OtaWriteReport |
| + | |- |
| + | | 0x74 || OtaEraseReport |
| + | |- |
| + | | 0x75 || OtaLaunchReport |
| + | |- |
| + | | 0x80 || ExtGripOutputReport |
| + | |- |
| + | | 0x81 || ExtGripInputReport |
| + | |- |
| + | | 0x82 || |
| + | |} |
| + | |
| + | == HidMotorData == |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x4 || [[#VibrationAmFmPackTag|JoyLeftVibrationAmFmPackTag]] |
| + | |- |
| + | | 0x4 || 0x8 || [[#VibrationAmFmPackTag|JoyRightVibrationAmFmPackTag]] |
| + | |} |
| | | |
− | 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.
| + | == VibrationAmFmPackTag == |
− | {| class="wikitable" | + | This is "nn::xcd::VibrationAmFmPackTag". This is a BitPack object. |
− | ! Controller || 1.0.0 | + | |
| + | === VibrationAmFmPackFormatZero === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0-29 || Reserved |
| + | |- |
| + | | 30-31 || PackFormat (must be 0) |
| + | |} |
| + | |
| + | === VibrationAmFmPackFormatOne === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0-19 || Reserved |
| + | |- |
| + | | 20-24 || ChannelCodesHigh |
| + | |- |
| + | | 25-29 || ChannelCodesLow |
| + | |- |
| + | | 30-31 || PackFormat (must be 1) |
| + | |} |
| + | |
| + | === VibrationAmFmPackFormatOne28bit === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0-1 || Reserved |
| + | |- |
| + | | 2-8 || ChannelFrequencyHigh |
| + | |- |
| + | | 9-15 || ChannelAmplitudeHigh |
| + | |- |
| + | | 16-22 || ChannelFrequencyLow |
| + | |- |
| + | | 23-29 || ChannelAmplitudeLow |
| + | |- |
| + | | 30-31 || PackFormat (must be 1) |
| + | |} |
| + | |
| + | === VibrationAmFmPackFormatTwo === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0-9 || Reserved |
| + | |- |
| + | | 10-14 || VibrationCodesHigh |
| + | |- |
| + | | 15-19 || VibrationCodesLow |
| + | |- |
| + | | 20-24 || ChannelCodesHigh |
| + | |- |
| + | | 25-29 || ChannelCodesLow |
| + | |- |
| + | | 30-31 || PackFormat (must be 2) |
| + | |} |
| + | |
| + | === VibrationAmFmPackFormatTwo14bitLow === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0 || IsChannelHigh (must be 0) |
| + | |- |
| + | | 1-7 || ChannelFrequency |
| + | |- |
| + | | 8-12 || VibrationCodesHigh1 |
| + | |- |
| + | | 13-17 || VibrationCodesLow1 |
| + | |- |
| + | | 18-22 || VibrationCodesHigh0 |
| + | |- |
| + | | 23-29 || ChannelAmplitude |
| + | |- |
| + | | 30-31 || PackFormat (must be 2) |
| + | |} |
| + | |
| + | === VibrationAmFmPackFormatTwo14bitHigh === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0 || IsChannelHigh (must be 1) |
| + | |- |
| + | | 1-7 || ChannelFrequency |
| + | |- |
| + | | 8-12 || VibrationCodesHigh1 |
| + | |- |
| + | | 13-17 || VibrationCodesLow1 |
| + | |- |
| + | | 18-22 || VibrationCodesLow0 |
| + | |- |
| + | | 23-29 || ChannelAmplitude |
| + | |- |
| + | | 30-31 || PackFormat (must be 2) |
| + | |} |
| + | |
| + | === VibrationAmFmPackFormatThree === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0-4 || VibrationCodesHigh1 |
| + | |- |
| + | | 5-9 || VibrationCodesLow1 |
| + | |- |
| + | | 10-14 || VibrationCodesHigh0 |
| + | |- |
| + | | 15-19 || VibrationCodesLow0 |
| + | |- |
| + | | 20-24 || ChannelCodesHigh |
| + | |- |
| + | | 25-29 || ChannelCodesLow |
| + | |- |
| + | | 30-31 || PackFormat (must be 3) |
| + | |} |
| + | |
| + | === VibrationAmFmPackFormatThree7bit === |
| + | {| class="wikitable" border="1" |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0 || IsChannelHigh |
| + | |- |
| + | | 1 || IsThree7bit (must be 1) |
| + | |- |
| + | | 2 || IsFm |
| + | |- |
| + | | 3-7 || VibrationCodesHigh1 |
| + | |- |
| + | | 8-12 || VibrationCodesLow1 |
| + | |- |
| + | | 13-17 || VibrationCodesHigh0 |
| + | |- |
| + | | 18-22 || VibrationCodesLow0 |
| + | |- |
| + | | 23-29 || ChannelAmFm |
| + | |- |
| + | | 30-31 || PackFormat (must be 1, instead of 3) |
| + | |} |
| + | |
| + | == AmFmCodes == |
| + | These are 32-bit values used by the Joy-Con firmware to represent combinations of amplitude/frequency pairs for vibration. |
| + | |
| + | === Unpacking === |
| + | The Joy-Con firmware receives vibration data packed as [[#VibrationAmFmPackTag|VibrationAmFmPackTag]] from output reports. Depending on the packing format, these tags are then converted to an array of AmFmCodes as follows. |
| + | |
| + | ==== AmFm5BitCodes ==== |
| + | Converted from [[#VibrationAmFmPackFormatOne|VibrationAmFmPackFormatOne]], [[#VibrationAmFmPackFormatTwo|VibrationAmFmPackFormatTwo]] or [[#VibrationAmFmPackFormatThree|VibrationAmFmPackFormatThree]]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x4 || <nowiki>(ChannelCodesLow & 0x1F)</nowiki> |
| + | |- |
| + | | 0x4 || 0x4 || <nowiki>(ChannelCodesHigh & 0x1F)</nowiki> |
| + | |- |
| + | | 0x8 || 0x4 || <nowiki>(VibrationCodesLow0 & 0x1F)</nowiki> |
| + | |- |
| + | | 0xC || 0x4 || <nowiki>(VibrationCodesHigh0 & 0x1F)</nowiki> |
| + | |- |
| + | | 0x10 || 0x4 || <nowiki>(VibrationCodesLow1 & 0x1F)</nowiki> |
| + | |- |
| + | | 0x14 || 0x4 || <nowiki>(VibrationCodesHigh1 & 0x1F)</nowiki> |
| + | |} |
| + | |
| + | ==== AmFm7BitOneCodes ==== |
| + | Converted from [[#VibrationAmFmPackFormatOne28bit|VibrationAmFmPackFormatOne28bit]]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x4 || <nowiki>(((ChannelFrequencyLow & 0x7F) << 8) | (ChannelAmplitudeLow & 0x7F) | 0x8080)</nowiki> |
| + | |- |
| + | | 0x4 || 0x4 || <nowiki>(((ChannelFrequencyHigh & 0x7F) << 8) | (ChannelAmplitudeHigh & 0x7F) | 0x8080)</nowiki> |
| + | |} |
| + | |
| + | ==== AmFm7BitTwoCodes ==== |
| + | Converted from [[#VibrationAmFmPackFormatTwo14bitLow|VibrationAmFmPackFormatTwo14bitLow]] or [[#VibrationAmFmPackFormatTwo14bitHigh|VibrationAmFmPackFormatTwo14bitHigh]]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x4 || <nowiki>IsChannelHigh ? (VibrationCodesLow0 & 0x1F) : (((ChannelFrequency & 0x7F) << 8) | (ChannelAmplitude & 0x7F) | 0x8080)</nowiki> |
| + | |- |
| + | | 0x4 || 0x4 || <nowiki>IsChannelHigh ? (((ChannelFrequency & 0x7F) << 8) | (ChannelAmplitude & 0x7F) | 0x8080) : (VibrationCodesHigh0 & 0x1F)</nowiki> |
| + | |- |
| + | | 0x8 || 0x4 || <nowiki>(VibrationCodesLow1 & 0x1F)</nowiki> |
| + | |- |
| + | | 0xC || 0x4 || <nowiki>(VibrationCodesHigh1 & 0x1F)</nowiki> |
| + | |- |
| + | | 0x10 || 0x4 || <nowiki>Always 0x18</nowiki> |
| + | |- |
| + | | 0x14 || 0x4 || <nowiki>Always 0x18</nowiki> |
| + | |} |
| + | |
| + | ==== AmFm7BitThreeCodes ==== |
| + | Converted from [[#VibrationAmFmPackFormatThree7bit|VibrationAmFmPackFormatThree7bit]]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x4 || <nowiki>IsChannelHigh ? 0x18 : (IsFm ? (((ChannelAmFm & 0x7F) << 8) | 0x8000) : ((ChannelAmFm & 0x7F) | 0x80))</nowiki> |
| + | |- |
| + | | 0x4 || 0x4 || <nowiki>IsChannelHigh ? (IsFm ? (((ChannelAmFm & 0x7F) << 8) | 0x8000) : ((ChannelAmFm & 0x7F) | 0x80)) : 0x18</nowiki> |
| + | |- |
| + | | 0x8 || 0x4 || <nowiki>(VibrationCodesLow0 & 0x1F)</nowiki> |
| + | |- |
| + | | 0xC || 0x4 || <nowiki>(VibrationCodesHigh0 & 0x1F)</nowiki> |
| |- | | |- |
− | | Joy-Con Left (Blue) || [[:File:pad.L.bin|flash dump]] | + | | 0x10 || 0x4 || <nowiki>(VibrationCodesLow1 & 0x1F)</nowiki> |
| |- | | |- |
− | | Joy-Con Right (Red) || [[:File:pad.R.bin|flash dump]] | + | | 0x14 || 0x4 || <nowiki>(VibrationCodesHigh1 & 0x1F)</nowiki> |
| |} | | |} |
− | The flash is in a patch-ram format. Tools for dealing with it are available [https://github.com/shuffle2/nxpad].
| |
− | A dump of the ROM region (taken while firmware was running) can be found [[:File:bcm20734_rom.bin|here]]. Note this is the same SoC used on the other controller models, as well.
| |
| | | |
− | == Bluetooth HID == | + | == DeviceCommand == |
− | === Commands ===
| |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0x01 || Inquiry |
| |- | | |- |
− | ! Command || Name
| + | | 0x02 || WriteChargerSettings |
| |- | | |- |
− | | 0x00 || | + | | 0x03 || ReadChargerSettings |
| + | |- |
| + | | 0x04 || AttachmentEnable |
| + | |- |
| + | | 0x05 || IsAttachmentEnabled |
| + | |- |
| + | | 0x06 || GetBatteryVoltage |
| + | |- |
| + | | 0x07 || ReadWakeUpReason |
| + | |- |
| + | | 0x10 || CreateHidConnection |
| + | |- |
| + | | 0x11 || DisconnectHid |
| + | |- |
| + | | 0x12 || SetHidInterval |
| + | |- |
| + | | 0x13 || GetHidInterval |
| + | |- |
| + | | 0x18 || Pairing |
| + | |- |
| + | | 0x20 || UpdateUartBaudRate |
| + | |- |
| + | | 0x40 || Test |
| + | |} |
| + | |
| + | == HidCommand == |
| + | {| class="wikitable" border="1" |
| + | ! Value |
| + | ! Description |
| |- | | |- |
| | 0x01 || PairingOut | | | 0x01 || PairingOut |
Line 64: |
Line 974: |
| |- | | |- |
| | 0x22 || McuResume | | | 0x22 || McuResume |
− | |-
| |
− | | 0x23 ||
| |
| |- | | |- |
| | 0x24 || McuPollingEnable | | | 0x24 || McuPollingEnable |
Line 73: |
Line 981: |
| | 0x28 || AttachmentWrite | | | 0x28 || AttachmentWrite |
| |- | | |- |
− | | 0x29 || | + | | 0x29 || AttachmentRead |
| |- | | |- |
| | 0x2A || AttachmentEnable | | | 0x2A || AttachmentEnable |
| |- | | |- |
− | | 0x2B || | + | | 0x2B || GetAttachmentInfo |
| |- | | |- |
| | 0x30 || SetIndicatorLed | | | 0x30 || SetIndicatorLed |
Line 99: |
Line 1,007: |
| | 0x51 || WriteChargeSetting | | | 0x51 || WriteChargeSetting |
| |- | | |- |
− | | 0x52 || | + | | 0x52 || ReadChargeSetting |
| |- | | |- |
| | 0x58 || ExtDevWrite | | | 0x58 || ExtDevWrite |
Line 110: |
Line 1,018: |
| |- | | |- |
| | 0x5C || ExtDevInFormatConfig | | | 0x5C || ExtDevInFormatConfig |
| + | |- |
| + | | 0x5D || |
| |- | | |- |
| | 0x60 || InternalAttachmentWrite | | | 0x60 || InternalAttachmentWrite |
Line 120: |
Line 1,030: |
| |- | | |- |
| | 0x64 || InternalAttachmentPollingDisable | | | 0x64 || InternalAttachmentPollingDisable |
| + | |- |
| + | | 0x7A || AddButtonPlayData |
| + | |- |
| + | | 0x7B || StartStopButtonPlayData |
| |- | | |- |
| | 0x80 || Ack | | | 0x80 || Ack |
Line 134: |
Line 1,048: |
| |- | | |- |
| | 0xA8 || AttachmentData | | | 0xA8 || AttachmentData |
| + | |- |
| + | | 0xA9 || AttachmentInfo |
| |- | | |- |
| | 0xAA || InternalAttachmentRead | | | 0xAA || InternalAttachmentRead |
Line 148: |
Line 1,064: |
| |} | | |} |
| | | |
− | === Left & Right Separate Joy-con === | + | == ExtGripCommand == |
− | 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.
| + | {| class="wikitable" border="1" |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0x01 || Inquiry |
| + | |- |
| + | | 0x02 || CreateHidConnection |
| + | |- |
| + | | 0x03 || DeleteHidConnection |
| + | |- |
| + | | 0x04 || StartHidData |
| + | |- |
| + | | 0x05 || StopHidData |
| + | |- |
| + | | 0x06 || |
| + | |- |
| + | | 0x07 || GetFirmwareVersion |
| + | |- |
| + | | 0x08 || |
| + | |- |
| + | | 0x91 || LoopbackTest |
| + | |- |
| + | | 0x92 || |
| + | |- |
| + | | 0xA0 || SetUartClockTrim |
| + | |} |
| + | |
| + | = Firmware = |
| + | The firmware is stored inside the flash in Broadcom's PatchRAM format as follows: |
| | | |
− | HID Input Report Descriptor (Hexadecimal):
| + | {| class="wikitable" border="1" |
− | <pre>
| + | |- |
− | 00000000: 05010905 A1010601 FF852109 21750895 ....¡...ÿ…!.!u.•
| + | ! Offset |
− | 00000010: 30810285 30093075 08953081 02853109 0..…0.0u.•0..…1.
| + | ! Size |
− | 00000020: 31750896 69018102 85320932 75089669 1u.–i...…2.2u.–i
| + | ! Description |
− | 00000030: 01810285 33093375 08966901 8102853F ...…3.3u.–i...…?
| + | |- |
− | 00000040: 05091901 29101500 25017501 95108102 ....)...%.u.•...
| + | | 0x0 || 0x1000 || StaticSection |
− | 00000050: 05010939 15002507 75049501 81420509 ...9..%.u.•..B..
| + | |- |
− | 00000060: 75049501 81010501 09300931 09330934 u.•......0.1.3.4
| + | | 0x1000 || 0x1000 || [[#FailsafeSection|FailsafeSection]] |
− | 00000070: 16000027 FFFF0000 75109504 81020601 ...'ÿÿ..u.•.....
| + | |- |
− | 00000080: FF850109 01750895 30910285 10091075 ÿ…...u.•0‘.…...u
| + | | 0x2000 || 0x1000 || [[#VolatileSection|VolatileSection]] |
− | 00000090: 08953091 02851109 11750895 30910285 .•0‘.…...u.•0‘.…
| + | |- |
− | 000000A0: 12091275 08953091 02C0 ...u.•0‘.À
| + | | 0x3000 || 0x1000 || VolatileSectionBackup1 |
− | </pre>
| + | |- |
| + | | 0x4000 || 0x1000 || VolatileSectionBackup2 |
| + | |- |
| + | | 0x5000 || 0x1000 || [[#ShipmentInfo|ShipmentInfo]] |
| + | |- |
| + | | 0x6000 || 0x1000 || [[#FactoryConfiguration|FactoryConfiguration]] |
| + | |- |
| + | | 0x7000 || 0x1000 || Reserved |
| + | |- |
| + | | 0x8000 || 0x1000 || [[#UserCalibration|UserCalibration]] |
| + | |- |
| + | | 0x9000 || 0x7000 || Reserved |
| + | |- |
| + | | 0x10000 || 0x18000 || DynamicSection1 |
| + | |- |
| + | | 0x28000 || 0x18000 || DynamicSection2 |
| + | |- |
| + | | 0x40000 || 0x40000 || Reserved |
| + | |} |
| | | |
− | {| class="wikitable" | + | == FailsafeSection == |
− | ! Parsed Bytes || Description | + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0xFF4 || Reserved |
| + | |- |
| + | | 0xFF4 || 0x8 || Signature |
| + | |- |
| + | | 0xFFC || 0x4 || Ds2Offset |
| + | |} |
| + | |
| + | == VolatileSection == |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x26 || |
| + | |- |
| + | | 0x26 || 0xFDA || Reserved |
| + | |} |
| + | |
| + | == ShipmentInfo == |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x1 || Shipment |
| + | |- |
| + | | 0x1 || 0xFFF || Reserved |
| + | |} |
| + | |
| + | == FactoryConfiguration == |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x10 || IdentificationCode |
| + | |- |
| + | | 0x10 || 0x2 || Reserved |
| + | |- |
| + | | 0x12 || 0x1 || [[#DeviceType|DeviceType]] |
| + | |- |
| + | | 0x13 || 0x1 || BoardRevision |
| + | |- |
| + | | 0x14 || 0x7 || Reserved |
| + | |- |
| + | | 0x1B || 0x1 || FormatVersion |
| + | |- |
| + | | 0x1C || 0x4 || Reserved |
| + | |- |
| + | | 0x20 || 0x18 || [[#Cal1|Cal1]] |
| + | |- |
| + | | 0x38 || 0x5 || Reserved |
| + | |- |
| + | | 0x3D || 0x12 || [[#Cal2|Cal2]] |
| + | |- |
| + | | 0x4F || 0x1 || Reserved |
| + | |- |
| + | | 0x50 || 0xD || [[#Design|Design]] |
| + | |- |
| + | | 0x5D || 0x23 || Reserved |
| + | |- |
| + | | 0x80 || 0x18 || [[#Model1|Model1]] |
| + | |- |
| + | | 0x98 || 0x12 || [[#Model2|Model2]] |
| + | |- |
| + | | 0xAA || 0x1 || Reserved |
| + | |- |
| + | | 0xAB || 0x1 || AccelerometerAxisAssignment |
| + | |- |
| + | | 0xAC || 0x1 || GyroscopeAxisAssignment |
| + | |- |
| + | | 0xAD || 0x1 || AnalogStickMainAxisAssignment |
| + | |- |
| + | | 0xAE || 0x1 || AnalogStickSubAxisAssignment |
| + | |- |
| + | | 0xAF || 0x151 || Reserved |
| + | |- |
| + | | 0x200 || 0x2 || BatteryVoltage |
| + | |- |
| + | | 0x202 || 0xB7E || Reserved |
| + | |- |
| + | | 0xD80 || 0x2 || TarragonVid |
| + | |- |
| + | | 0xD82 || 0x2 || TarragonPid |
| + | |- |
| + | | 0xD84 || 0x7C || Reserved |
| + | |- |
| + | | 0xE00 || 0x100 || InspectionLog |
| + | |- |
| + | | 0xF00 || 0x100 || Reserved |
| + | |} |
| + | |
| + | === DeviceType === |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0x01 || JoyConLeft |
| + | |- |
| + | | 0x02 || JoyConRight |
| + | |- |
| + | | 0x03 || SwitchProController |
| + | |- |
| + | | 0x04 || MiyabiLeft |
| + | |- |
| + | | 0x05 || MiyabiRight |
| + | |- |
| + | | 0x06 || Tarragon |
| + | |- |
| + | | 0x07 || LarkH1 |
| + | |- |
| + | | 0x08 || LarkH2 |
| + | |- |
| + | | 0x09 || LarkNL |
| + | |- |
| + | | 0x0A || LarkNR |
| + | |- |
| + | | 0x0B || Lucia |
| + | |- |
| + | | 0x0C || [12.0.0+] Lagon |
| + | |- |
| + | | 0x0D || [13.0.0+] Lager |
| + | |- |
| + | | 0x0E || [14.0.0+] Tarragon2 |
| + | |- |
| + | | 0x21 || FiftyL |
| |- | | |- |
− | |0x05, 0x01, || Usage Page (Generic Desktop Ctrls) | + | | 0x22 || FiftyR |
| + | |} |
| + | |
| + | === Cal1 === |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x09, 0x05, || Usage (Game Pad)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0xA1, 0x01, || Collection (Application) | + | | 0x0 || 0x18 || [[#SixAxisSensorCalibrationValue|SixAxisSensorCalibrationValue]] |
| + | |} |
| + | |
| + | ==== SixAxisSensorCalibrationValue ==== |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x06, 0x01, 0xFF, || Usage Page (Vendor Defined 0xFF01)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x85, 0x21, || Report ID (33) | + | | 0x0 || 0x2 || Accelerometer0OffsetX |
| |- | | |- |
− | |0x09, 0x21, || Usage (0x21) | + | | 0x2 || 0x2 || Accelerometer0OffsetY |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8) | + | | 0x4 || 0x2 || Accelerometer0OffsetZ |
| |- | | |- |
− | |0x95, 0x30, || Report Count (48) | + | | 0x6 || 0x2 || Accelerometer1gScaleX |
| |- | | |- |
− | |0x81, 0x02, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0x8 || 0x2 || Accelerometer1gScaleY |
| |- | | |- |
− | |0x85, 0x30, || Report ID (48) | + | | 0xA || 0x2 || Accelerometer1gScaleZ |
| |- | | |- |
− | |0x09, 0x30, || Usage (0x30) | + | | 0xC || 0x2 || Gyroscope0OffsetX |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8) | + | | 0xE || 0x2 || Gyroscope0OffsetY |
| |- | | |- |
− | |0x95, 0x30, || Report Count (48) | + | | 0x10 || 0x2 || Gyroscope0OffsetZ |
| |- | | |- |
− | |0x81, 0x02, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0x12 || 0x2 || Gyroscope78rpmScaleX |
| |- | | |- |
− | |0x85, 0x31, || Report ID (49) | + | | 0x14 || 0x2 || Gyroscope78rpmScaleY |
| |- | | |- |
− | |0x09, 0x31, || Usage (0x31) | + | | 0x16 || 0x2 || Gyroscope78rpmScaleZ |
| + | |} |
| + | |
| + | === Cal2 === |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x96, 0x69, 0x01, || Report Count (361) | + | | 0x0 || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickMainCalibrationValue]] |
| |- | | |- |
− | |0x81, 0x02, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0x9 || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickSubCalibrationValue]] |
| + | |} |
| + | |
| + | ==== AnalogStickCalibrationValue ==== |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x85, 0x32, || Report ID (50)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x09, 0x32, || Usage (0x32) | + | | 0x0 || 0x1 || AnalogStickCalXPositive |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8) | + | | 0x1 || 0x2 || AnalogStickCalYPositive |
| |- | | |- |
− | |0x96, 0x69, 0x01, || Report Count (361) | + | | 0x3 || 0x1 || AnalogStickCalX0 |
| |- | | |- |
− | |0x81, 0x02, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0x4 || 0x2 || AnalogStickCalY0 |
| |- | | |- |
− | |0x85, 0x33, || Report ID (51) | + | | 0x6 || 0x1 || AnalogStickCalXNegative |
| |- | | |- |
− | |0x09, 0x33, || Usage (0x33) | + | | 0x7 || 0x2 || AnalogStickCalYNegative |
| + | |} |
| + | |
| + | === Design === |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x96, 0x69, 0x01, || Report Count (361) | + | | 0x0 || 0xC || [[#ControllerColor|ControllerColor]] |
| |- | | |- |
− | |0x81, 0x02, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0xC || 0x1 || [[#DesignVariation|DesignVariation]] |
| + | |} |
| + | |
| + | ==== ControllerColor ==== |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x85, 0x3F, || Report ID (63)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x05, 0x09, || Usage Page (Button) | + | | 0x0 || 0x1 || MainColorR |
| |- | | |- |
− | |0x19, 0x01, || Usage Minimum (0x01) | + | | 0x1 || 0x1 || MainColorG |
| |- | | |- |
− | |0x29, 0x10, || Usage Maximum (0x10) | + | | 0x2 || 0x1 || MainColorB |
| |- | | |- |
− | |0x15, 0x00, || Logical Minimum (0) | + | | 0x3 || 0x1 || SubColorR |
| |- | | |- |
− | |0x25, 0x01, || Logical Maximum (1) | + | | 0x4 || 0x1 || SubColorG |
| |- | | |- |
− | |0x75, 0x01, || Report Size (1) | + | | 0x5 || 0x1 || SubColorB |
| |- | | |- |
− | |0x95, 0x10, || Report Count (16) | + | | 0x6 || 0x1 || 3rdColorR |
| |- | | |- |
− | |0x81, 0x02, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0x7 || 0x1 || 3rdColorG |
| |- | | |- |
− | |0x05, 0x01, || Usage Page (Generic Desktop Ctrls) | + | | 0x8 || 0x1 || 3rdColorB |
| |- | | |- |
− | |0x09, 0x39, || Usage (Hat switch) | + | | 0x9 || 0x1 || 4thColorR |
| |- | | |- |
− | |0x15, 0x00, || Logical Minimum (0) | + | | 0xA || 0x1 || 4thColorG |
| |- | | |- |
− | |0x25, 0x07, || Logical Maximum (7) | + | | 0xB || 0x1 || 4thColorB |
| + | |} |
| + | |
| + | ==== DesignVariation ==== |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x75, 0x04, || Report Size (4)
| + | ! Value |
| + | ! Name |
| |- | | |- |
− | |0x95, 0x01, || Report Count (1) | + | | 0x0 || LuciaJ, LagerJ |
| |- | | |- |
− | |0x81, 0x42, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) | + | | 0x1 || LuciaE, LagerE |
| |- | | |- |
− | |0x05, 0x09, || Usage Page (Button) | + | | 0x2 || LuciaU, LagerU |
| + | |} |
| + | |
| + | === Model1 === |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x75, 0x04, || Report Size (4)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x95, 0x01, || Report Count (1) | + | | 0x0 || 0x6 || [[#SixAxisSensorModelValue|SixAxisSensorModelValue]] |
| |- | | |- |
− | |0x81, 0x01, || Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0x6 || 0x12 || [[#AnalogStickModelValue|AnalogStickMainModelValue]] |
| + | |} |
| + | |
| + | ==== SixAxisSensorModelValue ==== |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x05, 0x01, || Usage Page (Generic Desktop Ctrls)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x09, 0x30, || Usage (X) | + | | 0x0 || 0x2 || SixAxisHorizontalOffsetX |
| |- | | |- |
− | |0x09, 0x31, || Usage (Y) | + | | 0x2 || 0x2 || SixAxisHorizontalOffsetY |
| |- | | |- |
− | |0x09, 0x33, || Usage (Rx) | + | | 0x4 || 0x2 || SixAxisHorizontalOffsetZ |
| + | |} |
| + | |
| + | ==== AnalogStickModelValue ==== |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x09, 0x34, || Usage (Ry)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x16, 0x00, 0x00, || Logical Minimum (0) | + | | 0x0 || 0x1 || AnalogStickModelNoise |
| |- | | |- |
− | |0x27, 0xFF, 0xFF, 0x00, 0x00, || Logical Maximum (65534) | + | | 0x1 || 0x2 || AnalogStickModelTypicalStroke |
| |- | | |- |
− | |0x75, 0x10, || Report Size (16) | + | | 0x3 || 0x1 || AnalogStickModelCenterDeadZoneSize |
| |- | | |- |
− | |0x95, 0x04, || Report Count (4) | + | | 0x4 || 0x2 || AnalogStickModelCircuitDeadZoneScale |
| |- | | |- |
− | |0x81, 0x02, || Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | + | | 0x6 || 0x1 || AnalogStickModelMinimumStrokeXPositive |
| |- | | |- |
− | |0x06, 0x01, 0xFF, || Usage Page (Vendor Defined 0xFF01) | + | | 0x7 || 0x2 || AnalogStickModelMinimumStrokeYPositive |
| |- | | |- |
− | |0x85, 0x01, || Report ID (1) | + | | 0x9 || 0x1 || AnalogStickModelMinimumStrokeXNegative |
| |- | | |- |
− | |0x09, 0x01, || Usage (0x01) | + | | 0xA || 0x2 || AnalogStickModelMinimumStrokeYNegative |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8) | + | | 0xC || 0x1 || AnalogStickModelCenterRangeXPositive |
| |- | | |- |
− | |0x95, 0x30, || Report Count (48) | + | | 0xD || 0x2 || AnalogStickModelCenterRangeYPositive |
| |- | | |- |
− | |0x91, 0x02, || Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | + | | 0xF || 0x1 || AnalogStickModelCenterRangeXNegative |
| |- | | |- |
− | |0x85, 0x10, || Report ID (16) | + | | 0x10 || 0x2 || AnalogStickModelCenterRangeYNegative |
| + | |} |
| + | |
| + | === Model2 === |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x09, 0x10, || Usage (0x10)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8) | + | | 0x0 || 0x12 || [[#AnalogStickModelValue|AnalogStickSubModelValue]] |
| + | |} |
| + | |
| + | == UserCalibration == |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x95, 0x30, || Report Count (48)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x91, 0x02, || Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | + | | 0x0 || 0x10 || Reserved |
| |- | | |- |
− | |0x85, 0x11, || Report ID (17) | + | | 0x10 || 0x16 || [[#UserCal1|UserCal1]] |
| |- | | |- |
− | |0x09, 0x11, || Usage (0x11) | + | | 0x26 || 0x1A || [[#UserCal2|UserCal2]] |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8) | + | | 0x40 || 0xFC0 || Reserved |
| + | |} |
| + | |
| + | === UserCal1 === |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x95, 0x30, || Report Count (48)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x91, 0x02, || Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | + | | 0x0 || 0x2 || AnalogStickMainUserMagicNumber |
| |- | | |- |
− | |0x85, 0x12, || Report ID (18) | + | | 0x2 || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickMainUserCalibrationValue]] |
| |- | | |- |
− | |0x09, 0x12, || Usage (0x12) | + | | 0xB || 0x2 || AnalogStickSubUserMagicNumber |
| |- | | |- |
− | |0x75, 0x08, || Report Size (8) | + | | 0xD || 0x9 || [[#AnalogStickCalibrationValue|AnalogStickSubUserCalibrationValue]] |
| + | |} |
| + | |
| + | === UserCal2 === |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | |0x95, 0x30, || Report Count (48)
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| |- | | |- |
− | |0x91, 0x02, || Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) | + | | 0x0 || 0x2 || SixAxisUserCalibrationMagicNumber |
| |- | | |- |
− | |0xC0, || End Collection | + | | 0x2 || 0x18 || [[#SixAxisSensorCalibrationValue|SixAxisUserCalibrationValue]] |
| |} | | |} |
| | | |
| == Colors == | | == 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. | | 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. |
| + | |
| {| class="wikitable" | | {| class="wikitable" |
| ! Developer Kit Joy-Con || Release || Body HEX || Button HEX | | ! Developer Kit Joy-Con || Release || Body HEX || Button HEX |
Line 362: |
Line 1,543: |
| |- | | |- |
| | White / ホワイト || 2021.10.08 || #E6E6E6 || #323232 | | | White / ホワイト || 2021.10.08 || #E6E6E6 || #323232 |
| + | |- |
| + | | Pastel Pink / パステルピンク || 2023.06.30 || #FFAFAF || #372D2D |
| + | |- |
| + | | Pastel Yellow / パステルイエロー || 2023.06.30 || #F5FF82 || #32332D |
| + | |- |
| + | | Pastel Purple / パステルパープル || 2023.06.30 || #F0CBEB || #373037 |
| + | |- |
| + | | Pastel Green / パステルグリーン || 2023.06.30 || #BCFFC8 || #2D322D |
| |- | | |- |
| ! Special Edition Joy-Con Color || Release || Body HEX || Button HEX | | ! Special Edition Joy-Con Color || Release || Body HEX || Button HEX |
| |- | | |- |
− | | Super Smash Bros. Ultimate Edition Gray Joy-Con / 大乱闘スマッシュブラザーズ SPECIAL || 2018.11.02 || #828282 || #0F0F0F | + | | Nintendo Switch Gray Joy-Con / Nintendo Switch グレー || 2017.03.03 || #828282 || #0F0F0F |
| + | |- |
| + | | Nintendo Switch Neon-Blue Left Joy-Con / Nintendo Switch ネオンブルー・ネオンレッド || 2017.03.03 || #0AB9E6 || #001E1E |
| + | |- |
| + | | Nintendo Switch Neon-Red Right Joy-Con / Nintendo Switch ネオンブルー・ネオンレッド || 2017.03.03 || #FF3C28 || #1E0A0A |
| + | |- |
| + | | 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 | + | | Pokémon: Let's Go! Edition 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 | + | | Pokémon: Let's Go! Edition 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 | | | *Nintendo Labo Creators Contest Edition "Cardboard"-Colored Joy-Con || 2018. (...?) || #D7AA73 || #1E1914 |
Line 375: |
Line 1,576: |
| | **Dragon Quest XI S Lotto Edition Royal-Blue Joy-Con / ドラゴン クエスト XI S (ロト版) || 2019.09.27 || #1473FA || #00000F | | | **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 Edition Neon-Purple Left Joy-Con / ディズニー ツムツム フェスティバル || 2019.10.10 || #B400E6 || #140014 |
| |- | | |- |
− | | **Disney Tsum Tsum Festival Neon-Pink Right Joy-Con / ディズニー ツムツム フェスティバル || 2019.10.10 || #FF3278 || #28001E | + | | **Disney Tsum Tsum Festival Edition 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 Edition Pastel-Green Left Joy-Con / あつまれ どうぶつの森 || 2020.03.13 || #82FF96 || #0A1E0A |
| |- | | |- |
− | | Animal Crossing: New Horizons Pastel-Blue Right Joy-Con / あつまれ どうぶつの森 || 2020.03.13 || #96F5F5 || #0A1E28 | + | | Animal Crossing: New Horizons Edition 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 Yellow Left Joy-Con / フォートナイト ワイルドキャット(山猫) || 2020.10.30 || #FFCC00 || #1A1100 |
| |- | | |- |
− | | Fortnite Wildcat Edition Dark-Blue Right Joy-Con || 2020.10.30 || #0084FF || #000F1E | + | | 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 | + | | Mario Red × Blue Edition Red Joy-Con / マリオ レッド × ブルー || 2021.02.12 || #F04614 || #1E1914 |
| |- | | |- |
| | Monster Hunter Rise Edition Gray Joy-Con / モンスターハンターライズ || 2021.03.26 || #818282 || #0E0F0F | | | 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 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 Edition Dark-Blue Left Joy-Con / ゼルダの伝説 スカイウォードソード || 2021.07.16 || #2D50F0 || #1E0F46 |
| + | |- |
| + | | Legend of Zelda: Skyward Sword Edition 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 || #6455F5 || #28282D |
| + | |- |
| + | | Splatoon 3 OLED Edition Neon-Yellow-Gradient Right Joy-Con / (有機ELモデル) スプラトゥーン3 || 2022.08.26 || #C3FA05 || #1E1E28 |
| |- | | |- |
− | | Fortnite Fleet Force Edition Yellow Right Joy-Con || 2021.06.04 || #FFCC00 || #1A1100 | + | | Pokémon: Scarlet × Violet OLED Edition Scarlet Left Joy-Con / (有機ELモデル) ポケットモンスター スカーレット・バイオレット || 2022.11.04 || #F07341 || #322D1E |
| |- | | |- |
− | | Legend of Zelda: Skyward Sword Dark-Blue Left Joy-Con / ゼルダの伝説 スカイウォードソード || 2021.07.16 || #2D50F0 || #1E0F46 | + | | Pokémon: Scarlet × Violet OLED Edition Violet Right Joy-Con / (有機ELモデル) ポケットモンスター スカーレット・バイオレット || 2022.11.04 || #9650AA || #32322D |
| |- | | |- |
− | | Legend of Zelda: Skyward Sword Dark-Purple Right Joy-Con / ゼルダの伝説 スカイウォードソード || 2021.07.16 || #500FC8 || #00051E | + | | Legend of Zelda: Tears of the Kingdom Edition Gold Joy-Con / (有機ELモデル) ゼルダの伝説 ティアーズ オブ ザ キングダム || 2023.04.28 || #D2BE69 || #32322D |
| |- | | |- |
| | // *(Prize Awarded for Labo Contest - No Retail) // **(Available Japan Only) | | | // *(Prize Awarded for Labo Contest - No Retail) // **(Available Japan Only) |
| |} | | |} |
− |
| |
− | == Additional Links ==
| |
− | [https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering Reverse Engineering of the Joy-Con by Github user dekuNukem]
| |