diff --git a/Makefile b/Makefile index 60f3d60..b9b7634 100644 --- a/Makefile +++ b/Makefile @@ -26,13 +26,14 @@ LDFLAGS := CXXCOMMON := -Wall -Isrc debug: BUILD_TYPE := debug -debug: CXXFLAGS := -g -O0 -fsanitize=address -fno-omit-frame-pointer +debug: CXXFLAGS := -g -O0 -fsanitize=address -fno-omit-frame-pointer -DPROTOCOL_DEBUG debug: LDFLAGS += -fsanitize=address -fno-omit-frame-pointer debug: TARGET := $(TARGET_NAME)-debug debug: prepare release: BUILD_TYPE := release -release: CXXFLAGS := -O2 +release: CXXFLAGS := -O2 -march=native -flto -fno-plt -fdata-sections -ffunction-sections -DNDEBUG +release: LDFLAGS += -Wl,--gc-sections -flto release: TARGET := $(TARGET_NAME) release: prepare diff --git a/settings.txt b/settings.txt index 34fe25f..14a3938 100644 --- a/settings.txt +++ b/settings.txt @@ -70,4 +70,12 @@ # fi # #on-connect-script = -#on-disconnect-script = \ No newline at end of file +#on-disconnect-script = + +# Protocol debug level. Works on debug builds only with PROTOCOL_DEBUG flag set. +# 0 - nothing +# 1 - unknown commands +# 2 - all commands except data streams +# 3 - include outgoing commands +# 4 - log everything +#protocol-debug = 0 \ No newline at end of file diff --git a/src/connector.cpp b/src/connector.cpp index 3e0dace..16cfefb 100644 --- a/src/connector.cpp +++ b/src/connector.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "helper/protocol_const.h" @@ -183,6 +184,10 @@ int Connector::send(int cmd, bool encrypt, uint8_t *data, uint32_t size) if (data && size > 0) libusb_bulk_transfer(_device, _endpoint_out, data, size, &transferred, 0); +#ifdef PROTOCOL_DEBUG + printMessage(cmd, size, data, magic == MAGIC_ENC, true); +#endif + return transferred; } @@ -203,13 +208,94 @@ void Connector::setEncryption(bool enabled) _ecnrypt = true; } +void Connector::printInts(uint32_t length, uint8_t *data, uint16_t max) +{ + if (data && length >= 4) + { + std::cout << " > "; + size_t count = length / 4; + for (size_t i = 0; (i < count) & (i < max); ++i) + { + uint32_t val = + ((uint32_t)data[i * 4 + 0]) | + ((uint32_t)data[i * 4 + 1] << 8) | + ((uint32_t)data[i * 4 + 2] << 16) | + ((uint32_t)data[i * 4 + 3] << 24); + std::cout << val; + } + std::cout << std::endl; + } +} + +void Connector::printBytes(uint32_t length, uint8_t *data, uint16_t max) +{ + if (data && length >= 4) + { + std::cout << " > "; + for (size_t i = 0; (i < length) & (i < max); ++i) + { + std::cout << data[i]; + } + std::cout << std::endl; + } +} + +const char *Connector::cmdString(int cmd) +{ + for (const ProtocolCmdEntry &entry : protocolCmdList) + { + if (entry.cmd == cmd) + return entry.name; + } + return nullptr; +} + +void Connector::printMessage(uint32_t cmd, uint32_t length, uint8_t *data, bool encrypted, bool out) +{ + if (Settings::protocolDebug <= PROTOCOL_DEBUG_NONE) + return; + + const char *cmds = cmdString(cmd); + + if (Settings::protocolDebug <= PROTOCOL_DEBUG_UNKNOWN && cmds) + return; + + if (Settings::protocolDebug < PROTOCOL_DEBUG_OUT && out) + return; + + bool stream = (cmd == CMD_AUDIO_DATA || cmd == CMD_VIDEO_DATA) && length > 50; + if (Settings::protocolDebug < PROTOCOL_DEBUG_ALL && stream) + return; + + std::ostringstream oss; + + oss << (out ? "<" : ">") << (encrypted ? "*" : " ") + << std::setw(3) << std::right << static_cast(cmd) + << std::setw(8) << std::left << ("[" + std::to_string(length) + "]") + << std::setw(15) << std::left << (cmds ? cmds : "Unknown"); + + if (data && length > 0) + { + for (size_t i = 0; i < 50 && i < length; ++i) + { + char ch = static_cast(data[i]); + if (ch == '\n' || ch == '\r') + oss << '.'; + else + oss << (std::isprint(static_cast(ch)) ? ch : '.'); + } + } + + std::cout << oss.str() << std::endl; +} + void Connector::read_loop() { std::mutex mtx; std::condition_variable cv; Header header; int transferred = 0; - uint8_t *data; + uint8_t *data = nullptr; // Set thread name setThreadName("protocol-reader"); @@ -251,6 +337,10 @@ void Connector::read_loop() libusb_bulk_transfer(_device, _endpoint_in, data, header.length, &transferred, READ_TIMEOUT); } +#ifdef PROTOCOL_DEBUG + printMessage(header.type, header.length, data, header.magic == MAGIC_ENC, false); +#endif + if (!_protocol) { free(data); @@ -262,14 +352,14 @@ void Connector::read_loop() if (!_cipher) { - std::cout << "[Connection] Received encrypted command " << header.type <<" but cipher is not initialised" << std::endl; + std::cout << "[Connection] Received encrypted command " << header.type << " but cipher is not initialised" << std::endl; continue; } if (!_cipher->Decrypt(data, header.length)) { std::cout << "[Connection] Can't decrypt command " << header.type << std::endl; continue; - } + } } if (padding > 0) @@ -292,6 +382,7 @@ void Connector::write_loop() if (_connected) { status("Initialising dongle"); + std::cout << "[Connection] Device connected" << std::endl; if (_protocol) _protocol->onDevice(true); diff --git a/src/connector.h b/src/connector.h index 5208212..f49f2a5 100644 --- a/src/connector.h +++ b/src/connector.h @@ -14,6 +14,12 @@ #define READ_TIMEOUT 5000 #define ENCRYPTION_BASE "SkBRDy3gmrw1ieH0" +#define PROTOCOL_DEBUG_NONE 0 +#define PROTOCOL_DEBUG_UNKNOWN 1 +#define PROTOCOL_DEBUG_NOSTREAM 2 +#define PROTOCOL_DEBUG_OUT 3 +#define PROTOCOL_DEBUG_ALL 4 + #pragma pack(push, 1) struct Header { @@ -49,6 +55,11 @@ private: void status(const char *status); + static void printInts(uint32_t length, uint8_t *data, uint16_t max); + static void printBytes(uint32_t length, uint8_t *data, uint16_t max); + static const char *cmdString(int cmd); + static void printMessage(uint32_t cmd, uint32_t length, uint8_t *data, bool encrypted, bool out); + libusb_context *_context = nullptr; libusb_device_handle *_device = nullptr; uint8_t _endpoint_in; diff --git a/src/helper/protocol_const.h b/src/helper/protocol_const.h index 6bc18ae..97c2e85 100644 --- a/src/helper/protocol_const.h +++ b/src/helper/protocol_const.h @@ -20,6 +20,7 @@ #define CMD_JSON_CONTROL 25 #define CMD_MANUFACTURER 20 #define CMD_UNKNOWN_38 38 +#define CMD_MEDIA_INFO 42 #define CMD_SEND_FILE 153 #define CMD_UNKNOWN_136 136 #define CMD_DAYNIGHT 162 @@ -48,10 +49,12 @@ const ProtocolCmdEntry protocolCmdList[] = { {CMD_DEVICE_LIST, "Device List"}, {CMD_JSON_CONTROL, "Control JSON"}, {CMD_MANUFACTURER, "Manufacturer"}, + {CMD_MEDIA_INFO, "Media info"}, {CMD_SEND_FILE, "File"}, {CMD_DAYNIGHT, "DeyNight Mode"}, {CMD_HEARTBEAT, "Heartbeat"}, {CMD_VERSION, "Version"}, {CMD_ENCRYPTION, "Encryption"}}; + #endif /* SRC_HELPER_PROTOCOL_CONST */ diff --git a/src/main.cpp b/src/main.cpp index a68405f..ead460f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,7 +110,7 @@ void processKey(Protocol &protocol, SDL_Keysym key) case SDLK_q: active = false; - break; + break; case SDLK_LEFT: protocol.sendKey(100); @@ -131,9 +131,15 @@ void processKey(Protocol &protocol, SDL_Keysym key) } } -void processEvents(Protocol &protocol) +void processEvents(Protocol &protocol, bool processMouse) { SDL_Event e; + int motionX = -1; + int motionY = -1; + int downX = -1; + int downY = -1; + int upX = -1; + int upY = -1; while (SDL_PollEvent(&e)) { switch (e.type) @@ -145,27 +151,24 @@ void processEvents(Protocol &protocol) case SDL_MOUSEBUTTONDOWN: { mouseDown = true; - int window_width, window_height; - SDL_GetWindowSize(window, &window_width, &window_height); - protocol.sendClick(1.0 * e.button.x / window_width, 1.0 * e.button.y / window_height, true); + downX = e.button.x; + downY = e.button.y; break; } case SDL_MOUSEBUTTONUP: { mouseDown = false; - int window_width, window_height; - SDL_GetWindowSize(window, &window_width, &window_height); - protocol.sendClick(1.0 * e.button.x / window_width, 1.0 * e.button.y / window_height, false); + upX = e.button.x; + upY = e.button.y; break; } case SDL_MOUSEMOTION: { if (!mouseDown) break; - int window_width, window_height; - SDL_GetWindowSize(window, &window_width, &window_height); - protocol.sendMove(1.0 * e.motion.x / window_width, 1.0 * e.motion.y / window_height); + motionX = e.motion.x; + motionY = e.motion.y; break; } case SDL_KEYDOWN: @@ -175,6 +178,18 @@ void processEvents(Protocol &protocol) } } } + + if(processMouse && (downX>=0 || upX>=0 || motionX>=0)) + { + int window_width, window_height; + SDL_GetWindowSize(window, &window_width, &window_height); + if(downX>=0) + protocol.sendClick(1.0 * downX / window_width, 1.0 * downY / window_height, true); + if(motionX>=0) + protocol.sendMove(1.0 * motionX / window_width, 1.0 * motionY / window_height); + if(upX>=0) + protocol.sendClick(1.0 * upX / window_width, 1.0 * upY / window_height, false); + } } void application() @@ -224,7 +239,7 @@ void application() while (active) { Uint32 frameStart = SDL_GetTicks(); - processEvents(protocol); + processEvents(protocol, videoPrepared); if (connected != protocol.phoneConnected) { @@ -251,6 +266,8 @@ void application() SDL_RenderCopy(renderer, videoRenderer.texture, nullptr, nullptr); SDL_RenderPresent(renderer); } + if(frameid!=latestid+1) + std::cout << "[Main] Fram drop from " << frameid - latestid - 1 << std::endl; latestid = frameid; videoBuffer.consume(); } @@ -327,7 +344,7 @@ int main(int argc, char **argv) } // Create SDL window centered on screen - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, diff --git a/src/protocol.cpp b/src/protocol.cpp index 0f56850..6cf8491 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -24,16 +24,6 @@ Protocol::~Protocol() stop(); } -const char *Protocol::cmdString(int cmd) -{ - for (const ProtocolCmdEntry &entry : protocolCmdList) - { - if (entry.cmd == cmd) - return entry.name; - } - return "Unknown"; -} - void Protocol::start(StatusCallback onStatus) { _statusCallback = onStatus; @@ -197,6 +187,8 @@ void Protocol::onPhone(bool connected) return; phoneConnected = connected; + std::cout << (connected ? "[Protocol] Phone connected" : "[Protocol] Phone disconnected") << std::endl; + if (connected && Settings::onConnect.value.length() > 1) execute(Settings::onConnect.value.c_str()); @@ -221,7 +213,6 @@ void Protocol::onData(uint32_t cmd, uint32_t length, uint8_t *data) { if (length <= 13) { - print_message(cmd, length, data); break; } int channel = 0; @@ -244,83 +235,22 @@ void Protocol::onData(uint32_t cmd, uint32_t length, uint8_t *data) dispose = false; break; } - print_message(cmd, length, data); break; } case CMD_PLUGGED: - { onPhone(true); break; - } + case CMD_UNPLUGGED: - { onPhone(false); break; - } + case CMD_ENCRYPTION: - { if (length == 0) connector.setEncryption(true); - print_message(cmd, length, data); - break; - } - - default: - print_message(cmd, length, data); break; } if (dispose && length > 0 && data) free(data); } - -void Protocol::print_ints(uint32_t length, uint8_t *data, uint16_t max) -{ - if (data && length >= 4) - { - std::cout << " > "; - size_t count = length / 4; - for (size_t i = 0; (i < count) & (i < max); ++i) - { - uint32_t val = - ((uint32_t)data[i * 4 + 0]) | - ((uint32_t)data[i * 4 + 1] << 8) | - ((uint32_t)data[i * 4 + 2] << 16) | - ((uint32_t)data[i * 4 + 3] << 24); - std::cout << val; - } - std::cout << endl; - } -} - -void Protocol::print_bytes(uint32_t length, uint8_t *data, uint16_t max) -{ - if (data && length >= 4) - { - std::cout << " > "; - for (size_t i = 0; (i < length) & (i < max); ++i) - { - std::cout << data[i]; - } - std::cout << endl; - } -} - -void Protocol::print_message(uint32_t cmd, uint32_t length, uint8_t *data) -{ - std::cout << "> " - << std::setw(3) << std::right << static_cast(cmd) - << std::setw(8) << std::left << ("[" + std::to_string(length) + "]") - << std::setw(15) << std::left << cmdString(cmd); - - if (data && length > 0) - { - for (size_t i = 0; i < 50 && i < length; ++i) - { - char ch = static_cast(data[i]); - std::cout << (std::isprint(static_cast(ch)) ? ch : '.'); - } - } - - std::cout << std::endl; -} diff --git a/src/protocol.h b/src/protocol.h index 99239c4..6741b54 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -7,7 +7,6 @@ #include "settings.h" #include "connector.h" - class Protocol : public IProtocol { @@ -46,10 +45,6 @@ private: void onDevice(bool connected) override; void onData(uint32_t cmd, uint32_t length, uint8_t *data) override; - void print_message(uint32_t cmd, uint32_t length, uint8_t *data); - void print_ints(uint32_t length, uint8_t *data, uint16_t max); - void print_bytes(uint32_t length, uint8_t *data, uint16_t max); - void onPhone(bool connected); uint16_t _width; diff --git a/src/settings.h b/src/settings.h index 3a8cd19..aaf84a1 100644 --- a/src/settings.h +++ b/src/settings.h @@ -24,7 +24,8 @@ public: static inline Setting encryption{"encryption", false}; static inline Setting autoconnect{"autoconnect", true}; static inline Setting onConnect{"on-connect-script", ""}; - static inline Setting onDisconnect{"on-disconnect-script", ""}; + static inline Setting onDisconnect{"on-disconnect-script", ""}; + static inline Setting protocolDebug{"protocol-debug", 0}; static void load(const std::string &filename); static void print();