diff --git a/ESP32-CardReader.ino b/ESP32-CardReader.ino index eb7a0d6..c858d1e 100644 --- a/ESP32-CardReader.ino +++ b/ESP32-CardReader.ino @@ -7,7 +7,7 @@ #define SW1_MODE 33 #define SW2_OTA 25 -#define SW3_LED 26 +#define SW3_CARD 26 #define SW4_FW 27 bool ReaderMode, FWSW; @@ -34,15 +34,13 @@ uint16_t SleepDelay = 10000; // ms void setup() { pinMode(SW1_MODE, INPUT_PULLUP); // Switch mode pinMode(SW2_OTA, INPUT_PULLUP); // Enable OTA - pinMode(SW3_LED, INPUT_PULLUP); // LED brightness + pinMode(SW3_CARD, INPUT_PULLUP); // Hardcode mifare pinMode(SW4_FW, INPUT_PULLUP); // (Aime) Baudrate & fw/hw | (Spice) 1P 2P u8g2.begin(); u8g2.setFont(u8g2_font_6x12_mf); FastLED.addLeds(leds, 8); - if (digitalRead(SW3_LED)) { - FastLED.setBrightness(20); - } + FastLED.setBrightness(20); // LED brightness FastLED.showColor(0); #ifdef OTA_Enable diff --git a/README.md b/README.md index ce536f3..face51e 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ https://user-images.githubusercontent.com/28331534/170975661-137f3474-f61a-4a4d- - SW2:切换启动时的 OTA 开关 - ON:连接 WiFi 获取更新,如未能连接到 WiFi 则会持续到连接成功后才能启动 - OFF:跳过检查更新,直接启动 -- SW3:切换 LED 亮度 - - ON:全亮度 - - OFF:亮度降低到指定值 +- SW3:无卡测试模式,适用于在没有卡片的情况下模拟读取代码指定的卡,例如授权卡 + - ON:跳过读卡,使用硬编码的 `mifare_data` 数据 + - OFF:读取实际卡片 - SW4:不同模式的功能切换 - Spice 模式(可在运行中切换) - ON:卡号发送到 2P 槽位(需要游戏支持) diff --git a/ReaderCmd.h b/ReaderCmd.h index 078cf76..cc55ac4 100644 --- a/ReaderCmd.h +++ b/ReaderCmd.h @@ -14,6 +14,13 @@ U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0); #include "src/wrappers.h" spiceapi::Connection CON(512); +static uint8_t mifare_data[][16] = { + // https://github.com/Sucareto/Arduino-Aime-Reader/blob/main/doc/aime%E7%A4%BA%E4%BE%8B.mct + { 0x8A, 0x1B, 0x72, 0xE1, 0x02, 0x08, 0x04, 0x00, 0x02, 0xFE, 0x9F, 0xC6, 0xDD, 0x8A, 0x3D, 0x1D }, // 前 4 位是 UID + {}, // 空数据占位符 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x45, 0x14, 0x19, 0x19, 0x81, 0x02, 0x33, 0x33 }, // access code + { 0x57, 0x43, 0x43, 0x46, 0x76, 0x32, 0x08, 0x77, 0x8F, 0x11, 0x57, 0x43, 0x43, 0x46, 0x76, 0x32 }, +}; // static unsigned char usb_disconnect[] = { // 0x00, 0x40, 0x00, 0xAE, 0x00, 0x51, 0x80, 0x20, 0x00, 0x41, 0x80, 0x42, 0x40, 0x44, 0x08, 0x28, @@ -314,6 +321,16 @@ static void sg_nfc_cmd_radio_off() { } static void sg_nfc_cmd_poll() { //卡号发送 + if (!digitalRead(SW3_CARD)) { + memcpy(res.mifare_uid, mifare_data[0], 0x04); + res.id_len = 0x04; + sg_res_init(0x07); + res.count = 1; + res.type = 0x10; + u8g2.drawXBM(113, 0, 16, 16, card); + u8g2.sendBuffer(); + return; + } uint16_t SystemCode; if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, res.mifare_uid, &res.id_len)) { sg_res_init(0x07); @@ -337,6 +354,13 @@ static void sg_nfc_cmd_poll() { //卡号发送 static void sg_nfc_cmd_aime_authenticate() { sg_res_init(); + if (!digitalRead(SW3_CARD)) { + uint8_t key_block_no = (req.block_no / 4) * 4 + 3; + if (memcmp(AimeKey, mifare_data[key_block_no], 6)) { + res.status = 1; + } + return; + } if (nfc.mifareclassic_AuthenticateBlock(req.uid, 4, req.block_no, 1, AimeKey)) { return; } else { @@ -346,6 +370,13 @@ static void sg_nfc_cmd_aime_authenticate() { static void sg_nfc_cmd_bana_authenticate() { sg_res_init(); + if (!digitalRead(SW3_CARD)) { + uint8_t key_block_no = (req.block_no / 4) * 4 + 3; + if (memcmp(BanaKey, mifare_data[key_block_no], 6)) { + res.status = 1; + } + return; + } if (nfc.mifareclassic_AuthenticateBlock(req.uid, 4, req.block_no, 0, BanaKey)) { return; } else { @@ -354,6 +385,11 @@ static void sg_nfc_cmd_bana_authenticate() { } static void sg_nfc_cmd_mifare_read_block() { //读取卡扇区数据 + if (!digitalRead(SW3_CARD)) { + memcpy(res.block, mifare_data[req.block_no], 16); + sg_res_init(0x10); + return; + } if (nfc.mifareclassic_ReadDataBlock(req.block_no, res.block)) { sg_res_init(0x10); return;