#include <windows.h> #include <assert.h> #include <stdbool.h> #include <stdint.h> #include "board/aime-dll.h" #include "board/sg-led.h" #include "board/sg-nfc.h" #include "board/sg-reader.h" #include "hook/iohook.h" #include "hooklib/uart.h" #include "util/dprintf.h" #include "util/dump.h" static HRESULT sg_reader_handle_irp(struct irp *irp); static HRESULT sg_reader_handle_irp_locked(struct irp *irp); static HRESULT sg_reader_nfc_poll(void *ctx); static HRESULT sg_reader_nfc_get_aime_id( void *ctx, uint8_t *luid, size_t luid_size); static HRESULT sg_reader_nfc_get_felica_id(void *ctx, uint64_t *IDm); static void sg_reader_led_set_color(void *ctx, uint8_t r, uint8_t g, uint8_t b); static const struct sg_nfc_ops sg_reader_nfc_ops = { .poll = sg_reader_nfc_poll, .get_aime_id = sg_reader_nfc_get_aime_id, .get_felica_id = sg_reader_nfc_get_felica_id, }; static const struct sg_led_ops sg_reader_led_ops = { .set_color = sg_reader_led_set_color, }; static CRITICAL_SECTION sg_reader_lock; static bool sg_reader_started; static HRESULT sg_reader_start_hr; static struct uart sg_reader_uart; static uint8_t sg_reader_written_bytes[520]; static uint8_t sg_reader_readable_bytes[520]; static struct sg_nfc sg_reader_nfc; static struct sg_led sg_reader_led; HRESULT sg_reader_hook_init( const struct aime_config *cfg, unsigned int port_no, HINSTANCE self) { HRESULT hr; assert(cfg != NULL); assert(self != NULL); if (!cfg->enable) { return S_FALSE; } hr = aime_dll_init(&cfg->dll, self); if (FAILED(hr)) { return hr; } sg_nfc_init(&sg_reader_nfc, 0x00, &sg_reader_nfc_ops, NULL); sg_led_init(&sg_reader_led, 0x08, &sg_reader_led_ops, NULL); InitializeCriticalSection(&sg_reader_lock); uart_init(&sg_reader_uart, port_no); sg_reader_uart.written.bytes = sg_reader_written_bytes; sg_reader_uart.written.nbytes = sizeof(sg_reader_written_bytes); sg_reader_uart.readable.bytes = sg_reader_readable_bytes; sg_reader_uart.readable.nbytes = sizeof(sg_reader_readable_bytes); return iohook_push_handler(sg_reader_handle_irp); } static HRESULT sg_reader_handle_irp(struct irp *irp) { HRESULT hr; assert(irp != NULL); if (!uart_match_irp(&sg_reader_uart, irp)) { return iohook_invoke_next(irp); } EnterCriticalSection(&sg_reader_lock); hr = sg_reader_handle_irp_locked(irp); LeaveCriticalSection(&sg_reader_lock); return hr; } static HRESULT sg_reader_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(&sg_reader_uart.readable); } #endif if (irp->op == IRP_OP_OPEN) { /* Unfortunately the card reader UART gets opened and closed repeatedly */ if (!sg_reader_started) { dprintf("NFC Assembly: Starting backend DLL\n"); hr = aime_dll.init(); sg_reader_started = true; sg_reader_start_hr = hr; if (FAILED(hr)) { dprintf("NFC Assembly: Backend error: %x\n", (int) hr); return hr; } } else { hr = sg_reader_start_hr; if (FAILED(hr)) { return hr; } } } hr = uart_handle_irp(&sg_reader_uart, irp); if (FAILED(hr) || irp->op != IRP_OP_WRITE) { return hr; } sg_nfc_transact( &sg_reader_nfc, &sg_reader_uart.readable, sg_reader_uart.written.bytes, sg_reader_uart.written.pos); sg_led_transact( &sg_reader_led, &sg_reader_uart.readable, sg_reader_uart.written.bytes, sg_reader_uart.written.pos); sg_reader_uart.written.pos = 0; return hr; } static HRESULT sg_reader_nfc_poll(void *ctx) { return aime_dll.nfc_poll(0); } static HRESULT sg_reader_nfc_get_aime_id( void *ctx, uint8_t *luid, size_t luid_size) { return aime_dll.nfc_get_aime_id(0, luid, luid_size); } static HRESULT sg_reader_nfc_get_felica_id(void *ctx, uint64_t *IDm) { return aime_dll.nfc_get_felica_id(0, IDm); } static void sg_reader_led_set_color(void *ctx, uint8_t r, uint8_t g, uint8_t b) { aime_dll.led_set_color(0, r, g, b); }