diff --git a/CMakeLists.txt b/CMakeLists.txt index dbad207..5568c55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") include_directories("${CMAKE_SOURCE_DIR}/include/") set(CMAKE_CXX_STANDARD 17) +set(CMAKE_C_COMPILER "gcc") +set(CMAKE_CXX_COMPILER "g++") + link_directories(src) add_library(chuniio_brokenithm SHARED src/chuniio.c src/chuniio.h @@ -16,5 +19,5 @@ add_library(chuniio_brokenithm SHARED src/chuniio.c src/util/dprintf.h) set_target_properties(chuniio_brokenithm PROPERTIES PREFIX "") -set_target_properties(chuniio_brokenithm PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32") -target_link_libraries(chuniio_brokenithm ws2_32) +set_target_properties(chuniio_brokenithm PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32 -Wl,--allow-multiple-definition") +target_link_libraries(chuniio_brokenithm "-static-libgcc -Wl,-Bstatic -limobiledevice-1.0 -lssl -lcrypto -lplist-2.0 -lusbmuxd-2.0 -lwinpthread -Wl,-Bdynamic -lws2_32 -lcrypt32 -liphlpapi") diff --git a/src/chuniio.c b/src/chuniio.c index 6259ef3..ad5e375 100644 --- a/src/chuniio.c +++ b/src/chuniio.c @@ -6,10 +6,10 @@ #include #include -#include #include #include -#include + +#include #include "config.h" #include "struct.h" @@ -20,15 +20,10 @@ struct IPCMemoryInfo* chuni_io_file_mapping; const char *memFileName = "Local\\BROKENITHM_SHARED_BUFFER"; -char remote_address[BUFSIZ]; -uint16_t remote_port = 52468; +//region Brokenithm Android uint16_t server_port = 52468; bool tcp_mode = false; -volatile sig_atomic_t EXIT_FLAG = false, CONNECTED = false; - -uint32_t last_input_packet_id = 0; - enum { CARD_AIME, CARD_FELICA, @@ -40,16 +35,21 @@ enum { }; typedef struct { - SOCKET sHost; + SOCKET sock; + char remote_address[BUFSIZ]; + uint16_t remote_port; + bool exit_flag; + bool connected; + uint32_t last_input_packet_id; struct IPCMemoryInfo* memory; -} thread_args; +} android_thread_ctx; -void socket_set_timeout(SOCKET sHost, int timeout) { +void socket_set_timeout(const SOCKET sHost, int timeout) { setsockopt(sHost, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(int)); setsockopt(sHost, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(int)); } -int socket_bind(SOCKET sHost, unsigned long addr, uint16_t port) { +int socket_bind(const SOCKET sHost, const unsigned long addr, const uint16_t port) { struct sockaddr_in srcaddr = {}; memset(&srcaddr, 0, sizeof(srcaddr)); srcaddr.sin_family = AF_INET; @@ -58,13 +58,13 @@ int socket_bind(SOCKET sHost, unsigned long addr, uint16_t port) { return bind(sHost, (struct sockaddr*)&srcaddr, sizeof(srcaddr)); } -int socket_send_to(SOCKET sHost, const struct sockaddr_in* addr, const char* buf, int len) { +int socket_send_to(const SOCKET sHost, const struct sockaddr_in* addr, const char* buf, const int len) { return sendto(sHost, buf, len, 0, (struct sockaddr*)&addr, sizeof(&addr)); } void print_err(const char* fmt, ...) { - time_t lt = time(NULL); - struct tm *local = localtime(<); + const time_t lt = time(NULL); + const struct tm *local = localtime(<); char tmpbuf[32]; strftime(tmpbuf, 32, "%Y-%m-%d %H:%M:%S", local); @@ -77,7 +77,7 @@ void print_err(const char* fmt, ...) { va_end(ap); } -void get_socks_address(const struct PacketConnect* pkt, char* address, int address_len, uint16_t *port) { +void get_socks_address(const struct PacketConnect* pkt, char* address, const int address_len, uint16_t *port) { if (!pkt || !address || !port) { return; } @@ -96,23 +96,21 @@ void get_socks_address(const struct PacketConnect* pkt, char* address, int addre } } -void update_packet_id(uint32_t new_packet_id) +void update_packet_id(android_thread_ctx* ctx, const uint32_t new_packet_id) { - if (last_input_packet_id > new_packet_id) { + if (ctx->last_input_packet_id > new_packet_id) { print_err("[WARN] Packet #%" PRIu32 " came too late\n", new_packet_id); - } else if (new_packet_id > last_input_packet_id + 1) { + } else if (new_packet_id > ctx->last_input_packet_id + 1) { print_err("[WARN] Packets between #%" PRIu32 " and #%" PRIu32 " total %" PRIu32 " packet(s) are missing, probably too late or dropped\n", - last_input_packet_id, new_packet_id, new_packet_id - last_input_packet_id - 1); - } else if (new_packet_id == last_input_packet_id) { + ctx->last_input_packet_id, new_packet_id, new_packet_id - ctx->last_input_packet_id - 1); + } else if (new_packet_id == ctx->last_input_packet_id) { print_err("[WARN] Packet #%" PRIu32 " duplicated\n", new_packet_id); } - last_input_packet_id = new_packet_id; + ctx->last_input_packet_id = new_packet_id; } -void dump_bytes(const void *ptr, size_t nbytes, bool hex_string) +void dump_bytes(const void *ptr, const size_t nbytes, const bool hex_string) { - const uint8_t *bytes; - uint8_t c; size_t i; size_t j; @@ -120,7 +118,7 @@ void dump_bytes(const void *ptr, size_t nbytes, bool hex_string) dprintf("\t--- Empty ---\n"); } - bytes = (const unsigned char*)ptr; + const uint8_t* bytes = ptr; if (hex_string) { for (i = 0 ; i < nbytes ; i++) { @@ -145,7 +143,7 @@ void dump_bytes(const void *ptr, size_t nbytes, bool hex_string) dprintf(" "); for (j = 0 ; i + j < nbytes && j < 16 ; j++) { - c = bytes[i + j]; + uint8_t c = bytes[i + j]; if (c < 0x20 || c >= 0x7F) { c = '.'; @@ -160,7 +158,7 @@ void dump_bytes(const void *ptr, size_t nbytes, bool hex_string) dprintf("\n"); } -void print_card_info(uint8_t card_type, uint8_t *card_id) { +void print_card_info(const uint8_t card_type, const uint8_t *card_id) { switch (card_type) { case CARD_AIME: print_err("[INFO] Card type: AiMe, ID: "); @@ -175,7 +173,7 @@ void print_card_info(uint8_t card_type, uint8_t *card_id) { } } -int make_ipv4_address(struct sockaddr_in* addr, char* host, uint16_t port) { +int make_ipv4_address(struct sockaddr_in* addr, const char* host, const uint16_t port) { addr->sin_family = AF_INET; addr->sin_port = htons(port); return inet_pton(AF_INET, host, (struct in_addr *)&addr->sin_addr.s_addr); @@ -185,25 +183,25 @@ uint8_t previous_led_status[3 * 32]; bool has_previous_led_status = false; int skip_count = 0; -unsigned int __stdcall thread_led_broadcast(void *ctx) { - thread_args *args = (thread_args*)ctx; +unsigned int __stdcall android_led_broadcast_thread_proc(void *v) { + android_thread_ctx *ctx = v; - SOCKET sHost = args->sHost; - struct IPCMemoryInfo* memory = args->memory; + const SOCKET sHost = ctx->sock; + const struct IPCMemoryInfo* memory = ctx->memory; struct sockaddr_in addr = {}; - make_ipv4_address(&addr, remote_address, remote_port); + make_ipv4_address(&addr, ctx->remote_address, ctx->remote_port); char send_buffer[4 + 3 * 32]; - send_buffer[0] = 100; + send_buffer[0] = 99; send_buffer[1] = 'L'; send_buffer[2] = 'E'; send_buffer[3] = 'D'; - uint8_t current_led_status[3 * 32]; + while (!ctx->exit_flag) { + uint8_t current_led_status[3 * 32]; - while (!EXIT_FLAG) { - if (!CONNECTED) { + if (!ctx->connected) { Sleep(50); continue; } @@ -213,7 +211,7 @@ unsigned int __stdcall thread_led_broadcast(void *ctx) { bool same; if (!has_previous_led_status) { - same = (memcmp(previous_led_status, current_led_status, 3 * 32) == 0); + same = memcmp(previous_led_status, current_led_status, 3 * 32) == 0; } else { same = false; } @@ -230,12 +228,12 @@ unsigned int __stdcall thread_led_broadcast(void *ctx) { if (tcp_mode) { if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { continue; - } else { - print_err("[INFO] Device disconnected!\n"); - CONNECTED = false; - EXIT_FLAG = true; - break; } + + print_err("[INFO] Device disconnected!\n"); + ctx->connected = false; + ctx->exit_flag = true; + break; } } @@ -250,21 +248,21 @@ unsigned int __stdcall thread_led_broadcast(void *ctx) { uint8_t last_card_id[10]; -unsigned int __stdcall thread_input_recv(void *ctx) { - thread_args *args = (thread_args*)ctx; +unsigned int __stdcall android_input_recv_thread_proc(void *v) { + android_thread_ctx *ctx = v; - SOCKET sHost = args->sHost; - struct IPCMemoryInfo* memory = args->memory; - - char buffer[BUFSIZ]; + const SOCKET sHost = ctx->sock; + struct IPCMemoryInfo* memory = ctx->memory; struct sockaddr_in addr = {}; - make_ipv4_address(&addr, remote_address, remote_port); + make_ipv4_address(&addr, ctx->remote_address, ctx->remote_port); int recv_len, packet_len; uint8_t real_len; - while (!EXIT_FLAG) { + while (!ctx->exit_flag) { + char buffer[BUFSIZ]; + if (!tcp_mode) { /** on UDP mode data is sent as packets, so just receive into a buffer big enough for 1 packet @@ -290,17 +288,17 @@ unsigned int __stdcall thread_input_recv(void *ctx) { recv_len = 0; while (recv_len < 4) { - int read = recv(sHost, buffer + recv_len, 4 - recv_len, 0); + const int read = recv(sHost, buffer + recv_len, 4 - recv_len, 0); if (read == -1) { if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { continue; - } else { - print_err("[INFO] Device disconnected!\n"); - CONNECTED = false; - EXIT_FLAG = true; - break; } + + print_err("[INFO] Device disconnected!\n"); + ctx->connected = false; + ctx->exit_flag = true; + break; } recv_len = recv_len + read; @@ -310,42 +308,42 @@ unsigned int __stdcall thread_input_recv(void *ctx) { packet_len = real_len + 1; while (recv_len < packet_len) { - int read = recv(sHost, buffer + recv_len, packet_len - recv_len, 0); + const int read = recv(sHost, buffer + recv_len, packet_len - recv_len, 0); if (read == -1) { if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { continue; - } else { - print_err("[INFO] Device disconnected!\n"); - CONNECTED = false; - EXIT_FLAG = true; - break; } + + print_err("[INFO] Device disconnected!\n"); + ctx->connected = false; + ctx->exit_flag = true; + break; } recv_len = recv_len + read; } } - if (packet_len >= sizeof(struct PacketInput) && buffer[1] == 'I' && buffer[2] == 'N' && buffer[3] == 'P') { - struct PacketInput* pkt = (struct PacketInput*)buffer; + if (packet_len >= sizeof(struct PacketInput) && memcmp(buffer + 1, "INP", 3) == 0) { + const struct PacketInput* pkt = (struct PacketInput*)buffer; memcpy(memory->airIoStatus, pkt->airIoStatus, sizeof(pkt->airIoStatus)); memcpy(memory->sliderIoStatus, pkt->sliderIoStatus, sizeof(pkt->sliderIoStatus)); memory->testBtn = pkt->testBtn; memory->serviceBtn = pkt->serviceBtn; - update_packet_id(ntohl(pkt->packetId)); - } else if (packet_len >= sizeof(struct PacketInputNoAir) && buffer[1] == 'I' && buffer[2] == 'P' && buffer[3] == 'T') { // without air - struct PacketInputNoAir* pkt = (struct PacketInputNoAir*)buffer; + update_packet_id(ctx, ntohl(pkt->packetId)); + } else if (packet_len >= sizeof(struct PacketInputNoAir) && memcmp(buffer + 1, "IPT", 3) == 0) { // without air + const struct PacketInputNoAir* pkt = (struct PacketInputNoAir*)buffer; memcpy(memory->sliderIoStatus, pkt->sliderIoStatus, sizeof(pkt->sliderIoStatus)); memory->testBtn = pkt->testBtn; memory->serviceBtn = pkt->serviceBtn; - update_packet_id(ntohl(pkt->packetId)); - } else if (packet_len >= sizeof(struct PacketFunction) && buffer[1] == 'F' && buffer[2] == 'N' && buffer[3] == 'C') { - struct PacketFunction* pkt = (struct PacketFunction*)buffer; + update_packet_id(ctx, ntohl(pkt->packetId)); + } else if (packet_len >= sizeof(struct PacketFunction) && memcmp(buffer + 1, "FNC", 3) == 0) { + const struct PacketFunction* pkt = (struct PacketFunction*)buffer; switch (pkt->funcBtn) { case FUNCTION_COIN: @@ -354,30 +352,36 @@ unsigned int __stdcall thread_input_recv(void *ctx) { case FUNCTION_CARD: memory->cardRead = 1; break; + default: + break; } - } else if (packet_len >= sizeof(struct PacketConnect) && buffer[1] == 'C' && buffer[2] == 'O' && buffer[3] == 'N') { - struct PacketConnect* pkt = (struct PacketConnect*)buffer; + } else if (packet_len >= sizeof(struct PacketConnect) && memcmp(buffer + 1, "CON", 3) == 0) { + const struct PacketConnect* pkt = (struct PacketConnect*)buffer; - get_socks_address(pkt, remote_address, BUFSIZ - 1, &remote_port); - print_err("[INFO] Device %s:%d connected.\n", remote_address, remote_port); + get_socks_address(pkt, ctx->remote_address, BUFSIZ - 1, &ctx->remote_port); + print_err("[INFO] Device %s:%d connected.\n", ctx->remote_address, ctx->remote_port); - last_input_packet_id = 0; - CONNECTED = true; - } else if (packet_len >= 4 && buffer[1] == 'D' && buffer[2] == 'I' && buffer[3] == 'S') { - CONNECTED = false; + ctx->last_input_packet_id = 0; + ctx->connected = true; + } else if (packet_len >= 4 && memcmp(buffer + 1, "DIS", 3) == 0) { + ctx->connected = false; if (tcp_mode) { - EXIT_FLAG = 1; + ctx->exit_flag = true; print_err("[INFO] Device disconnected!\n"); break; } - if (strlen(remote_address)) { - print_err("[INFO] Device %s:%d disconnected.\n", remote_address, remote_port); - memset(remote_address, 0, BUFSIZ); + if (strlen(ctx->remote_address)) { + print_err("[INFO] Device %s:%d disconnected.\n", ctx->remote_address, ctx->remote_port); + memset(ctx->remote_address, 0, BUFSIZ); } - } else if (packet_len >= sizeof(struct PacketPing) && buffer[1] == 'P' && buffer[2] == 'I' && buffer[3] == 'N') { - if (!CONNECTED) { + + if (tcp_mode) { + break; + } + } else if (packet_len >= sizeof(struct PacketPing) && memcmp(buffer + 1, "PIN", 3) == 0) { + if (!ctx->connected) { continue; } @@ -386,8 +390,8 @@ unsigned int __stdcall thread_input_recv(void *ctx) { response[2] = 'O'; socket_send_to(sHost, &addr, response, 13); - } else if (packet_len >= sizeof(struct PacketCard) && buffer[1] == 'C' && buffer[2] == 'R' && buffer[3] == 'D') { - struct PacketCard* pkt = (struct PacketCard*)buffer; + } else if (packet_len >= sizeof(struct PacketCard) && memcmp(buffer + 1, "CRD", 3) == 0) { + const struct PacketCard* pkt = (struct PacketCard*)buffer; if (pkt->remoteCardRead) { if (memcmp(last_card_id, pkt->remoteCardId, 10) != 0) { @@ -410,21 +414,27 @@ unsigned int __stdcall thread_input_recv(void *ctx) { } unsigned int __stdcall server_thread_proc(void* ctx) { - struct IPCMemoryInfo* memory = (struct IPCMemoryInfo*)ctx; + struct IPCMemoryInfo* memory = ctx; if (!tcp_mode) { print_err("[INFO] Mode: UDP\n"); - SOCKET sHost = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - socket_set_timeout(sHost, 2000); - socket_bind(sHost, htonl(INADDR_ANY), server_port); + const SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + socket_set_timeout(sock, 2000); + socket_bind(sock, htonl(INADDR_ANY), server_port); print_err("[INFO] Waiting for device on port %d...\n", server_port); - thread_args args = { .memory = memory, .sHost = sHost }; + android_thread_ctx args = { + .sock = sock, + .exit_flag = false, + .connected = true, + .last_input_packet_id = 0, + .memory = memory, + }; - HANDLE led_thread = (HANDLE)_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL); - HANDLE input_thread = (HANDLE)_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL); + HANDLE led_thread = (HANDLE) _beginthreadex(NULL, 0, android_led_broadcast_thread_proc, &args, 0, NULL); + HANDLE input_thread = (HANDLE) _beginthreadex(NULL, 0, android_input_recv_thread_proc, &args, 0, NULL); WaitForSingleObject(led_thread, INFINITE); WaitForSingleObject(input_thread, INFINITE); @@ -433,20 +443,22 @@ unsigned int __stdcall server_thread_proc(void* ctx) { CloseHandle(input_thread); } else { print_err("[INFO] Mode: TCP\n"); - SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + const SOCKET sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); socket_set_timeout(sHost, 50); socket_bind(sHost, htonl(INADDR_ANY), server_port); listen(sHost, 10); + print_err("[INFO] Waiting for device on port %d...\n", server_port); + #pragma clang diagnostic push #pragma ide diagnostic ignored "EndlessLoop" + // ReSharper disable once CppDFAEndlessLoop for (;;) { - print_err("[INFO] Waiting for device on port %d...\n", server_port); struct sockaddr_in user_socket = {}; socklen_t sock_size = sizeof(struct sockaddr_in); - SOCKET acc_socket = accept(sHost, (struct sockaddr *)&user_socket, &sock_size); + const SOCKET acc_socket = accept(sHost, (struct sockaddr *)&user_socket, &sock_size); char buffer[20] = {}; const char* user_address = inet_ntop(AF_INET, &user_socket.sin_addr, buffer, 20); @@ -454,41 +466,219 @@ unsigned int __stdcall server_thread_proc(void* ctx) { print_err("[INFO] Device %s:%d connected.\n", user_address, user_socket.sin_port); } - CONNECTED = true; - EXIT_FLAG = false; + android_thread_ctx args = { + .sock = acc_socket, + .exit_flag = false, + .connected = true, + .last_input_packet_id = 0, + .memory = memory, + }; - thread_args args = { .memory = memory, .sHost = acc_socket }; - - HANDLE led_thread = (HANDLE)_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL); - HANDLE input_thread = (HANDLE)_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL); - - WaitForSingleObject(led_thread, INFINITE); - WaitForSingleObject(input_thread, INFINITE); - - CloseHandle(led_thread); - CloseHandle(input_thread); - - print_err("[INFO] Exiting gracefully...\n"); - last_input_packet_id = 0; - EXIT_FLAG = true; - CONNECTED = false; + _beginthreadex(NULL, 0, android_led_broadcast_thread_proc, &args, 0, NULL); + _beginthreadex(NULL, 0, android_input_recv_thread_proc, &args, 0, NULL); } #pragma clang diagnostic pop } return 0; } +//endregion + +//region Brokenithm iOS +typedef struct { + char remote_udid[41]; + bool exit_flag; + struct IPCMemoryInfo* memory; + idevice_t device; + idevice_connection_t connection; +} ios_thread_ctx; + +unsigned int __stdcall ios_led_broadcast_thread_proc(void *v) { + ios_thread_ctx* ctx = v; + + char send_buffer[4 + 3 * 32]; + send_buffer[0] = 99; + send_buffer[1] = 'L'; + send_buffer[2] = 'E'; + send_buffer[3] = 'D'; + + while (!ctx->exit_flag) { + uint8_t current_led_status[3 * 32]; + + memcpy(current_led_status, ctx->memory->ledRgbData, 3 * 32); + + bool same; + + if (!has_previous_led_status) { + same = memcmp(previous_led_status, current_led_status, 3 * 32) == 0; + } else { + same = false; + } + + memcpy(previous_led_status, current_led_status, 3 * 32); + has_previous_led_status = true; + + if (!same || ++skip_count > 50) { + memcpy(send_buffer + 4, current_led_status, 3 * 32); + + int status; + uint32_t sent; + if ((status = idevice_connection_send(ctx->connection, send_buffer, 100, &sent))) { + print_err("[ERROR] Cannot send LED packet: error %d\n", status); + } + + skip_count = 0; + } + + Sleep(10); + } + + return 0; +} + +unsigned int __stdcall ios_input_recv_thread_proc(void *v) { + ios_thread_ctx* ctx = v; + + bool air_enabled = true; + + while (!ctx->exit_flag) { + char buffer[BUFSIZ]; + int status; + uint32_t read; + + if ((status = idevice_connection_receive_timeout(ctx->connection, buffer, 4, &read, 5))) { + if (status == IDEVICE_E_TIMEOUT) { + continue; + } + + print_err("[ERROR] Could not read data from device: %d\n", status); + ctx->exit_flag = true; + + break; + } + + int len = (unsigned char)buffer[0]; + + if ((status = idevice_connection_receive_timeout(ctx->connection, buffer + 4, len - 3, &read, 5))) { + print_err("[ERROR] Could not read data from device: %d\n", status); + ctx->exit_flag = true; + + break; + } + + if (len >= sizeof(struct iOSPacketInput) && memcmp(buffer + 1, "INP", 3) == 0) { + struct iOSPacketInput* pkt = (struct iOSPacketInput*)buffer; + + if (air_enabled) { + memcpy(ctx->memory->airIoStatus, pkt->airIoStatus, sizeof(pkt->airIoStatus)); + } + + memcpy(ctx->memory->sliderIoStatus, pkt->sliderIoStatus, sizeof(pkt->sliderIoStatus)); + ctx->memory->testBtn = pkt->testBtn; + ctx->memory->serviceBtn = pkt->serviceBtn; + } else if (len >= 4 && memcmp(buffer + 1, "AIR", 3) == 0) { + air_enabled = buffer[3] != 0; + + print_err("[INFO] Air input %s", air_enabled ? "enabled" : "disabled"); + } else if (len >= sizeof(struct PacketFunction) && memcmp(buffer + 1, "FNC", 3) == 0) { + const struct PacketFunction *pkt = (struct PacketFunction *) buffer; + + switch (pkt->funcBtn) { + case FUNCTION_COIN: + ctx->memory->coinInsertion = 1; + break; + case FUNCTION_CARD: + ctx->memory->cardRead = 1; + break; + default: + break; + } + } + } + + print_err("[INFO] Device disconnected."); + idevice_disconnect(ctx->connection); + free(ctx->connection); + idevice_free(ctx->device); +} + +unsigned int __stdcall connect_device(void* v) { + ios_thread_ctx* ctx = v; + + int status; + if ((status = idevice_new(&ctx->device, ctx->remote_udid))) { + print_err("[ERROR] Create device failed: %d\n", status); + idevice_free(ctx->device); + return 1; + } + + if ((status = idevice_connect(ctx->device, 24864, &ctx->connection))) { + print_err("[ERROR] Connection failed: %d, retrying in 5 seconds\n", status); + free(ctx->connection); + idevice_free(ctx->device); + + Sleep(5000); + + _beginthreadex(NULL, 0, connect_device, ctx, 0, NULL); + + return 1; + } + + char buf[5]; + uint32_t read; + + if ((status = idevice_connection_receive(ctx->connection, buf, 4, &read))) { + print_err("[ERROR] Receiving data failed: %d\n", status); + idevice_disconnect(ctx->connection); + free(ctx->connection); + idevice_free(ctx->device); + return 1; + } + + if (memcmp(buf, "\x03WEL", 4) != 0) { + print_err("[ERROR] Client sent invalid data\n"); + idevice_disconnect(ctx->connection); + free(ctx->connection); + idevice_free(ctx->device); + return 1; + } + + print_err("[INFO] Connected to device\n"); + _beginthreadex(NULL, 0, ios_input_recv_thread_proc, ctx, 0, NULL); + _beginthreadex(NULL, 0, ios_led_broadcast_thread_proc, ctx, 0, NULL); + + return 0; +} + +void device_event_callback(const idevice_event_t* event, void* user_data) { + struct IPCMemoryInfo* memory = user_data; + + switch (event->event) { + case IDEVICE_DEVICE_ADD: + print_err("[INFO] iDevice added, udid: %s\n", event->udid); + + ios_thread_ctx args = { + .exit_flag = false, + .memory = memory, + }; + + memcpy(args.remote_udid, event->udid, strlen(event->udid)); + _beginthreadex(NULL, 0, connect_device, &args, 0, NULL); + break; + case IDEVICE_DEVICE_REMOVE: + print_err("[INFO] iDevice removed, udid: %s\n", event->udid); + break; + case IDEVICE_DEVICE_PAIRED: + print_err("[INFO] iDevice paired, udid: %s\n", event->udid); + break; + } +} +//endregion HRESULT server_start() { tcp_mode = GetPrivateProfileIntW(L"brokenithm", L"tcp", 0, L".\\segatools.ini") == 1; server_port = GetPrivateProfileIntW(L"brokenithm", L"port", 52468, L".\\segatools.ini"); - struct WSAData wsaData = {}; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - print_err("[ERROR] WSA startup failed!\n"); - return E_FAIL; - } - HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, memFileName); if (hMapFile == NULL) { @@ -499,7 +689,7 @@ HRESULT server_start() { } } - struct IPCMemoryInfo* memory = (struct IPCMemoryInfo*)MapViewOfFileEx(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024, NULL); + struct IPCMemoryInfo* memory = MapViewOfFileEx(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024, NULL); chuni_io_file_mapping = memory; if (memory == NULL) { @@ -507,8 +697,22 @@ HRESULT server_start() { return E_FAIL; } + struct WSAData wsaData = {}; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + print_err("[ERROR] WSA startup failed!\n"); + return E_FAIL; + } + _beginthreadex(NULL, 0, server_thread_proc, memory, 0, NULL); + int status; + if ((status = idevice_event_subscribe(device_event_callback, memory))) { + print_err("[ERROR] Subscribing for iDevice events failed: %d\n", status); + return E_FAIL; + } else { + print_err("[INFO] Waiting for iDevices..."); + } + return S_OK; } //endregion @@ -530,7 +734,7 @@ uint16_t chuni_io_get_api_version() { HRESULT chuni_io_jvs_init() { chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini"); - HRESULT result = server_start(); + const HRESULT result = server_start(); if (result != S_OK) { return result; } @@ -538,8 +742,8 @@ HRESULT chuni_io_jvs_init() { return S_OK; } -void chuni_io_jvs_read_coin_counter(uint16_t *out) { - if (out == NULL) { +void chuni_io_jvs_read_coin_counter(uint16_t *total) { + if (total == NULL) { return; } @@ -557,7 +761,7 @@ void chuni_io_jvs_read_coin_counter(uint16_t *out) { } } - *out = chuni_io_coins; + *total = chuni_io_coins; } void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) { @@ -590,9 +794,9 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) { // IR format is beams[5:0] = {b5,b6,b3,b4,b1,b2}; for (i = 0 ; i < 3 ; i++) { if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i*2]) - *beams |= (1 << (i*2+1)); + *beams |= 1 << (i * 2 + 1); if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i*2+1]) - *beams |= (1 << (i*2)); + *beams |= 1 << i * 2; } } @@ -641,14 +845,13 @@ void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {} static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx) { - chuni_io_slider_callback_t callback; - uint8_t pressure[32]; - - callback = (chuni_io_slider_callback_t)ctx; + const chuni_io_slider_callback_t callback = ctx; #pragma clang diagnostic push #pragma ide diagnostic ignored "LoopDoesntUseConditionVariableInspection" + // ReSharper disable once CppDFALoopConditionNotUpdated while (!chuni_io_slider_stop_flag) { + uint8_t pressure[32]; if (chuni_io_file_mapping) { memcpy(pressure, chuni_io_file_mapping->sliderIoStatus, 32); } diff --git a/src/struct.h b/src/struct.h index e8f5cda..f767cbe 100644 --- a/src/struct.h +++ b/src/struct.h @@ -25,6 +25,15 @@ struct IPCMemoryInfo uint8_t remoteCardId[10]; }; +struct iOSPacketInput { + uint8_t packetSize; + uint8_t packetName[3]; + uint8_t airIoStatus[6]; + uint8_t sliderIoStatus[32]; + uint8_t testBtn; + uint8_t serviceBtn; +}; + struct PacketInput { uint8_t packetSize;