mirror of
https://gitea.tendokyu.moe/TeamTofuShop/taitools.git
synced 2026-09-22 22:28:06 +03:00
153 lines
3.7 KiB
C
153 lines
3.7 KiB
C
#define WIN32_NO_STATUS
|
|
#include <windows.h>
|
|
#undef WIN32_NO_STATUS
|
|
#include <winternl.h>
|
|
|
|
#include <ntstatus.h>
|
|
|
|
#include <assert.h>
|
|
#include <stddef.h>
|
|
|
|
#include "idmac/jvs.h"
|
|
|
|
#include "hook/iobuf.h"
|
|
#include "hook/iohook.h"
|
|
#include "hooklib/uart.h"
|
|
|
|
#include "hooklib/setupapi.h"
|
|
|
|
#include "jvs/jvs-bus.h"
|
|
|
|
#include "util/dprintf.h"
|
|
#include "util/dump.h"
|
|
#include "util/str.h"
|
|
|
|
enum {
|
|
JVS_IOCTL_HELLO = 0x80006004,
|
|
JVS_IOCTL_SENSE = 0x8000600C,
|
|
JVS_IOCTL_TRANSACT = 0x8000E008,
|
|
};
|
|
|
|
static HRESULT jvs_handle_irp(struct irp *irp);
|
|
static HRESULT jvs_handle_irp_locked(struct irp *irp);
|
|
|
|
static CRITICAL_SECTION jvs_lock;
|
|
static struct uart jvs_uart;
|
|
static uint8_t jvs_written_bytes[516];
|
|
static uint8_t jvs_readable_bytes[516];
|
|
static uint8_t temp_bytes[516];
|
|
static struct jvs_node *jvs_root;
|
|
static jvs_provider_t jvs_provider;
|
|
static struct iobuf tmp = {
|
|
.nbytes = 516,
|
|
.pos = 0,
|
|
.bytes = temp_bytes
|
|
};
|
|
static bool last = false;
|
|
static uint8_t num_cts = 0;
|
|
|
|
HRESULT jvs_hook_init(const struct jvs_config *cfg, jvs_provider_t provider)
|
|
{
|
|
HRESULT hr;
|
|
|
|
assert(cfg != NULL);
|
|
|
|
if (!cfg->enable) {
|
|
return S_FALSE;
|
|
}
|
|
|
|
InitializeCriticalSection(&jvs_lock);
|
|
|
|
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)) {
|
|
return iohook_invoke_next(irp);
|
|
}
|
|
|
|
EnterCriticalSection(&jvs_lock);
|
|
hr = jvs_handle_irp_locked(irp);
|
|
LeaveCriticalSection(&jvs_lock);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT jvs_handle_irp_locked(struct irp *irp)
|
|
{
|
|
#if 0
|
|
dprintf("\nJVS Port: Outbound frame:\n");
|
|
dump_const_iobuf(&irp->write);
|
|
#endif
|
|
|
|
struct iobuf req_iobuf;
|
|
HRESULT hr;
|
|
struct jvs_node *root;
|
|
|
|
if (irp->op == IRP_OP_OPEN) {
|
|
dprintf("iDmac JVS: Starting backend\n");
|
|
if (jvs_provider != NULL) {
|
|
hr = jvs_provider(&root);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
jvs_root = root;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (irp->op == IRP_OP_IOCTL) {
|
|
switch (irp->ioctl) {
|
|
case IOCTL_SERIAL_GET_MODEMSTATUS:
|
|
//jvs_uart.cts_on = jvs_root->sense_out;
|
|
//dprintf("JVS: Set CTS to %X\n", jvs_root->sense_out);
|
|
jvs_uart.cts_on = !jvs_root->sense_out; // ??
|
|
break;
|
|
case IOCTL_SERIAL_GET_COMMSTATUS:
|
|
//dprintf("JVS: Set cbInQue to %d\n", (int)tmp.pos);
|
|
jvs_uart.readable.pos = tmp.pos;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
if (irp->op == IRP_OP_READ) {
|
|
if (irp->read.nbytes == 1) {
|
|
iobuf_write_8(&irp->read, 1);
|
|
return S_OK;
|
|
}
|
|
if (irp->read.nbytes >= tmp.pos) {
|
|
//dprintf("JVS: Readable buffer is %d / %d\n", (int)irp->read.nbytes, (int)tmp.pos);
|
|
iobuf_write(&irp->read, tmp.bytes, tmp.pos);
|
|
tmp.pos = 0;
|
|
} else {
|
|
dprintf("JVS: READ need %d bytes but only have room for %d\n", tmp.pos, irp->read.nbytes);
|
|
iobuf_write(&irp->read, tmp.bytes, irp->read.nbytes);
|
|
tmp.pos -= irp->read.nbytes;
|
|
}
|
|
}
|
|
|
|
hr = uart_handle_irp(&jvs_uart, irp);
|
|
|
|
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
|
return hr;
|
|
}
|
|
|
|
jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &tmp);
|
|
|
|
jvs_uart.written.pos = 0;
|
|
|
|
return S_OK;
|
|
}
|