1
0
mirror of synced 2024-11-24 08:00:09 +01:00
Arduino-Aime-Reader/tools/segatools-edit/vfd.c

196 lines
5.9 KiB
C
Raw Normal View History

2024-10-20 09:26:29 +02:00
/* This is some sort of LCD display found on various cabinets. It is driven
directly by amdaemon, and it has something to do with displaying the status
of electronic payments.
Part number in schematics is "VFD GP1232A02A FUTABA".
Little else about this board is known. Black-holing the RS232 comms that it
receives seems to be sufficient for the time being. */
#include <windows.h>
#include <assert.h>
#include <stdint.h>
#include "board/vfd.h"
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "util/dprintf.h"
#include "util/dump.h"
static HRESULT vfd_handle_irp(struct irp *irp);
static struct uart vfd_uart;
static uint8_t vfd_written[512];
static uint8_t vfd_readable[512];
static uint8_t vfd_enable, vfd_redirect;
static HANDLE com_device;
UINT codepage;
HRESULT vfd_hook_init(unsigned int port_no)
{
vfd_enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, L".\\segatools.ini");
vfd_redirect = GetPrivateProfileIntW(L"vfd", L"redirect", 0, L".\\segatools.ini");
if (!vfd_enable)
{
return S_FALSE;
}
char com_name[10];
// sprintf(com_name, "\\\\.\\COM%d", port_no);
// com_device = CreateFile(com_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
// if (com_device != INVALID_HANDLE_VALUE)
// {
// CloseHandle(com_device);
// if (!vfd_redirect)
// {
// return S_FALSE;
// }
// }
uart_init(&vfd_uart, port_no);
vfd_uart.written.bytes = vfd_written;
vfd_uart.written.nbytes = sizeof(vfd_written);
vfd_uart.readable.bytes = vfd_readable;
vfd_uart.readable.nbytes = sizeof(vfd_readable);
if (vfd_redirect) // 将 vfd 串口数据重写到另一个 com用于调试
{
dprintf("VFD: redirect enable, target COM%d.\n", vfd_redirect);
sprintf(com_name, "\\\\.\\COM%d", vfd_redirect);
com_device = CreateFile(com_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (com_device != INVALID_HANDLE_VALUE)
{
dprintf("VFD: CreateFile OK.\n");
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
GetCommState(com_device, &dcbSerialParams);
dcbSerialParams.BaudRate = 115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
SetCommState(com_device, &dcbSerialParams);
// COMMTIMEOUTS timeouts = {0};
// timeouts.ReadIntervalTimeout = 1;
// timeouts.ReadTotalTimeoutConstant = 1;
// timeouts.ReadTotalTimeoutMultiplier = 1;
// timeouts.WriteTotalTimeoutConstant = 1;
// timeouts.WriteTotalTimeoutMultiplier = 1;
// SetCommTimeouts(com_device, &timeouts);
EscapeCommFunction(com_device, SETDTR);
EscapeCommFunction(com_device, SETRTS);
}
else
{
dprintf("VFD: CreateFile error.\n");
}
}
codepage = GetACP(); // 获取当前系统的 Code page用于后续转码显示
dprintf("VFD: hook enabled.\n");
return iohook_push_handler(vfd_handle_irp);
}
static HRESULT vfd_handle_irp(struct irp *irp)
{
HRESULT hr;
assert(irp != NULL);
if (!uart_match_irp(&vfd_uart, irp))
{
return iohook_invoke_next(irp);
}
hr = uart_handle_irp(&vfd_uart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE)
{
return hr;
}
if (vfd_redirect && com_device != INVALID_HANDLE_VALUE)
{
DWORD bytesWritten;
if (WriteFile(com_device, vfd_uart.written.bytes, vfd_uart.written.pos, &bytesWritten, NULL))
{
dprintf("VFD: WriteFile %lu.\n", bytesWritten);
}
}
else
{
uint8_t cmd = 0;
uint8_t str_1[512]; // 两行数据的缓冲区
uint8_t str_2[512];
uint8_t str_1_len = 0;
uint8_t str_2_len = 0;
for (size_t i = 0; i < vfd_uart.written.pos; i++)
{
if (vfd_uart.written.bytes[i] == 0x1B)
{
i++;
cmd = vfd_uart.written.bytes[i];
if (cmd == 0x30)
{
i += 3;
}
else if (cmd == 0x50)
{
i++;
}
continue;
}
if (cmd == 0x30)
{
str_1[str_1_len++] = vfd_uart.written.bytes[i];
}
else if (cmd == 0x50)
{
str_2[str_2_len++] = vfd_uart.written.bytes[i];
}
}
if (str_1_len)
{
str_1[str_1_len++] = '\0';
if (codepage != 932)
{ // 如果非日文系统,则转码后输出 https://en.wikipedia.org/wiki/Code_page_932_(Microsoft_Windows)
WCHAR buffer[512];
MultiByteToWideChar(932, 0, (LPCSTR)str_1, str_1_len, buffer, str_1_len);
char str_recode[str_1_len * 3];
WideCharToMultiByte(codepage, 0, buffer, str_1_len, str_recode, str_1_len * 3, NULL, NULL);
dprintf("VFD: %s\n", str_recode);
}
else
{
dprintf("VFD: %s\n", str_1);
}
}
if (str_2_len)
{
str_2[str_2_len++] = '\0';
if (codepage != 932)
{
WCHAR buffer[512];
MultiByteToWideChar(932, 0, (LPCSTR)str_2, str_2_len, buffer, str_2_len);
char str_recode[str_2_len * 3];
WideCharToMultiByte(codepage, 0, buffer, str_2_len, str_recode, str_2_len * 3, NULL, NULL);
dprintf("VFD: %s\n", str_recode);
}
else
{
dprintf("VFD: %s\n", str_2);
}
}
}
vfd_uart.written.pos = 0;
return hr;
}