diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0aadfd0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "aic_pico"] + path = firmware/modules/aic_pico + url = https://github.com/whowechina/aic_pico diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..100b0f8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.associations": { + "mpr121.h": "c", + "board_defs.h": "c", + "pn532.h": "c", + "cli.h": "c", + "vl53l0x.h": "c" + } +} \ No newline at end of file diff --git a/Production/Firmware/chu_pico.uf2 b/Production/Firmware/chu_pico.uf2 index 55769af..b8c60dc 100644 Binary files a/Production/Firmware/chu_pico.uf2 and b/Production/Firmware/chu_pico.uf2 differ diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index b328053..dea1997 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -1,11 +1,14 @@ cmake_minimum_required(VERSION 3.12) +project(chu_pico C CXX ASM) # Pull in SDK (must set be before project) include(pico_sdk_import.cmake) -project(iidx_pico C CXX ASM) set(CMAKE_C_STANDARD 11) pico_sdk_init() +add_subdirectory(modules/aic_pico/firmware aic) +include_directories(modules/aic_pico/firmware/include) + add_subdirectory(src) diff --git a/firmware/src/CMakeLists.txt b/firmware/src/CMakeLists.txt index 88b5b02..611c266 100644 --- a/firmware/src/CMakeLists.txt +++ b/firmware/src/CMakeLists.txt @@ -1,12 +1,8 @@ -set(BTSTACK_ROOT ${PICO_SDK_PATH}/lib/btstack) -set(LWIP_ROOT ${PICO_SDK_PATH}/lib/lwip) - function(make_firmware board board_def) pico_sdk_init() add_executable(${board} main.c slider.c air.c rgb.c save.c config.c commands.c - aime.c cli.c lzfx.c - vl53l0x.c mpr121.c pn532.c usb_descriptors.c) + cli.c lzfx.c vl53l0x.c mpr121.c usb_descriptors.c) target_compile_definitions(${board} PUBLIC ${board_def}) pico_enable_stdio_usb(${board} 1) pico_enable_stdio_uart(${board} 0) @@ -15,11 +11,9 @@ function(make_firmware board board_def) target_compile_options(${board} PRIVATE -Wall -Werror -Wfatal-errors -O3) target_include_directories(${board} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) - target_include_directories(${board} PRIVATE - ${BTSTACK_ROOT}/src - ${LWIP_ROOT}/src/include) target_link_libraries(${board} PRIVATE + aic pico_multicore pico_stdlib hardware_pio hardware_pwm hardware_flash hardware_adc hardware_i2c hardware_watchdog tinyusb_device tinyusb_board) @@ -31,4 +25,3 @@ function(make_firmware board board_def) endfunction() make_firmware(chu_pico BOARD_CHU_PICO) - diff --git a/firmware/src/aime.c b/firmware/src/aime.c deleted file mode 100644 index 6e5a16b..0000000 --- a/firmware/src/aime.c +++ /dev/null @@ -1,712 +0,0 @@ -/* - * AIME Reader - * WHowe - * - * Use PN532 to read AIME - */ - -#include -#include - -#include "bsp/board.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "board_defs.h" - -#include "i2c_hub.h" - -#include "pn532.h" - -#define FRAME_TIMEOUT 200000 - -enum { - CMD_GET_FW_VERSION = 0x30, - CMD_GET_HW_VERSION = 0x32, - // Card read - CMD_START_POLLING = 0x40, - CMD_STOP_POLLING = 0x41, - CMD_CARD_DETECT = 0x42, - CMD_CARD_SELECT = 0x43, - CMD_CARD_HALT = 0x44, - // MIFARE - CMD_MIFARE_KEY_SET_A = 0x50, - CMD_MIFARE_AUTHORIZE_A = 0x51, - CMD_MIFARE_READ = 0x52, - CMD_MIFARE_WRITE = 0x53, - CMD_MIFARE_KEY_SET_B = 0x54, - CMD_MIFARE_AUTHORIZE_B = 0x55, - // Boot,update - CMD_TO_UPDATER_MODE = 0x60, - CMD_SEND_HEX_DATA = 0x61, - CMD_TO_NORMAL_MODE = 0x62, - CMD_SEND_BINDATA_INIT = 0x63, - CMD_SEND_BINDATA_EXEC = 0x64, - // FeliCa - CMD_FELICA_PUSH = 0x70, - CMD_FELICA_OP = 0x71, - CMD_FELICA_OP_POLL = 0x00, - CMD_FELICA_OP_READ = 0x06, - CMD_FELICA_OP_WRITE = 0x08, - CMD_FELICA_OP_GET_SYSTEM_CODE = 0x0C, - CMD_FELICA_OP_NDA_A4 = 0xA4, - // LED board - CMD_EXT_BOARD_LED = 0x80, - CMD_EXT_BOARD_LED_RGB = 0x81, - CMD_EXT_BOARD_LED_RGB_UNKNOWN = 0x82, - CMD_EXT_BOARD_INFO = 0xf0, - CMD_EXT_FIRM_SUM = 0xf2, - CMD_EXT_SEND_HEX_DATA = 0xf3, - CMD_EXT_TO_BOOT_MODE = 0xf4, - CMD_EXT_TO_NORMAL_MODE = 0xf5, -}; - -enum { - STATUS_OK = 0, - STATUS_NFCRW_INIT_ERROR = 1, - STATUS_NFCRW_FIRMWARE_UP_TO_DATE = 3, - STATUS_NFCRW_ACCESS_ERROR = 4, - STATUS_CARD_DETECT_TIMEOUT = 5, - STATUS_CARD_DETECT_ERROR = 32, - STATUS_FELICA_ERROR = 33, -}; - -const char *fw_version[] = { "TN32MSEC003S F/W Ver1.2", "\x94" }; -const char *hw_version[] = { "TN32MSEC003S H/W Ver3.0", "837-15396" }; -const char *led_info[] = { "15084\xFF\x10\x00\x12", "000-00000\xFF\x11\x40" }; -static int baudrate_mode = 0; - -static struct { - bool enabled; // feature enabled - bool active; // currently active - uint8_t idm[8]; - const uint8_t pmm[8]; - const uint8_t syscode[2]; -} virtual_aic = { true, false, "", "\x00\xf1\x00\x00\x00\x01\x43\x00", "\x88\xb4" }; - -void aime_set_baudrate(int mode) -{ - baudrate_mode = (mode == 0) ? 0 : 1; -} - -void aime_set_virtual_aic(bool enable) -{ - virtual_aic.enabled = enable; -} - -static int aime_interface = -1; - -void aime_init(int interface) -{ - aime_interface = interface; - - i2c_select(I2C_PORT, 1 << 5); // PN532 on IR1 (I2C mux chn 5) - pn532_config_sam(); -} - -static uint8_t mifare_keys[2][6]; // 'KeyA' and 'KeyB' - -static union __attribute__((packed)) { - struct { - uint8_t len; - uint8_t addr; - uint8_t seq; - uint8_t cmd; - uint8_t status; - uint8_t payload_len; - uint8_t payload[]; - }; - uint8_t raw[256]; -} response; - -static union __attribute__((packed)) { - struct { - uint8_t len; - uint8_t addr; - uint8_t seq; - uint8_t cmd; - uint8_t payload_len; - union { - struct { - uint8_t uid[4]; - uint8_t block_id; - } mifare; - struct { - uint8_t idm[8]; - uint8_t len; - uint8_t code; - uint8_t data[0]; - } felica; - uint8_t payload[250]; - }; - }; - uint8_t raw[256]; -} request; - -struct { - bool active; - uint8_t len; - uint8_t check_sum; - bool escaping; - uint64_t time; -} req_ctx; - -static void build_response(int payload_len) -{ - response.len = payload_len + 6; - response.addr = request.addr; - response.seq = request.seq; - response.cmd = request.cmd; - response.status = STATUS_OK; - response.payload_len = payload_len; -} - -static void send_response() -{ - uint8_t checksum = 0; - - uint8_t sync = 0xe0; - tud_cdc_n_write(aime_interface, &sync, 1); - - for (int i = 0; i < response.len; i++) { - uint8_t c = response.raw[i]; - checksum += c; - if (c == 0xe0 || c == 0xd0) { - uint8_t escape = 0xd0; - tud_cdc_n_write(aime_interface, &escape, 1); - c--; - } - tud_cdc_n_write(aime_interface, &c, 1); - } - - tud_cdc_n_write(aime_interface, &checksum, 1); - tud_cdc_n_write_flush(aime_interface); -} - -static void send_simple_response(uint8_t status) -{ - build_response(0); - response.status = status; - send_response(); -} - -static void cmd_to_normal_mode() -{ - send_simple_response(pn532_firmware_ver() ? STATUS_NFCRW_FIRMWARE_UP_TO_DATE - : STATUS_NFCRW_INIT_ERROR); -} - -static void cmd_fake_version(const char *version[]) -{ - int len = strlen(version[baudrate_mode]); - build_response(len); - memcpy(response.payload, version[baudrate_mode], len); - send_response(); -} - -static void cmd_key_set(uint8_t key[6]) -{ - memcpy(key, request.payload, 6); - send_simple_response(STATUS_OK); -} - -static void cmd_set_polling(bool enabled) -{ - pn532_set_rf_field(0, enabled ? 1 : 0); - send_simple_response(STATUS_OK); -} - -typedef struct __attribute__((packed)) { - uint8_t count; - uint8_t type; - uint8_t id_len; - union { - struct { - uint8_t idm[8]; - uint8_t pmm[8]; - uint8_t syscode[2]; - }; - uint8_t uid[6]; - }; -} card_info_t; - -static void handle_mifare_card(const uint8_t *uid, int len) -{ - card_info_t *card = (card_info_t *) response.payload; - - build_response(len > 4 ? 10 : 7); - card->count = 1; - card->type = 0x10; - card->id_len = len; - - memcpy(card->uid, uid, len); -} - -static void handle_felica_card(const uint8_t felica_ids[18]) -{ - build_response(19); - card_info_t *card = (card_info_t *) response.payload; - - card->count = 1; - card->type = 0x20; - card->id_len = 16; - memcpy(card->idm, felica_ids, 8); - memcpy(card->pmm, felica_ids + 8, 8); -} - -static void fake_felica_card() -{ - build_response(19); - card_info_t *card = (card_info_t *) response.payload; - - card->count = 1; - card->type = 0x20; - card->id_len = 16; - memcpy(card->idm, virtual_aic.idm, 8); - memcpy(card->pmm, virtual_aic.pmm, 8); -} - -static void handle_no_card() -{ - build_response(1); - card_info_t *card = (card_info_t *) response.payload; - - card->count = 0; - response.status = STATUS_OK; -} - -static void printf_hex(const uint8_t *hex, int len, const char *tail) -{ - for (int i = 0; i < len; i ++) { - printf(" %02x", hex[i]); - } - printf("%s", tail); -} - -static void cmd_detect_card() -{ - uint8_t buf[18]; - - virtual_aic.active = false; - - int len = sizeof(buf); - if (pn532_poll_mifare(buf, &len)) { - printf("Detected Mifare - "); - printf_hex(buf, len, "\n"); - - if (virtual_aic.enabled) { - virtual_aic.active = true; - memset(virtual_aic.idm, 0, 8); - memcpy(virtual_aic.idm, "\x01\x01", 2); - memcpy(virtual_aic.idm + 2, buf, len); - - printf("Virtual AIC -"); - printf_hex(virtual_aic.idm, 8, ","); - printf_hex(virtual_aic.pmm, 8, ","); - printf_hex(virtual_aic.syscode, 2, "\n"); - - fake_felica_card(); - } else { - handle_mifare_card(buf, len); - } - } else if (pn532_poll_felica(buf, buf + 8, buf + 16, false)) { - printf("Detected Felica -"); - printf_hex(buf, 8, ","); - printf_hex(buf + 8, 8, ","); - printf_hex(buf + 16, 2, "\n"); - - handle_felica_card(buf); - } else { - handle_no_card(); - } - - send_response(); -} - -static void cmd_card_select() -{ - printf("CARD SELECT %d\n", request.payload_len); - send_simple_response(STATUS_OK); -} - -static void cmd_mifare_auth(int type) -{ - printf("MIFARE AUTH\n"); - pn532_mifare_auth(request.mifare.uid, request.mifare.block_id, type, mifare_keys[type]); - send_simple_response(STATUS_OK); -} - -static void cmd_mifare_read() -{ - printf("MIFARE READ %02x %02x %02x %02x %02x\n", request.mifare.block_id, - request.mifare.uid[0], request.mifare.uid[1], request.mifare.uid[2], - request.mifare.uid[3]); - build_response(16); - memset(response.payload, 0, 16); - pn532_mifare_read(request.mifare.block_id, response.payload); - send_response(); -} - -static void cmd_mifare_halt() -{ - printf("MIFARE HALT\n"); - send_simple_response(STATUS_OK); -} - -typedef struct __attribute__((packed)) { - uint8_t len; - uint8_t code; - uint8_t idm[8]; - uint8_t data[0]; -} felica_resp_t; - -typedef struct __attribute__((packed)) { - uint8_t idm[8]; - uint8_t pmm[8]; - uint8_t syscode[2]; -} card_id_t; - -static int cmd_felica_poll(const card_id_t *card) -{ - typedef struct __attribute__((packed)) { - uint8_t pmm[8]; - uint8_t syscode[2]; - } felica_poll_resp_t; - - printf("FELICA POLL\n"); - - felica_resp_t *felica_resp = (felica_resp_t *) response.payload; - felica_poll_resp_t *poll_resp = (felica_poll_resp_t *) felica_resp->data; - - if (virtual_aic.active) { - memcpy(poll_resp->pmm, virtual_aic.pmm, 8); - memcpy(poll_resp->syscode, virtual_aic.syscode, 2); - } else { - memcpy(poll_resp->pmm, card->pmm, 8); - memcpy(poll_resp->syscode, card->syscode, 2); - } - - return sizeof(*poll_resp); -} - -static int cmd_felica_get_syscode(const card_id_t *card) -{ - printf("FELICA GET_SYSTEM_CODE\n"); - felica_resp_t *felica_resp = (felica_resp_t *) response.payload; - felica_resp->data[0] = 0x01; - if (virtual_aic.active) { - memcpy(felica_resp->data, virtual_aic.syscode, 2); - } else { - felica_resp->data[1] = card->syscode[0]; - felica_resp->data[2] = card->syscode[1]; - } - return 3; -} - -static int cmd_felica_read() -{ - printf("FELICA READ\n"); - uint8_t *req_data = request.felica.data; - - if (req_data[8] != 1) { - printf("Felica Encap READ Error: service_num != 1\n"); - return -1; - } - - uint16_t svc_code = req_data[9] | (req_data[10] << 8); - - typedef struct __attribute__((packed)) { - uint8_t rw_status[2]; - uint8_t block_num; - uint8_t block_data[0][16]; - } encap_read_resp_t; - - felica_resp_t *felica_resp = (felica_resp_t *) response.payload; - encap_read_resp_t *read_resp = (encap_read_resp_t *) felica_resp->data; - - uint8_t *block = req_data + 11; - uint8_t block_num = block[0]; - - memset(read_resp->block_data, 0, block_num * 16); - - for (int i = 0; i < block_num; i++) { - uint16_t block_id = (block[i * 2 + 1] << 8) | block[i * 2 + 2]; - if (block_id == 0x8082) { - memcpy(read_resp->block_data[i], felica_resp->idm, 8); - } - if (!virtual_aic.active) { - pn532_felica_read_wo_encrypt(svc_code, block_id, read_resp->block_data[i]); - } - } - - read_resp->rw_status[0] = 0x00; - read_resp->rw_status[1] = 0x00; - read_resp->block_num = block_num; - - return sizeof(*read_resp) + block_num * 16; -} - -static int cmd_felica_write() -{ - printf("FELICA WRITE\n"); - uint8_t *req_data = request.felica.data; - - if (req_data[8] != 1) { - printf("Felica Encap Write Error: service_num != 1\n"); - return -1; - } - - uint16_t svc_code = req_data[9] | (req_data[10] << 8); - - uint8_t *block = req_data + 11; - uint8_t block_num = block[0]; - - felica_resp_t *felica_resp = (felica_resp_t *) response.payload; - uint8_t *rw_status = felica_resp->data; - - printf("svc code: %04x\n", svc_code); - printf("blocks:"); - for (int i = 0; i < block_num; i++) { - uint16_t block_id = (block[i * 2 + 1] << 8) | block[i * 2 + 2]; - printf(" %04x", block_id); - } - printf("\n"); - - uint8_t *block_data = block + 1 + block_num * 2; - - rw_status[0] = 0x00; - rw_status[1] = 0x00; - - for (int i = 0; i < block_num; i++) { - printf("writing %02x %02x\n", block_data[i * 16], block_data[i * 16 + 15]); - // uint16_t block_id = (block[i * 2 + 1] << 8) | block[i * 2 + 2]; - // int result = pn532_felica_write_wo_encrypt(svc_code, block_id, block_data + i * 16); - int result = 0; - if (result < 0) { - rw_status[0] = 0x01; - rw_status[1] = 0x01; - } - } - - return 2; -} - -#if 0 - - case CMD_FELICA_OP_NDA_A4: - printf("\tNDA_A4\n"); - build_response(11); - resp->payload[0] = 0x00; - break; - default: - printf("\tUnknown through: %02x\n", code); - build_response(0); - response.status = STATUS_OK; -#endif - -static void cmd_felica() -{ - card_id_t card; - if (!pn532_poll_felica(card.idm, card.pmm, card.syscode, true)) { - send_simple_response(STATUS_FELICA_ERROR); - } - - uint8_t felica_code = request.felica.code; - printf("Felica (%02x):", felica_code); - for (int i = 0; i < request.payload_len; i++) { - printf(" %02x", request.payload[i]); - } - printf("\n"); - - int datalen = -1; - switch (felica_code) { - case CMD_FELICA_OP_GET_SYSTEM_CODE: - datalen = cmd_felica_get_syscode(&card); - break; - case CMD_FELICA_OP_POLL: - datalen = cmd_felica_poll(&card); - break; - case CMD_FELICA_OP_READ: - datalen = cmd_felica_read(); - break; - case CMD_FELICA_OP_WRITE: - datalen = cmd_felica_write(); - break; - default: - printf("Unknown code %d\n", felica_code); - break; - } - - if (datalen < 0) { - send_simple_response(STATUS_FELICA_ERROR); - return; - } - - felica_resp_t *felica_resp = (felica_resp_t *) response.payload; - build_response(sizeof(*felica_resp) + datalen); - felica_resp->len = response.payload_len; - felica_resp->code = felica_code + 1; - if (virtual_aic.active) { - memcpy(felica_resp->idm, virtual_aic.idm, 8); - } else { - memcpy(felica_resp->idm, card.idm, 8); - } - - send_response(); - - printf("Felica Response:"); - for (int i = 0; i < felica_resp->len - 10; i++) { - printf(" %02x", felica_resp->data[i]); - } - printf("\n"); -} - -static uint32_t led_color; - -static void cmd_led_rgb() -{ - led_color = request.payload[0] << 16 | request.payload[1] << 8 | request.payload[2]; - build_response(0); - send_response(); -} - -static void aime_handle_frame() -{ - i2c_select(I2C_PORT, 1 << 5); // PN532 on IR1 (I2C mux chn 5) - - switch (request.cmd) { - case CMD_TO_NORMAL_MODE: - cmd_to_normal_mode(); - break; - case CMD_GET_FW_VERSION: - printf("CMD_GET_FW_VERSION\n"); - cmd_fake_version(fw_version); - break; - case CMD_GET_HW_VERSION: - printf("CMD_GET_HW_VERSION\n"); - cmd_fake_version(hw_version); - break; - case CMD_MIFARE_KEY_SET_A: - printf("CMD_MIFARE_KEY_SET_A\n"); - cmd_key_set(mifare_keys[0]); - break; - case CMD_MIFARE_KEY_SET_B: - printf("CMD_MIFARE_KEY_SET_B\n"); - cmd_key_set(mifare_keys[1]); - break; - - case CMD_START_POLLING: - cmd_set_polling(true); - break; - case CMD_STOP_POLLING: - cmd_set_polling(false); - break; - case CMD_CARD_DETECT: - cmd_detect_card(); - break; - case CMD_FELICA_OP: - cmd_felica(); - break; - - case CMD_CARD_SELECT: - cmd_card_select(); - break; - - case CMD_MIFARE_AUTHORIZE_A: - cmd_mifare_auth(0); - break; - - case CMD_MIFARE_AUTHORIZE_B: - cmd_mifare_auth(1); - break; - - case CMD_MIFARE_READ: - cmd_mifare_read(); - break; - - case CMD_CARD_HALT: - cmd_mifare_halt(); - break; - - case CMD_EXT_BOARD_INFO: - cmd_fake_version(led_info); - break; - case CMD_EXT_BOARD_LED_RGB: - cmd_led_rgb(); - break; - - case CMD_SEND_HEX_DATA: - case CMD_EXT_TO_NORMAL_MODE: - send_simple_response(STATUS_OK); - break; - - default: - printf("Unknown command: %02x [", request.cmd); - for (int i = 0; i < request.len; i++) { - printf(" %02x", request.raw[i]); - } - printf("]\n"); - send_simple_response(STATUS_OK); - break; - } -} - -static bool aime_feed(int c) -{ - if (c == 0xe0) { - req_ctx.active = true; - req_ctx.len = 0; - req_ctx.check_sum = 0; - req_ctx.escaping = false; - req_ctx.time = time_us_64(); - return true; - } - - if (!req_ctx.active) { - return false; - } - - if (c == 0xd0) { - req_ctx.escaping = true; - return true; - } - - if (req_ctx.escaping) { - c++; - req_ctx.escaping = false; - } - - if (req_ctx.len != 0 && req_ctx.len == request.len) { - if (req_ctx.check_sum == c) { - aime_handle_frame(); - req_ctx.active = false; - } - return true; - } - - request.raw[req_ctx.len] = c; - req_ctx.len++; - req_ctx.check_sum += c; - - return true; -} - -void aime_update() -{ - if (req_ctx.active && time_us_64() - req_ctx.time > FRAME_TIMEOUT) { - req_ctx.active = false; - } - - if (tud_cdc_n_available(aime_interface)) { - uint8_t buf[32]; - uint32_t count = tud_cdc_n_read(aime_interface, buf, sizeof(buf)); - for (int i = 0; i < count; i++) { - aime_feed(buf[i]); - } - } -} - -uint32_t aime_led_color() -{ - return led_color; -} diff --git a/firmware/src/aime.h b/firmware/src/aime.h deleted file mode 100644 index dd0b841..0000000 --- a/firmware/src/aime.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * AIME Reader - * WHowe - */ - -#ifndef AIME_H -#define AIME_H - -void aime_init(int interface); -void aime_update(); -uint32_t aime_led_color(); - -// mode 0 or 1 -void aime_set_baudrate(int mode); -void aime_set_virtual_aic(bool enable); - -#endif diff --git a/firmware/src/commands.c b/firmware/src/commands.c index 617161d..ad14727 100644 --- a/firmware/src/commands.c +++ b/firmware/src/commands.c @@ -7,6 +7,8 @@ #include "pico/stdio.h" #include "pico/stdlib.h" +#include "aime.h" + #include "config.h" #include "air.h" #include "slider.h" @@ -14,8 +16,7 @@ #include "cli.h" #include "i2c_hub.h" - -#include "pn532.h" +#include "nfc.h" #define SENSE_LIMIT_MAX 9 #define SENSE_LIMIT_MIN -9 @@ -73,6 +74,12 @@ static void disp_hid() chu_cfg->hid.nkro ? "on" : "off" ); } +static void disp_aime() +{ + printf("[AIME]\n"); + printf(" Virtual AIC: %s\n", chu_cfg->virtual_aic ? "ON" : "OFF"); +} + void handle_display(int argc, char *argv[]) { const char *usage = "Usage: display [colors|style|tof|sense|hid]\n"; @@ -87,11 +94,12 @@ void handle_display(int argc, char *argv[]) disp_tof(); disp_sense(); disp_hid(); + disp_aime(); return; } - const char *choices[] = {"colors", "style", "tof", "sense", "hid"}; - switch (cli_match_prefix(choices, 5, argv[0])) { + const char *choices[] = {"colors", "style", "tof", "sense", "hid", "aime"}; + switch (cli_match_prefix(choices, 6, argv[0])) { case 0: disp_colors(); break; @@ -107,6 +115,9 @@ void handle_display(int argc, char *argv[]) case 4: disp_hid(); break; + case 5: + disp_aime(); + break; default: printf(usage); break; @@ -402,30 +413,36 @@ static void handle_factory_reset() static void handle_nfc() { i2c_select(I2C_PORT, 1 << 5); // PN532 on IR1 (I2C mux chn 5) - - bool ret = pn532_config_sam(); - printf("Sam: %d\n", ret); - - uint8_t buf[32]; - - int len = sizeof(buf); - ret = pn532_poll_mifare(buf, &len); - printf("Mifare: %d -", len); - - if (ret) { - for (int i = 0; i < len; i++) { - printf(" %02x", buf[i]); - } + printf("NFC module: %s\n", nfc_module_name()); + nfc_rf_field(true); + nfc_card_t card = nfc_detect_card(); + nfc_rf_field(false); + printf("Card: %s", nfc_card_name(card.card_type)); + for (int i = 0; i < card.len; i++) { + printf(" %02x", card.uid[i]); } printf("\n"); +} - printf("Felica: "); - if (pn532_poll_felica(buf, buf + 8, buf + 16, false)) { - for (int i = 0; i < 18; i++) { - printf(" %02x%s", buf[i], (i % 8 == 7) ? "," : ""); - } +static void handle_virtual(int argc, char *argv[]) +{ + const char *usage = "Usage: virtual \n"; + if (argc != 1) { + printf("%s", usage); + return; } - printf("\n"); + + const char *commands[] = { "on", "off" }; + int match = cli_match_prefix(commands, 2, argv[0]); + if (match < 0) { + printf("%s", usage); + return; + } + + chu_cfg->virtual_aic = (match == 0); + + aime_virtual_aic(chu_cfg->virtual_aic); + config_changed(); } void commands_init() @@ -442,4 +459,5 @@ void commands_init() cli_register("save", handle_save, "Save config to flash."); cli_register("factory", handle_factory_reset, "Reset everything to default."); cli_register("nfc", handle_nfc, "NFC debug."); + cli_register("virtual", handle_virtual, "Virtual AIC card."); } diff --git a/firmware/src/config.c b/firmware/src/config.c index da5be3d..cd5bc8b 100644 --- a/firmware/src/config.c +++ b/firmware/src/config.c @@ -38,6 +38,7 @@ static chu_cfg_t default_cfg = { .joy = 1, .nkro = 0, }, + .virtual_aic = false, }; chu_runtime_t *chu_runtime; diff --git a/firmware/src/config.h b/firmware/src/config.h index 15906eb..5194590 100644 --- a/firmware/src/config.h +++ b/firmware/src/config.h @@ -38,6 +38,7 @@ typedef struct __attribute__((packed)) { uint8_t joy : 4; uint8_t nkro : 4; } hid; + bool virtual_aic; } chu_cfg_t; typedef struct { diff --git a/firmware/src/main.c b/firmware/src/main.c index b4a15a6..fa30fd8 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -21,14 +21,16 @@ #include "tusb.h" #include "usb_descriptors.h" -#include "board_defs.h" +#include "aime.h" +#include "nfc.h" +#include "board_defs.h" #include "save.h" #include "config.h" #include "cli.h" #include "commands.h" -#include "aime.h" +#include "i2c_hub.h" #include "slider.h" #include "air.h" #include "rgb.h" @@ -144,6 +146,26 @@ static void run_lights() } } +const int aime_intf = 1; +static void cdc_aime_putc(uint8_t byte) +{ + tud_cdc_n_write(aime_intf, &byte, 1); + tud_cdc_n_write_flush(aime_intf); +} + +static void aime_run() +{ + if (tud_cdc_n_available(aime_intf)) { + uint8_t buf[32]; + uint32_t count = tud_cdc_n_read(aime_intf, buf, sizeof(buf)); + + i2c_select(I2C_PORT, 1 << 5); // PN532 on IR1 (I2C mux chn 5) + for (int i = 0; i < count; i++) { + aime_feed(buf[i]); + } + } +} + static mutex_t core1_io_lock; static void core1_loop() { @@ -164,7 +186,7 @@ static void core0_loop() tud_task(); cli_run(); - aime_update(); + aime_run(); save_loop(); cli_fps_count(0); @@ -194,7 +216,11 @@ void init() air_init(); rgb_init(); - aime_init(1); + nfc_attach_i2c(I2C_PORT); + i2c_select(I2C_PORT, 1 << 5); // PN532 on IR1 (I2C mux chn 5) + nfc_init(); + aime_init(cdc_aime_putc); + aime_virtual_aic(chu_cfg->virtual_aic); cli_init("chu_pico>", "\n << Chu Pico Controller >>\n" " https://github.com/whowechina\n\n"); diff --git a/firmware/src/pn532.c b/firmware/src/pn532.c deleted file mode 100644 index 9ada649..0000000 --- a/firmware/src/pn532.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * PN532 NFC Reader - * WHowe - * - */ - -#include -#include -#include - -#include "hardware/i2c.h" -#include "hardware/gpio.h" - -//#define DEBUG - -#include "pn532.h" -#include "board_defs.h" - -#define IO_TIMEOUT_US 1000 -#define PN532_I2C_ADDRESS 0x24 - -#define PN532_PREAMBLE 0 -#define PN532_STARTCODE1 0 -#define PN532_STARTCODE2 0xff -#define PN532_POSTAMBLE 0 - -#define PN532_HOSTTOPN532 0xd4 -#define PN532_PN532TOHOST 0xd5 - -void pn532_init() -{ - i2c_init(I2C_PORT, I2C_FREQ); - gpio_set_function(I2C_SDA, GPIO_FUNC_I2C); - gpio_set_function(I2C_SCL, GPIO_FUNC_I2C); - gpio_pull_up(I2C_SDA); - gpio_pull_up(I2C_SCL); -} - -static int pn532_write(const uint8_t *data, uint8_t len) -{ - return i2c_write_blocking_until(I2C_PORT, PN532_I2C_ADDRESS, data, len, false, - time_us_64() + IO_TIMEOUT_US * len); -} - -static int pn532_read(uint8_t *data, uint8_t len) -{ - return i2c_read_blocking_until(I2C_PORT, PN532_I2C_ADDRESS, data, len, false, - time_us_64() + IO_TIMEOUT_US * len); -} - -static bool pn532_wait_ready() -{ - uint8_t status = 0; - - for (int retry = 0; retry < 20; retry++) { - if (pn532_read(&status, 1) == 1 && status == 0x01) { - return true; - } - sleep_us(1000); - } - - return false; -} - -static int read_frame(uint8_t *frame, uint8_t len) -{ - uint8_t buf[len + 1]; - int ret = pn532_read(buf, len + 1); - -#ifdef DEBUG - printf("I2C data read: %d -", ret); - for (int i = 0; i < len + 1; i++) { - printf(" %02x", buf[i]); - } - printf("\n"); -#endif - - if (ret == len + 1) { - memcpy(frame, buf + 1, len); - return len; - } - return ret; -} - -static int write_frame(const uint8_t *frame, uint8_t len) -{ - #ifdef DEBUG - printf("I2C frame write: %d -", len); - for (int i = 0; i < len; i++) { - printf(" %02x", frame[i]); - } - printf("\n"); - #endif - - return pn532_write(frame, len); -} - -static bool read_ack() -{ - uint8_t resp[6]; - - if (!pn532_wait_ready()) { - return false; - } - - read_frame(resp, 6); - - const uint8_t expect_ack[] = {0, 0, 0xff, 0, 0xff, 0}; - if (memcmp(resp, expect_ack, 6) != 0) { - return false; - } - - return true; -} - -int pn532_write_data(const uint8_t *data, uint8_t len) -{ - uint8_t frame[5 + len]; - frame[0] = PN532_PREAMBLE; - frame[1] = PN532_STARTCODE1; - frame[2] = PN532_STARTCODE2; - uint8_t checksum = 0xff; - - frame[3] = len; - frame[4] = (~len + 1); - - for (int i = 0; i < len; i++) { - frame[5 + i] = data[i]; - checksum += data[i]; - } - - frame[5 + len] = ~checksum; - frame[6 + len] = PN532_POSTAMBLE; - - write_frame(frame, 7 + len); - - return read_ack(); -} - -int pn532_read_data(uint8_t *data, uint8_t len) -{ - uint8_t resp[len + 7]; - - read_frame(resp, len + 7); - - if (resp[0] != PN532_PREAMBLE || - resp[1] != PN532_STARTCODE1 || - resp[2] != PN532_STARTCODE2) { - return -1; - } - - uint8_t length = resp[3]; - uint8_t length_check = length + resp[4]; - - if (length > len || - length_check != 0 || - resp[length + 6] != PN532_POSTAMBLE) { - return -1; - } - - uint8_t checksum = 0; - for (int i = 0; i <= length; i++) { - data[i] = resp[5 + i]; - checksum += resp[5 + i]; - } - - if (checksum != 0) { - return -1; - } - - return length; -} - -int pn532_write_command(uint8_t cmd, const uint8_t *param, uint8_t len) -{ - uint8_t data[len + 2]; - data[0] = PN532_HOSTTOPN532; - data[1] = cmd; - - memcpy(data + 2, param, len); - - return pn532_write_data(data, len + 2); -} - -static void write_nack() -{ - const uint8_t nack[] = {0, 0, 0xff, 0xff, 0, 0}; - pn532_write(nack, 6); -} - -int pn532_peak_response_len() -{ - uint8_t buf[6]; - if (!pn532_wait_ready()) { - return -1; - } - pn532_read(buf, 6); - if (buf[0] != 0x01 || - buf[1] != PN532_PREAMBLE || - buf[2] != PN532_STARTCODE1 || - buf[3] != PN532_STARTCODE2) { - return -1; - } - - write_nack(); - return buf[4]; -} - -int pn532_read_response(uint8_t cmd, uint8_t *resp, uint8_t len) -{ - int real_len = pn532_peak_response_len(); - if (real_len < 0) { - return -1; - } - - if (!pn532_wait_ready()) { - return -1; - } - - if (real_len < 2) { - return -1; - } - - uint8_t data[real_len]; - int ret = pn532_read_data(data, real_len); - if (ret != real_len || - data[0] != PN532_PN532TOHOST || - data[1] != cmd + 1) { - return -1; - } - - int data_len = real_len - 2; - if (data_len > len) { - return -1; - } - - if (data_len > 0) { - memcpy(resp, data + 2, data_len); - } - - return data_len; -} - -uint32_t pn532_firmware_ver() -{ - int ret = pn532_write_command(0x02, NULL, 0); - if (ret < 0) { - return 0; - } - - uint8_t ver[4]; - int result = pn532_read_response(0x4a, ver, sizeof(ver)); - if (result < 4) { - return 0; - } - - uint32_t version = 0; - for (int i = 0; i < 4; i++) { - version <<= 8; - version |= ver[i]; - } - return version; -} - -bool pn532_config_rf() -{ - uint8_t param[] = {0x05, 0xff, 0x01, 0x50}; - pn532_write_command(0x32, param, sizeof(param)); - - return pn532_read_response(0x32, param, sizeof(param)) == 0; -} - -bool pn532_config_sam() -{ - uint8_t param[] = {0x01, 0x14, 0x01}; - pn532_write_command(0x14, param, sizeof(param)); - - return pn532_read_response(0x14, NULL, 0) == 0; -} - - -bool pn532_set_rf_field(uint8_t auto_rf, uint8_t on_off) -{ - uint8_t param[] = { 1, auto_rf | on_off }; - pn532_write_command(0x32, param, 2); - - return pn532_read_response(0x32, NULL, 0) >= 0; -} - -static uint8_t readbuf[255]; - -bool pn532_poll_mifare(uint8_t *uid, int *len) -{ - uint8_t param[] = {0x01, 0x00}; - int ret = pn532_write_command(0x4a, param, sizeof(param)); - if (ret < 0) { - return false; - } - - int result = pn532_read_response(0x4a, readbuf, sizeof(readbuf)); - if (result < 1 || readbuf[0] != 1) { - return false; - } - - if (result != readbuf[5] + 6) { - return false; - } - - if (*len < readbuf[5]) { - return false; - } - - memcpy(uid, readbuf + 6, readbuf[5]); - *len = readbuf[5]; - - return true; -} - -bool pn532_poll_14443b(uint8_t *uid, int *len) -{ - uint8_t param[] = {0x01, 0x03, 0x00}; - int ret = pn532_write_command(0x4a, param, sizeof(param)); - if (ret < 0) { - return false; - } - - int result = pn532_read_response(0x4a, readbuf, sizeof(readbuf)); - if (result < 1 || readbuf[0] != 1) { - printf("result: %d\n", result); - return false; - } - - if (result != readbuf[5] + 6) { - printf("result: %d %d\n", result, readbuf[5]); - return false; - } - - if (*len < readbuf[5]) { - printf("result: %d %d\n", result, readbuf[5]); - return false; - } - - memcpy(uid, readbuf + 6, readbuf[5]); - *len = readbuf[5]; - - return true; -} - -static struct __attribute__((packed)) { - uint8_t idm[8]; - uint8_t pmm[8]; - uint8_t syscode[2]; - uint8_t inlist_tag; -} felica_poll_cache; - -bool pn532_poll_felica(uint8_t uid[8], uint8_t pmm[8], uint8_t syscode[2], bool from_cache) -{ - if (from_cache) { - memcpy(uid, felica_poll_cache.idm, 8); - memcpy(pmm, felica_poll_cache.pmm, 8); - memcpy(syscode, felica_poll_cache.syscode, 2); - return true; - } - - uint8_t param[] = { 1, 1, 0, 0xff, 0xff, 1, 0}; - int ret = pn532_write_command(0x4a, param, sizeof(param)); - if (ret < 0) { - return false; - } - - int result = pn532_read_response(0x4a, readbuf, sizeof(readbuf)); - if (result != 22 || readbuf[0] != 1 || readbuf[2] != 20) { - return false; - } - - memcpy(&felica_poll_cache, readbuf + 4, 18); - felica_poll_cache.inlist_tag = readbuf[1]; - - memcpy(uid, readbuf + 4, 8); - memcpy(pmm, readbuf + 12, 8); - memcpy(syscode, readbuf + 20, 2); - - return true; -} - -bool pn532_mifare_auth(const uint8_t uid[4], uint8_t block_id, uint8_t key_id, const uint8_t *key) -{ - uint8_t param[] = { 1, key_id ? 1 : 0, block_id, - key[0], key[1], key[2], key[3], key[4], key[5], - uid[0], uid[1], uid[2], uid[3] }; - int ret = pn532_write_command(0x40, param, sizeof(param)); - if (ret < 0) { - printf("Failed mifare auth command\n"); - return false; - } - int result = pn532_read_response(0x40, readbuf, sizeof(readbuf)); - if (readbuf[0] != 0) { - printf("PN532 Mifare AUTH failed %d %02x\n", result, readbuf[0]); - return false; - } - - return true; -} - -bool pn532_mifare_read(uint8_t block_id, uint8_t block_data[16]) -{ - uint8_t param[] = { 1, 0x30, block_id }; - - int ret = pn532_write_command(0x40, param, sizeof(param)); - if (ret < 0) { - printf("Failed mifare read command\n"); - return false; - } - - int result = pn532_read_response(0x40, readbuf, sizeof(readbuf)); - - if (readbuf[0] != 0 || result != 17) { - printf("PN532 Mifare READ failed %d %02x\n", result, readbuf[0]); - return false; - } - - memmove(block_data, readbuf + 1, 16); - - return true; -} - -int pn532_felica_command(uint8_t cmd, const uint8_t *param, uint8_t param_len, uint8_t *outbuf) -{ - int cmd_len = param_len + 11; - uint8_t cmd_buf[cmd_len + 1]; - - cmd_buf[0] = felica_poll_cache.inlist_tag; - cmd_buf[1] = cmd_len; - cmd_buf[2] = cmd; - memcpy(cmd_buf + 3, felica_poll_cache.idm, 8); - memcpy(cmd_buf + 11, param, param_len); - - int ret = pn532_write_command(0x40, cmd_buf, sizeof(cmd_buf)); - if (ret < 0) { - printf("Failed send felica command\n"); - return -1; - } - - int result = pn532_read_response(0x40, readbuf, sizeof(readbuf)); - - int outlen = readbuf[1] - 1; - if ((readbuf[0] & 0x3f) != 0 || result - 2 != outlen) { - return -1; - } - - memmove(outbuf, readbuf + 2, outlen); - - return outlen; -} - - -bool pn532_felica_read_wo_encrypt(uint16_t svc_code, uint16_t block_id, uint8_t block_data[16]) -{ - uint8_t param[] = { 1, svc_code & 0xff, svc_code >> 8, - 1, block_id >> 8, block_id & 0xff }; - - int result = pn532_felica_command(0x06, param, sizeof(param), readbuf); - - if (result != 12 + 16 || readbuf[9] != 0 || readbuf[10] != 0) { - printf("PN532 Felica READ read failed %d %02x %02x\n", - result, readbuf[9], readbuf[10]); - for (int i = 0; i < result; i++) { - printf(" %02x", readbuf[i]); - } - printf("\n"); - return false; - } - - const uint8_t *result_data = readbuf + 12; - memcpy(block_data, result_data, 16); - - return true; -} - -bool pn532_felica_write_wo_encrypt(uint16_t svc_code, uint16_t block_id, const uint8_t block_data[16]) -{ - uint8_t param[22] = { 1, svc_code & 0xff, svc_code >> 8, - 1, block_id >> 8, block_id & 0xff }; - memcpy(param + 6, block_data, 16); - int result = pn532_felica_command(0x08, param, sizeof(param), readbuf); - - if (result < 0) { - printf("PN532 Felica WRITE failed %d\n", result); - return false; - } - - for (int i = 0; i < result; i++) { - printf(" %02x", readbuf[i]); - } - printf("\n"); - return false; -} diff --git a/firmware/src/pn532.h b/firmware/src/pn532.h deleted file mode 100644 index a863f9b..0000000 --- a/firmware/src/pn532.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * PN532 NFC Reader - * WHowe - * - */ - -#ifndef PN532_H -#define PN532_H - -void pn532_init(); -int pn532_write_command(uint8_t cmd, const uint8_t *param, uint8_t len); -int pn532_read_response(uint8_t cmd, uint8_t *resp, uint8_t len); - -uint32_t pn532_firmware_ver(); - -bool pn532_config_sam(); -bool pn532_config_rf(); - -bool pn532_set_rf_field(uint8_t auto_rf, uint8_t on_off); - -bool pn532_poll_mifare(uint8_t *uid, int *len); -bool pn532_poll_14443b(uint8_t *uid, int *len); -bool pn532_poll_felica(uint8_t uid[8], uint8_t pmm[8], uint8_t syscode[2], bool from_cache); - -bool pn532_mifare_auth(const uint8_t uid[4], uint8_t block_id, uint8_t key_id, const uint8_t *key); -bool pn532_mifare_read(uint8_t block_id, uint8_t block_data[16]); - -bool pn532_felica_read_wo_encrypt(uint16_t svc_code, uint16_t block_id, uint8_t block_data[16]); -bool pn532_felica_write_wo_encrypt(uint16_t svc_code, uint16_t block_id, const uint8_t block_data[16]); - -#endif