forked from beerpsi/chuniio-brokenithm
ios code, but it doesn't work because linking bullshit
This commit is contained in:
parent
bf14d32980
commit
cd5503d380
@ -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")
|
||||
|
467
src/chuniio.c
467
src/chuniio.c
@ -6,10 +6,10 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libimobiledevice/libimobiledevice.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user