bananatools/board/qr.c

197 lines
5.1 KiB
C

#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "board/qr.h"
#include "hook/table.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "hooklib/fdshark.h"
#include "util/dprintf.h"
#include "util/dump.h"
/*
* Scans QR Codes that the Taiko twitter sometimes
* puts out to unlock songs and other things. Huge
* thanks to mon for writing most of this!
*/
static HRESULT qr_handle_irp_locked(struct irp *irp);
static HRESULT qr_handle_irp(struct irp *irp);
static struct uart qr_uart;
static CRITICAL_SECTION qr_lock;
static uint8_t qr_written_bytes[520];
static uint8_t qr_readable_bytes[520];
static bool reader_active;
HRESULT qr_hook_init(const struct qr_config *cfg, unsigned int port)
{
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
if (cfg->port > 0) {
port = cfg->port;
}
dprintf("QR: Init on COM%d\n", port);
uart_init(&qr_uart, port);
qr_uart.written.bytes = qr_written_bytes;
qr_uart.written.nbytes = sizeof(qr_written_bytes);
qr_uart.readable.bytes = qr_readable_bytes;
qr_uart.readable.nbytes = sizeof(qr_readable_bytes);
InitializeCriticalSection(&qr_lock);
return iohook_push_handler(qr_handle_irp);
return S_OK;
}
/*
QR port opened
all requests and responses end with 0x55 0x00
all requests appear to start with 0x57 0x00 followed by a command code
Requests:
Lamp on: 57 00 17 52 00 02 00 01 00 55 00
Lamp off: 57 00 17 52 00 01 00 01 00 55 00
Scan off: 57 00 19 00 55 00
Scan on : 57 00 18 00 55 00
Responses:
Bit index 2 appears to be used as a status code
"OK" : 31 00 00 00 55 00
example QR code (thx tung)
[83,49,50,0,0,255,255,17,1,0,67,79,76,76,65,66,79,95,84,79,72,79,95,50,48,50,48,238,255]
WRITE:
00000000: W..R.....U.
*/
static HRESULT qr_handle_irp(struct irp* irp)
{
HRESULT hr;
assert(irp != NULL);
// dprintf("QR: IRP request to %ls\n", irp->open_filename);
if (!uart_match_irp(&qr_uart, irp)) {
return iohook_invoke_next(irp);
}
EnterCriticalSection(&qr_lock);
hr = qr_handle_irp_locked(irp);
LeaveCriticalSection(&qr_lock);
return hr;
}
static HRESULT qr_handle_irp_locked(struct irp* irp)
{
HRESULT hr;
#if 0
if (irp->op == IRP_OP_WRITE) {
dprintf("WRITE:\n");
dump_const_iobuf(&irp->write);
}
#endif
#if 0
if (irp->op == IRP_OP_READ) {
dprintf("READ:\n");
dump_iobuf(&qr_uart.readable);
}
#endif
if (irp->op == IRP_OP_OPEN) {
dprintf("QR: port opened\n");
///* Unfortunately the card reader UART gets opened and closed
// repeatedly */
//if (!qr_started) {
// dprintf("NFC Assembly: Starting backend DLL\n");
// hr = aime_io_init();
// qr_started = true;
// qr_start_hr = hr;
// if (FAILED(hr)) {
// dprintf("NFC Assembly: Backend error: %x\n", (int)hr);
// return hr;
// }
//}
//else {
// hr = qr_start_hr;
// if (FAILED(hr)) {
// return hr;
// }
//}
}
if (irp->op == IRP_OP_READ) {
// page up key
if (reader_active && GetAsyncKeyState(VK_PRIOR) & 0x8000) {
dprintf("QR: Scanning\n");
// data from scans is literally just sent as raw bytes, nothing fancy lol
// https://twitter.com/taiko_team/status/1377425481855799299
unsigned char taiko_aprilfools_2021[] = {
0x53, 0x31, 0x32, 0x00, 0x01, 0xC3, 0x93, 0xC3, 0xA1, 0xC2, 0x92, 0xC3,
0x87, 0xC4, 0xA0, 0x44, 0x16, 0xC3, 0xB8, 0x4B, 0xC2, 0xA0, 0x44, 0xC3,
0xBD, 0xC3, 0xBA, 0x29, 0xC5, 0xB6, 0xC3, 0xA5, 0x06, 0xE1, 0xB8, 0x9F,
0x2A, 0x43, 0x6F, 0x25, 0x79, 0xC2, 0x84, 0x2B, 0xC2, 0x90, 0x29, 0xC2,
0xAE, 0xC3, 0xAD, 0x54, 0x3E, 0xC3, 0xAB, 0x0A
};
/*const uint8_t scan_response[] = {
83,49,50,0,0,255,255,17,1,0,67,79,76,76,65,66,79,95,84,79,72,79,95,50,48,50,48,238,255
};*/
iobuf_write(&qr_uart.readable, taiko_aprilfools_2021, sizeof(taiko_aprilfools_2021));
}
}
hr = uart_handle_irp(&qr_uart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
return hr;
}
const uint8_t scan_on[] = {
0x57, 0x00, 0x18, 0x00, 0x55, 0x00,
};
const uint8_t scan_off[] = {
0x57, 0x00, 0x19, 0x00, 0x55, 0x00,
};
const uint8_t qr_response[6] = {
0x31, 0x00, 0x00, 0x00, 0x55, 0x00
};
if (qr_uart.written.pos == sizeof(scan_on) && memcmp(qr_uart.written.bytes, scan_on, sizeof(scan_on)) == 0) {
if (!reader_active) {
dprintf("QR: Scanning enabled\n");
}
reader_active = true;
} else if (qr_uart.written.pos == sizeof(scan_off) && memcmp(qr_uart.written.bytes, scan_off, sizeof(scan_off)) == 0) {
if (reader_active) {
dprintf("QR: Scanning disabled\n");
}
reader_active = false;
}
iobuf_write(&qr_uart.readable, qr_response, sizeof(qr_response));
qr_uart.written.pos = 0;
return hr;
}