mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-02-16 02:21:07 +00:00
Introduce new protocol extensions for controller RGB LEDs and battery state
This commit is contained in:
@@ -87,6 +87,7 @@ static PPLT_CRYPTO_CONTEXT decryptionCtx;
|
||||
#define IDX_HDR_INFO 8
|
||||
#define IDX_RUMBLE_TRIGGER_DATA 9
|
||||
#define IDX_SET_MOTION_EVENT 10
|
||||
#define IDX_SET_RGB_LED 11
|
||||
|
||||
#define CONTROL_STREAM_TIMEOUT_SEC 10
|
||||
#define CONTROL_STREAM_LINGER_TIMEOUT_SEC 2
|
||||
@@ -103,6 +104,7 @@ static const short packetTypesGen3[] = {
|
||||
-1, // HDR mode (unused)
|
||||
-1, // Rumble triggers (unused)
|
||||
-1, // Set motion event (unused)
|
||||
-1, // Set RGB LED (unused)
|
||||
};
|
||||
static const short packetTypesGen4[] = {
|
||||
0x0606, // Request IDR frame
|
||||
@@ -116,6 +118,7 @@ static const short packetTypesGen4[] = {
|
||||
-1, // HDR mode (unused)
|
||||
-1, // Rumble triggers (unused)
|
||||
-1, // Set motion event (unused)
|
||||
-1, // Set RGB LED (unused)
|
||||
};
|
||||
static const short packetTypesGen5[] = {
|
||||
0x0305, // Start A
|
||||
@@ -129,6 +132,7 @@ static const short packetTypesGen5[] = {
|
||||
-1, // HDR mode (unknown)
|
||||
-1, // Rumble triggers (unused)
|
||||
-1, // Set motion event (unused)
|
||||
-1, // Set RGB LED (unused)
|
||||
};
|
||||
static const short packetTypesGen7[] = {
|
||||
0x0305, // Start A
|
||||
@@ -142,6 +146,7 @@ static const short packetTypesGen7[] = {
|
||||
0x010e, // HDR mode
|
||||
-1, // Rumble triggers (unused)
|
||||
-1, // Set motion event (unused)
|
||||
-1, // Set RGB LED (unused)
|
||||
};
|
||||
static const short packetTypesGen7Enc[] = {
|
||||
0x0302, // Request IDR frame
|
||||
@@ -155,6 +160,7 @@ static const short packetTypesGen7Enc[] = {
|
||||
0x010e, // HDR mode
|
||||
0x5500, // Rumble triggers (Sunshine protocol extension)
|
||||
0x5501, // Set motion event (Sunshine protocol extension)
|
||||
0x5502, // Set RGB LED (Sunshine protocol extension)
|
||||
};
|
||||
|
||||
static const char requestIdrFrameGen3[] = { 0, 0 };
|
||||
@@ -941,6 +947,21 @@ static void controlReceiveThreadFunc(void* context) {
|
||||
|
||||
ListenerCallbacks.setMotionEventState(controllerNumber, motionType, reportRateHz);
|
||||
}
|
||||
else if (ctlHdr->type == packetTypes[IDX_SET_RGB_LED]) {
|
||||
BYTE_BUFFER bb;
|
||||
|
||||
BbInitializeWrappedBuffer(&bb, (char*)ctlHdr, sizeof(*ctlHdr), packetLength - sizeof(*ctlHdr), BYTE_ORDER_LITTLE);
|
||||
|
||||
uint16_t controllerNumber;
|
||||
uint8_t r, g, b;
|
||||
|
||||
BbGet16(&bb, &controllerNumber);
|
||||
BbGet8(&bb, &r);
|
||||
BbGet8(&bb, &g);
|
||||
BbGet8(&bb, &b);
|
||||
|
||||
ListenerCallbacks.setControllerLED(controllerNumber, r, g, b);
|
||||
}
|
||||
else if (ctlHdr->type == packetTypes[IDX_HDR_INFO]) {
|
||||
BYTE_BUFFER bb;
|
||||
uint8_t enableByte;
|
||||
|
||||
@@ -39,6 +39,7 @@ static void fakeClConnectionStatusUpdate(int connectionStatus) {}
|
||||
static void fakeClSetHdrMode(bool enabled) {}
|
||||
static void fakeClRumbleTriggers(uint16_t controllerNumber, uint16_t leftTriggerMotor, uint16_t rightTriggerMotor) {}
|
||||
static void fakeClSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz) {}
|
||||
static void fakeClSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b) {}
|
||||
|
||||
static CONNECTION_LISTENER_CALLBACKS fakeClCallbacks = {
|
||||
.stageStarting = fakeClStageStarting,
|
||||
@@ -52,6 +53,7 @@ static CONNECTION_LISTENER_CALLBACKS fakeClCallbacks = {
|
||||
.setHdrMode = fakeClSetHdrMode,
|
||||
.rumbleTriggers = fakeClRumbleTriggers,
|
||||
.setMotionEventState = fakeClSetMotionEventState,
|
||||
.setControllerLED = fakeClSetControllerLED,
|
||||
};
|
||||
|
||||
void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks,
|
||||
@@ -136,5 +138,8 @@ void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_REND
|
||||
if ((*clCallbacks)->setMotionEventState == NULL) {
|
||||
(*clCallbacks)->setMotionEventState = fakeClSetMotionEventState;
|
||||
}
|
||||
if ((*clCallbacks)->setControllerLED == NULL) {
|
||||
(*clCallbacks)->setControllerLED = fakeClSetControllerLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,4 +181,13 @@ typedef struct _SS_CONTROLLER_MOTION_PACKET {
|
||||
netfloat z;
|
||||
} SS_CONTROLLER_MOTION_PACKET, *PSS_CONTROLLER_MOTION_PACKET;
|
||||
|
||||
#define SS_CONTROLLER_BATTERY_MAGIC 0x55000007
|
||||
typedef struct _SS_CONTROLLER_BATTERY_PACKET {
|
||||
NV_INPUT_HEADER header;
|
||||
uint8_t controllerNumber;
|
||||
uint8_t batteryState;
|
||||
uint8_t batteryPercentage;
|
||||
uint8_t zero[1]; // Alignment/reserved
|
||||
} SS_CONTROLLER_BATTERY_PACKET, *PSS_CONTROLLER_BATTERY_PACKET;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -63,6 +63,7 @@ typedef struct _PACKET_HOLDER {
|
||||
SS_CONTROLLER_ARRIVAL_PACKET controllerArrival;
|
||||
SS_CONTROLLER_TOUCH_PACKET controllerTouch;
|
||||
SS_CONTROLLER_MOTION_PACKET controllerMotion;
|
||||
SS_CONTROLLER_BATTERY_PACKET controllerBattery;
|
||||
NV_UNICODE_PACKET unicode;
|
||||
} packet;
|
||||
} PACKET_HOLDER, *PPACKET_HOLDER;
|
||||
@@ -1344,3 +1345,38 @@ int LiSendControllerMotionEvent(uint8_t controllerNumber, uint8_t motionType, fl
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int LiSendControllerBatteryEvent(uint8_t controllerNumber, uint8_t batteryState, uint8_t batteryPercentage) {
|
||||
PPACKET_HOLDER holder;
|
||||
int err;
|
||||
|
||||
if (!initialized) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
// This is a protocol extension only supported with Sunshine
|
||||
if (!IS_SUNSHINE()) {
|
||||
return LI_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
holder = allocatePacketHolder(0);
|
||||
if (holder == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
holder->packet.controllerBattery.header.size = BE32(sizeof(SS_CONTROLLER_BATTERY_PACKET) - sizeof(uint32_t));
|
||||
holder->packet.controllerBattery.header.magic = LE32(SS_CONTROLLER_BATTERY_MAGIC);
|
||||
holder->packet.controllerBattery.controllerNumber = controllerNumber;
|
||||
holder->packet.controllerBattery.batteryState = batteryState;
|
||||
holder->packet.controllerBattery.batteryPercentage = batteryPercentage;
|
||||
memset(holder->packet.controllerBattery.zero, 0, sizeof(holder->packet.controllerBattery.zero));
|
||||
|
||||
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
|
||||
if (err != LBQ_SUCCESS) {
|
||||
LC_ASSERT(err == LBQ_BOUND_EXCEEDED);
|
||||
Limelog("Input queue reached maximum size limit\n");
|
||||
freePacketHolder(holder);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -465,6 +465,9 @@ typedef void(*ConnListenerRumbleTriggers)(uint16_t controllerNumber, uint16_t le
|
||||
// If reportRateHz is 0, the host is asking for motion event reporting to stop.
|
||||
typedef void(*ConnListenerSetMotionEventState)(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz);
|
||||
|
||||
// This callback is invoked to set a controller's RGB LED (if present).
|
||||
typedef void(*ConnListenerSetControllerLED)(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
typedef struct _CONNECTION_LISTENER_CALLBACKS {
|
||||
ConnListenerStageStarting stageStarting;
|
||||
ConnListenerStageComplete stageComplete;
|
||||
@@ -477,6 +480,7 @@ typedef struct _CONNECTION_LISTENER_CALLBACKS {
|
||||
ConnListenerSetHdrMode setHdrMode;
|
||||
ConnListenerRumbleTriggers rumbleTriggers;
|
||||
ConnListenerSetMotionEventState setMotionEventState;
|
||||
ConnListenerSetControllerLED setControllerLED;
|
||||
} CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS;
|
||||
|
||||
// Use this function to zero the connection callbacks when allocated on the stack or heap
|
||||
@@ -692,12 +696,14 @@ int LiSendMultiControllerEvent(short controllerNumber, short activeGamepadMask,
|
||||
#define LI_CTYPE_XBOX 0x01
|
||||
#define LI_CTYPE_PS 0x02
|
||||
#define LI_CTYPE_NINTENDO 0x03
|
||||
#define LI_CCAP_ANALOG_TRIGGERS 0x01
|
||||
#define LI_CCAP_RUMBLE 0x02
|
||||
#define LI_CCAP_TRIGGER_RUMBLE 0x04
|
||||
#define LI_CCAP_TOUCHPAD 0x08
|
||||
#define LI_CCAP_ACCEL 0x10
|
||||
#define LI_CCAP_GYRO 0x20
|
||||
#define LI_CCAP_ANALOG_TRIGGERS 0x01 // Reports values between 0x00 and 0xFF for trigger axes
|
||||
#define LI_CCAP_RUMBLE 0x02 // Can rumble in response to ConnListenerRumble() callback
|
||||
#define LI_CCAP_TRIGGER_RUMBLE 0x04 // Can rumble triggers in response to ConnListenerRumbleTriggers() callback
|
||||
#define LI_CCAP_TOUCHPAD 0x08 // Reports touchpad events via LiSendControllerTouchEvent()
|
||||
#define LI_CCAP_ACCEL 0x10 // Can report accelerometer events via LiSendControllerMotionEvent()
|
||||
#define LI_CCAP_GYRO 0x20 // Can report gyroscope events via LiSendControllerMotionEvent()
|
||||
#define LI_CCAP_BATTERY_STATE 0x40 // Reports battery state via LiSendControllerBatteryEvent()
|
||||
#define LI_CCAP_RGB_LED 0x80 // Can set RGB LED state via ConnListenerSetControllerLED()
|
||||
int LiSendControllerArrivalEvent(uint8_t controllerNumber, uint16_t activeGamepadMask, uint8_t type,
|
||||
uint32_t supportedButtonFlags, uint16_t capabilities);
|
||||
|
||||
@@ -719,6 +725,17 @@ int LiSendControllerTouchEvent(uint8_t controllerNumber, uint8_t eventType, uint
|
||||
#define LI_MOTION_TYPE_GYRO 0x02
|
||||
int LiSendControllerMotionEvent(uint8_t controllerNumber, uint8_t motionType, float x, float y, float z);
|
||||
|
||||
// This function allows clients to send controller battery state to a supported host. If the
|
||||
// host can adjust battery state on the emulated controller, it can use this information to
|
||||
// make the virtual controller match the physical controller on the client.
|
||||
#define LI_BATTERY_STATE_UNKNOWN 0x00
|
||||
#define LI_BATTERY_STATE_NOT_PRESENT 0x01
|
||||
#define LI_BATTERY_STATE_DISCHARGING 0x02
|
||||
#define LI_BATTERY_STATE_CHARGING 0x03
|
||||
#define LI_BATTERY_STATE_NOT_CHARGING 0x04 // Connected to power but not charging
|
||||
#define LI_BATTERY_STATE_FULL 0x05
|
||||
int LiSendControllerBatteryEvent(uint8_t controllerNumber, uint8_t batteryState, uint8_t batteryPercentage);
|
||||
|
||||
// This function queues a vertical scroll event to the remote server.
|
||||
// The number of "clicks" is multiplied by WHEEL_DELTA (120) before
|
||||
// being sent to the PC.
|
||||
|
||||
Reference in New Issue
Block a user