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>
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;

View File

@ -3,5 +3,8 @@
#include <windows.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 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)

View File

@ -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);

View File

@ -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();

View File

@ -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)

View File

@ -1,3 +1,7 @@
#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;
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) {

View File

@ -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) {

View File

@ -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

View File

@ -5,15 +5,15 @@
#include <stdbool.h>
#include <stdint.h>
/* 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 ^^^

View File

@ -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();

View File

@ -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)

View File

@ -1,3 +1,7 @@
#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;
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) {

View File

@ -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) {

View File

@ -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

View File

@ -5,15 +5,15 @@
#include <stdbool.h>
#include <stdint.h>
/* 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. */

View File

@ -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 */

View File

@ -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;
}

View File

@ -2,4 +2,6 @@
#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 uint16_t idz_io_coins;
HRESULT idz_io_init(void)
HRESULT idz_io_jvs_init(void)
{
HRESULT hr;

View File

@ -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

View File

@ -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);