diff --git a/board/config.c b/board/config.c index 5515e92..e347b36 100644 --- a/board/config.c +++ b/board/config.c @@ -7,14 +7,6 @@ #include "board/config.h" -void io4_config_load(struct io4_config *cfg, const wchar_t *filename) -{ - assert(cfg != NULL); - assert(filename != NULL); - - cfg->enable = GetPrivateProfileIntW(L"io4", L"enable", 1, filename); -} - void k92x0249_config_load(struct k92x0249_config *cfg, const wchar_t *filename) { assert(cfg != NULL); diff --git a/board/config.h b/board/config.h index d29f9be..ca3bb31 100644 --- a/board/config.h +++ b/board/config.h @@ -3,12 +3,10 @@ #include #include -#include "board/io4.h" #include "board/dongle.h" #include "board/k92x0249.h" #include "board/k9101258.h" -void io4_config_load(struct io4_config *cfg, const wchar_t *filename); void k92x0249_config_load(struct k92x0249_config *cfg, const wchar_t *filename); void k9101258_config_load(struct usbio_config *cfg, const wchar_t *filename); void dongle_config_load(struct dongle_config *cfg, const wchar_t *filename); diff --git a/board/io4.c b/board/io4.c deleted file mode 100644 index e7fe9e3..0000000 --- a/board/io4.c +++ /dev/null @@ -1,353 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include - -#include "board/config.h" -#include "board/guid.h" -#include "board/io4.h" - -#include "hook/iobuf.h" -#include "hook/iohook.h" - -#include "hooklib/setupapi.h" - -#include "util/async.h" -#include "util/dprintf.h" - -#pragma pack(push, 1) - -enum { - IO4_CMD_SET_COMM_TIMEOUT = 0x01, - IO4_CMD_SET_SAMPLING_COUNT = 0x02, - IO4_CMD_CLEAR_BOARD_STATUS = 0x03, - IO4_CMD_SET_GENERAL_OUTPUT = 0x04, - IO4_CMD_SET_PWM_OUTPUT = 0x05, - IO4_CMD_UNIMPLEMENTED = 0x41, - IO4_CMD_UPDATE_FIRMWARE = 0x85, -}; - -struct io4_report_in { - uint8_t report_id; - uint16_t adcs[8]; - uint16_t spinners[4]; - uint16_t chutes[2]; - uint16_t buttons[2]; - uint8_t system_status; - uint8_t usb_status; - uint8_t unknown[29]; -}; - -static_assert(sizeof(struct io4_report_in) == 0x40, "IO4 IN report size"); - -struct io4_report_out { - uint8_t report_id; - uint8_t cmd; - uint8_t payload[62]; -}; - -static_assert(sizeof(struct io4_report_out) == 0x40, "IO4 OUT report size"); - -#pragma pack(pop) - - -static HRESULT io4_handle_irp(struct irp *irp); -static HRESULT io4_handle_open(struct irp *irp); -static HRESULT io4_handle_close(struct irp *irp); -static HRESULT io4_handle_read(struct irp *irp); -static HRESULT io4_handle_write(struct irp *irp); -static HRESULT io4_handle_ioctl(struct irp *irp); - -static HRESULT io4_ioctl_get_manufacturer_string(struct irp *irp); -static HRESULT io4_ioctl_get_product_string(struct irp *irp); - -static HRESULT io4_async_poll(void *ctx, struct irp *irp); - -/* Device node path must contain substring "vid_0ca3" (case-insensitive). */ -static const wchar_t io4_path[] = L"$io4\\vid_0ca3"; - -static const wchar_t io4_manf[] = L"SEGA"; -static const wchar_t io4_prod[] = - /* "Product" (N.B. numbers are in hex) */ - - L"I/O CONTROL BD;" /* Board type */ - L"15257;" /* Board number */ - L"01;" /* "Mode" (prob. USB vs JVS?) */ - L"90;" /* Firmware revision */ - L"1831;" /* Firmware checksum */ - L"6679A;" /* "Custom chip no" */ - L"00;" /* "Config" */ - - /* "Function" (N.B. all values are in hex) */ - - L"GOUT=14_" /* General-purpose output */ - L"ADIN=8,E_" /* ADC inputs */ - L"ROTIN=4_" /* Rotary inputs */ - L"COININ=2_" /* Coin inputs */ - L"SWIN=2,E_" /* Switch inputs */ - L"UQ1=41,6" /* "Unique function 1" */ - ; - -static HANDLE io4_fd; -static struct async io4_async; -static uint8_t io4_system_status; -static const struct io4_ops *io4_ops; -static void *io4_ops_ctx; - -HRESULT io4_hook_init( - const struct io4_config *cfg, - const struct io4_ops *ops, - void *ctx) -{ - HRESULT hr; - - assert(cfg != NULL); - assert(ops != NULL); - - if (!cfg->enable) { - return S_FALSE; - } - - async_init(&io4_async, NULL); - - hr = iohook_open_nul_fd(&io4_fd); - - if (FAILED(hr)) { - return hr; - } - - io4_ops = ops; - io4_ops_ctx = ctx; - io4_system_status = 0x02; /* idk */ - iohook_push_handler(io4_handle_irp); - - hr = setupapi_add_phantom_dev(&hid_guid, io4_path); - - if (FAILED(hr)) { - return hr; - } - - return S_OK; -} - -static HRESULT io4_handle_irp(struct irp *irp) -{ - assert(irp != NULL); - - if (irp->op != IRP_OP_OPEN && irp->fd != io4_fd) { - return iohook_invoke_next(irp); - } - - switch (irp->op) { - case IRP_OP_OPEN: return io4_handle_open(irp); - case IRP_OP_CLOSE: return io4_handle_close(irp); - case IRP_OP_READ: return io4_handle_read(irp); - case IRP_OP_WRITE: return io4_handle_write(irp); - case IRP_OP_IOCTL: return io4_handle_ioctl(irp); - default: return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); - } -} - -static HRESULT io4_handle_open(struct irp *irp) -{ - if (wcscmp(irp->open_filename, io4_path) != 0) { - return iohook_invoke_next(irp); - } - - dprintf("USB I/O: Device opened\n"); - irp->fd = io4_fd; - - return S_OK; -} - -static HRESULT io4_handle_close(struct irp *irp) -{ - dprintf("USB I/O: Device closed\n"); - - return S_OK; -} - -static HRESULT io4_handle_read(struct irp *irp) -{ - /* The amdaemon USBIO driver will continuously poll the IO until the IO - call returns an async operation in progress. We have to return and then - signal the OVERLAPPED event object "a little bit later" in order to avoid - an infinite loop. */ - - return async_submit(&io4_async, irp, io4_async_poll); -} - -static HRESULT io4_handle_write(struct irp *irp) -{ - struct io4_report_out out; - HRESULT hr; - - hr = iobuf_read(&irp->write, &out, sizeof(out)); - - if (FAILED(hr)) { - return hr; - } - - if (out.report_id != 0x10) { - dprintf("USB I/O: OUT Report ID is incorrect"); - - return E_FAIL; - } - - switch (out.cmd) { - case IO4_CMD_SET_COMM_TIMEOUT: - dprintf("USB I/O: Set comm timeout\n"); - - // Ongeki Summer expects the system status to be 0x30 at this point - io4_system_status = 0x30; - - return S_OK; - - case IO4_CMD_SET_SAMPLING_COUNT: - dprintf("USB I/O: Set sampling count\n"); - - // Ongeki Summer expects the system status to be 0x30 at this point - io4_system_status = 0x30; - - return S_OK; - - case IO4_CMD_CLEAR_BOARD_STATUS: - dprintf("USB I/O: Clear board status\n"); - io4_system_status = 0x00; - - return S_OK; - - case IO4_CMD_SET_GENERAL_OUTPUT: - dprintf("USB I/O: GPIO Out\n"); - - return S_OK; - - case IO4_CMD_SET_PWM_OUTPUT: - dprintf("USB I/O: PWM Out\n"); - - return S_OK; - - case IO4_CMD_UPDATE_FIRMWARE: - dprintf("USB I/O: Update firmware..?\n"); - - return E_FAIL; - - case IO4_CMD_UNIMPLEMENTED: - //dprintf("USB I/O: Unimplemented cmd 41\n"); - - return S_OK; - - default: - dprintf("USB I/O: Unknown command %02x\n", out.cmd); - - return E_FAIL; - } -} - -static HRESULT io4_handle_ioctl(struct irp *irp) -{ - switch (irp->ioctl) { - case IOCTL_HID_GET_MANUFACTURER_STRING: - return io4_ioctl_get_manufacturer_string(irp); - - case IOCTL_HID_GET_PRODUCT_STRING: - return io4_ioctl_get_product_string(irp); - - case IOCTL_HID_GET_INPUT_REPORT: - dprintf("USB I/O: Control IN (untested!!)\n"); - - return io4_handle_read(irp); - - case IOCTL_HID_SET_OUTPUT_REPORT: - dprintf("USB I/O: Control OUT (untested!!)\n"); - - return io4_handle_write(irp); - - default: - dprintf("USB I/O: Unknown ioctl %#08x, write %i read %i\n", - irp->ioctl, - (int) irp->write.nbytes, - (int) irp->read.nbytes); - - return HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); - } -} - -static HRESULT io4_ioctl_get_manufacturer_string(struct irp *irp) -{ - dprintf("USB I/O: Get manufacturer string\n"); - - if (irp->read.nbytes < sizeof(io4_manf)) { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - memcpy(irp->read.bytes, io4_manf, sizeof(io4_manf)); - irp->read.pos = sizeof(io4_manf); - - return S_OK; -} - -static HRESULT io4_ioctl_get_product_string(struct irp *irp) -{ - dprintf("USB I/O: Get product string\n"); - - if (irp->read.nbytes < sizeof(io4_prod)) { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - memcpy(irp->read.bytes, io4_prod, sizeof(io4_prod)); - irp->read.pos = sizeof(io4_prod); - - return S_OK; -} - -static HRESULT io4_async_poll(void *ctx, struct irp *irp) -{ - struct io4_report_in in; - struct io4_state state; - HRESULT hr; - size_t i; - - /* Delay long enough for the instigating thread in amdaemon to be satisfied - that all queued-up reports have been drained. */ - - Sleep(1); - - /* Call into ops to poll the underlying inputs */ - - memset(&state, 0, sizeof(state)); - hr = io4_ops->poll(io4_ops_ctx, &state); - - if (FAILED(hr)) { - return hr; - } - - /* Construct IN report. Values are all little-endian, unlike JVS. */ - - memset(&in, 0, sizeof(in)); - in.report_id = 0x01; - in.system_status = io4_system_status; - - for (i = 0 ; i < 8 ; i++) { - in.adcs[i] = state.adcs[i]; - } - - for (i = 0 ; i < 4 ; i++) { - in.spinners[i] = state.spinners[i]; - } - - for (i = 0 ; i < 2 ; i++) { - in.chutes[i] = state.chutes[i]; - } - - for (i = 0 ; i < 2 ; i++) { - in.buttons[i] = state.buttons[i]; - } - - return iobuf_write(&irp->read, &in, sizeof(in)); -} diff --git a/board/io4.h b/board/io4.h deleted file mode 100644 index 9310eb6..0000000 --- a/board/io4.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -#include -#include - -enum { - /* System buttons in button[0] */ - - IO4_BUTTON_TEST = 1 << 9, - IO4_BUTTON_SERVICE = 1 << 6, -}; - -struct io4_config { - bool enable; -}; - -struct io4_state { - uint16_t adcs[8]; - uint16_t spinners[4]; - uint16_t chutes[2]; - uint16_t buttons[2]; -}; - -struct io4_ops { - HRESULT (*poll)(void *ctx, struct io4_state *state); -}; - -HRESULT io4_hook_init( - const struct io4_config *cfg, - const struct io4_ops *ops, - void *ctx); diff --git a/board/k92x0249.c b/board/k92x0249.c index ded66a9..ab424a2 100644 --- a/board/k92x0249.c +++ b/board/k92x0249.c @@ -13,6 +13,8 @@ #include "jvs/jvs-cmd.h" #include "jvs/jvs-util.h" +#include "iccard/nesica.h" + #include "util/dprintf.h" #include "util/dump.h" @@ -84,6 +86,8 @@ void k92x0249_init( k92x0249->addr = 0xFF; k92x0249->state = IDLE; k92x0249->ops_ctx = ops_ctx; + + nesica_card_populate(&k92x0249->mifare, cfg.serial, 16); } struct jvs_node *k92x0249_to_jvs_node(struct k92x0249 *k92x0249) @@ -411,13 +415,27 @@ static HRESULT k92x0249_cmd_taito_nesica_read(struct k92x0249 *k92x0249, struct return hr; } - hr = iobuf_write(resp_buf, card_uid, 8); // AICC: Unused, should be IDm + // Mifare: UID (3 bytes from page 1, 4 bytes from page 2, null byte) + hr = iobuf_write(resp_buf, k92x0249->mifare.pages[0].bytes, 3); // AICC: Unused, should be IDm + + if (FAILED(hr)) { + return hr; + } + + hr = iobuf_write(resp_buf, k92x0249->mifare.pages[1].bytes, 4); // AICC: Unused, should be IDm + + if (FAILED(hr)) { + return hr; + } + + hr = iobuf_write_8(resp_buf, 0x00); // AICC: Unused, should be IDm if (FAILED(hr)) { return hr; } - return iobuf_write(resp_buf, cfg.serial, 16); // AICC: SPAD0 + // Mifare: sn (pages 5-8) + return iobuf_write(resp_buf, k92x0249->mifare.pages[5].bytes, 16); // AICC: SPAD0 } static HRESULT k92x0249_cmd_taito_aic_read(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf) diff --git a/board/k92x0249.h b/board/k92x0249.h index 8445a89..714052c 100644 --- a/board/k92x0249.h +++ b/board/k92x0249.h @@ -2,6 +2,8 @@ #include #include "jvs/jvs-bus.h" +#include "iccard/mifare.h" +#include "iccard/felica.h" #pragma pack(push,1) struct k92x0249 { @@ -9,6 +11,8 @@ struct k92x0249 { uint8_t state; uint8_t addr; void *ops_ctx; + struct mifare_ul mifare; + struct felica felica; }; struct k92x0249_config { diff --git a/board/meson.build b/board/meson.build index ab44008..e5bb9f8 100644 --- a/board/meson.build +++ b/board/meson.build @@ -22,17 +22,5 @@ board_lib = static_library( 'k92x0249.h', 'k9101258.c', 'k9101258.h', - 'io4.c', - 'io4.h', - 'sg-cmd.c', - 'sg-cmd.h', - 'sg-frame.c', - 'sg-frame.h', - 'sg-led.c', - 'sg-led.h', - 'sg-led-cmd.h', - 'sg-nfc.c', - 'sg-nfc.h', - 'sg-nfc-cmd.h', ], ) diff --git a/board/sg-cmd.c b/board/sg-cmd.c deleted file mode 100644 index 0ed6f25..0000000 --- a/board/sg-cmd.c +++ /dev/null @@ -1,134 +0,0 @@ -#include - -#include "board/sg-cmd.h" -#include "board/sg-frame.h" - -#include "hook/iobuf.h" - -#include "util/dprintf.h" - -union sg_req_any { - struct sg_req_header req; - uint8_t bytes[256]; -}; - -union sg_res_any { - struct sg_res_header res; - uint8_t bytes[256]; -}; - -static HRESULT sg_req_validate(const void *ptr, size_t nbytes); - -static void sg_res_error( - struct sg_res_header *res, - const struct sg_req_header *req); - -static HRESULT sg_req_validate(const void *ptr, size_t nbytes) -{ - const struct sg_req_header *req; - size_t payload_len; - - assert(ptr != NULL); - - if (nbytes < sizeof(*req)) { - dprintf("SG Cmd: Request header truncated\n"); - - return E_FAIL; - } - - req = ptr; - - if (req->hdr.frame_len != nbytes) { - dprintf("SG Cmd: Frame length mismatch: got %i exp %i\n", - req->hdr.frame_len, - (int) nbytes); - - return E_FAIL; - } - - payload_len = req->hdr.frame_len - sizeof(*req); - - if (req->payload_len != payload_len) { - dprintf("SG Cmd: Payload length mismatch: got %i exp %i\n", - req->payload_len, - (int) payload_len); - - return E_FAIL; - } - - return S_OK; -} - -void sg_req_transact( - struct iobuf *res_frame, - const uint8_t *req_bytes, - size_t req_nbytes, - sg_dispatch_fn_t dispatch, - void *ctx) -{ - struct iobuf req_span; - union sg_req_any req; - union sg_res_any res; - HRESULT hr; - - assert(res_frame != NULL); - assert(req_bytes != NULL); - assert(dispatch != NULL); - - req_span.bytes = req.bytes; - req_span.nbytes = sizeof(req.bytes); - req_span.pos = 0; - - hr = sg_frame_decode(&req_span, req_bytes, req_nbytes); - - if (FAILED(hr)) { - return; - } - - hr = sg_req_validate(req.bytes, req_span.pos); - - if (FAILED(hr)) { - return; - } - - hr = dispatch(ctx, &req, &res); - - if (hr != S_FALSE) { - if (FAILED(hr)) { - sg_res_error(&res.res, &req.req); - } - - sg_frame_encode(res_frame, res.bytes, res.res.hdr.frame_len); - } -} - -void sg_res_init( - struct sg_res_header *res, - const struct sg_req_header *req, - size_t payload_len) -{ - assert(res != NULL); - assert(req != NULL); - - res->hdr.frame_len = sizeof(*res) + payload_len; - res->hdr.addr = req->hdr.addr; - res->hdr.seq_no = req->hdr.seq_no; - res->hdr.cmd = req->hdr.cmd; - res->status = 0; - res->payload_len = payload_len; -} - -static void sg_res_error( - struct sg_res_header *res, - const struct sg_req_header *req) -{ - assert(res != NULL); - assert(req != NULL); - - res->hdr.frame_len = sizeof(*res); - res->hdr.addr = req->hdr.addr; - res->hdr.seq_no = req->hdr.seq_no; - res->hdr.cmd = req->hdr.cmd; - res->status = 1; - res->payload_len = 0; -} diff --git a/board/sg-cmd.h b/board/sg-cmd.h deleted file mode 100644 index 685377f..0000000 --- a/board/sg-cmd.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include "hook/iobuf.h" - -struct sg_header { - uint8_t frame_len; - uint8_t addr; - uint8_t seq_no; - uint8_t cmd; -}; - -struct sg_req_header { - struct sg_header hdr; - uint8_t payload_len; -}; - -struct sg_res_header { - struct sg_header hdr; - uint8_t status; - uint8_t payload_len; -}; - -typedef HRESULT (*sg_dispatch_fn_t)( - void *ctx, - const void *req, - void *res); - -void sg_req_transact( - struct iobuf *res_frame, - const uint8_t *req_bytes, - size_t req_nbytes, - sg_dispatch_fn_t dispatch, - void *ctx); - -void sg_res_init( - struct sg_res_header *res, - const struct sg_req_header *req, - size_t payload_len); diff --git a/board/sg-frame.c b/board/sg-frame.c deleted file mode 100644 index d65dbb1..0000000 --- a/board/sg-frame.c +++ /dev/null @@ -1,165 +0,0 @@ -#include - -#include -#include -#include -#include - -#include "board/sg-frame.h" - -#include "hook/iobuf.h" - -#include "util/dprintf.h" - -static HRESULT sg_frame_accept(struct iobuf *dest); -static HRESULT sg_frame_encode_byte(struct iobuf *dest, uint8_t byte); - -/* Frame structure: - - [0] Sync byte (0xE0) - [1] Frame size (including self) - [2] Address - [3] Sequence no - ... Body - [n] Checksum: Sum of all non-framing bytes - - Byte stuffing: - - 0xD0 is an escape byte. Un-escape the subsequent byte by adding 1. */ - -static HRESULT sg_frame_accept(struct iobuf *dest) -{ - uint8_t checksum; - size_t i; - - if (dest->pos < 1 || dest->pos != dest->bytes[0] + 1) { - dprintf("SG Frame: Size mismatch\n"); - - return S_FALSE; - } - - checksum = 0; - - for (i = 0 ; i < dest->pos - 1 ; i++) { - checksum += dest->bytes[i]; - } - - if (checksum != dest->bytes[dest->pos - 1]) { - dprintf("SG Frame: Checksum mismatch\n"); - - return HRESULT_FROM_WIN32(ERROR_CRC); - } - - /* Discard checksum */ - dest->pos--; - - return S_OK; -} - -HRESULT sg_frame_decode(struct iobuf *dest, const uint8_t *bytes, size_t nbytes) -{ - uint8_t byte; - size_t i; - - assert(dest != NULL); - assert(dest->bytes != NULL || dest->nbytes == 0); - assert(dest->pos <= dest->nbytes); - assert(bytes != NULL); - - if (nbytes < 1 || bytes[0] != 0xE0) { - dprintf("SG Frame: Bad sync\n"); - - return E_FAIL; - } - - dest->pos = 0; - i = 1; - - while (i < nbytes) { - if (dest->pos >= dest->nbytes) { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - byte = bytes[i++]; - - if (byte == 0xE0) { - dprintf("SG Frame: Unescaped sync\n"); - - return E_FAIL; - } else if (byte == 0xD0) { - if (i >= nbytes) { - dprintf("SG Frame: Trailing escape\n"); - - return E_FAIL; - } - - byte = bytes[i++]; - dest->bytes[dest->pos++] = byte + 1; - } else { - dest->bytes[dest->pos++] = byte; - } - } - - return sg_frame_accept(dest); -} - -HRESULT sg_frame_encode( - struct iobuf *dest, - const void *ptr, - size_t nbytes) -{ - const uint8_t *src; - uint8_t checksum; - uint8_t byte; - size_t i; - HRESULT hr; - - assert(dest != NULL); - assert(dest->bytes != NULL || dest->nbytes == 0); - assert(dest->pos <= dest->nbytes); - assert(ptr != NULL); - - src = ptr; - - assert(nbytes != 0 && src[0] == nbytes); - - if (dest->pos >= dest->nbytes) { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - dest->bytes[dest->pos++] = 0xE0; - checksum = 0; - - for (i = 0 ; i < nbytes ; i++) { - byte = src[i]; - checksum += byte; - - hr = sg_frame_encode_byte(dest, byte); - - if (FAILED(hr)) { - return hr; - } - } - - return sg_frame_encode_byte(dest, checksum); -} - -static HRESULT sg_frame_encode_byte(struct iobuf *dest, uint8_t byte) -{ - if (byte == 0xD0 || byte == 0xE0) { - if (dest->pos + 2 > dest->nbytes) { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - dest->bytes[dest->pos++] = 0xD0; - dest->bytes[dest->pos++] = byte - 1; - } else { - if (dest->pos + 1 > dest->nbytes) { - return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); - } - - dest->bytes[dest->pos++] = byte; - } - - return S_OK; -} diff --git a/board/sg-frame.h b/board/sg-frame.h deleted file mode 100644 index d74d9b3..0000000 --- a/board/sg-frame.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include "hook/iobuf.h" - -HRESULT sg_frame_decode( - struct iobuf *dest, - const uint8_t *bytes, - size_t nbytes); - -HRESULT sg_frame_encode(struct iobuf *dest, const void *ptr, size_t nbytes); diff --git a/board/sg-led-cmd.h b/board/sg-led-cmd.h deleted file mode 100644 index f74505b..0000000 --- a/board/sg-led-cmd.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -#include "board/sg-cmd.h" - -enum { - SG_RGB_CMD_SET_COLOR = 0x81, - SG_RGB_CMD_RESET = 0xF5, - SG_RGB_CMD_GET_INFO = 0xF0, -}; - -struct sg_led_res_reset { - struct sg_res_header res; - uint8_t payload; -}; - -struct sg_led_res_get_info { - struct sg_res_header res; - uint8_t payload[9]; -}; - -struct sg_led_req_set_color { - struct sg_req_header req; - uint8_t payload[3]; -}; - -union sg_led_req_any { - uint8_t bytes[256]; - struct sg_req_header simple; - struct sg_led_req_set_color set_color; -}; - -union sg_led_res_any { - uint8_t bytes[256]; - struct sg_res_header simple; - struct sg_led_res_reset reset; - struct sg_led_res_get_info get_info; -}; diff --git a/board/sg-led.c b/board/sg-led.c deleted file mode 100644 index 855e36b..0000000 --- a/board/sg-led.c +++ /dev/null @@ -1,178 +0,0 @@ -#include - -#include - -#include "board/sg-cmd.h" -#include "board/sg-led.h" -#include "board/sg-led-cmd.h" - -#include "util/dprintf.h" - -static HRESULT sg_led_dispatch( - void *ctx, - const void *v_req, - void *v_res); - -static HRESULT sg_led_cmd_reset( - const struct sg_led *led, - const struct sg_req_header *req, - struct sg_led_res_reset *res); - -static HRESULT sg_led_cmd_get_info( - const struct sg_led *led, - const struct sg_req_header *req, - struct sg_led_res_get_info *res); - -static HRESULT sg_led_cmd_set_color( - const struct sg_led *led, - const struct sg_led_req_set_color *req); - -static const uint8_t sg_led_info[] = { - '1', '5', '0', '8', '4', 0xFF, 0x10, 0x00, 0x12, -}; - -void sg_led_init( - struct sg_led *led, - uint8_t addr, - const struct sg_led_ops *ops, - void *ctx) -{ - assert(led != NULL); - assert(ops != NULL); - - led->ops = ops; - led->ops_ctx = ctx; - led->addr = addr; -} - -void sg_led_transact( - struct sg_led *led, - struct iobuf *res_frame, - const void *req_bytes, - size_t req_nbytes) -{ - assert(led != NULL); - assert(res_frame != NULL); - assert(req_bytes != NULL); - - sg_req_transact(res_frame, req_bytes, req_nbytes, sg_led_dispatch, led); -} - -#ifdef NDEBUG -#define sg_led_dprintfv(led, fmt, ap) -#define sg_led_dprintf(led, fmt, ...) -#else -static void sg_led_dprintfv( - const struct sg_led *led, - const char *fmt, - va_list ap) -{ - dprintf("RGB LED %02x: ", led->addr); - dprintfv(fmt, ap); -} - -static void sg_led_dprintf( - const struct sg_led *led, - const char *fmt, - ...) -{ - va_list ap; - - va_start(ap, fmt); - sg_led_dprintfv(led, fmt, ap); - va_end(ap); -} -#endif - -static HRESULT sg_led_dispatch( - void *ctx, - const void *v_req, - void *v_res) -{ - const struct sg_led *led; - const union sg_led_req_any *req; - union sg_led_res_any *res; - - led = ctx; - req = v_req; - res = v_res; - - if (req->simple.hdr.addr != led->addr) { - /* Not addressed to us, don't send a response */ - return S_FALSE; - } - - switch (req->simple.hdr.cmd) { - case SG_RGB_CMD_RESET: - return sg_led_cmd_reset(led, &req->simple, &res->reset); - - case SG_RGB_CMD_GET_INFO: - return sg_led_cmd_get_info(led, &req->simple, &res->get_info); - - case SG_RGB_CMD_SET_COLOR: - return sg_led_cmd_set_color(led, &req->set_color); - - default: - sg_led_dprintf(led, "Unimpl command %02x\n", req->simple.hdr.cmd); - - return E_NOTIMPL; - } -} - -static HRESULT sg_led_cmd_reset( - const struct sg_led *led, - const struct sg_req_header *req, - struct sg_led_res_reset *res) -{ - HRESULT hr; - - sg_led_dprintf(led, "Reset\n"); - sg_res_init(&res->res, req, sizeof(res->payload)); - res->payload = 0; - - if (led->ops->reset != NULL) { - hr = led->ops->reset(led->ops_ctx); - } else { - hr = S_OK; - } - - if (FAILED(hr)) { - sg_led_dprintf(led, "led->ops->reset: Error %x\n", hr); - return hr; - } - - return S_OK; -} - -static HRESULT sg_led_cmd_get_info( - const struct sg_led *led, - const struct sg_req_header *req, - struct sg_led_res_get_info *res) -{ - sg_led_dprintf(led, "Get info\n"); - sg_res_init(&res->res, req, sizeof(res->payload)); - memcpy(res->payload, sg_led_info, sizeof(sg_led_info)); - - return S_OK; -} - -static HRESULT sg_led_cmd_set_color( - const struct sg_led *led, - const struct sg_led_req_set_color *req) -{ - if (req->req.payload_len != sizeof(req->payload)) { - sg_led_dprintf(led, "%s: Payload size is incorrect\n", __func__); - - goto fail; - } - - led->ops->set_color( - led->ops_ctx, - req->payload[0], - req->payload[1], - req->payload[2]); - -fail: - /* No response */ - return S_FALSE; -} diff --git a/board/sg-led.h b/board/sg-led.h deleted file mode 100644 index de3caa6..0000000 --- a/board/sg-led.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -#include - -#include "hook/iobuf.h" - -struct sg_led_ops { - HRESULT (*reset)(void *ctx); - void (*set_color)(void *ctx, uint8_t r, uint8_t g, uint8_t b); -}; - -struct sg_led { - const struct sg_led_ops *ops; - void *ops_ctx; - uint8_t addr; -}; - -void sg_led_init( - struct sg_led *led, - uint8_t addr, - const struct sg_led_ops *ops, - void *ctx); - -void sg_led_transact( - struct sg_led *led, - struct iobuf *res_frame, - const void *req_bytes, - size_t req_nbytes); diff --git a/board/sg-nfc-cmd.h b/board/sg-nfc-cmd.h deleted file mode 100644 index b6754c2..0000000 --- a/board/sg-nfc-cmd.h +++ /dev/null @@ -1,115 +0,0 @@ -#pragma once - -#include - -#pragma pack(push, 1) - -enum { - SG_NFC_CMD_GET_FW_VERSION = 0x30, - SG_NFC_CMD_GET_HW_VERSION = 0x32, - SG_NFC_CMD_RADIO_ON = 0x40, - SG_NFC_CMD_RADIO_OFF = 0x41, - SG_NFC_CMD_POLL = 0x42, - SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43, - SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x50, - SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52, - SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x54, - SG_NFC_CMD_MIFARE_AUTHENTICATE = 0x55, /* guess based on time sent */ - SG_NFC_CMD_RESET = 0x62, - SG_NFC_CMD_FELICA_ENCAP = 0x71, -}; - -struct sg_nfc_res_get_fw_version { - struct sg_res_header res; - char version[23]; -}; - -struct sg_nfc_res_get_hw_version { - struct sg_res_header res; - char version[23]; -}; - -struct sg_nfc_req_mifare_set_key { - struct sg_req_header req; - uint8_t key_a[6]; -}; - -struct sg_nfc_req_mifare_50 { - struct sg_req_header req; - uint8_t payload[6]; -}; - -struct sg_nfc_req_poll_40 { - struct sg_req_header req; - uint8_t payload; -}; - -struct sg_nfc_poll_mifare { - uint8_t type; - uint8_t id_len; - uint32_t uid; -}; - -struct sg_nfc_poll_felica { - uint8_t type; - uint8_t id_len; - uint64_t IDm; - uint64_t PMm; -}; - -struct sg_nfc_res_poll { - struct sg_res_header res; - uint8_t count; - uint8_t payload[250]; -}; - -struct sg_nfc_req_mifare_select_tag { - struct sg_res_header res; - uint32_t uid; -}; - -struct sg_nfc_req_mifare_read_block { - struct sg_req_header req; - struct { - uint32_t uid; - uint8_t block_no; - } payload; -}; - -struct sg_nfc_res_mifare_read_block { - struct sg_res_header res; - uint8_t block[16]; -}; - -struct sg_nfc_req_felica_encap { - struct sg_req_header req; - uint64_t IDm; - uint8_t payload[243]; -}; - -struct sg_nfc_res_felica_encap { - struct sg_res_header res; - uint8_t payload[250]; -}; - -union sg_nfc_req_any { - uint8_t bytes[256]; - struct sg_req_header simple; - struct sg_nfc_req_mifare_set_key mifare_set_key; - struct sg_nfc_req_mifare_read_block mifare_read_block; - struct sg_nfc_req_mifare_50 mifare_50; - struct sg_nfc_req_poll_40 poll_40; - struct sg_nfc_req_felica_encap felica_encap; -}; - -union sg_nfc_res_any { - uint8_t bytes[256]; - struct sg_res_header simple; - struct sg_nfc_res_get_fw_version get_fw_version; - struct sg_nfc_res_get_hw_version get_hw_version; - struct sg_nfc_res_poll poll; - struct sg_nfc_res_mifare_read_block mifare_read_block; - struct sg_nfc_res_felica_encap felica_encap; -}; - -#pragma pack(pop) diff --git a/board/sg-nfc.c b/board/sg-nfc.c deleted file mode 100644 index ce5d620..0000000 --- a/board/sg-nfc.c +++ /dev/null @@ -1,434 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include - -#include "board/sg-cmd.h" -#include "board/sg-nfc.h" -#include "board/sg-nfc-cmd.h" - -#include "iccard/nesica.h" -#include "iccard/felica.h" - -#include "util/dprintf.h" -#include "util/dump.h" - -static HRESULT sg_nfc_dispatch( - void *ctx, - const void *v_req, - void *v_res); - -static HRESULT sg_nfc_cmd_reset( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_res_header *res); - -static HRESULT sg_nfc_cmd_get_fw_version( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_nfc_res_get_fw_version *res); - -static HRESULT sg_nfc_cmd_get_hw_version( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_nfc_res_get_hw_version *res); - -static HRESULT sg_nfc_cmd_poll( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_nfc_res_poll *res); - -static HRESULT sg_nfc_poll_aime( - struct sg_nfc *nfc, - struct sg_nfc_poll_mifare *mifare); - -static HRESULT sg_nfc_poll_felica( - struct sg_nfc *nfc, - struct sg_nfc_poll_felica *felica); - -static HRESULT sg_nfc_cmd_mifare_read_block( - struct sg_nfc *nfc, - const struct sg_nfc_req_mifare_read_block *req, - struct sg_nfc_res_mifare_read_block *res); - -static HRESULT sg_nfc_cmd_felica_encap( - struct sg_nfc *nfc, - const struct sg_nfc_req_felica_encap *req, - struct sg_nfc_res_felica_encap *res); - -static HRESULT sg_nfc_cmd_dummy( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_res_header *res); - -void sg_nfc_init( - struct sg_nfc *nfc, - uint8_t addr, - const struct sg_nfc_ops *ops, - void *ops_ctx) -{ - assert(nfc != NULL); - assert(ops != NULL); - - nfc->ops = ops; - nfc->ops_ctx = ops_ctx; - nfc->addr = addr; -} - -#ifdef NDEBUG -#define sg_nfc_dprintfv(nfc, fmt, ap) -#define sg_nfc_dprintf(nfc, fmt, ...) -#else -static void sg_nfc_dprintfv( - const struct sg_nfc *nfc, - const char *fmt, - va_list ap) -{ - dprintf("NFC %02x: ", nfc->addr); - dprintfv(fmt, ap); -} - -static void sg_nfc_dprintf( - const struct sg_nfc *nfc, - const char *fmt, - ...) -{ - va_list ap; - - va_start(ap, fmt); - sg_nfc_dprintfv(nfc, fmt, ap); - va_end(ap); -} -#endif - -void sg_nfc_transact( - struct sg_nfc *nfc, - struct iobuf *res_frame, - const void *req_bytes, - size_t req_nbytes) -{ - assert(nfc != NULL); - assert(res_frame != NULL); - assert(req_bytes != NULL); - - sg_req_transact(res_frame, req_bytes, req_nbytes, sg_nfc_dispatch, nfc); -} - -static HRESULT sg_nfc_dispatch( - void *ctx, - const void *v_req, - void *v_res) -{ - struct sg_nfc *nfc; - const union sg_nfc_req_any *req; - union sg_nfc_res_any *res; - - nfc = ctx; - req = v_req; - res = v_res; - - if (req->simple.hdr.addr != nfc->addr) { - /* Not addressed to us, don't send a response */ - return S_FALSE; - } - - switch (req->simple.hdr.cmd) { - case SG_NFC_CMD_RESET: - return sg_nfc_cmd_reset(nfc, &req->simple, &res->simple); - - case SG_NFC_CMD_GET_FW_VERSION: - return sg_nfc_cmd_get_fw_version( - nfc, - &req->simple, - &res->get_fw_version); - - case SG_NFC_CMD_GET_HW_VERSION: - return sg_nfc_cmd_get_hw_version( - nfc, - &req->simple, - &res->get_hw_version); - - case SG_NFC_CMD_POLL: - return sg_nfc_cmd_poll( - nfc, - &req->simple, - &res->poll); - - case SG_NFC_CMD_MIFARE_READ_BLOCK: - return sg_nfc_cmd_mifare_read_block( - nfc, - &req->mifare_read_block, - &res->mifare_read_block); - - case SG_NFC_CMD_FELICA_ENCAP: - return sg_nfc_cmd_felica_encap( - nfc, - &req->felica_encap, - &res->felica_encap); - - case SG_NFC_CMD_MIFARE_AUTHENTICATE: - case SG_NFC_CMD_MIFARE_SELECT_TAG: - case SG_NFC_CMD_MIFARE_SET_KEY_AIME: - case SG_NFC_CMD_MIFARE_SET_KEY_BANA: - case SG_NFC_CMD_RADIO_ON: - case SG_NFC_CMD_RADIO_OFF: - return sg_nfc_cmd_dummy(nfc, &req->simple, &res->simple); - - default: - sg_nfc_dprintf(nfc, "Unimpl command %02x\n", req->simple.hdr.cmd); - - return E_NOTIMPL; - } -} - -static HRESULT sg_nfc_cmd_reset( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_res_header *res) -{ - sg_nfc_dprintf(nfc, "Reset\n"); - sg_res_init(res, req, 0); - res->status = 3; - - return S_OK; -} - -static HRESULT sg_nfc_cmd_get_fw_version( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_nfc_res_get_fw_version *res) -{ - /* Dest version is not NUL terminated, this is intentional */ - sg_res_init(&res->res, req, sizeof(res->version)); - memcpy(res->version, "TN32MSEC003S F/W Ver1.2E", sizeof(res->version)); - - return S_OK; -} - -static HRESULT sg_nfc_cmd_get_hw_version( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_nfc_res_get_hw_version *res) -{ - /* Dest version is not NUL terminated, this is intentional */ - sg_res_init(&res->res, req, sizeof(res->version)); - memcpy(res->version, "TN32MSEC003S H/W Ver3.0J", sizeof(res->version)); - - return S_OK; -} - -static HRESULT sg_nfc_cmd_poll( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_nfc_res_poll *res) -{ - struct sg_nfc_poll_mifare mifare; - struct sg_nfc_poll_felica felica; - HRESULT hr; - - hr = nfc->ops->poll(nfc->ops_ctx); - - if (FAILED(hr)) { - return hr; - } - - hr = sg_nfc_poll_felica(nfc, &felica); - - if (SUCCEEDED(hr) && hr != S_FALSE) { - sg_res_init(&res->res, req, 1 + sizeof(felica)); - memcpy(res->payload, &felica, sizeof(felica)); - res->count = 1; - - return S_OK; - } - - hr = sg_nfc_poll_aime(nfc, &mifare); - - if (SUCCEEDED(hr) && hr != S_FALSE) { - sg_res_init(&res->res, req, 1 + sizeof(mifare)); - memcpy(res->payload, &mifare, sizeof(mifare)); - res->count = 1; - - return S_OK; - } - - sg_res_init(&res->res, req, 1); - res->count = 0; - - return S_OK; -} - -static HRESULT sg_nfc_poll_aime( - struct sg_nfc *nfc, - struct sg_nfc_poll_mifare *mifare) -{ - uint8_t luid[10]; - HRESULT hr; - - /* Call backend */ - - if (nfc->ops->get_aime_id != NULL) { - hr = nfc->ops->get_aime_id(nfc->ops_ctx, luid, sizeof(luid)); - } else { - hr = S_FALSE; - } - - if (FAILED(hr) || hr == S_FALSE) { - return hr; - } - - sg_nfc_dprintf(nfc, "AiMe card is present\n"); - - /* Construct response (use an arbitrary UID) */ - - mifare->type = 0x10; - mifare->id_len = sizeof(mifare->uid); - mifare->uid = _byteswap_ulong(0x01020304); - - /* Initialize MIFARE IC emulator */ - - hr = aime_card_populate(&nfc->mifare, luid, sizeof(luid)); - - if (FAILED(hr)) { - return hr; - } - - return S_OK; -} - -static HRESULT sg_nfc_poll_felica( - struct sg_nfc *nfc, - struct sg_nfc_poll_felica *felica) -{ - uint64_t IDm; - HRESULT hr; - - /* Call backend */ - - if (nfc->ops->get_felica_id != NULL) { - hr = nfc->ops->get_felica_id(nfc->ops_ctx, &IDm); - } else { - hr = S_FALSE; - } - - if (FAILED(hr) || hr == S_FALSE) { - return hr; - } - - sg_nfc_dprintf(nfc, "FeliCa card is present\n"); - - /* Construct poll response */ - - felica->type = 0x20; - felica->id_len = sizeof(felica->IDm) + sizeof(felica->PMm); - felica->IDm = _byteswap_uint64(IDm); - felica->PMm = _byteswap_uint64(felica_get_generic_PMm()); - - /* Initialize FeliCa IC emulator */ - - nfc->felica.IDm = IDm; - nfc->felica.PMm = felica_get_generic_PMm(); - nfc->felica.system_code = 0x0000; - - return S_OK; -} - -static HRESULT sg_nfc_cmd_mifare_read_block( - struct sg_nfc *nfc, - const struct sg_nfc_req_mifare_read_block *req, - struct sg_nfc_res_mifare_read_block *res) -{ - uint32_t uid; - - if (req->req.payload_len != sizeof(req->payload)) { - sg_nfc_dprintf(nfc, "%s: Payload size is incorrect\n", __func__); - - return E_FAIL; - } - - uid = _byteswap_ulong(req->payload.uid); - - sg_nfc_dprintf(nfc, "Read uid %08x block %i\n", uid, req->payload.block_no); - - if (req->payload.block_no > 3) { - sg_nfc_dprintf(nfc, "MIFARE block number out of range\n"); - - return E_FAIL; - } - - sg_res_init(&res->res, &req->req, sizeof(res->block)); - - memcpy( res->block, - nfc->mifare.sectors[0].blocks[req->payload.block_no].bytes, - sizeof(res->block)); - - return S_OK; -} - -static HRESULT sg_nfc_cmd_felica_encap( - struct sg_nfc *nfc, - const struct sg_nfc_req_felica_encap *req, - struct sg_nfc_res_felica_encap *res) -{ - struct const_iobuf f_req; - struct iobuf f_res; - HRESULT hr; - - /* First byte of encapsulated request and response is a length byte - (inclusive of itself). The FeliCa emulator expects its caller to handle - that length byte on its behalf (we adopt the convention that the length - byte is part of the FeliCa protocol's framing layer). */ - - if (req->req.payload_len != 8 + req->payload[0]) { - sg_nfc_dprintf( - nfc, - "FeliCa encap payload length mismatch: sg %i != felica %i + 8", - req->req.payload_len, - req->payload[0]); - - return E_FAIL; - } - - f_req.bytes = req->payload; - f_req.nbytes = req->payload[0]; - f_req.pos = 1; - - f_res.bytes = res->payload; - f_res.nbytes = sizeof(res->payload); - f_res.pos = 1; - -#if 0 - dprintf("FELICA OUTBOUND:\n"); - dump_const_iobuf(&f_req); -#endif - - hr = felica_transact(&nfc->felica, &f_req, &f_res); - - if (FAILED(hr)) { - return hr; - } - - sg_res_init(&res->res, &req->req, f_res.pos); - res->payload[0] = f_res.pos; - -#if 0 - dprintf("FELICA INBOUND:\n"); - dump_iobuf(&f_res); -#endif - - return S_OK; -} - -static HRESULT sg_nfc_cmd_dummy( - struct sg_nfc *nfc, - const struct sg_req_header *req, - struct sg_res_header *res) -{ - sg_res_init(res, req, 0); - - return S_OK; -} diff --git a/board/sg-nfc.h b/board/sg-nfc.h deleted file mode 100644 index 5562b2b..0000000 --- a/board/sg-nfc.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include "hook/iobuf.h" - -#include "iccard/felica.h" -#include "iccard/mifare.h" - -struct sg_nfc_ops { - HRESULT (*poll)(void *ctx); - HRESULT (*get_aime_id)(void *ctx, uint8_t *luid, size_t nbytes); - HRESULT (*get_felica_id)(void *ctx, uint64_t *IDm); - - // TODO Banapass, AmuseIC -}; - -struct sg_nfc { - const struct sg_nfc_ops *ops; - void *ops_ctx; - uint8_t addr; - struct felica felica; - struct mifare mifare; -}; - -void sg_nfc_init( - struct sg_nfc *nfc, - uint8_t addr, - const struct sg_nfc_ops *ops, - void *ops_ctx); - -void sg_nfc_transact( - struct sg_nfc *nfc, - struct iobuf *res_frame, - const void *req_bytes, - size_t req_nbytes); diff --git a/gchook/dllmain.c b/gchook/dllmain.c index dd8fc3c..c4657df 100644 --- a/gchook/dllmain.c +++ b/gchook/dllmain.c @@ -2,8 +2,6 @@ #include #include -#include "board/io4.h" - #include "hook/process.h" #include "hooklib/serial.h" diff --git a/gchook/fastio.c b/gchook/fastio.c index 9c9b323..8f0b7ff 100644 --- a/gchook/fastio.c +++ b/gchook/fastio.c @@ -14,6 +14,7 @@ static uint16_t coins; static uint16_t services; static void gc_fastio_digital_read(void *ctx, uint32_t *out); +static void gc_fastio_analog_read(void* ctx, uint8_t num, uint32_t *out); static void gc_fastio_coin_read(void *ctx, uint8_t slot_no, uint32_t *out); HRESULT gc_fastio_init(struct fastio_node *out) @@ -24,6 +25,7 @@ HRESULT gc_fastio_init(struct fastio_node *out) out->digital_in = gc_fastio_digital_read; out->coins_in = gc_fastio_coin_read; + out->analog_in = gc_fastio_analog_read; dprintf("Gc Nesica Fastio: Init\n"); @@ -116,3 +118,9 @@ static void gc_fastio_coin_read(void *ctx, uint8_t slot_no, uint32_t *out) *out += coin; *out += service; } + +static void gc_fastio_analog_read(void* ctx, uint8_t num, uint32_t *out) +{ + if (num == 2) { *out = 0xff; } + else { *out = 0x00; } +} diff --git a/gcio/config.c b/gcio/config.c index a4c738a..1131455 100644 --- a/gcio/config.c +++ b/gcio/config.c @@ -30,4 +30,4 @@ void gc_io_config_load(struct gc_input_config *cfg, const wchar_t *filename) cfg->stick_r_right = GetPrivateProfileIntW(L"deck", L"right_stick_right", 'L', filename); cfg->stick_r_down = GetPrivateProfileIntW(L"deck", L"right_stick_down", 'K', filename); cfg->stick_r_left = GetPrivateProfileIntW(L"deck", L"right_stick_left", 'J', filename); -} \ No newline at end of file +} diff --git a/gcio/config.h b/gcio/config.h index 7a5ac97..95a0b1b 100644 --- a/gcio/config.h +++ b/gcio/config.h @@ -28,4 +28,4 @@ struct gc_input_config { }; #pragma pack(pop) -void gc_io_config_load(struct gc_input_config *cfg, const wchar_t *filename); \ No newline at end of file +void gc_io_config_load(struct gc_input_config *cfg, const wchar_t *filename); diff --git a/gcio/gcio.h b/gcio/gcio.h index 5733efe..3f76505 100644 --- a/gcio/gcio.h +++ b/gcio/gcio.h @@ -56,4 +56,4 @@ HRESULT gc_io_init(void); void gc_io_get_btns(uint8_t *btn, uint8_t *stick); -void gc_io_read_coin_counter(uint16_t *coins, uint16_t *services); \ No newline at end of file +void gc_io_read_coin_counter(uint16_t *coins, uint16_t *services); diff --git a/iccard/mifare.h b/iccard/mifare.h index c4f4e83..0e97271 100644 --- a/iccard/mifare.h +++ b/iccard/mifare.h @@ -15,6 +15,14 @@ struct mifare { struct mifare_sector sectors[16]; }; +struct mifare_ul_page { + uint8_t bytes[4]; +}; + +struct mifare_ul { + struct mifare_ul_page pages[16]; +}; + struct nesica_mifare { uint8_t uid[7]; char nesica_id[16]; diff --git a/iccard/nesica.c b/iccard/nesica.c index ef40009..4c04f33 100644 --- a/iccard/nesica.c +++ b/iccard/nesica.c @@ -7,8 +7,8 @@ #include "util/dprintf.h" -HRESULT aime_card_populate( - struct mifare *mifare, +HRESULT nesica_card_populate( + struct mifare_ul *mifare, const uint8_t *card_sn, size_t nbytes) { @@ -18,7 +18,7 @@ HRESULT aime_card_populate( assert(mifare != NULL); assert(card_sn != NULL); - memset(mifare, 0, sizeof(*mifare)); + memset(mifare, 0xFF, sizeof(*mifare)); if (nbytes != 16) { dprintf("Nesica IC: Card Serial must be 16 characters\n"); @@ -26,19 +26,44 @@ HRESULT aime_card_populate( return E_INVALIDARG; } - for (int i = 0; i < 16; i++) { - mifare->sectors[0].blocks[0].bytes[i] = i; - } + // page0: first 3 bytes of the UID, BCC0 + // page1: rest of the UID + // page2: BCC1, INT, LOCK0+1 + // page3: 4 one-time programmable bytes + // page4: "T053" (T<3 numbers of unknown purpose>) + // page5-8: 16-byte ascii nesica ID + // page9-f: FF - memset(mifare->sectors[0].blocks[2].bytes, 0xff, 16); - memset(mifare->sectors[0].blocks[3].bytes, 0xff, 16); + // https://www.nxp.com/docs/en/data-sheet/MF0ICU2.pdf + // BCC0 is CT (0x88) ^ UIC[0] ^ UIC[1] ^ UIC[2] + // BCC1 is UIC[3] ^ UIC[4] ^ UIC[5] ^ UIC[6] + // Lock bits signal which parts of the card are write-locked + // On real blue nesicas, OTP and pages 4-8 inclusive are locked (0xF8 0x01) + // Internal is "reserved for internal data" and observed to be 0x48 + // OTP bytes are impl specific, observed to be 0x23 0x21 0x54 0x55 on sample card (#!TU) - mifare->sectors[0].blocks[0].bytes[14] = 'T'; - mifare->sectors[0].blocks[0].bytes[15] = 'U'; + // UID of 00010203040506 with BCC0 8B and BCC1 04 + // TODO: User-setable UID? + mifare->pages[0].bytes[0] = 0x00; + mifare->pages[0].bytes[1] = 0x01; + mifare->pages[0].bytes[2] = 0x02; + mifare->pages[0].bytes[3] = 0x8B; + mifare->pages[1].bytes[0] = 0x03; + mifare->pages[1].bytes[1] = 0x04; + mifare->pages[1].bytes[2] = 0x05; + mifare->pages[1].bytes[3] = 0x06; + mifare->pages[2].bytes[0] = 0x04; - memcpy_s(mifare->sectors[0].blocks[1].bytes, 4, (uint8_t *)"T053", 4); - memcpy_s(mifare->sectors[0].blocks[1].bytes + 4, 12, card_sn, 12); - memcpy_s(mifare->sectors[0].blocks[2].bytes, 16, card_sn + 12, 4); + // INT + lock bits + mifare->pages[2].bytes[1] = 0x48; + mifare->pages[2].bytes[2] = 0xF8; + mifare->pages[2].bytes[3] = 0x01; + + memcpy_s(mifare->pages[3].bytes, 4, (uint8_t *)"#!TU", 4); // OTP + memcpy_s(mifare->pages[4].bytes, 4, (uint8_t *)"T053", 4); // UID header? + memcpy_s(mifare->pages[5].bytes, 16, card_sn, 16); // UID, should clobber pages 5-8 safely + + // The rest of the card was set to 0xFF above, so we're done here return S_OK; } diff --git a/iccard/nesica.h b/iccard/nesica.h index 34857ef..07eb7a6 100644 --- a/iccard/nesica.h +++ b/iccard/nesica.h @@ -7,7 +7,7 @@ #include "iccard/mifare.h" -HRESULT aime_card_populate( - struct mifare *mifare, +HRESULT nesica_card_populate( + struct mifare_ul *mifare, const uint8_t *luid, size_t nbytes); diff --git a/idmac/idmac.c b/idmac/idmac.c index 96e726f..fab341c 100644 --- a/idmac/idmac.c +++ b/idmac/idmac.c @@ -312,6 +312,7 @@ static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* regist *register_val = 0; *err = 0; + EnterCriticalSection(&idmac_critsec); switch (register_id) { case 0x0400: *register_val = 0x00010201; break; // DMA card ID @@ -321,9 +322,7 @@ static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* regist case 0x4004: *register_val = 0x00FF0000; break; // Sub Status case 0x4120: // Main Buttons - EnterCriticalSection(&idmac_critsec); fastio_digital_read(NULL, 0, (uint32_t *)register_val); - LeaveCriticalSection(&idmac_critsec); break; case 0x4124: // Analog 1 @@ -386,6 +385,7 @@ static int hook_iDmacDrvRegisterRead(HANDLE a1, DWORD register_id, DWORD* regist dprintf("iDmac: Requested read register %04lX\n", register_id); break; } + LeaveCriticalSection(&idmac_critsec); return 0; } diff --git a/sivahook/dllmain.c b/sivahook/dllmain.c index 31851d4..3c353fa 100644 --- a/sivahook/dllmain.c +++ b/sivahook/dllmain.c @@ -2,8 +2,6 @@ #include #include -#include "board/io4.h" - #include "hook/process.h" #include "hooklib/serial.h"