248 lines
7.0 KiB
C
248 lines
7.0 KiB
C
//
|
|
// Created by beerpsi on 12/31/2023.
|
|
//
|
|
|
|
#include "ios.h"
|
|
#include "arch.h"
|
|
|
|
#ifdef ENV32BIT
|
|
#include <libimobiledevice/libimobiledevice.h>
|
|
#include <process.h>
|
|
#include <stdatomic.h>
|
|
|
|
#include "servers/common.h"
|
|
|
|
typedef struct {
|
|
char remote_udid[41];
|
|
idevice_t device;
|
|
idevice_connection_t connection;
|
|
|
|
atomic_bool exit_flag;
|
|
|
|
bool has_previous_led_status;
|
|
uint8_t previous_led_status[3 * 32];
|
|
uint8_t led_skip_count;
|
|
|
|
struct IPCMemoryInfo *memory;
|
|
} 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 (!atomic_load(&ctx->exit_flag)) {
|
|
uint8_t current_led_status[3 * 32];
|
|
|
|
memcpy(current_led_status, ctx->memory->ledRgbData, 3 * 32);
|
|
|
|
bool same;
|
|
|
|
if (!ctx->has_previous_led_status) {
|
|
same = memcmp(ctx->previous_led_status, current_led_status, 3 * 32) == 0;
|
|
} else {
|
|
same = false;
|
|
}
|
|
|
|
memcpy(ctx->previous_led_status, current_led_status, 3 * 32);
|
|
ctx->has_previous_led_status = true;
|
|
|
|
if (!same || ++ctx->led_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("[iOS:ERROR] Cannot send LED packet: error %d\n", status);
|
|
}
|
|
|
|
ctx->led_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 (!atomic_load(&ctx->exit_flag)) {
|
|
char buffer[96];
|
|
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("[iOS:ERROR] Could not read data from device: %d\n", status);
|
|
atomic_store(&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("[iOS:ERROR] Could not read data from device: %d\n", status);
|
|
atomic_store(&ctx->exit_flag, true);
|
|
|
|
break;
|
|
}
|
|
|
|
if (len >= sizeof(struct PacketInput) && memcmp(buffer + 1, "INP", 3) == 0) {
|
|
struct PacketInput *pkt = (struct PacketInput *)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 >= sizeof(struct PacketAirStatus) && memcmp(buffer + 1, "AIR", 3) == 0) {
|
|
struct PacketAirStatus *pkt = (struct PacketAirStatus *)buffer;
|
|
|
|
air_enabled = pkt->airEnabled != 0;
|
|
|
|
print_err("[iOS: INFO] Air input %s\n", 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("[iOS: INFO] Device disconnected.\n");
|
|
|
|
idevice_disconnect(ctx->connection);
|
|
ctx->connection = NULL;
|
|
|
|
idevice_free(ctx->device);
|
|
free(ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
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("[iOS:ERROR] Create device failed: %d\n", status);
|
|
idevice_free(ctx->device);
|
|
return 1;
|
|
}
|
|
|
|
if ((status = idevice_connect(ctx->device, 24864, &ctx->connection))) {
|
|
print_err("[iOS:ERROR] Connection failed: %d, retrying in 5 seconds\n", status);
|
|
|
|
ctx->connection = NULL;
|
|
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("[iOS:ERROR] Receiving data failed: %d\n", status);
|
|
|
|
idevice_disconnect(ctx->connection);
|
|
ctx->connection = NULL;
|
|
|
|
idevice_free(ctx->device);
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (memcmp(buf, "\x03WEL", 4) != 0) {
|
|
print_err("[iOS:ERROR] Client sent invalid data\n");
|
|
|
|
idevice_disconnect(ctx->connection);
|
|
ctx->connection = NULL;
|
|
|
|
idevice_free(ctx->device);
|
|
|
|
return 1;
|
|
}
|
|
|
|
print_err("[iOS: INFO] Connected to device\n");
|
|
atomic_store(&ctx->exit_flag, false);
|
|
_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("[iOS: INFO] iDevice added, udid: %s\n", event->udid);
|
|
|
|
ios_thread_ctx *args = malloc(sizeof(ios_thread_ctx));
|
|
memcpy(args->remote_udid, event->udid, strlen(event->udid));
|
|
args->device = NULL;
|
|
args->connection = NULL;
|
|
args->exit_flag = ATOMIC_VAR_INIT(false);
|
|
args->has_previous_led_status = false;
|
|
args->led_skip_count = 0;
|
|
args->memory = memory;
|
|
|
|
_beginthreadex(NULL, 0, connect_device, args, 0, NULL);
|
|
break;
|
|
case IDEVICE_DEVICE_REMOVE:
|
|
print_err("[iOS: INFO] iDevice removed, udid: %s\n", event->udid);
|
|
break;
|
|
case IDEVICE_DEVICE_PAIRED:
|
|
print_err("[iOS: INFO] iDevice paired, udid: %s\n", event->udid);
|
|
break;
|
|
}
|
|
}
|
|
#endif // defined(ENV32BIT)
|
|
|
|
HRESULT ios_init_server(struct IPCMemoryInfo *memory) {
|
|
#ifdef ENV32BIT
|
|
int status;
|
|
if ((status = idevice_event_subscribe(device_event_callback, memory))) {
|
|
print_err("[iOS:ERROR] Subscribing for iDevice events failed: %d\n", status);
|
|
return E_FAIL;
|
|
} else {
|
|
print_err("[iOS: INFO] Waiting for iDevices...\n");
|
|
}
|
|
#endif // defined(ENV32BIT)
|
|
|
|
return S_OK;
|
|
}
|