Compare commits

...

9 Commits

27 changed files with 832 additions and 386 deletions

View File

@ -5,6 +5,12 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include_directories("${CMAKE_SOURCE_DIR}/include/")
set(CMAKE_C_STANDARD 11)
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if (IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif ()
include_directories(.)
add_subdirectory(aimeio)

View File

@ -27,10 +27,10 @@ coin=0x33
ir=0x20
[brokenithm]
; Use TCP instead of UDP for connections (default TCP)
; Brokenithm-Android: Use TCP instead of UDP for connections (default TCP)
tcp=1
; Port to accept connections on (default 52468)
; Brokenithm-Android: Port to accept connections on (default 52468)
port=52468
```

View File

@ -53,10 +53,7 @@ HRESULT aime_io_nfc_poll(uint8_t unit_no);
Minimum API version: 0x0100
*/
HRESULT aime_io_nfc_get_aime_id(
uint8_t unit_no,
uint8_t *luid,
size_t luid_size);
HRESULT aime_io_nfc_get_aime_id(uint8_t unit_no, uint8_t *luid, size_t luid_size);
/*
Attempt to read out a FeliCa card ID ("IDm"). The following are examples

View File

@ -1,33 +1,40 @@
cmake_minimum_required(VERSION 3.27)
project(chuniio_brokenithm)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include_directories("${CMAKE_SOURCE_DIR}/include/")
set(CMAKE_C_STANDARD 11)
link_directories(src)
add_library(chuniio_brokenithm SHARED src/chuniio.c
src/chuniio.h
src/config.c
src/config.h
src/socket.h
src/struct.h
src/servers/android.c
src/servers/android.h
src/servers/common.h
src/servers/common.c
src/servers/ios.c
src/servers/ios.h)
target_link_libraries(chuniio_brokenithm util)
set_target_properties(chuniio_brokenithm PROPERTIES PREFIX "")
target_include_directories(chuniio_brokenithm PRIVATE src)
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
# Ugly hack around libimobiledevice shipping a DllMain for some reason???
set_target_properties(chuniio_brokenithm PROPERTIES LINK_FLAGS "-Wl,--allow-multiple-definition")
target_link_libraries(chuniio_brokenithm "-static-libgcc -Wl,-Bstatic -limobiledevice-1.0 -lssl -lcrypto -lplist-2.0 -lusbmuxd-2.0 -lpthread -Wl,-Bdynamic -lws2_32 -lcrypt32 -liphlpapi")
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
target_link_libraries(chuniio_brokenithm "-static-libgcc")
endif ()
cmake_minimum_required(VERSION 3.27)
project(chuniio_brokenithm)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include_directories("${CMAKE_SOURCE_DIR}/include/")
set(CMAKE_C_STANDARD 11)
link_directories(src)
add_library(chuniio_brokenithm SHARED src/chuniio.c
src/chuniio.h
src/config.c
src/config.h
src/leddata.h
src/ledoutput.c
src/ledoutput.h
src/pipeimpl.c
src/pipeimpl.h
src/serialimpl.c
src/serialimpl.h
src/servers/socket.h
src/ipc_memory_info.h
src/servers/android.c
src/servers/android.h
src/servers/common.h
src/servers/common.c
src/servers/ios.c
src/servers/ios.h)
target_link_libraries(chuniio_brokenithm util)
set_target_properties(chuniio_brokenithm PROPERTIES PREFIX "")
target_include_directories(chuniio_brokenithm PRIVATE src)
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
# Ugly hack around libimobiledevice shipping a DllMain for some reason???
set_target_properties(chuniio_brokenithm PROPERTIES LINK_FLAGS "-Wl,--allow-multiple-definition")
target_link_libraries(chuniio_brokenithm "-static-libgcc -Wl,-Bstatic -limobiledevice-1.0 -lssl -lcrypto -lplist-2.0 -lusbmuxd-2.0 -lpthread -Wl,-Bdynamic -lws2_32 -lcrypt32 -liphlpapi")
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
target_link_libraries(chuniio_brokenithm "-static-libgcc")
endif ()

View File

@ -5,20 +5,14 @@
#ifndef BROKENITHM_ARCH_H
#define BROKENITHM_ARCH_H
#if _WIN32 || _WIN64
#if _WIN64
#define ENV64BIT
#else
#define ENV32BIT
#endif // _WIN64
#endif // _WIN32 || _WIN64
#include <stdint.h>
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENV64BIT
#if UINTPTR_MAX == UINT32_MAX
#define ENV32BIT
#elif UINTPTR_MAX == UINT64_MAX
#define ENV64BIT
#else
#define ENV32BIT
#endif // __x86_64__ || __ppc64__
#error "Environment is neither 32-bit nor 64-bit."
#endif
#endif // BROKENITHM_ARCH_H

View File

@ -5,85 +5,54 @@
#include "chuniio.h"
#include <process.h>
#include <stdatomic.h>
#include "arch.h"
#include "config.h"
#include "struct.h"
#define MEM_FILE_NAME "Local\\BROKENITHM_SHARED_BUFFER"
struct IPCMemoryInfo *chuni_io_file_mapping;
#include "ledoutput.h"
#include "ipc_memory_info.h"
#include "util/dprintf.h"
#ifdef ENV32BIT
#include "servers/android.h"
#include "servers/common.h"
#include "servers/ios.h"
HRESULT server_start() {
HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, MEM_FILE_NAME);
if (hMapFile == NULL) {
hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
1024, MEM_FILE_NAME);
if (hMapFile == NULL) {
print_err("[ERROR] CreateFileMapping failed! error: %lu\n", GetLastError());
return E_FAIL;
}
}
struct IPCMemoryInfo *memory =
MapViewOfFileEx(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024, NULL);
chuni_io_file_mapping = memory;
HRESULT result;
if ((result = android_init_server(memory))) {
print_err("[ERROR] Android server intialization failed: %ld", result);
return result;
}
if ((result = ios_init_server(memory))) {
print_err("[ERROR] iOS server initialization failed: %ld", result);
return result;
}
return S_OK;
}
#endif
#ifdef ENV64BIT
#include "util/dprintf.h"
#define MEM_FILE_NAME "Local\\BROKENITHM_SHARED_BUFFER"
static HANDLE chuni_io_file_mapping_handle;
struct IPCMemoryInfo *chuni_io_file_mapping;
void chuni_io_init_shared_memory() {
HRESULT chuni_io_init_shared_memory() {
if (chuni_io_file_mapping) {
dprintf("chuni_io_init_shared_memory: shared memory already exists\n");
return;
return E_FAIL;
}
if ((chuni_io_file_mapping_handle =
CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
sizeof(struct IPCMemoryInfo), MEM_FILE_NAME)) == 0) {
CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
sizeof(struct IPCMemoryInfo), MEM_FILE_NAME)) == 0) {
dprintf("chuni_io_init_shared_memory: could not create file mapping: %ld\n",
GetLastError());
return;
return E_FAIL;
}
if ((chuni_io_file_mapping = (struct IPCMemoryInfo *)MapViewOfFile(
chuni_io_file_mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0,
sizeof(struct IPCMemoryInfo))) == 0) {
if ((chuni_io_file_mapping = (struct IPCMemoryInfo *) MapViewOfFile(
chuni_io_file_mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0,
sizeof(struct IPCMemoryInfo))) == 0) {
dprintf("chuni_io_init_shared_memory: could not get view of file: %ld\n",
GetLastError());
return;
return E_FAIL;
}
memset(chuni_io_file_mapping, 0, sizeof(struct IPCMemoryInfo));
SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
return S_OK;
}
#endif
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx);
@ -91,7 +60,7 @@ static bool chuni_io_coin;
static uint16_t chuni_io_coins;
static uint8_t chuni_io_hand_pos;
static HANDLE chuni_io_slider_thread;
static bool chuni_io_slider_stop_flag;
static volatile atomic_flag chuni_io_slider_run_flag;
static struct chuni_io_config chuni_io_cfg;
uint16_t chuni_io_get_api_version() { return 0x0102; }
@ -99,14 +68,30 @@ uint16_t chuni_io_get_api_version() { return 0x0102; }
HRESULT chuni_io_jvs_init() {
chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini");
#ifdef ENV32BIT
HRESULT result = server_start();
if (result != S_OK) {
HRESULT result;
if ((result = chuni_io_init_shared_memory())) {
return result;
}
led_init_mutex = CreateMutex(NULL, FALSE, NULL);
if (led_init_mutex == NULL) {
return E_FAIL;
}
#ifdef ENV32BIT
if ((result = android_init_server(chuni_io_file_mapping))) {
print_err("[ERROR] Android server intialization failed: %ld", result);
return result;
}
if ((result = ios_init_server(chuni_io_file_mapping))) {
print_err("[ERROR] iOS server initialization failed: %ld", result);
return result;
}
#endif
#ifdef ENV64BIT
chuni_io_init_shared_memory();
#endif
return S_OK;
@ -139,12 +124,12 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) {
if ((chuni_io_file_mapping && chuni_io_file_mapping->testBtn) ||
GetAsyncKeyState(chuni_io_cfg.vk_test)) {
*opbtn |= CHUNI_IO_OPBTN_TEST; /* Test */
*opbtn |= CHUNI_IO_OPBTN_TEST;
}
if ((chuni_io_file_mapping && chuni_io_file_mapping->serviceBtn) ||
GetAsyncKeyState(chuni_io_cfg.vk_service)) {
*opbtn |= CHUNI_IO_OPBTN_SERVICE; /* Service */
*opbtn |= CHUNI_IO_OPBTN_SERVICE;
}
if (GetAsyncKeyState(chuni_io_cfg.vk_ir_emu)) {
@ -172,15 +157,19 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) {
}
}
HRESULT chuni_io_slider_init() { return S_OK; }
HRESULT chuni_io_slider_init() {
return led_output_init(&chuni_io_cfg);
}
void chuni_io_slider_start(void *callback) {
if (chuni_io_slider_thread != NULL) {
return;
}
atomic_flag_test_and_set(&chuni_io_slider_run_flag);
chuni_io_slider_thread =
(HANDLE)_beginthreadex(NULL, 0, chuni_io_slider_thread_proc, callback, 0, NULL);
(HANDLE) _beginthreadex(NULL, 0, chuni_io_slider_thread_proc, callback, 0, NULL);
}
void chuni_io_slider_stop(void) {
@ -188,31 +177,33 @@ void chuni_io_slider_stop(void) {
return;
}
chuni_io_slider_stop_flag = true;
atomic_flag_clear(&chuni_io_slider_run_flag);
WaitForSingleObject(chuni_io_slider_thread, INFINITE);
CloseHandle(chuni_io_slider_thread);
chuni_io_slider_thread = NULL;
chuni_io_slider_stop_flag = false;
}
void chuni_io_slider_set_leds(const uint8_t *rgb) {
led_output_update(2, rgb);
if (chuni_io_file_mapping) {
memcpy(chuni_io_file_mapping->ledRgbData, rgb, 32 * 3);
}
}
HRESULT chuni_io_led_init(void) { return S_OK; }
HRESULT chuni_io_led_init(void) {
return led_output_init(&chuni_io_cfg);
}
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {}
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {
led_output_update(board, rgb);
}
static unsigned int __stdcall chuni_io_slider_thread_proc(void *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) {
while (atomic_flag_test_and_set(&chuni_io_slider_run_flag)) {
uint8_t pressure[32];
if (chuni_io_file_mapping) {
memcpy(pressure, chuni_io_file_mapping->sliderIoStatus, 32);
@ -221,7 +212,6 @@ static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx) {
callback(pressure);
Sleep(1);
}
#pragma clang diagnostic pop
return 0;
}

View File

@ -70,7 +70,6 @@ void __declspec(dllexport) chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams);
void __declspec(dllexport) chuni_io_jvs_read_coin_counter(uint16_t *total);
/* Initialize touch slider emulation. This function will be called before any
other chuni_io_slider_*() function calls.
@ -155,11 +154,13 @@ HRESULT __declspec(dllexport) chuni_io_led_init(void);
/* Update the RGB LEDs. rgb is a pointer to an array of up to 63 * 3 = 189 bytes.
Chunithm uses two chains/boards with WS2811 protocol (each logical led corresponds to 3 physical leds).
board 0 is on the left side and board 1 on the right side of the cab
Chunithm uses two chains/boards with WS2811 protocol (each logical led corresponds to
3 physical leds). board 0 is on the left side and board 1 on the right side of the
cab
left side has 5*10 rgb values for the billboard, followed by 3 rgb values for the air tower
right side has 6*10 rgb values for the billboard, followed by 3 rgb values for the air tower
left side has 5*10 rgb values for the billboard, followed by 3 rgb values for the air
tower right side has 6*10 rgb values for the billboard, followed by 3 rgb values for
the air tower
Each rgb value is comprised of 3 bytes in R,G,B order
@ -169,4 +170,4 @@ HRESULT __declspec(dllexport) chuni_io_led_init(void);
void __declspec(dllexport) chuni_io_led_set_colors(uint8_t board, uint8_t *rgb);
#endif //CHUNIIO_BROKENITHM_CHUNIIO_H
#endif // CHUNIIO_BROKENITHM_CHUNIIO_H

View File

@ -8,24 +8,13 @@
#include "config.h"
static const int chuni_io_default_cells[] = {
'L', 'L', 'L', 'L',
'K', 'K', 'K', 'K',
'J', 'J', 'J', 'J',
'H', 'H', 'H', 'H',
'G', 'G', 'G', 'G',
'F', 'F', 'F', 'F',
'D', 'D', 'D', 'D',
'S', 'S', 'S', 'S',
'L', 'L', 'L', 'L', 'K', 'K', 'K', 'K', 'J', 'J', 'J', 'J', 'H', 'H', 'H', 'H',
'G', 'G', 'G', 'G', 'F', 'F', 'F', 'F', 'D', 'D', 'D', 'D', 'S', 'S', 'S', 'S',
};
static const int chuni_io_default_ir[] = {
'4', '5', '6', '7', '8', '9'
};
static const int chuni_io_default_ir[] = {'4', '5', '6', '7', '8', '9'};
void chuni_io_config_load(
struct chuni_io_config *cfg,
const wchar_t *filename)
{
void chuni_io_config_load(struct chuni_io_config *cfg, const wchar_t *filename) {
wchar_t key[16];
int i;
wchar_t port_input[6];
@ -39,39 +28,32 @@ void chuni_io_config_load(
cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", '3', filename);
cfg->vk_ir_emu = GetPrivateProfileIntW(L"io3", L"ir", VK_SPACE, filename);
for (i = 0 ; i < 6 ; i++) {
for (i = 0; i < 6; i++) {
swprintf_s(key, _countof(key), L"ir%i", i + 1);
cfg->vk_ir[i] = GetPrivateProfileIntW(
L"ir",
key,
chuni_io_default_ir[i],
filename);
cfg->vk_ir[i] =
GetPrivateProfileIntW(L"ir", key, chuni_io_default_ir[i], filename);
}
for (i = 0 ; i < 32 ; i++) {
for (i = 0; i < 32; i++) {
swprintf_s(key, _countof(key), L"cell%i", i + 1);
cfg->vk_cell[i] = GetPrivateProfileIntW(
L"slider",
key,
chuni_io_default_cells[i],
filename);
cfg->vk_cell[i] =
GetPrivateProfileIntW(L"slider", key, chuni_io_default_cells[i], filename);
}
cfg->led_output_pipe = GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename);
cfg->led_output_serial = GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename);
cfg->slider_led_output_pipe = GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename);
cfg->slider_led_output_serial = GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename);
cfg->led_output_pipe =
GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename);
cfg->led_output_serial =
GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename);
cfg->led_serial_baud = GetPrivateProfileIntW(L"led", L"serialBaud", 921600, filename);
cfg->slider_led_output_pipe =
GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename);
cfg->slider_led_output_serial =
GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename);
GetPrivateProfileStringW(
L"led",
L"serialPort",
L"COM5",
port_input,
6,
filename);
cfg->led_serial_baud =
GetPrivateProfileIntW(L"led", L"serialBaud", 921600, filename);
GetPrivateProfileStringW(L"led", L"serialPort", L"COM5", port_input, 6, filename);
// Sanitize the output path. If it's a serial COM port, it needs to be prefixed
// with `\\.\`.

View File

@ -4,9 +4,9 @@
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
struct chuni_io_config {
uint8_t vk_test;
@ -26,12 +26,9 @@ struct chuni_io_config {
// The name of a COM port to output LED data on, in serial mode
wchar_t led_serial_port[12];
int32_t led_serial_baud;
};
void chuni_io_config_load(
struct chuni_io_config *cfg,
const wchar_t *filename);
void chuni_io_config_load(struct chuni_io_config *cfg, const wchar_t *filename);
#ifdef __cplusplus
}

View File

@ -0,0 +1,27 @@
//
// Created by beerpsi on 12/29/2023.
//
#ifndef CHUNIIO_BROKENITHM_STRUCT_H
#define CHUNIIO_BROKENITHM_STRUCT_H
#include <stdint.h>
;
#pragma pack(push)
#pragma pack(1)
struct IPCMemoryInfo {
uint8_t airIoStatus[6];
uint8_t sliderIoStatus[32];
uint8_t ledRgbData[32 * 3];
uint8_t testBtn;
uint8_t serviceBtn;
uint8_t coinInsertion;
uint8_t cardRead;
uint8_t remoteCardRead;
uint8_t remoteCardType;
uint8_t remoteCardId[10];
};
#pragma pack(pop)
#endif // CHUNIIO_BROKENITHM_STRUCT_H

22
chuniio/src/leddata.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <windows.h>
#include <stdint.h>
#define LED_PACKET_FRAMING 0xE0
#define LED_PACKET_ESCAPE 0xD0
#define LED_NUM_MAX 66
#define LED_BOARDS_TOTAL 3
#define LED_OUTPUT_HEADER_SIZE 2
#define LED_OUTPUT_DATA_SIZE_MAX LED_NUM_MAX * 3 * 2 // max if every byte's escaped
#define LED_OUTPUT_TOTAL_SIZE_MAX LED_OUTPUT_HEADER_SIZE + LED_OUTPUT_DATA_SIZE_MAX
// This struct is used to send data related to the slider and billboard LEDs
struct _chuni_led_data_buf_t {
byte framing; // Sync byte
uint8_t board; // LED output the data is for (0-1: billboard, 2: slider)
byte data[LED_OUTPUT_DATA_SIZE_MAX]; // Buffer for LEDs
byte data_len; // How many bytes to output from the buffer
};
static byte chuni_led_board_data_lens[LED_BOARDS_TOTAL] = {53*3, 63*3, 31*3};

131
chuniio/src/ledoutput.c Normal file
View File

@ -0,0 +1,131 @@
#include <windows.h>
#include <stdbool.h>
#include "config.h"
#include "leddata.h"
#include "ledoutput.h"
#include "pipeimpl.h"
#include "serialimpl.h"
static struct _chuni_led_data_buf_t led_unescaped_buf[LED_BOARDS_TOTAL];
static struct _chuni_led_data_buf_t led_escaped_buf[LED_BOARDS_TOTAL];
static bool led_output_is_init = false;
static struct chuni_io_config* config;
static bool any_outputs_enabled;
HANDLE led_init_mutex;
HRESULT led_output_init(struct chuni_io_config* const cfg)
{
DWORD dwWaitResult = WaitForSingleObject(led_init_mutex, INFINITE);
if (dwWaitResult == WAIT_FAILED)
{
return HRESULT_FROM_WIN32(GetLastError());
// return 1;
}
else if (dwWaitResult != WAIT_OBJECT_0)
{
return E_FAIL;
// return 1;
}
if (!led_output_is_init)
{
config = cfg;
// Set up the framing bytes for the packets
for (int i = 0; i < LED_BOARDS_TOTAL; i++) {
led_unescaped_buf[i].framing = LED_PACKET_FRAMING;
led_unescaped_buf[i].board = i;
led_unescaped_buf[i].data_len = chuni_led_board_data_lens[i];
led_escaped_buf[i].framing = LED_PACKET_FRAMING;
led_escaped_buf[i].board = i;
led_escaped_buf[i].data_len = chuni_led_board_data_lens[i];
}
any_outputs_enabled = config->led_output_pipe || config->slider_led_output_pipe
|| config->led_output_serial || config->slider_led_output_serial;
if (config->led_output_pipe || config->slider_led_output_pipe)
{
led_pipe_init(); // don't really care about errors here tbh
}
if (config->led_output_serial || config->slider_led_output_serial)
{
led_serial_init(config->led_serial_port, config->led_serial_baud);
}
}
led_output_is_init = true;
ReleaseMutex(led_init_mutex);
return S_OK;
// return 0;
}
struct _chuni_led_data_buf_t* escape_led_data(struct _chuni_led_data_buf_t* unescaped)
{
struct _chuni_led_data_buf_t* out_struct = &led_escaped_buf[unescaped->board];
byte* in_buf = unescaped->data;
byte* out_buf = out_struct->data;
int i = 0;
int o = 0;
while (i < unescaped->data_len)
{
byte b = in_buf[i++];
if (b == LED_PACKET_FRAMING || b == LED_PACKET_ESCAPE)
{
out_buf[o++] = LED_PACKET_ESCAPE;
b--;
}
out_buf[o++] = b;
}
out_struct->data_len = o;
return out_struct;
}
void led_output_update(uint8_t board, const uint8_t* rgb)
{
if (board < 0 || board > 2 || !any_outputs_enabled)
{
return;
}
memcpy(led_unescaped_buf[board].data, rgb, led_unescaped_buf[board].data_len);
struct _chuni_led_data_buf_t* escaped_data = escape_led_data(&led_unescaped_buf[board]);
if (board < 2)
{
// billboard
if (config->led_output_pipe)
{
led_pipe_update(escaped_data);
}
if (config->led_output_serial)
{
led_serial_update(escaped_data);
}
}
else
{
// slider
if (config->slider_led_output_pipe)
{
led_pipe_update(escaped_data);
}
if (config->slider_led_output_serial)
{
led_serial_update(escaped_data);
}
}
}

19
chuniio/src/ledoutput.h Normal file
View File

@ -0,0 +1,19 @@
/*
LED output functions
Credits:
somewhatlurker, skogaby
*/
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "config.h"
extern HANDLE led_init_mutex;
HRESULT led_output_init(struct chuni_io_config* const cfg);
void led_output_update(uint8_t board, const uint8_t* rgb);

160
chuniio/src/pipeimpl.c Normal file
View File

@ -0,0 +1,160 @@
#include <windows.h>
#include <process.h>
#include <stdbool.h>
#include <stdint.h>
#include "leddata.h"
#include "pipeimpl.h"
static bool pipe_update[LED_BOARDS_TOTAL];
// incoming data is copied into these to ensure it isn't written during output
static struct _chuni_led_data_buf_t pipe_write_buf[LED_BOARDS_TOTAL];
static HANDLE pipe_write_mutex;
static HRESULT pipe_create(LPHANDLE hPipe, LPCWSTR lpszPipename, DWORD dwBufSize)
{
*hPipe = INVALID_HANDLE_VALUE;
*hPipe = CreateNamedPipeW(
lpszPipename, // pipe name
PIPE_ACCESS_OUTBOUND, // read/write access
PIPE_TYPE_BYTE | // byte type pipe
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
dwBufSize, // output buffer size
0, // input buffer size
0, // client time-out
NULL); // default security attribute
if (*hPipe == INVALID_HANDLE_VALUE)
{
return E_FAIL;
}
return S_OK;
}
static HRESULT pipe_write(HANDLE hPipe, LPCVOID lpBuffer, DWORD dwSize)
{
DWORD cbWritten = 0;
bool fSuccess = WriteFile(
hPipe,
lpBuffer,
dwSize,
&cbWritten,
NULL);
if (!fSuccess || cbWritten != dwSize)
{
DWORD last_err = GetLastError();
return (last_err == ERROR_BROKEN_PIPE) ? E_ABORT : E_FAIL;
}
return S_OK;
}
static unsigned int __stdcall chuni_io_led_pipe_thread_proc(void *ctx)
{
HANDLE hPipe;
LPCWSTR lpszPipename = L"\\\\.\\pipe\\chuni_led";
while (true)
{
hPipe = INVALID_HANDLE_VALUE;
if (pipe_create(&hPipe, lpszPipename, LED_OUTPUT_TOTAL_SIZE_MAX) != S_OK)
{
continue;
}
// wait for a connection to the pipe
bool fConnected = ConnectNamedPipe(hPipe, NULL) ?
true : (GetLastError() == ERROR_PIPE_CONNECTED);
while (fConnected)
{
if (WaitForSingleObject(pipe_write_mutex, INFINITE) != WAIT_OBJECT_0)
{
continue;
}
for (int i = 0; i < LED_BOARDS_TOTAL; i++) {
if (pipe_update[i])
{
HRESULT result = pipe_write(
hPipe,
&pipe_write_buf[i],
LED_OUTPUT_HEADER_SIZE + pipe_write_buf[i].data_len);
if (result != S_OK)
{
//if (result == E_ABORT)
//{
fConnected = false;
//}
break;
}
pipe_update[i] = false;
}
}
ReleaseMutex(pipe_write_mutex);
}
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
}
return 0;
}
HRESULT led_pipe_init()
{
pipe_write_mutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (pipe_write_mutex == NULL)
{
return E_FAIL;
}
// clear out update bools
for (int i = 0; i < LED_BOARDS_TOTAL; i++) {
pipe_update[i] = false;
}
_beginthreadex(
NULL,
0,
chuni_io_led_pipe_thread_proc,
0,
0,
NULL);
return S_OK;
}
void led_pipe_update(struct _chuni_led_data_buf_t* data)
{
if (data->board > 2)
{
return;
}
if (WaitForSingleObject(pipe_write_mutex, INFINITE) != WAIT_OBJECT_0)
{
return;
}
memcpy(&pipe_write_buf[data->board], data, sizeof(struct _chuni_led_data_buf_t));
pipe_update[data->board] = true;
ReleaseMutex(pipe_write_mutex);
}

14
chuniio/src/pipeimpl.h Normal file
View File

@ -0,0 +1,14 @@
/*
Pipe implementation for chuniio
Credits:
somewhatlurker, skogaby
*/
#pragma once
#include <windows.h>
#include "leddata.h"
HRESULT led_pipe_init();
void led_pipe_update(struct _chuni_led_data_buf_t* data);

99
chuniio/src/serialimpl.c Normal file
View File

@ -0,0 +1,99 @@
#include <windows.h>
#include <process.h>
#include <stdbool.h>
#include <stdint.h>
#include "leddata.h"
#include "serialimpl.h"
#include "util/dprintf.h"
static HANDLE serial_port;
static HANDLE serial_write_mutex;
HRESULT led_serial_init(wchar_t led_com[12], DWORD baud)
{
// Setup the serial communications
BOOL status;
serial_port = CreateFileW(led_com,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (serial_port == INVALID_HANDLE_VALUE)
dprintf("Chunithm Serial LEDs: Failed to open COM port (Attempted on %S)\n", led_com);
else
dprintf("Chunithm Serial LEDs: COM port success!\n");
DCB dcb_serial_params = { 0 };
dcb_serial_params.DCBlength = sizeof(dcb_serial_params);
status = GetCommState(serial_port, &dcb_serial_params);
dcb_serial_params.BaudRate = baud;
dcb_serial_params.ByteSize = 8;
dcb_serial_params.StopBits = ONESTOPBIT;
dcb_serial_params.Parity = NOPARITY;
SetCommState(serial_port, &dcb_serial_params);
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(serial_port, &timeouts);
if (!status)
{
return E_FAIL;
}
serial_write_mutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (serial_write_mutex == NULL)
{
return E_FAIL;
}
return S_OK;
}
void led_serial_update(struct _chuni_led_data_buf_t* data)
{
if (data->board > 2)
{
return;
}
if (WaitForSingleObject(serial_write_mutex, INFINITE) != WAIT_OBJECT_0)
{
return;
}
BOOL status = true;
DWORD bytes_written = 0;
if (serial_port != INVALID_HANDLE_VALUE) {
status = WriteFile(
serial_port,
data,
LED_OUTPUT_HEADER_SIZE + data->data_len,
&bytes_written,
NULL);
}
if (!status) {
DWORD last_err = GetLastError();
// dprintf("Chunithm Serial LEDs: Serial port write failed -- %d\n", last_err);
}
ReleaseMutex(serial_write_mutex);
}

15
chuniio/src/serialimpl.h Normal file
View File

@ -0,0 +1,15 @@
/*
Serial LED implementation for chuniio
Credits:
somewhatlurker, skogaby
*/
#pragma once
#include <windows.h>
#include "leddata.h"
HRESULT led_serial_init(wchar_t led_com[12], DWORD baud);
void led_serial_update(struct _chuni_led_data_buf_t* data);

View File

@ -13,7 +13,7 @@
#include <stdint.h>
#include "servers/common.h"
#include "socket.h"
#include "servers/socket.h"
bool tcp_mode = true;
uint16_t server_port = 52468;
@ -27,17 +27,17 @@ typedef struct {
SOCKET sock;
char remote_address[40];
uint16_t remote_port;
atomic_bool exit_flag;
atomic_bool connected;
volatile atomic_flag keep_running_flag;
volatile atomic_bool connected;
uint32_t last_input_packet_id;
uint8_t last_card_id[10];
bool has_previous_led_status;
uint8_t previous_led_status[3 * 32];
uint8_t led_skip_count;
struct IPCMemoryInfo *memory;
} android_thread_ctx;
@ -119,7 +119,7 @@ unsigned int __stdcall led_broadcast_thread_proc(void *v) {
android_thread_ctx *ctx = v;
const SOCKET sock = ctx->sock;
const struct IPCMemoryInfo* memory = ctx->memory;
const struct IPCMemoryInfo *memory = ctx->memory;
struct sockaddr_in addr = {};
make_ipv4_address(&addr, ctx->remote_address, ctx->remote_port);
@ -130,7 +130,7 @@ unsigned int __stdcall led_broadcast_thread_proc(void *v) {
send_buffer[2] = 'E';
send_buffer[3] = 'D';
while (!atomic_load(&ctx->exit_flag)) {
while (atomic_flag_test_and_set(&ctx->keep_running_flag)) {
uint8_t current_led_status[3 * 32];
if (!atomic_load(&ctx->connected)) {
@ -155,7 +155,8 @@ unsigned int __stdcall led_broadcast_thread_proc(void *v) {
memcpy(send_buffer + 4, current_led_status, 3 * 32);
if (socket_send_to(sock, &addr, send_buffer, 100) < 0) {
print_err("[Android:ERROR] Cannot send packet: error %lu\n", WSAGetLastError());
print_err("[Android:ERROR] Cannot send packet: error %lu\n",
WSAGetLastError());
if (tcp_mode) {
if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
@ -164,7 +165,7 @@ unsigned int __stdcall led_broadcast_thread_proc(void *v) {
print_err("[Android: INFO] Device disconnected!\n");
ctx->connected = false;
ctx->exit_flag = true;
atomic_flag_clear(&ctx->keep_running_flag);
break;
}
}
@ -190,7 +191,7 @@ unsigned int __stdcall input_recv_thread_proc(void *v) {
int recv_len, packet_len;
uint8_t real_len;
while (!atomic_load(&ctx->exit_flag)) {
while (atomic_flag_test_and_set(&ctx->keep_running_flag)) {
char buffer[96];
if (!tcp_mode) {
@ -229,19 +230,22 @@ unsigned int __stdcall input_recv_thread_proc(void *v) {
continue;
}
print_err("[Android: INFO] Device disconnected (could not read data, errno "
print_err("[Android: INFO] Device disconnected (could not read "
"data, errno "
"%d, os error %ld)\n",
errno, error);
atomic_store(&ctx->connected, false);
atomic_store(&ctx->exit_flag, true);
break;
atomic_flag_clear(&ctx->keep_running_flag);
free(ctx);
return 1;
}
recv_len = recv_len + read;
}
real_len = buffer[0];
packet_len = real_len + 1; // 1 for the packet length
packet_len = real_len + 1; // 1 for the packet length
while (recv_len < packet_len) {
const int read =
@ -255,21 +259,24 @@ unsigned int __stdcall input_recv_thread_proc(void *v) {
continue;
}
print_err("[Android: INFO] Device disconnected (could not read data, errno "
print_err("[Android: INFO] Device disconnected (could not read "
"data, errno "
"%d, os error %ld)\n",
errno, error);
atomic_store(&ctx->connected, false);
atomic_store(&ctx->exit_flag, true);
break;
atomic_flag_clear(&ctx->keep_running_flag);
free(ctx);
return 1;
}
recv_len = recv_len + read;
}
}
if (packet_len >= sizeof(struct PacketInput) &&
if (packet_len >= sizeof(struct AndroidPacketInput) &&
memcmp(buffer + 1, "INP", 3) == 0) {
const struct PacketInput *pkt = (struct PacketInput *)buffer;
const struct AndroidPacketInput *pkt = (struct AndroidPacketInput *)buffer;
memcpy(memory->airIoStatus, pkt->airIoStatus, sizeof(pkt->airIoStatus));
memcpy(memory->sliderIoStatus, pkt->sliderIoStatus,
@ -316,14 +323,14 @@ unsigned int __stdcall input_recv_thread_proc(void *v) {
atomic_store(&ctx->connected, false);
if (tcp_mode) {
atomic_store(&ctx->exit_flag, true);
atomic_flag_clear(&ctx->keep_running_flag);
print_err("[Android: INFO] Device disconnected (clean disconnect).\n");
break;
}
if (strlen(ctx->remote_address)) {
print_err("[Android: INFO] Device %s:%d disconnected.\n", ctx->remote_address,
ctx->remote_port);
print_err("[Android: INFO] Device %s:%d disconnected.\n",
ctx->remote_address, ctx->remote_port);
memset(ctx->remote_address, 0, 40);
}
@ -381,8 +388,8 @@ unsigned int __stdcall server_thread_proc(void *v) {
print_err("[Android: INFO] Waiting for device on port %d...\n", server_port);
android_thread_ctx *ctx = malloc(sizeof(android_thread_ctx));
atomic_flag_test_and_set(&ctx->keep_running_flag);
ctx->sock = sock;
ctx->exit_flag = ATOMIC_VAR_INIT(false);
ctx->connected = ATOMIC_VAR_INIT(false);
ctx->last_input_packet_id = 0;
ctx->memory = memory;
@ -428,8 +435,8 @@ unsigned int __stdcall server_thread_proc(void *v) {
}
android_thread_ctx *ctx = malloc(sizeof(android_thread_ctx));
atomic_flag_test_and_set(&ctx->keep_running_flag);
ctx->sock = acc_socket;
ctx->exit_flag = ATOMIC_VAR_INIT(false);
ctx->connected = ATOMIC_VAR_INIT(true);
ctx->last_input_packet_id = 0;
ctx->memory = memory;

View File

@ -1,15 +1,66 @@
//
// Created by beerpsi on 12/31/2023.
//
#ifndef CHUNIIO_BROKENITHM_ANDROID_H
#define CHUNIIO_BROKENITHM_ANDROID_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "struct.h"
HRESULT android_init_server(struct IPCMemoryInfo* memory);
#endif // CHUNIIO_BROKENITHM_ANDROID_H
//
// Created by beerpsi on 12/31/2023.
//
#ifndef CHUNIIO_BROKENITHM_ANDROID_H
#define CHUNIIO_BROKENITHM_ANDROID_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "ipc_memory_info.h"
;
#pragma pack(push)
#pragma pack(1)
struct AndroidPacketInput {
uint8_t packetSize;
uint8_t packetName[3];
uint32_t packetId;
uint8_t airIoStatus[6];
uint8_t sliderIoStatus[32];
uint8_t testBtn;
uint8_t serviceBtn;
};
struct PacketInputNoAir {
uint8_t packetSize;
uint8_t packetName[3];
uint32_t packetId;
uint8_t sliderIoStatus[32];
uint8_t testBtn;
uint8_t serviceBtn;
};
struct PacketConnect {
uint8_t packetSize;
uint8_t packetName[3];
uint8_t addrType;
uint16_t port;
union {
struct {
uint8_t addr[4];
uint8_t padding[12];
} addr4;
uint8_t addr6[16];
} addr;
};
struct PacketCard {
uint8_t packetSize;
uint8_t packetName[3];
uint8_t remoteCardRead;
uint8_t remoteCardType;
uint8_t remoteCardId[10];
};
struct PacketPing {
uint8_t packetSize;
uint8_t packetName[3];
uint64_t remotePingTime;
};
#pragma pack(pop)
HRESULT android_init_server(struct IPCMemoryInfo *memory);
#endif // CHUNIIO_BROKENITHM_ANDROID_H

View File

@ -8,7 +8,7 @@
#include "util/dprintf.h"
void print_err(const char* fmt, ...) {
void print_err(const char *fmt, ...) {
const time_t lt = time(NULL);
const struct tm *local = localtime(&lt);
char tmpbuf[32];
@ -31,20 +31,20 @@ void dump_bytes(const void *ptr, const size_t nbytes, const bool hex_string) {
dprintf("\t--- Empty ---\n");
}
const uint8_t* bytes = ptr;
const uint8_t *bytes = ptr;
if (hex_string) {
for (i = 0 ; i < nbytes ; i++) {
for (i = 0; i < nbytes; i++) {
dprintf("%02x", bytes[i]);
}
dprintf("\n");
return;
}
for (i = 0 ; i < nbytes ; i += 16) {
dprintf(" %08x:", (int) i);
for (i = 0; i < nbytes; i += 16) {
dprintf(" %08x:", (int)i);
for (j = 0 ; i + j < nbytes && j < 16 ; j++) {
for (j = 0; i + j < nbytes && j < 16; j++) {
dprintf(" %02x", bytes[i + j]);
}
@ -55,7 +55,7 @@ void dump_bytes(const void *ptr, const size_t nbytes, const bool hex_string) {
dprintf(" ");
for (j = 0 ; i + j < nbytes && j < 16 ; j++) {
for (j = 0; i + j < nbytes && j < 16; j++) {
uint8_t c = bytes[i + j];
if (c < 0x20 || c >= 0x7F) {

View File

@ -9,13 +9,22 @@
#include <stdint.h>
enum FunctionButton {
INVALID,
INVALID __attribute__((unused)),
FUNCTION_COIN,
FUNCTION_CARD,
};
void print_err(const char* fmt, ...);
#pragma pack(push)
#pragma pack(1)
struct PacketFunction {
uint8_t packetSize;
uint8_t packetName[3];
uint8_t funcBtn;
};
#pragma pack(pop)
void dump_bytes(const void *ptr, const size_t nbytes, const bool hex_string);
void print_err(const char *fmt, ...);
void dump_bytes(const void *ptr, size_t nbytes, bool hex_string);
#endif // CHUNIIO_BROKENITHM_COMMON_H

View File

@ -6,9 +6,9 @@
#include "arch.h"
#ifdef ENV32BIT
#include <libimobiledevice/libimobiledevice.h>
#include <process.h>
#include <stdatomic.h>
#include <libimobiledevice/libimobiledevice.h>
#include "servers/common.h"
@ -17,17 +17,17 @@ typedef struct {
idevice_t device;
idevice_connection_t connection;
atomic_bool exit_flag;
volatile atomic_flag keep_running_flag;
bool has_previous_led_status;
uint8_t previous_led_status[3 * 32];
uint8_t led_skip_count;
struct IPCMemoryInfo* memory;
struct IPCMemoryInfo *memory;
} ios_thread_ctx;
unsigned int __stdcall ios_led_broadcast_thread_proc(void *v) {
ios_thread_ctx* ctx = v;
ios_thread_ctx *ctx = v;
char send_buffer[4 + 3 * 32];
send_buffer[0] = 99;
@ -35,7 +35,7 @@ unsigned int __stdcall ios_led_broadcast_thread_proc(void *v) {
send_buffer[2] = 'E';
send_buffer[3] = 'D';
while (!atomic_load(&ctx->exit_flag)) {
while (atomic_flag_test_and_set(&ctx->keep_running_flag)) {
uint8_t current_led_status[3 * 32];
memcpy(current_led_status, ctx->memory->ledRgbData, 3 * 32);
@ -56,7 +56,8 @@ unsigned int __stdcall ios_led_broadcast_thread_proc(void *v) {
int status;
uint32_t sent;
if ((status = idevice_connection_send(ctx->connection, send_buffer, 100, &sent))) {
if ((status = idevice_connection_send(ctx->connection, send_buffer, 100,
&sent))) {
print_err("[iOS:ERROR] Cannot send LED packet: error %d\n", status);
}
@ -70,51 +71,58 @@ unsigned int __stdcall ios_led_broadcast_thread_proc(void *v) {
}
unsigned int __stdcall ios_input_recv_thread_proc(void *v) {
ios_thread_ctx* ctx = v;
ios_thread_ctx *ctx = v;
bool air_enabled = true;
while (!atomic_load(&ctx->exit_flag)) {
while (atomic_flag_test_and_set(&ctx->keep_running_flag)) {
char buffer[96];
int status;
uint32_t read;
if ((status = idevice_connection_receive_timeout(ctx->connection, buffer, 4, &read, 5))) {
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);
atomic_flag_clear(&ctx->keep_running_flag);
break;
}
int len = (unsigned char)buffer[0];
if ((status = idevice_connection_receive_timeout(ctx->connection, buffer + 4, len - 3, &read, 5))) {
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);
atomic_flag_clear(&ctx->keep_running_flag);
break;
}
if (len >= sizeof(struct iOSPacketInput) && memcmp(buffer + 1, "INP", 3) == 0) {
struct iOSPacketInput* pkt = (struct iOSPacketInput*)buffer;
struct iOSPacketInput *pkt = (struct iOSPacketInput *)buffer;
if (air_enabled) {
memcpy(ctx->memory->airIoStatus, pkt->airIoStatus, sizeof(pkt->airIoStatus));
memcpy(ctx->memory->airIoStatus, pkt->airIoStatus,
sizeof(pkt->airIoStatus));
}
memcpy(ctx->memory->sliderIoStatus, pkt->sliderIoStatus, sizeof(pkt->sliderIoStatus));
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;
} else if (len >= sizeof(struct PacketAirStatus) && memcmp(buffer + 1, "AIR", 3) == 0) {
struct PacketAirStatus *pkt = (struct PacketAirStatus *)buffer;
print_err("[iOS: 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;
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:
@ -129,7 +137,7 @@ unsigned int __stdcall ios_input_recv_thread_proc(void *v) {
}
}
print_err("[iOS: INFO] Device disconnected.");
print_err("[iOS: INFO] Device disconnected.\n");
idevice_disconnect(ctx->connection);
ctx->connection = NULL;
@ -140,8 +148,8 @@ unsigned int __stdcall ios_input_recv_thread_proc(void *v) {
return 0;
}
unsigned int __stdcall connect_device(void* v) {
ios_thread_ctx* ctx = v;
unsigned int __stdcall connect_device(void *v) {
ios_thread_ctx *ctx = v;
int status;
if ((status = idevice_new(&ctx->device, ctx->remote_udid))) {
@ -189,25 +197,24 @@ unsigned int __stdcall connect_device(void* v) {
}
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;
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));
ios_thread_ctx *args = malloc(sizeof(ios_thread_ctx));
strcpy_s(args->remote_udid, 41, event->udid);
atomic_flag_test_and_set(&args->keep_running_flag);
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;

View File

@ -8,8 +8,27 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "struct.h"
#include "ipc_memory_info.h"
HRESULT ios_init_server(struct IPCMemoryInfo* memory);
;
#pragma pack(push)
#pragma pack(1)
struct iOSPacketInput {
uint8_t packetSize;
uint8_t packetName[3];
uint8_t airIoStatus[6];
uint8_t sliderIoStatus[32];
uint8_t testBtn;
uint8_t serviceBtn;
};
struct PacketAirStatus {
uint8_t packetSize;
uint8_t packetName[3];
uint8_t airEnabled;
};
#pragma pack(pop)
HRESULT ios_init_server(struct IPCMemoryInfo *memory);
#endif // CHUNIIO_BROKENITHM_IOS_H

View File

@ -9,36 +9,36 @@
#ifndef WINVER
#define WINVER 0x0501
#endif // WINVER
#include <ws2tcpip.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#else
//translate windows functions to linux functions
#include <unistd.h>
// translate windows functions to linux functions
#include <string.h>
#define SOCKET int
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
#define closesocket close
#define SOCKADDR_IN sockaddr_in
#define ZeroMemory(d,l) memset((d), 0, (l))
#define ioctlsocket ioctl
#include <unistd.h>
#define SOCKET int
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
#define closesocket close
#define SOCKADDR_IN sockaddr_in
#define ZeroMemory(d, l) memset((d), 0, (l))
#define ioctlsocket ioctl
#ifndef SA_INTERRUPT
#define SA_INTERRUPT 0 //ignore this setting
#define SA_INTERRUPT 0 // ignore this setting
#endif
#define SD_BOTH SHUT_RDWR
#ifndef __hpux
#include <sys/select.h>
#endif /* __hpux */
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <signal.h>
#include <unistd.h>
typedef sockaddr *LPSOCKADDR;
#endif // _WIN32
#endif //CHUNIIO_BROKENITHM_SOCKET_H
#endif // CHUNIIO_BROKENITHM_SOCKET_H

View File

@ -1,100 +0,0 @@
//
// Created by beerpsi on 12/29/2023.
//
#ifndef CHUNIIO_BROKENITHM_STRUCT_H
#define CHUNIIO_BROKENITHM_STRUCT_H
#include <stdint.h>
;
#pragma pack(push)
#pragma pack(1)
struct IPCMemoryInfo
{
uint8_t airIoStatus[6];
uint8_t sliderIoStatus[32];
uint8_t ledRgbData[32 * 3];
uint8_t testBtn;
uint8_t serviceBtn;
uint8_t coinInsertion;
uint8_t cardRead;
uint8_t remoteCardRead;
uint8_t remoteCardType;
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;
uint8_t packetName[3];
uint32_t packetId;
uint8_t airIoStatus[6];
uint8_t sliderIoStatus[32];
uint8_t testBtn;
uint8_t serviceBtn;
};
struct PacketInputNoAir
{
uint8_t packetSize;
uint8_t packetName[3];
uint32_t packetId;
uint8_t sliderIoStatus[32];
uint8_t testBtn;
uint8_t serviceBtn;
};
struct PacketFunction
{
uint8_t packetSize;
uint8_t packetName[3];
uint8_t funcBtn;
};
struct PacketConnect
{
uint8_t packetSize;
uint8_t packetName[3];
uint8_t addrType;
uint16_t port;
union
{
struct
{
uint8_t addr[4];
uint8_t padding[12];
} addr4;
uint8_t addr6[16];
} addr;
};
struct PacketCard
{
uint8_t packetSize;
uint8_t packetName[3];
uint8_t remoteCardRead;
uint8_t remoteCardType;
uint8_t remoteCardId[10];
};
struct PacketPing
{
uint8_t packetSize;
uint8_t packetName[3];
uint64_t remotePingTime;
};
#pragma pack(pop)
#endif //CHUNIIO_BROKENITHM_STRUCT_H

View File

@ -14,8 +14,7 @@ static CRITICAL_SECTION dbg_buf_lock;
static char dbg_buf[16384];
static size_t dbg_buf_pos;
void dprintf(const char *fmt, ...)
{
void dprintf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
@ -23,8 +22,7 @@ void dprintf(const char *fmt, ...)
va_end(ap);
}
void dprintfv(const char *fmt, va_list ap)
{
void dprintfv(const char *fmt, va_list ap) {
long init;
/* Static constructors in C are difficult to do in a way that works under
@ -45,12 +43,8 @@ void dprintfv(const char *fmt, va_list ap)
EnterCriticalSection(&dbg_buf_lock);
dbg_buf_pos += vsnprintf_s(
dbg_buf + dbg_buf_pos,
sizeof(dbg_buf) - dbg_buf_pos,
sizeof(dbg_buf) - dbg_buf_pos - 1,
fmt,
ap);
dbg_buf_pos += vsnprintf_s(dbg_buf + dbg_buf_pos, sizeof(dbg_buf) - dbg_buf_pos,
sizeof(dbg_buf) - dbg_buf_pos - 1, fmt, ap);
if (dbg_buf_pos + 1 > sizeof(dbg_buf)) {
abort();
@ -65,8 +59,7 @@ void dprintfv(const char *fmt, va_list ap)
LeaveCriticalSection(&dbg_buf_lock);
}
void dwprintf(const wchar_t *fmt, ...)
{
void dwprintf(const wchar_t *fmt, ...) {
va_list ap;
va_start(ap, fmt);
@ -74,8 +67,7 @@ void dwprintf(const wchar_t *fmt, ...)
va_end(ap);
}
void dwprintfv(const wchar_t *fmt, va_list ap)
{
void dwprintfv(const wchar_t *fmt, va_list ap) {
wchar_t msg[512];
_vsnwprintf_s(msg, _countof(msg), _countof(msg) - 1, fmt, ap);

View File

@ -8,7 +8,7 @@ extern "C" {
#include <stddef.h>
#ifdef __GNUC__
#define DPRINTF_CHK __attribute__(( format(printf, 1, 2) ))
#define DPRINTF_CHK __attribute__((format(printf, 1, 2)))
#else
#define DPRINTF_CHK
#endif