From 0e1cfb66db5d2f217531e21ae56509b274171031 Mon Sep 17 00:00:00 2001 From: Tau Date: Sun, 3 Nov 2019 13:01:03 -0500 Subject: [PATCH] Improve JVS bus life cycle handling --- amex/amex.c | 4 ++-- amex/amex.h | 5 ++++- amex/jvs.c | 43 ++++++++++++++++++++++++++++++------------- amex/jvs.h | 5 +++-- chunihook/dllmain.c | 11 +---------- chunihook/jvs.c | 19 +++++++++++++++++-- chunihook/jvs.h | 6 +++++- chunihook/slider.c | 11 +++++++++++ chuniio/chuniio.c | 7 ++++++- chuniio/chuniio.def | 3 ++- chuniio/chuniio.h | 17 +++++++++++++---- divahook/dllmain.c | 7 +------ divahook/jvs.c | 19 +++++++++++++++++-- divahook/jvs.h | 6 +++++- divahook/slider.c | 11 +++++++++++ divaio/divaio.c | 7 ++++++- divaio/divaio.def | 3 ++- divaio/divaio.h | 17 +++++++++++++---- idzhook/dllmain.c | 7 +------ idzhook/jvs.c | 11 ++++++++--- idzhook/jvs.h | 4 +++- idzio/dllmain.c | 2 +- idzio/idzio.def | 2 +- idzio/idzio.h | 2 +- 24 files changed, 164 insertions(+), 65 deletions(-) diff --git a/amex/amex.c b/amex/amex.c index 00f3713..903665f 100644 --- a/amex/amex.c +++ b/amex/amex.c @@ -9,7 +9,7 @@ #include -HRESULT amex_hook_init(const struct amex_config *cfg) +HRESULT amex_hook_init(const struct amex_config *cfg, jvs_provider_t jvs) { HRESULT hr; @@ -33,7 +33,7 @@ HRESULT amex_hook_init(const struct amex_config *cfg) return hr; } - hr = jvs_hook_init(&cfg->jvs); + hr = jvs_hook_init(&cfg->jvs, jvs); if (FAILED(hr)) { return hr; diff --git a/amex/amex.h b/amex/amex.h index ce6c1d5..6e9e7ce 100644 --- a/amex/amex.h +++ b/amex/amex.h @@ -3,5 +3,8 @@ #include #include "amex/config.h" +#include "amex/jvs.h" -HRESULT amex_hook_init(const struct amex_config *cfg); +HRESULT amex_hook_init( + const struct amex_config *cfg, + jvs_provider_t jvs); diff --git a/amex/jvs.c b/amex/jvs.c index 1097267..556644f 100644 --- a/amex/jvs.c +++ b/amex/jvs.c @@ -39,8 +39,9 @@ static HRESULT jvs_ioctl_transact(struct irp *irp); static HANDLE jvs_fd; static struct jvs_node *jvs_root; +static jvs_provider_t jvs_provider; -HRESULT jvs_hook_init(const struct jvs_config *cfg) +HRESULT jvs_hook_init(const struct jvs_config *cfg, jvs_provider_t provider) { HRESULT hr; @@ -50,12 +51,6 @@ HRESULT jvs_hook_init(const struct jvs_config *cfg) return S_FALSE; } - hr = iohook_open_nul_fd(&jvs_fd); - - if (FAILED(hr)) { - return hr; - } - hr = iohook_push_handler(jvs_handle_irp); if (FAILED(hr)) { @@ -68,12 +63,9 @@ HRESULT jvs_hook_init(const struct jvs_config *cfg) return hr; } - return S_OK; -} + jvs_provider = provider; -void jvs_attach(struct jvs_node *root) -{ - jvs_root = root; + return S_OK; } static HRESULT jvs_handle_irp(struct irp *irp) @@ -94,11 +86,35 @@ static HRESULT jvs_handle_irp(struct irp *irp) static HRESULT jvs_handle_open(struct irp *irp) { + struct jvs_node *root; + HRESULT hr; + if (!wstr_eq(irp->open_filename, L"$jvs")) { return iohook_invoke_next(irp); } + if (jvs_fd != NULL) { + dprintf("JVS Port: Already open\n"); + + return HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION); + } + + hr = iohook_open_nul_fd(&jvs_fd); + + if (FAILED(hr)) { + return hr; + } + dprintf("JVS Port: Open device\n"); + + if (jvs_provider != NULL) { + hr = jvs_provider(&root); + + if (SUCCEEDED(hr)) { + jvs_root = root; + } + } + irp->fd = jvs_fd; return S_OK; @@ -107,8 +123,9 @@ static HRESULT jvs_handle_open(struct irp *irp) static HRESULT jvs_handle_close(struct irp *irp) { dprintf("JVS Port: Close device\n"); + jvs_fd = NULL; - return S_OK; + return iohook_invoke_next(irp); } static HRESULT jvs_handle_ioctl(struct irp *irp) diff --git a/amex/jvs.h b/amex/jvs.h index 281163f..569cab7 100644 --- a/amex/jvs.h +++ b/amex/jvs.h @@ -13,5 +13,6 @@ DEFINE_GUID( 0x4288, 0xAA, 0x00, 0x6C, 0x00, 0xD7, 0x67, 0xBD, 0xBF); -HRESULT jvs_hook_init(const struct jvs_config *cfg); -void jvs_attach(struct jvs_node *root); +typedef HRESULT (*jvs_provider_t)(struct jvs_node **root); + +HRESULT jvs_hook_init(const struct jvs_config *cfg, jvs_provider_t provider); diff --git a/chunihook/dllmain.c b/chunihook/dllmain.c index 973c5e7..d9ec27b 100644 --- a/chunihook/dllmain.c +++ b/chunihook/dllmain.c @@ -58,12 +58,7 @@ static DWORD CALLBACK chuni_pre_startup(void) "AAV1", chuni_hook_mod); - amex_hook_init(&chuni_hook_cfg.amex); - - if (chuni_hook_cfg.amex.jvs.enable) { - chunithm_jvs_init(); - } - + amex_hook_init(&chuni_hook_cfg.amex, chunithm_jvs_init); slider_hook_init(&chuni_hook_cfg.slider); /* Initialize debug helpers */ @@ -72,10 +67,6 @@ static DWORD CALLBACK chuni_pre_startup(void) dprintf("--- End chuni_pre_startup ---\n"); - /* Initialize IO DLL */ - - chuni_io_init(); - /* Jump to EXE start address */ return chuni_startup(); diff --git a/chunihook/jvs.c b/chunihook/jvs.c index a78d902..a036fb7 100644 --- a/chunihook/jvs.c +++ b/chunihook/jvs.c @@ -42,10 +42,25 @@ static const struct chunithm_jvs_ir_mask chunithm_jvs_ir_masks[] = { static struct io3 chunithm_jvs_io3; -void chunithm_jvs_init(void) +HRESULT chunithm_jvs_init(struct jvs_node **out) { + HRESULT hr; + + assert(out != NULL); + + dprintf("JVS I/O: Starting Chunithm backend DLL\n"); + hr = chuni_io_jvs_init(); + + if (FAILED(hr)) { + dprintf("JVS I/O: Backend error, I/O disconnected: %x\n", (int) hr); + + return hr; + } + io3_init(&chunithm_jvs_io3, NULL, &chunithm_jvs_io3_ops, NULL); - jvs_attach(&chunithm_jvs_io3.jvs); + *out = io3_to_jvs_node(&chunithm_jvs_io3); + + return S_OK; } static void chunithm_jvs_read_switches(void *ctx, struct io3_switch_state *out) diff --git a/chunihook/jvs.h b/chunihook/jvs.h index 72d8921..eb581c5 100644 --- a/chunihook/jvs.h +++ b/chunihook/jvs.h @@ -1,3 +1,7 @@ #pragma once -void chunithm_jvs_init(void); +#include + +#include "jvs/jvs-bus.h" + +HRESULT chunithm_jvs_init(struct jvs_node **root); diff --git a/chunihook/slider.c b/chunihook/slider.c index 8820273..b9a89e2 100644 --- a/chunihook/slider.c +++ b/chunihook/slider.c @@ -81,6 +81,17 @@ static HRESULT slider_handle_irp_locked(struct irp *irp) struct iobuf req_iobuf; HRESULT hr; + if (irp->op == IRP_OP_OPEN) { + dprintf("Chunithm slider: Starting backend DLL\n"); + hr = chuni_io_slider_init(); + + if (FAILED(hr)) { + dprintf("Chunithm slider: Backend DLL error: %x\n", (int) hr); + + return hr; + } + } + hr = uart_handle_irp(&slider_uart, irp); if (FAILED(hr) || irp->op != IRP_OP_WRITE) { diff --git a/chuniio/chuniio.c b/chuniio/chuniio.c index 7d61648..ed02ace 100644 --- a/chuniio/chuniio.c +++ b/chuniio/chuniio.c @@ -18,7 +18,7 @@ static uint8_t chuni_io_hand_pos; static HANDLE chuni_io_slider_thread; static bool chuni_io_slider_stop_flag; -HRESULT chuni_io_init(void) +HRESULT chuni_io_jvs_init(void) { return S_OK; } @@ -73,6 +73,11 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) void chuni_io_jvs_set_coin_blocker(bool open) {} +HRESULT chuni_io_slider_init(void) +{ + return S_OK; +} + void chuni_io_slider_start(chuni_io_slider_callback_t callback) { if (chuni_io_slider_thread != NULL) { diff --git a/chuniio/chuniio.def b/chuniio/chuniio.def index b8e2754..f3ba8c6 100644 --- a/chuniio/chuniio.def +++ b/chuniio/chuniio.def @@ -1,10 +1,11 @@ LIBRARY chuniio EXPORTS - chuni_io_init + chuni_io_jvs_init chuni_io_jvs_poll chuni_io_jvs_read_coin_counter chuni_io_jvs_set_coin_blocker + chuni_io_slider_init chuni_io_slider_set_leds chuni_io_slider_start chuni_io_slider_stop diff --git a/chuniio/chuniio.h b/chuniio/chuniio.h index 7e71a5b..0823272 100644 --- a/chuniio/chuniio.h +++ b/chuniio/chuniio.h @@ -5,15 +5,15 @@ #include #include -/* Initialize the Chunithm IO provider DLL. This is the first function to be - called on this DLL. Returning failure from this function will cause the - main application to immediately exit. +/* Initialize JVS-based input. This function will be called before any other + chuni_io_jvs_*() function calls. Errors returned from this function will + manifest as a disconnected JVS bus. All subsequent calls may originate from arbitrary threads and some may overlap with each other. Ensuring synchronization inside your IO DLL is your responsibility. */ -HRESULT chuni_io_init(void); +HRESULT chuni_io_jvs_init(void); /* Poll JVS input. @@ -44,6 +44,15 @@ void chuni_io_jvs_read_coin_counter(uint16_t *total); void chuni_io_jvs_set_coin_blocker(bool open); +/* Initialize touch slider emulation. This function will be called before any + other chuni_io_slider_*() function calls. + + All subsequent calls may originate from arbitrary threads and some may + overlap with each other. Ensuring synchronization inside your IO DLL is + your responsibility. */ + +HRESULT chuni_io_slider_init(void); + /* Chunithm touch slider layout: ^^^ Toward screen ^^^ diff --git a/divahook/dllmain.c b/divahook/dllmain.c index 60eb385..59e11ca 100644 --- a/divahook/dllmain.c +++ b/divahook/dllmain.c @@ -45,12 +45,7 @@ static DWORD CALLBACK diva_pre_startup(void) "AAV0", diva_hook_mod); - amex_hook_init(&diva_hook_cfg.amex); - - if (diva_hook_cfg.amex.jvs.enable) { - diva_jvs_init(); - } - + amex_hook_init(&diva_hook_cfg.amex, diva_jvs_init); sg_reader_hook_init(&diva_hook_cfg.aime, 10); slider_hook_init(); diff --git a/divahook/jvs.c b/divahook/jvs.c index dc3e3c5..ebfaaae 100644 --- a/divahook/jvs.c +++ b/divahook/jvs.c @@ -28,10 +28,25 @@ static const struct io3_ops diva_jvs_io3_ops = { static struct io3 diva_jvs_io3; -void diva_jvs_init(void) +HRESULT diva_jvs_init(struct jvs_node **out) { + HRESULT hr; + + assert(out != NULL); + + dprintf("JVS I/O: Starting Diva backend DLL\n"); + hr = diva_io_jvs_init(); + + if (FAILED(hr)) { + dprintf("JVS I/O: Backend error, I/O disconnected: %x\n", (int) hr); + + return hr; + } + io3_init(&diva_jvs_io3, NULL, &diva_jvs_io3_ops, NULL); - jvs_attach(&diva_jvs_io3.jvs); + *out = io3_to_jvs_node(&diva_jvs_io3); + + return S_OK; } static void diva_jvs_read_switches(void *ctx, struct io3_switch_state *out) diff --git a/divahook/jvs.h b/divahook/jvs.h index 1ca7a32..5601eff 100644 --- a/divahook/jvs.h +++ b/divahook/jvs.h @@ -1,3 +1,7 @@ #pragma once -void diva_jvs_init(void); +#include + +#include "jvs/jvs-bus.h" + +HRESULT diva_jvs_init(struct jvs_node **root); diff --git a/divahook/slider.c b/divahook/slider.c index 4d71477..8e7d75c 100644 --- a/divahook/slider.c +++ b/divahook/slider.c @@ -73,6 +73,17 @@ static HRESULT slider_handle_irp_locked(struct irp *irp) struct iobuf req_iobuf; HRESULT hr; + if (irp->op == IRP_OP_OPEN) { + dprintf("Diva slider: Starting backend DLL\n"); + hr = diva_io_jvs_init(); + + if (FAILED(hr)) { + dprintf("Diva slider: Backend DLL error: %x\n", (int) hr); + + return hr; + } + } + hr = uart_handle_irp(&slider_uart, irp); if (FAILED(hr) || irp->op != IRP_OP_WRITE) { diff --git a/divaio/divaio.c b/divaio/divaio.c index 8fbeaa9..6817e86 100644 --- a/divaio/divaio.c +++ b/divaio/divaio.c @@ -14,7 +14,7 @@ static uint16_t diva_io_coins; static HANDLE diva_io_slider_thread; static bool diva_io_slider_stop_flag; -HRESULT diva_io_init(void) +HRESULT diva_io_jvs_init(void) { return S_OK; } @@ -68,6 +68,11 @@ void diva_io_jvs_read_coin_counter(uint16_t *out) void diva_io_jvs_set_coin_blocker(bool open) {} +HRESULT diva_io_slider_init(void) +{ + return S_OK; +} + void diva_io_slider_start(diva_io_slider_callback_t callback) { if (diva_io_slider_thread != NULL) { diff --git a/divaio/divaio.def b/divaio/divaio.def index 46b79c0..3191f7b 100644 --- a/divaio/divaio.def +++ b/divaio/divaio.def @@ -1,10 +1,11 @@ LIBRARY divaio EXPORTS - diva_io_init + diva_io_jvs_init diva_io_jvs_poll diva_io_jvs_read_coin_counter diva_io_jvs_set_coin_blocker + diva_io_slider_init diva_io_slider_set_leds diva_io_slider_start diva_io_slider_stop diff --git a/divaio/divaio.h b/divaio/divaio.h index 0328324..3de0d1a 100644 --- a/divaio/divaio.h +++ b/divaio/divaio.h @@ -5,15 +5,15 @@ #include #include -/* Initialize the Project Diva IO provider DLL. This is the first function to be - called on this DLL. Returning failure from this function will cause the main - application to immediately exit. +/* Initialize JVS-based input. This function will be called before any other + diva_io_jvs_*() function calls. Errors returned from this function will + manifest as a disconnected JVS bus. All subsequent calls may originate from arbitrary threads and some may overlap with each other. Ensuring synchronization inside your IO DLL is your responsibility. */ -HRESULT diva_io_init(void); +HRESULT diva_io_jvs_init(void); /* Poll JVS input. @@ -38,6 +38,15 @@ void diva_io_jvs_read_coin_counter(uint16_t *out); void diva_io_jvs_set_coin_blocker(bool open); +/* Initialize touch slider emulation. This function will be called before any + other diva_io_slider_*() function calls. + + All subsequent calls may originate from arbitrary threads and some may + overlap with each other. Ensuring synchronization inside your IO DLL is + your responsibility. */ + +HRESULT diva_io_slider_init(void); + /* Project Diva touch sliders consist of 32 pressure sensitive cells, where cell 1 (array index 0) is the rightmost cell and cell 32 (array index 31) is the leftmost cell. */ diff --git a/idzhook/dllmain.c b/idzhook/dllmain.c index aabcc3d..400ff5e 100644 --- a/idzhook/dllmain.c +++ b/idzhook/dllmain.c @@ -39,12 +39,7 @@ static DWORD CALLBACK idz_pre_startup(void) /* Initialize emulation hooks */ platform_hook_init(&idz_hook_cfg.platform, "SDDF", "AAV2", idz_hook_mod); - amex_hook_init(&idz_hook_cfg.amex); - - if (idz_hook_cfg.amex.jvs.enable) { - idz_jvs_init(); - } - + amex_hook_init(&idz_hook_cfg.amex, idz_jvs_init); sg_reader_hook_init(&idz_hook_cfg.aime, 10); /* Initialize debug helpers */ diff --git a/idzhook/jvs.c b/idzhook/jvs.c index 8517e4b..fce5849 100644 --- a/idzhook/jvs.c +++ b/idzhook/jvs.c @@ -51,18 +51,23 @@ static const uint16_t idz_jvs_gear_signals[] = { static struct io3 idz_jvs_io3; -HRESULT idz_jvs_init(void) +HRESULT idz_jvs_init(struct jvs_node **out) { HRESULT hr; - hr = idz_io_init(); + assert(out != NULL); + + dprintf("JVS I/O: Starting Initial D Zero backend DLL\n"); + hr = idz_io_jvs_init(); if (FAILED(hr)) { + dprintf("JVS I/O: Backend error, I/O disconnected; %x\n", (int) hr); + return hr; } io3_init(&idz_jvs_io3, NULL, &idz_jvs_io3_ops, NULL); - jvs_attach(&idz_jvs_io3.jvs); + *out = io3_to_jvs_node(&idz_jvs_io3); return S_OK; } diff --git a/idzhook/jvs.h b/idzhook/jvs.h index 5320541..6a7c72a 100644 --- a/idzhook/jvs.h +++ b/idzhook/jvs.h @@ -2,4 +2,6 @@ #include -HRESULT idz_jvs_init(void); +#include "jvs/jvs-bus.h" + +HRESULT idz_jvs_init(struct jvs_node **root); diff --git a/idzio/dllmain.c b/idzio/dllmain.c index ee97ba0..75c7e95 100644 --- a/idzio/dllmain.c +++ b/idzio/dllmain.c @@ -19,7 +19,7 @@ static const struct idz_io_backend *idz_io_backend; static bool idz_io_coin; static uint16_t idz_io_coins; -HRESULT idz_io_init(void) +HRESULT idz_io_jvs_init(void) { HRESULT hr; diff --git a/idzio/idzio.def b/idzio/idzio.def index 3a418c9..b177000 100644 --- a/idzio/idzio.def +++ b/idzio/idzio.def @@ -1,7 +1,7 @@ LIBRARY idzio EXPORTS - idz_io_init + idz_io_jvs_init idz_io_jvs_read_analogs idz_io_jvs_read_buttons idz_io_jvs_read_coin_counter diff --git a/idzio/idzio.h b/idzio/idzio.h index 486fdb6..9900791 100644 --- a/idzio/idzio.h +++ b/idzio/idzio.h @@ -24,7 +24,7 @@ struct idz_io_analog_state { uint16_t brake; }; -HRESULT idz_io_init(void); +HRESULT idz_io_jvs_init(void); void idz_io_jvs_read_analogs(struct idz_io_analog_state *out);