5 changed files with 310 additions and 3 deletions
-
2src/input_common/CMakeLists.txt
-
54src/input_common/helpers/joycon_driver.cpp
-
2src/input_common/helpers/joycon_driver.h
-
147src/input_common/helpers/joycon_protocol/generic_functions.cpp
-
108src/input_common/helpers/joycon_protocol/generic_functions.h
@ -0,0 +1,147 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
|||
#include "common/logging/log.h"
|
|||
#include "input_common/helpers/joycon_protocol/generic_functions.h"
|
|||
|
|||
namespace InputCommon::Joycon { |
|||
|
|||
GenericProtocol::GenericProtocol(std::shared_ptr<JoyconHandle> handle) |
|||
: JoyconCommonProtocol(handle) {} |
|||
|
|||
DriverResult GenericProtocol::EnablePassiveMode() { |
|||
SetBlocking(); |
|||
const auto result = SetReportMode(ReportMode::SIMPLE_HID_MODE); |
|||
SetNonBlocking(); |
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::EnableActiveMode() { |
|||
SetBlocking(); |
|||
const auto result = SetReportMode(ReportMode::STANDARD_FULL_60HZ); |
|||
SetNonBlocking(); |
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::GetDeviceInfo(DeviceInfo& device_info) { |
|||
std::vector<u8> output; |
|||
SetBlocking(); |
|||
|
|||
const auto result = SendSubCommand(SubCommand::REQ_DEV_INFO, {}, output); |
|||
|
|||
device_info = {}; |
|||
if (result == DriverResult::Success) { |
|||
memcpy(&device_info, output.data(), sizeof(DeviceInfo)); |
|||
} |
|||
|
|||
SetNonBlocking(); |
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::GetControllerType(ControllerType& controller_type) { |
|||
return GetDeviceType(controller_type); |
|||
} |
|||
|
|||
DriverResult GenericProtocol::EnableImu(bool enable) { |
|||
const std::vector<u8> buffer{static_cast<u8>(enable ? 1 : 0)}; |
|||
std::vector<u8> output; |
|||
SetBlocking(); |
|||
const auto result = SendSubCommand(SubCommand::ENABLE_IMU, buffer, output); |
|||
SetNonBlocking(); |
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, |
|||
AccelerometerSensitivity asen, |
|||
AccelerometerPerformance afrec) { |
|||
const std::vector<u8> buffer{static_cast<u8>(gsen), static_cast<u8>(asen), |
|||
static_cast<u8>(gfrec), static_cast<u8>(afrec)}; |
|||
std::vector<u8> output; |
|||
SetBlocking(); |
|||
const auto result = SendSubCommand(SubCommand::SET_IMU_SENSITIVITY, buffer, output); |
|||
SetNonBlocking(); |
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::GetBattery(u32& battery_level) { |
|||
battery_level = 0; |
|||
return DriverResult::NotSupported; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::GetColor(Color& color) { |
|||
std::vector<u8> buffer; |
|||
SetBlocking(); |
|||
const auto result = ReadSPI(CalAddr::COLOR_DATA, 12, buffer); |
|||
SetNonBlocking(); |
|||
|
|||
color = {}; |
|||
if (result == DriverResult::Success) { |
|||
color.body = static_cast<u32>((buffer[0] << 16) | (buffer[1] << 8) | buffer[2]); |
|||
color.buttons = static_cast<u32>((buffer[3] << 16) | (buffer[4] << 8) | buffer[5]); |
|||
color.left_grip = static_cast<u32>((buffer[6] << 16) | (buffer[7] << 8) | buffer[8]); |
|||
color.right_grip = static_cast<u32>((buffer[9] << 16) | (buffer[10] << 8) | buffer[11]); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::GetSerialNumber(SerialNumber& serial_number) { |
|||
std::vector<u8> buffer; |
|||
SetBlocking(); |
|||
const auto result = ReadSPI(CalAddr::SERIAL_NUMBER, 16, buffer); |
|||
SetNonBlocking(); |
|||
|
|||
serial_number = {}; |
|||
if (result == DriverResult::Success) { |
|||
memcpy(serial_number.data(), buffer.data() + 1, sizeof(SerialNumber)); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::GetTemperature(u32& temperature) { |
|||
// Not all devices have temperature sensor
|
|||
temperature = 25; |
|||
return DriverResult::NotSupported; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::GetVersionNumber(FirmwareVersion& version) { |
|||
DeviceInfo device_info{}; |
|||
|
|||
const auto result = GetDeviceInfo(device_info); |
|||
version = device_info.firmware; |
|||
|
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::SetHomeLight() { |
|||
const std::vector<u8> buffer{0x0f, 0xf0, 0x00}; |
|||
std::vector<u8> output; |
|||
SetBlocking(); |
|||
|
|||
const auto result = SendSubCommand(SubCommand::SET_HOME_LIGHT, buffer, output); |
|||
|
|||
SetNonBlocking(); |
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::SetLedBusy() { |
|||
return DriverResult::NotSupported; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::SetLedPattern(u8 leds) { |
|||
const std::vector<u8> buffer{leds}; |
|||
std::vector<u8> output; |
|||
SetBlocking(); |
|||
|
|||
const auto result = SendSubCommand(SubCommand::SET_PLAYER_LIGHTS, buffer, output); |
|||
|
|||
SetNonBlocking(); |
|||
return result; |
|||
} |
|||
|
|||
DriverResult GenericProtocol::SetLedBlinkPattern(u8 leds) { |
|||
return SetLedPattern(static_cast<u8>(leds << 4)); |
|||
} |
|||
|
|||
} // namespace InputCommon::Joycon
|
|||
@ -0,0 +1,108 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
// Based on dkms-hid-nintendo implementation, CTCaer joycon toolkit and dekuNukem reverse |
|||
// engineering https://github.com/nicman23/dkms-hid-nintendo/blob/master/src/hid-nintendo.c |
|||
// https://github.com/CTCaer/jc_toolkit |
|||
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering |
|||
|
|||
#pragma once |
|||
|
|||
#include "input_common/helpers/joycon_protocol/common_protocol.h" |
|||
#include "input_common/helpers/joycon_protocol/joycon_types.h" |
|||
|
|||
namespace InputCommon::Joycon { |
|||
|
|||
/// Joycon driver functions that easily implemented |
|||
class GenericProtocol final : private JoyconCommonProtocol { |
|||
public: |
|||
GenericProtocol(std::shared_ptr<JoyconHandle> handle); |
|||
|
|||
/// Enables passive mode. This mode only sends button data on change. Sticks will return digital |
|||
/// data instead of analog. Motion will be disabled |
|||
DriverResult EnablePassiveMode(); |
|||
|
|||
/// Enables active mode. This mode will return the current status every 5-15ms |
|||
DriverResult EnableActiveMode(); |
|||
|
|||
/** |
|||
* Sends a request to obtain the joycon firmware and mac from handle |
|||
* @returns controller device info |
|||
*/ |
|||
DriverResult GetDeviceInfo(DeviceInfo& controller_type); |
|||
|
|||
/** |
|||
* Sends a request to obtain the joycon type from handle |
|||
* @returns controller type of the joycon |
|||
*/ |
|||
DriverResult GetControllerType(ControllerType& controller_type); |
|||
|
|||
/** |
|||
* Enables motion input |
|||
* @param enable if true motion data will be enabled |
|||
*/ |
|||
DriverResult EnableImu(bool enable); |
|||
|
|||
/** |
|||
* Configures the motion sensor with the specified parameters |
|||
* @param gsen gyroscope sensor sensitvity in degrees per second |
|||
* @param gfrec gyroscope sensor frequency in hertz |
|||
* @param asen accelerometer sensitivity in G force |
|||
* @param afrec accelerometer frequency in hertz |
|||
*/ |
|||
DriverResult SetImuConfig(GyroSensitivity gsen, GyroPerformance gfrec, |
|||
AccelerometerSensitivity asen, AccelerometerPerformance afrec); |
|||
|
|||
/** |
|||
* Request battery level from the device |
|||
* @returns battery level |
|||
*/ |
|||
DriverResult GetBattery(u32& battery_level); |
|||
|
|||
/** |
|||
* Request joycon colors from the device |
|||
* @returns colors of the body and buttons |
|||
*/ |
|||
DriverResult GetColor(Color& color); |
|||
|
|||
/** |
|||
* Request joycon serial number from the device |
|||
* @returns 16 byte serial number |
|||
*/ |
|||
DriverResult GetSerialNumber(SerialNumber& serial_number); |
|||
|
|||
/** |
|||
* Request joycon serial number from the device |
|||
* @returns 16 byte serial number |
|||
*/ |
|||
DriverResult GetTemperature(u32& temperature); |
|||
|
|||
/** |
|||
* Request joycon serial number from the device |
|||
* @returns 16 byte serial number |
|||
*/ |
|||
DriverResult GetVersionNumber(FirmwareVersion& version); |
|||
|
|||
/** |
|||
* Sets home led behaviour |
|||
*/ |
|||
DriverResult SetHomeLight(); |
|||
|
|||
/** |
|||
* Sets home led into a slow breathing state |
|||
*/ |
|||
DriverResult SetLedBusy(); |
|||
|
|||
/** |
|||
* Sets the 4 player leds on the joycon on a solid state |
|||
* @params bit flag containing the led state |
|||
*/ |
|||
DriverResult SetLedPattern(u8 leds); |
|||
|
|||
/** |
|||
* Sets the 4 player leds on the joycon on a blinking state |
|||
* @returns bit flag containing the led state |
|||
*/ |
|||
DriverResult SetLedBlinkPattern(u8 leds); |
|||
}; |
|||
} // namespace InputCommon::Joycon |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue