diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index ef9247ca..cfbefa5f 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include "control_msg.h" @@ -278,6 +280,73 @@ static void test_serialize_rotate_device(void) { assert(!memcmp(buf, expected, sizeof(expected))); } +static void test_serialize_inject_game_controller_axis(void) { + struct control_msg msg = { + .type = CONTROL_MSG_TYPE_INJECT_GAME_CONTROLLER_AXIS, + .inject_game_controller_axis = { + .id = 0x1234, + .axis = SDL_CONTROLLER_AXIS_RIGHTY, + .value = -32768, + }, + }; + + unsigned char buf[CONTROL_MSG_MAX_SIZE]; + size_t size = control_msg_serialize(&msg, buf); + assert(size == 6); + + const unsigned char expected[] = { + CONTROL_MSG_TYPE_INJECT_GAME_CONTROLLER_AXIS, + 0x12, 0x34, // id = 0x1234 + 0x03, // axis = SDL_CONTROLLER_AXIS_RIGHTY + 0x80, 0x00, // value = -32768 + }; + assert(!memcmp(buf, expected, sizeof(expected))); +} + +static void test_serialize_inject_game_controller_button(void) { + struct control_msg msg = { + .type = CONTROL_MSG_TYPE_INJECT_GAME_CONTROLLER_BUTTON, + .inject_game_controller_button = { + .id = 0x1234, + .button = SDL_CONTROLLER_BUTTON_START, + .state = 1, + }, + }; + + unsigned char buf[CONTROL_MSG_MAX_SIZE]; + size_t size = control_msg_serialize(&msg, buf); + assert(size == 5); + + const unsigned char expected[] = { + CONTROL_MSG_TYPE_INJECT_GAME_CONTROLLER_BUTTON, + 0x12, 0x34, // id = 0x1234 + 0x06, // button = SDL_CONTROLLER_BUTTON_START + 0x01, // state = 1 + }; + assert(!memcmp(buf, expected, sizeof(expected))); +} + +static void test_serialize_inject_game_controller_device(void) { + struct control_msg msg = { + .type = CONTROL_MSG_TYPE_INJECT_GAME_CONTROLLER_DEVICE, + .inject_game_controller_device = { + .id = 0x1234, + .event = (SDL_CONTROLLERDEVICEREMOVED) - SDL_CONTROLLERDEVICEADDED, + }, + }; + + unsigned char buf[CONTROL_MSG_MAX_SIZE]; + size_t size = control_msg_serialize(&msg, buf); + assert(size == 4); + + const unsigned char expected[] = { + CONTROL_MSG_TYPE_INJECT_GAME_CONTROLLER_DEVICE, + 0x12, 0x34, // id = 0x1234 + 0x01, // event = GameController.DEVICE_REMOVED + }; + assert(!memcmp(buf, expected, sizeof(expected))); +} + int main(int argc, char *argv[]) { (void) argc; (void) argv; @@ -295,5 +364,8 @@ int main(int argc, char *argv[]) { test_serialize_set_clipboard(); test_serialize_set_screen_power_mode(); test_serialize_rotate_device(); + test_serialize_inject_game_controller_axis(); + test_serialize_inject_game_controller_button(); + test_serialize_inject_game_controller_device(); return 0; } diff --git a/server/src/main/java/com/genymobile/scrcpy/GameController.java b/server/src/main/java/com/genymobile/scrcpy/GameController.java index a2b55382..4e92bf5d 100644 --- a/server/src/main/java/com/genymobile/scrcpy/GameController.java +++ b/server/src/main/java/com/genymobile/scrcpy/GameController.java @@ -174,28 +174,28 @@ public final class GameController { private static final short XBOX_ABS_LT = ABS_Z; private static final short XBOX_ABS_RT = ABS_RZ; - private static final int SDL_CONTROLLER_AXIS_LEFTX = 0; - private static final int SDL_CONTROLLER_AXIS_LEFTY = 1; - private static final int SDL_CONTROLLER_AXIS_RIGHTX = 2; - private static final int SDL_CONTROLLER_AXIS_RIGHTY = 3; - private static final int SDL_CONTROLLER_AXIS_TRIGGERLEFT = 4; - private static final int SDL_CONTROLLER_AXIS_TRIGGERRIGHT = 5; + public static final int SDL_CONTROLLER_AXIS_LEFTX = 0; + public static final int SDL_CONTROLLER_AXIS_LEFTY = 1; + public static final int SDL_CONTROLLER_AXIS_RIGHTX = 2; + public static final int SDL_CONTROLLER_AXIS_RIGHTY = 3; + public static final int SDL_CONTROLLER_AXIS_TRIGGERLEFT = 4; + public static final int SDL_CONTROLLER_AXIS_TRIGGERRIGHT = 5; - private static final int SDL_CONTROLLER_BUTTON_A = 0; - private static final int SDL_CONTROLLER_BUTTON_B = 1; - private static final int SDL_CONTROLLER_BUTTON_X = 2; - private static final int SDL_CONTROLLER_BUTTON_Y = 3; - private static final int SDL_CONTROLLER_BUTTON_BACK = 4; - private static final int SDL_CONTROLLER_BUTTON_GUIDE = 5; - private static final int SDL_CONTROLLER_BUTTON_START = 6; - private static final int SDL_CONTROLLER_BUTTON_LEFTSTICK = 7; - private static final int SDL_CONTROLLER_BUTTON_RIGHTSTICK = 8; - private static final int SDL_CONTROLLER_BUTTON_LEFTSHOULDER = 9; - private static final int SDL_CONTROLLER_BUTTON_RIGHTSHOULDER = 10; - private static final int SDL_CONTROLLER_BUTTON_DPAD_UP = 11; - private static final int SDL_CONTROLLER_BUTTON_DPAD_DOWN = 12; - private static final int SDL_CONTROLLER_BUTTON_DPAD_LEFT = 13; - private static final int SDL_CONTROLLER_BUTTON_DPAD_RIGHT = 14; + public static final int SDL_CONTROLLER_BUTTON_A = 0; + public static final int SDL_CONTROLLER_BUTTON_B = 1; + public static final int SDL_CONTROLLER_BUTTON_X = 2; + public static final int SDL_CONTROLLER_BUTTON_Y = 3; + public static final int SDL_CONTROLLER_BUTTON_BACK = 4; + public static final int SDL_CONTROLLER_BUTTON_GUIDE = 5; + public static final int SDL_CONTROLLER_BUTTON_START = 6; + public static final int SDL_CONTROLLER_BUTTON_LEFTSTICK = 7; + public static final int SDL_CONTROLLER_BUTTON_RIGHTSTICK = 8; + public static final int SDL_CONTROLLER_BUTTON_LEFTSHOULDER = 9; + public static final int SDL_CONTROLLER_BUTTON_RIGHTSHOULDER = 10; + public static final int SDL_CONTROLLER_BUTTON_DPAD_UP = 11; + public static final int SDL_CONTROLLER_BUTTON_DPAD_DOWN = 12; + public static final int SDL_CONTROLLER_BUTTON_DPAD_LEFT = 13; + public static final int SDL_CONTROLLER_BUTTON_DPAD_RIGHT = 14; private int fd; diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index da568486..678f15f7 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -314,6 +314,76 @@ public class ControlMessageReaderTest { Assert.assertEquals(ControlMessage.TYPE_ROTATE_DEVICE, event.getType()); } + @Test + public void testParseGameControllerAxisEvent() throws IOException { + ControlMessageReader reader = new ControlMessageReader(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + dos.writeByte(ControlMessage.TYPE_INJECT_GAME_CONTROLLER_AXIS); + dos.writeShort(0x1234); + dos.writeByte(GameController.SDL_CONTROLLER_AXIS_RIGHTY); + dos.writeShort(-32768); + byte[] packet = bos.toByteArray(); + + // The message type (1 byte) does not count + Assert.assertEquals(ControlMessageReader.INJECT_GAME_CONTROLLER_AXIS_PAYLOAD_LENGTH, packet.length - 1); + + reader.readFrom(new ByteArrayInputStream(packet)); + ControlMessage event = reader.next(); + + Assert.assertEquals(ControlMessage.TYPE_INJECT_GAME_CONTROLLER_AXIS, event.getType()); + Assert.assertEquals(0x1234, event.getGameControllerId()); + Assert.assertEquals(GameController.SDL_CONTROLLER_AXIS_RIGHTY, event.getGameControllerAxis()); + Assert.assertEquals(-32768, event.getGameControllerAxisValue()); + } + + @Test + public void testParseGameControllerButtonEvent() throws IOException { + ControlMessageReader reader = new ControlMessageReader(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + dos.writeByte(ControlMessage.TYPE_INJECT_GAME_CONTROLLER_BUTTON); + dos.writeShort(0x1234); + dos.writeByte(GameController.SDL_CONTROLLER_BUTTON_START); + dos.writeByte(1); + byte[] packet = bos.toByteArray(); + + // The message type (1 byte) does not count + Assert.assertEquals(ControlMessageReader.INJECT_GAME_CONTROLLER_BUTTON_PAYLOAD_LENGTH, packet.length - 1); + + reader.readFrom(new ByteArrayInputStream(packet)); + ControlMessage event = reader.next(); + + Assert.assertEquals(ControlMessage.TYPE_INJECT_GAME_CONTROLLER_BUTTON, event.getType()); + Assert.assertEquals(0x1234, event.getGameControllerId()); + Assert.assertEquals(GameController.SDL_CONTROLLER_BUTTON_START, event.getGameControllerButton()); + Assert.assertEquals(1, event.getGameControllerButtonState()); + } + + @Test + public void testParseGameControllerDeviceEvent() throws IOException { + ControlMessageReader reader = new ControlMessageReader(); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + dos.writeByte(ControlMessage.TYPE_INJECT_GAME_CONTROLLER_DEVICE); + dos.writeShort(0x1234); + dos.writeByte(GameController.DEVICE_REMOVED); + byte[] packet = bos.toByteArray(); + + // The message type (1 byte) does not count + Assert.assertEquals(ControlMessageReader.INJECT_GAME_CONTROLLER_DEVICE_PAYLOAD_LENGTH, packet.length - 1); + + reader.readFrom(new ByteArrayInputStream(packet)); + ControlMessage event = reader.next(); + + Assert.assertEquals(ControlMessage.TYPE_INJECT_GAME_CONTROLLER_DEVICE, event.getType()); + Assert.assertEquals(0x1234, event.getGameControllerId()); + Assert.assertEquals(GameController.DEVICE_REMOVED, event.getGameControllerDeviceEvent()); + } + @Test public void testMultiEvents() throws IOException { ControlMessageReader reader = new ControlMessageReader();