Improve JVS bus life cycle handling

This commit is contained in:
Tau 2019-11-03 13:01:03 -05:00
parent 93fcdf8f6d
commit 0e1cfb66db
24 changed files with 164 additions and 65 deletions

View File

@ -9,7 +9,7 @@
#include <assert.h> #include <assert.h>
HRESULT amex_hook_init(const struct amex_config *cfg) HRESULT amex_hook_init(const struct amex_config *cfg, jvs_provider_t jvs)
{ {
HRESULT hr; HRESULT hr;
@ -33,7 +33,7 @@ HRESULT amex_hook_init(const struct amex_config *cfg)
return hr; return hr;
} }
hr = jvs_hook_init(&cfg->jvs); hr = jvs_hook_init(&cfg->jvs, jvs);
if (FAILED(hr)) { if (FAILED(hr)) {
return hr; return hr;

View File

@ -3,5 +3,8 @@
#include <windows.h> #include <windows.h>
#include "amex/config.h" #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);

View File

@ -39,8 +39,9 @@ static HRESULT jvs_ioctl_transact(struct irp *irp);
static HANDLE jvs_fd; static HANDLE jvs_fd;
static struct jvs_node *jvs_root; 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; HRESULT hr;
@ -50,12 +51,6 @@ HRESULT jvs_hook_init(const struct jvs_config *cfg)
return S_FALSE; return S_FALSE;
} }
hr = iohook_open_nul_fd(&jvs_fd);
if (FAILED(hr)) {
return hr;
}
hr = iohook_push_handler(jvs_handle_irp); hr = iohook_push_handler(jvs_handle_irp);
if (FAILED(hr)) { if (FAILED(hr)) {
@ -68,12 +63,9 @@ HRESULT jvs_hook_init(const struct jvs_config *cfg)
return hr; return hr;
} }
return S_OK; jvs_provider = provider;
}
void jvs_attach(struct jvs_node *root) return S_OK;
{
jvs_root = root;
} }
static HRESULT jvs_handle_irp(struct irp *irp) 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) static HRESULT jvs_handle_open(struct irp *irp)
{ {
struct jvs_node *root;
HRESULT hr;
if (!wstr_eq(irp->open_filename, L"$jvs")) { if (!wstr_eq(irp->open_filename, L"$jvs")) {
return iohook_invoke_next(irp); 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"); dprintf("JVS Port: Open device\n");
if (jvs_provider != NULL) {
hr = jvs_provider(&root);
if (SUCCEEDED(hr)) {
jvs_root = root;
}
}
irp->fd = jvs_fd; irp->fd = jvs_fd;
return S_OK; return S_OK;
@ -107,8 +123,9 @@ static HRESULT jvs_handle_open(struct irp *irp)
static HRESULT jvs_handle_close(struct irp *irp) static HRESULT jvs_handle_close(struct irp *irp)
{ {
dprintf("JVS Port: Close device\n"); 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) static HRESULT jvs_handle_ioctl(struct irp *irp)

View File

@ -13,5 +13,6 @@ DEFINE_GUID(
0x4288, 0x4288,
0xAA, 0x00, 0x6C, 0x00, 0xD7, 0x67, 0xBD, 0xBF); 0xAA, 0x00, 0x6C, 0x00, 0xD7, 0x67, 0xBD, 0xBF);
HRESULT jvs_hook_init(const struct jvs_config *cfg); typedef HRESULT (*jvs_provider_t)(struct jvs_node **root);
void jvs_attach(struct jvs_node *root);
HRESULT jvs_hook_init(const struct jvs_config *cfg, jvs_provider_t provider);

View File

@ -58,12 +58,7 @@ static DWORD CALLBACK chuni_pre_startup(void)
"AAV1", "AAV1",
chuni_hook_mod); chuni_hook_mod);
amex_hook_init(&chuni_hook_cfg.amex); amex_hook_init(&chuni_hook_cfg.amex, chunithm_jvs_init);
if (chuni_hook_cfg.amex.jvs.enable) {
chunithm_jvs_init();
}
slider_hook_init(&chuni_hook_cfg.slider); slider_hook_init(&chuni_hook_cfg.slider);
/* Initialize debug helpers */ /* Initialize debug helpers */
@ -72,10 +67,6 @@ static DWORD CALLBACK chuni_pre_startup(void)
dprintf("--- End chuni_pre_startup ---\n"); dprintf("--- End chuni_pre_startup ---\n");
/* Initialize IO DLL */
chuni_io_init();
/* Jump to EXE start address */ /* Jump to EXE start address */
return chuni_startup(); return chuni_startup();

View File

@ -42,10 +42,25 @@ static const struct chunithm_jvs_ir_mask chunithm_jvs_ir_masks[] = {
static struct io3 chunithm_jvs_io3; 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); 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) static void chunithm_jvs_read_switches(void *ctx, struct io3_switch_state *out)

View File

@ -1,3 +1,7 @@
#pragma once #pragma once
void chunithm_jvs_init(void); #include <windows.h>
#include "jvs/jvs-bus.h"
HRESULT chunithm_jvs_init(struct jvs_node **root);

View File

@ -81,6 +81,17 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
struct iobuf req_iobuf; struct iobuf req_iobuf;
HRESULT hr; 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); hr = uart_handle_irp(&slider_uart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) { if (FAILED(hr) || irp->op != IRP_OP_WRITE) {

View File

@ -18,7 +18,7 @@ static uint8_t chuni_io_hand_pos;
static HANDLE chuni_io_slider_thread; static HANDLE chuni_io_slider_thread;
static bool chuni_io_slider_stop_flag; static bool chuni_io_slider_stop_flag;
HRESULT chuni_io_init(void) HRESULT chuni_io_jvs_init(void)
{ {
return S_OK; 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) 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) void chuni_io_slider_start(chuni_io_slider_callback_t callback)
{ {
if (chuni_io_slider_thread != NULL) { if (chuni_io_slider_thread != NULL) {

View File

@ -1,10 +1,11 @@
LIBRARY chuniio LIBRARY chuniio
EXPORTS EXPORTS
chuni_io_init chuni_io_jvs_init
chuni_io_jvs_poll chuni_io_jvs_poll
chuni_io_jvs_read_coin_counter chuni_io_jvs_read_coin_counter
chuni_io_jvs_set_coin_blocker chuni_io_jvs_set_coin_blocker
chuni_io_slider_init
chuni_io_slider_set_leds chuni_io_slider_set_leds
chuni_io_slider_start chuni_io_slider_start
chuni_io_slider_stop chuni_io_slider_stop

View File

@ -5,15 +5,15 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
/* Initialize the Chunithm IO provider DLL. This is the first function to be /* Initialize JVS-based input. This function will be called before any other
called on this DLL. Returning failure from this function will cause the chuni_io_jvs_*() function calls. Errors returned from this function will
main application to immediately exit. manifest as a disconnected JVS bus.
All subsequent calls may originate from arbitrary threads and some may All subsequent calls may originate from arbitrary threads and some may
overlap with each other. Ensuring synchronization inside your IO DLL is overlap with each other. Ensuring synchronization inside your IO DLL is
your responsibility. */ your responsibility. */
HRESULT chuni_io_init(void); HRESULT chuni_io_jvs_init(void);
/* Poll JVS input. /* 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); 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: /* Chunithm touch slider layout:
^^^ Toward screen ^^^ ^^^ Toward screen ^^^

View File

@ -45,12 +45,7 @@ static DWORD CALLBACK diva_pre_startup(void)
"AAV0", "AAV0",
diva_hook_mod); diva_hook_mod);
amex_hook_init(&diva_hook_cfg.amex); amex_hook_init(&diva_hook_cfg.amex, diva_jvs_init);
if (diva_hook_cfg.amex.jvs.enable) {
diva_jvs_init();
}
sg_reader_hook_init(&diva_hook_cfg.aime, 10); sg_reader_hook_init(&diva_hook_cfg.aime, 10);
slider_hook_init(); slider_hook_init();

View File

@ -28,10 +28,25 @@ static const struct io3_ops diva_jvs_io3_ops = {
static struct io3 diva_jvs_io3; 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); 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) static void diva_jvs_read_switches(void *ctx, struct io3_switch_state *out)

View File

@ -1,3 +1,7 @@
#pragma once #pragma once
void diva_jvs_init(void); #include <windows.h>
#include "jvs/jvs-bus.h"
HRESULT diva_jvs_init(struct jvs_node **root);

View File

@ -73,6 +73,17 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
struct iobuf req_iobuf; struct iobuf req_iobuf;
HRESULT hr; 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); hr = uart_handle_irp(&slider_uart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) { if (FAILED(hr) || irp->op != IRP_OP_WRITE) {

View File

@ -14,7 +14,7 @@ static uint16_t diva_io_coins;
static HANDLE diva_io_slider_thread; static HANDLE diva_io_slider_thread;
static bool diva_io_slider_stop_flag; static bool diva_io_slider_stop_flag;
HRESULT diva_io_init(void) HRESULT diva_io_jvs_init(void)
{ {
return S_OK; 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) 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) void diva_io_slider_start(diva_io_slider_callback_t callback)
{ {
if (diva_io_slider_thread != NULL) { if (diva_io_slider_thread != NULL) {

View File

@ -1,10 +1,11 @@
LIBRARY divaio LIBRARY divaio
EXPORTS EXPORTS
diva_io_init diva_io_jvs_init
diva_io_jvs_poll diva_io_jvs_poll
diva_io_jvs_read_coin_counter diva_io_jvs_read_coin_counter
diva_io_jvs_set_coin_blocker diva_io_jvs_set_coin_blocker
diva_io_slider_init
diva_io_slider_set_leds diva_io_slider_set_leds
diva_io_slider_start diva_io_slider_start
diva_io_slider_stop diva_io_slider_stop

View File

@ -5,15 +5,15 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
/* Initialize the Project Diva IO provider DLL. This is the first function to be /* Initialize JVS-based input. This function will be called before any other
called on this DLL. Returning failure from this function will cause the main diva_io_jvs_*() function calls. Errors returned from this function will
application to immediately exit. manifest as a disconnected JVS bus.
All subsequent calls may originate from arbitrary threads and some may All subsequent calls may originate from arbitrary threads and some may
overlap with each other. Ensuring synchronization inside your IO DLL is overlap with each other. Ensuring synchronization inside your IO DLL is
your responsibility. */ your responsibility. */
HRESULT diva_io_init(void); HRESULT diva_io_jvs_init(void);
/* Poll JVS input. /* 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); 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 /* 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 cell 1 (array index 0) is the rightmost cell and cell 32 (array index 31) is
the leftmost cell. */ the leftmost cell. */

View File

@ -39,12 +39,7 @@ static DWORD CALLBACK idz_pre_startup(void)
/* Initialize emulation hooks */ /* Initialize emulation hooks */
platform_hook_init(&idz_hook_cfg.platform, "SDDF", "AAV2", idz_hook_mod); platform_hook_init(&idz_hook_cfg.platform, "SDDF", "AAV2", idz_hook_mod);
amex_hook_init(&idz_hook_cfg.amex); amex_hook_init(&idz_hook_cfg.amex, idz_jvs_init);
if (idz_hook_cfg.amex.jvs.enable) {
idz_jvs_init();
}
sg_reader_hook_init(&idz_hook_cfg.aime, 10); sg_reader_hook_init(&idz_hook_cfg.aime, 10);
/* Initialize debug helpers */ /* Initialize debug helpers */

View File

@ -51,18 +51,23 @@ static const uint16_t idz_jvs_gear_signals[] = {
static struct io3 idz_jvs_io3; static struct io3 idz_jvs_io3;
HRESULT idz_jvs_init(void) HRESULT idz_jvs_init(struct jvs_node **out)
{ {
HRESULT hr; 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)) { if (FAILED(hr)) {
dprintf("JVS I/O: Backend error, I/O disconnected; %x\n", (int) hr);
return hr; return hr;
} }
io3_init(&idz_jvs_io3, NULL, &idz_jvs_io3_ops, NULL); 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; return S_OK;
} }

View File

@ -2,4 +2,6 @@
#include <windows.h> #include <windows.h>
HRESULT idz_jvs_init(void); #include "jvs/jvs-bus.h"
HRESULT idz_jvs_init(struct jvs_node **root);

View File

@ -19,7 +19,7 @@ static const struct idz_io_backend *idz_io_backend;
static bool idz_io_coin; static bool idz_io_coin;
static uint16_t idz_io_coins; static uint16_t idz_io_coins;
HRESULT idz_io_init(void) HRESULT idz_io_jvs_init(void)
{ {
HRESULT hr; HRESULT hr;

View File

@ -1,7 +1,7 @@
LIBRARY idzio LIBRARY idzio
EXPORTS EXPORTS
idz_io_init idz_io_jvs_init
idz_io_jvs_read_analogs idz_io_jvs_read_analogs
idz_io_jvs_read_buttons idz_io_jvs_read_buttons
idz_io_jvs_read_coin_counter idz_io_jvs_read_coin_counter

View File

@ -24,7 +24,7 @@ struct idz_io_analog_state {
uint16_t brake; 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); void idz_io_jvs_read_analogs(struct idz_io_analog_state *out);