Files
djhackersdev_bemanitools/src/main/ddrhook/spike.c
T
icex2 f9c0733af3 Adapt everything in BT5 to new capnhook API
This includes:
- Renaming of functions (iohook_invoke_next)
- Slight interface changes (com_proxy_wrap, iohook_push_handler)
- De-duplicate stuff from utils (iobuf, hr)
2020-09-02 19:35:15 +00:00

179 lines
4.5 KiB
C

#define LOG_MODULE "spike"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <devioctl.h>
#include <ntdef.h>
#include <ntddser.h>
// clang-format on
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "acioemu/addr.h"
#include "acioemu/emu.h"
#include "hook/iohook.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
static struct ac_io_emu spike_ac_io_emu;
static void spike_handle_broadcast(const struct ac_io_message *bcast);
static void spike_handle_get_version(const struct ac_io_message *req);
static void spike_handle_status(const struct ac_io_message *req);
static void spike_send_empty(const struct ac_io_message *req);
void spike_init(void)
{
ac_io_emu_init(&spike_ac_io_emu, L"COM2");
}
void spike_fini(void)
{
ac_io_emu_fini(&spike_ac_io_emu);
}
HRESULT
spike_dispatch_irp(struct irp *irp)
{
const struct ac_io_message *msg;
HRESULT hr;
log_assert(irp != NULL);
if (!ac_io_emu_match_irp(&spike_ac_io_emu, irp)) {
return iohook_invoke_next(irp);
}
for (;;) {
hr = ac_io_emu_dispatch_irp(&spike_ac_io_emu, irp);
if (hr != S_OK) {
return hr;
}
msg = ac_io_emu_request_peek(&spike_ac_io_emu);
switch (msg->addr) {
case 0:
ac_io_emu_cmd_assign_addrs(&spike_ac_io_emu, msg, 7);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
switch (ac_io_u16(msg->cmd.code)) {
case AC_IO_CMD_GET_VERSION:
spike_handle_get_version(msg);
break;
case AC_IO_CMD_START_UP:
spike_handle_status(msg);
break;
case AC_IO_CMD_KEEPALIVE:
spike_send_empty(msg);
break;
case 0x100:
case 0x110:
case 0x112:
case 0x128:
spike_handle_status(msg);
break;
default:
log_warning(
"Spike ACIO unhandled cmd: %04X",
ac_io_u16(msg->cmd.code));
}
break;
case AC_IO_BROADCAST:
spike_handle_broadcast(msg);
break;
default:
log_warning(
"Spike ACIO message on unhandled bus address: %d",
msg->addr);
break;
}
ac_io_emu_request_pop(&spike_ac_io_emu);
}
}
static void spike_handle_broadcast(const struct ac_io_message *bcast)
{
/* The payload consists of 7x10 byte chunks. Chunk 0 seems to correspond
to the front LED strip, and chunks 1-6 are the 2x3 spike bundles on the
side of a dedicab. No idea about the format of this data other than
that, try figuring it out if you're bored. */
}
static void spike_handle_get_version(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_LED_SPIKE);
resp.cmd.version.flag = 0x00;
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x01;
resp.cmd.version.revision = 0x00;
memcpy(
resp.cmd.version.product_code,
"DDRS",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
static void spike_handle_status(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.status);
resp.cmd.status = 0x00;
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}
static void spike_send_empty(const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = 0;
ac_io_emu_response_push(&spike_ac_io_emu, &resp, 0);
}