From 4564699a42e11198671098905d25ef30c04b8725 Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 8 Nov 2018 16:12:05 -0500 Subject: [PATCH] chunihook/slider.c: Add Chunithm slider emulation --- chunihook/meson.build | 2 + chunihook/slider.c | 269 ++++++++++++++++++++++++++++++++++++++++++ chunihook/slider.h | 3 + 3 files changed, 274 insertions(+) create mode 100644 chunihook/slider.c create mode 100644 chunihook/slider.h diff --git a/chunihook/meson.build b/chunihook/meson.build index 5cf005c..fc99af2 100644 --- a/chunihook/meson.build +++ b/chunihook/meson.build @@ -18,5 +18,7 @@ shared_library( sources : [ 'jvs.c', 'jvs.h', + 'slider.c', + 'slider.h', ], ) diff --git a/chunihook/slider.c b/chunihook/slider.c new file mode 100644 index 0000000..55fbf8a --- /dev/null +++ b/chunihook/slider.c @@ -0,0 +1,269 @@ +#include + +#include +#include +#include +#include +#include + +#include "util/dprintf.h" +#include "util/dump.h" + +#include "board/slider-cmd.h" +#include "board/slider-frame.h" + +#include "hook/iobuf.h" +#include "hook/iohook.h" + +#include "hooklib/uart.h" + +static HRESULT slider_handle_irp(struct irp *irp); +static HRESULT slider_handle_irp_locked(struct irp *irp); + +static HRESULT slider_req_dispatch(const union slider_req_any *req); +static HRESULT slider_req_reset(void); +static HRESULT slider_req_get_board_info(void); +static HRESULT slider_req_auto_scan_start(void); +static HRESULT slider_req_auto_scan_stop(void); +static HRESULT slider_req_set_led(const struct slider_req_set_led *req); + +static unsigned int __stdcall slider_thread_proc(void *ctx); + +static CRITICAL_SECTION slider_lock; +static struct uart slider_uart; +static uint8_t slider_written_bytes[520]; +static uint8_t slider_readable_bytes[520]; + +static HANDLE slider_thread; +static bool slider_stop; + +void slider_hook_init(void) +{ + InitializeCriticalSection(&slider_lock); + + uart_init(&slider_uart, 1); + slider_uart.written.bytes = slider_written_bytes; + slider_uart.written.nbytes = sizeof(slider_written_bytes); + slider_uart.readable.bytes = slider_readable_bytes; + slider_uart.readable.nbytes = sizeof(slider_readable_bytes); + + iohook_push_handler(slider_handle_irp); +} + +static HRESULT slider_handle_irp(struct irp *irp) +{ + HRESULT hr; + + assert(irp != NULL); + + if (!uart_match_irp(&slider_uart, irp)) { + return iohook_invoke_next(irp); + } + + EnterCriticalSection(&slider_lock); + hr = slider_handle_irp_locked(irp); + LeaveCriticalSection(&slider_lock); + + return hr; +} + +static HRESULT slider_handle_irp_locked(struct irp *irp) +{ + union slider_req_any req; + struct iobuf req_iobuf; + HRESULT hr; + + hr = uart_handle_irp(&slider_uart, irp); + + if (FAILED(hr) || irp->op != IRP_OP_WRITE) { + return hr; + } + + for (;;) { +#if 0 + dprintf("TX Buffer:\n"); + dump_iobuf(&slider_uart.written); +#endif + + req_iobuf.bytes = req.bytes; + req_iobuf.nbytes = sizeof(req.bytes); + req_iobuf.pos = 0; + + hr = slider_frame_decode(&req_iobuf, &slider_uart.written); + + if (hr != S_OK) { + if (FAILED(hr)) { + dprintf("Chunithm slider: Deframe error: %x\n", (int) hr); + } + + return hr; + } + +#if 0 + dprintf("Deframe Buffer:\n"); + dump_iobuf(&req_iobuf); +#endif + + hr = slider_req_dispatch(&req); + + if (FAILED(hr)) { + dprintf("Chunithm slider: Processing error: %x\n", (int) hr); + } + } +} + +static HRESULT slider_req_dispatch(const union slider_req_any *req) +{ + switch (req->hdr.cmd) { + case SLIDER_CMD_RESET: + return slider_req_reset(); + + case SLIDER_CMD_GET_BOARD_INFO: + return slider_req_get_board_info(); + + case SLIDER_CMD_SET_LED: + return slider_req_set_led(&req->set_led); + + case SLIDER_CMD_AUTO_SCAN_START: + return slider_req_auto_scan_start(); + + case SLIDER_CMD_AUTO_SCAN_STOP: + return slider_req_auto_scan_stop(); + + default: + dprintf("Unhandled command %02x\n", req->hdr.cmd); + + return S_OK; + } +} + +static HRESULT slider_req_reset(void) +{ + struct slider_hdr resp; + + dprintf("Chunithm slider: Reset\n"); + + resp.sync = 0xFF; + resp.cmd = SLIDER_CMD_RESET; + resp.nbytes = 0; + + return slider_frame_encode(&slider_uart.readable, &resp, sizeof(resp)); +} + +static HRESULT slider_req_get_board_info(void) +{ + struct slider_resp_get_board_info resp; + + dprintf("Chunithm slider: Get firmware version\n"); + + memset(&resp, 0, sizeof(resp)); + resp.hdr.sync = SLIDER_FRAME_SYNC; + resp.hdr.cmd = SLIDER_CMD_GET_BOARD_INFO; + resp.hdr.nbytes = sizeof(resp.version); + + strcpy_s( + resp.version, + sizeof(resp.version), + "15330 \xA0" "06712\xFF" "\x90"); + + return slider_frame_encode(&slider_uart.readable, &resp, sizeof(resp)); +} + +static HRESULT slider_req_auto_scan_start(void) +{ + dprintf("Chunithm slider: Start slider thread\n"); + + if (slider_thread != NULL) { + dprintf("Thread is already running\n"); + + return S_OK; + } + + slider_thread = (HANDLE) _beginthreadex( + NULL, + 0, + slider_thread_proc, + NULL, + 0, + NULL); + + if (slider_thread == NULL) { + dprintf("Thread launch failed\n"); + } + + /* This message is not acknowledged */ + + return S_OK; +} + +static HRESULT slider_req_auto_scan_stop(void) +{ + struct slider_hdr resp; + + dprintf("Chunithm slider: Stop slider thread\n"); + + if (slider_thread != NULL) { + slider_stop = true; + LeaveCriticalSection(&slider_lock); + + WaitForSingleObject(slider_thread, INFINITE); + CloseHandle(slider_thread); + slider_thread = NULL; + slider_stop = false; + + dprintf("Chunithm slider: Thread has terminated\n"); + + EnterCriticalSection(&slider_lock); + } + + resp.sync = SLIDER_FRAME_SYNC; + resp.cmd = SLIDER_CMD_AUTO_SCAN_STOP; + resp.nbytes = 0; + + return slider_frame_encode(&slider_uart.readable, &resp, sizeof(resp)); +} + +static HRESULT slider_req_set_led(const struct slider_req_set_led *req) +{ + /* This message is not acknowledged */ + return S_OK; +} + +static unsigned int WINAPI slider_thread_proc(void *ctx) +{ + static const int keys[] = { + 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', + }; + + struct slider_resp_auto_scan resp; + uint8_t pressure; + bool stop; + size_t i; + + for (;;) { + resp.hdr.sync = SLIDER_FRAME_SYNC; + resp.hdr.cmd = SLIDER_CMD_AUTO_SCAN; + resp.hdr.nbytes = sizeof(resp.pressure); + + for (i = 0 ; i < 8 ; i++) { + pressure = GetAsyncKeyState(keys[i]) ? 20 : 0; + memset(&resp.pressure[28 - 4 * i], pressure, 4); + } + + EnterCriticalSection(&slider_lock); + + stop = slider_stop; + + if (!stop) { + slider_frame_encode(&slider_uart.readable, &resp, sizeof(resp)); + } + + LeaveCriticalSection(&slider_lock); + + if (stop) { + return 0; + } + + Sleep(1); + } +} diff --git a/chunihook/slider.h b/chunihook/slider.h new file mode 100644 index 0000000..eb429e9 --- /dev/null +++ b/chunihook/slider.h @@ -0,0 +1,3 @@ +#pragma once + +void slider_hook_init(void);