106 lines
2.3 KiB
C
106 lines
2.3 KiB
C
|
#include <windows.h>
|
||
|
|
||
|
#include <assert.h>
|
||
|
#include <process.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "hook/iobuf.h"
|
||
|
#include "hook/iohook.h"
|
||
|
|
||
|
#include "hooklib/uart.h"
|
||
|
#include "hooklib/fdshark.h"
|
||
|
|
||
|
#include "util/dprintf.h"
|
||
|
#include "util/dump.h"
|
||
|
|
||
|
#include "platform/jvs.h"
|
||
|
|
||
|
|
||
|
static HRESULT jvs_handle_irp(struct irp *irp);
|
||
|
static HRESULT jvs_handle_irp_locked(struct irp *irp);
|
||
|
|
||
|
static struct uart jvs_uart;
|
||
|
static CRITICAL_SECTION jvs_lock;
|
||
|
static uint8_t jvs_written_bytes[520];
|
||
|
static uint8_t jvs_readable_bytes[520];
|
||
|
|
||
|
static struct jvs_node *jvs_root;
|
||
|
static jvs_provider_t jvs_provider;
|
||
|
|
||
|
HRESULT jvs_hook_init(const struct jvs_config *cfg, jvs_provider_t provider)
|
||
|
{
|
||
|
if (!cfg->enable || provider == NULL) {
|
||
|
dprintf("JVS I/O: Disabled\n");
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
InitializeCriticalSection(&jvs_lock);
|
||
|
dprintf("JVS I/O: init\n");
|
||
|
|
||
|
uart_init(&jvs_uart, cfg->port);
|
||
|
jvs_uart.written.bytes = jvs_written_bytes;
|
||
|
jvs_uart.written.nbytes = sizeof(jvs_written_bytes);
|
||
|
jvs_uart.readable.bytes = jvs_readable_bytes;
|
||
|
jvs_uart.readable.nbytes = sizeof(jvs_readable_bytes);
|
||
|
|
||
|
jvs_provider = provider;
|
||
|
|
||
|
return iohook_push_handler(jvs_handle_irp);
|
||
|
}
|
||
|
|
||
|
static HRESULT jvs_handle_irp(struct irp *irp)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
assert(irp != NULL);
|
||
|
|
||
|
if (uart_match_irp(&jvs_uart, irp)) {
|
||
|
EnterCriticalSection(&jvs_lock);
|
||
|
hr = jvs_handle_irp_locked(irp);
|
||
|
LeaveCriticalSection(&jvs_lock);
|
||
|
}
|
||
|
else {
|
||
|
return iohook_invoke_next(irp);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
static HRESULT jvs_handle_irp_locked(struct irp *irp)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
struct jvs_node *root;
|
||
|
|
||
|
if (irp->op == IRP_OP_OPEN) {
|
||
|
dprintf("JVS I/O: Starting backend\n");
|
||
|
|
||
|
if (jvs_provider != NULL) {
|
||
|
hr = jvs_provider(&root);
|
||
|
|
||
|
if (SUCCEEDED(hr)) {
|
||
|
jvs_root = root;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hr = uart_handle_irp(&jvs_uart, irp);
|
||
|
|
||
|
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
for (;;) {
|
||
|
#if 0
|
||
|
dprintf("JVS I/O: Written\n");
|
||
|
dump_iobuf(&jvs_uart.written);
|
||
|
#endif
|
||
|
|
||
|
jvs_bus_transact(jvs_root, jvs_uart.written.bytes, jvs_uart.written.pos, &jvs_uart.readable);
|
||
|
|
||
|
jvs_uart.written.pos = 0;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|