bananatools/board/usio.c

283 lines
6.0 KiB
C

#include <windows.h>
#include <devioctl.h>
#include <hidclass.h>
#include <winusb.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "board/config.h"
#include "board/guid.h"
#include "board/usio.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hook/table.h"
#include "hook/iohook.h"
#include "hooklib/setupapi.h"
#include "util/dprintf.h"
#include "util/dump.h"
static const wchar_t usio_path[] = L"$usio";
//static const wchar_t usio_path[] = L"USBIO_Device0";
static int my_bnusio_Open();
static int my_bnusio_Close();
static int my_bnusio_GetFirmwareVersion();
static int my_bnusio_SetSystemError(uint16_t err);
static int my_bnusio_ClearSram();
static BOOL my_bnusio_ResetIoBoard();
static int my_bnusio_Communication(uint64_t com);
static int my_bnusio_GetSystemError();
static void my_bnusio_SetPLCounter(uint16_t pl_ct);
static int my_bnusio_SetGout(uint8_t id, uint8_t value);
static int my_bnusio_GetAnalogIn(uint8_t id);
static int my_bnusio_GetSwIn();
static int my_bnusio_SetCoinLock(uint8_t id, char value);
static int my_bnusio_GetCoin(uint8_t id);
static int my_bnusio_GetCoinError(uint8_t id);
static int my_bnusio_GetService(uint8_t id);
static int my_bnusio_GetServiceError(uint8_t id);
static const struct hook_symbol winusb_syms[] = {
{
.name = "bnusio_Open",
.patch = my_bnusio_Open
},
{
.name = "bnusio_GetFirmwareVersion",
.patch = my_bnusio_GetFirmwareVersion
},
{
.name = "bnusio_Close",
.patch = my_bnusio_Close
},
{
.name = "bnusio_SetSystemError",
.patch = my_bnusio_SetSystemError
},
{
.name = "bnusio_ClearSram",
.patch = my_bnusio_ClearSram
},
{
.name = "bnusio_ResetIoBoard",
.patch = my_bnusio_ResetIoBoard
},
{
.name = "bnusio_Communication",
.patch = my_bnusio_Communication
},
{
.name = "bnusio_GetSystemError",
.patch = my_bnusio_GetSystemError
},
{
.name = "bnusio_SetPLCounter",
.patch = my_bnusio_SetPLCounter
},
{
.name = "bnusio_SetGout",
.patch = my_bnusio_SetGout
},
{
.name = "bnusio_GetAnalogIn",
.patch = my_bnusio_GetAnalogIn
},
{
.name = "bnusio_GetSwIn",
.patch = my_bnusio_GetSwIn
},
{
.name = "bnusio_SetCoinLock",
.patch = my_bnusio_SetCoinLock
},
{
.name = "bnusio_GetCoin",
.patch = my_bnusio_GetCoin
},
{
.name = "bnusio_GetCoinError",
.patch = my_bnusio_GetCoinError
},
{
.name = "bnusio_GetService",
.patch = my_bnusio_GetService
},
{
.name = "bnusio_GetServiceError",
.patch = my_bnusio_GetServiceError
}
};
static HANDLE usio_fd;
static const struct usio_ops *usio_ops;
static void *usio_ops_ctx;
static struct usio_state state;
HRESULT usio_hook_init(
const struct usio_config *cfg,
const struct usio_ops *ops,
void *ctx,
HMODULE target)
{
HRESULT hr;
assert(cfg != NULL);
assert(ops != NULL);
if (!cfg->enable) {
return S_FALSE;
}
usio_ops = ops;
usio_ops_ctx = ctx;
hook_table_apply(target, "bnusio.dll", winusb_syms, _countof(winusb_syms));
memset(&state, 0, sizeof(state));
dprintf("USIO: Init\n");
return S_OK;
}
static int my_bnusio_Open()
{
dprintf("USIO: Open\n");
return 0;
}
static int my_bnusio_GetFirmwareVersion()
{
dprintf("USIO: GetFirmwareVersion\n");
return 126;
}
static int my_bnusio_Close()
{
dprintf("USIO: Close\n");
return 0;
}
static int my_bnusio_SetSystemError(uint16_t err)
{
dprintf("USIO: SetSystemError %d\n", err);
state.err = err;
return 0;
}
static int my_bnusio_ClearSram()
{
dprintf("USIO: ClearSram\n");
return 0;
}
static BOOL my_bnusio_ResetIoBoard()
{
dprintf("USIO: ResetIoBoard\n");
return false;
}
static int my_bnusio_Communication(uint64_t com)
{
//dprintf("USIO: Communication\n");
return 0;
}
static int my_bnusio_GetSystemError()
{
dprintf("USIO: GetSystemError\n");
return state.err;
}
static void my_bnusio_SetPLCounter(uint16_t pl_ct)
{
//dprintf("USIO: SetPLCounter\n");
state.pl_count = pl_ct;
}
static int my_bnusio_SetGout(uint8_t id, uint8_t value)
{
//dprintf("USIO: SetGout ID %d Val %d\n", id, value);
if (id <= 32) {
state.gpio[id - 1] = value;
return 0;
}
return 0xFFFFFFEA;
}
static int my_bnusio_SetCoinLock(uint8_t id, char value)
{
dprintf("USIO: SetCoinLock %d %x\n", id, value);
state.coins[id].is_lock = value;
return 0;
}
static int my_bnusio_GetCoin(uint8_t id)
{
//dprintf("USIO: GetCoin ID %d\n", id);
usio_ops->poll(usio_ops_ctx, &state);
if (id < 2) {
return state.coins[id].current_coin_count;
}
return 0;
}
static int my_bnusio_GetCoinError(uint8_t id)
{
//dprintf("USIO: GetCoinErrorID %d\n", id);
if (id >= _countof(state.coins)) {
return 0;
}
return state.coins[id].err;
}
static int my_bnusio_GetService(uint8_t id)
{
//dprintf("USIO: GetService ID %d\n", id);
usio_ops->poll(usio_ops_ctx, &state);
if (id < 1) {
return state.service.current_coin_count;
}
return 0;
}
static int my_bnusio_GetServiceError(uint8_t id)
{
// TODO: multiple service switches?
//dprintf("USIO: GetServiceError ID %d\n", id);
if (id < 1) {
return state.service.err;
}
return 0;
}
static int my_bnusio_GetAnalogIn(uint8_t id)
{
//dprintf("USIO: GetAnalogIn ID %d\n", id);
uint8_t gamebtns = 0;
usio_ops->poll(usio_ops_ctx, &state);
if (id < 8) {
return state.analog[id];
}
return 0;
}
static int my_bnusio_GetSwIn()
{
//dprintf("USIO: GetSwitchIn\n");
uint32_t opbtn_out = 0;
usio_ops->poll(usio_ops_ctx, &state);
opbtn_out = (state.p2_btns << 16) | (state.p1_btns << 8) | state.op_btns;
return opbtn_out;
}