From 95a08d43f754828f6664f2c0314ad00d03c8d14a Mon Sep 17 00:00:00 2001 From: Sucareto <28331534+Sucareto@users.noreply.github.com> Date: Sun, 10 Oct 2021 01:16:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20Felica=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Arduino-Aime-Reader.ino | 126 ++++++++++++++++++++-------------------- README.md | 9 ++- cmd.h | 105 ++++++++++++++++++++------------- 3 files changed, 136 insertions(+), 104 deletions(-) diff --git a/Arduino-Aime-Reader.ino b/Arduino-Aime-Reader.ino index bf6ecd8..adc1877 100644 --- a/Arduino-Aime-Reader.ino +++ b/Arduino-Aime-Reader.ino @@ -1,68 +1,20 @@ -#include "cmd.h" - //#define SerialDevice SerialUSB //32u4,samd21 #define SerialDevice Serial //esp8266 - -void SerialCheck() { - switch (packet_read()) { - case SG_NFC_CMD_RESET: - sg_nfc_cmd_reset(); - break; - case SG_NFC_CMD_GET_FW_VERSION: - sg_nfc_cmd_get_fw_version(); - break; - case SG_NFC_CMD_GET_HW_VERSION: - sg_nfc_cmd_get_hw_version(); - break; - case SG_NFC_CMD_POLL: - sg_nfc_cmd_poll(); - break; - case SG_NFC_CMD_MIFARE_READ_BLOCK: - sg_nfc_cmd_mifare_read_block(); - break; - case SG_NFC_CMD_FELICA_ENCAP: - sg_nfc_cmd_felica_encap(); - break; - case SG_NFC_CMD_MIFARE_AUTHENTICATE: - sg_res_init(); - break; - case SG_NFC_CMD_MIFARE_SELECT_TAG: - sg_nfc_cmd_mifare_select_tag(); - break; - case SG_NFC_CMD_MIFARE_SET_KEY_AIME: - sg_nfc_cmd_mifare_set_key(); - break; - case SG_NFC_CMD_MIFARE_SET_KEY_BANA: - sg_nfc_cmd_mifare_set_key(); - break; - case SG_NFC_CMD_RADIO_ON: - sg_nfc_cmd_radio_on(); - break; - case SG_NFC_CMD_RADIO_OFF: - sg_nfc_cmd_radio_off(); - break; - case SG_RGB_CMD_RESET: - sg_led_cmd_reset(); - break; - case SG_RGB_CMD_GET_INFO: - sg_led_cmd_get_info(); - break; - case SG_RGB_CMD_SET_COLOR: - sg_led_cmd_set_color(); - break; - case 0: - break; - default: - sg_res_init(); - } -} +//#define high_baudrate +#define M2F //取消注释此行,将默认密钥的mifare模拟为felica +#include "cmd.h" void setup() { +#ifdef high_baudrate + SerialDevice.begin(115200);//high_baudrate=true +#else SerialDevice.begin(38400); - // SerialDevice.begin(115200);//high_baudrate=true +#endif SerialDevice.setTimeout(0); FastLED.addLeds(leds, NUM_LEDS); FastLED.setBrightness(50); + FastLED.clear(); + FastLED.show(); nfc.begin(); while (!nfc.getFirmwareVersion()) { fill_solid(leds, NUM_LEDS, 0xFF0000); @@ -76,7 +28,7 @@ void setup() { nfc.SAMConfig(); memset(&req, 0, sizeof(req.bytes)); memset(&res, 0, sizeof(res.bytes)); - fill_solid(leds, NUM_LEDS, 0x0000FF); + fill_solid(leds, NUM_LEDS, 0xFFD700); FastLED.show(); } @@ -135,16 +87,66 @@ static void packet_write() { checksum += w; } if (w == 0xE0 || w == 0xD0) { - if (SerialDevice.availableForWrite() < 2) - return; SerialDevice.write(0xD0); SerialDevice.write(--w); } else { - if (SerialDevice.availableForWrite() < 1) - return; SerialDevice.write(w); } len++; } res.cmd = 0; } + +void SerialCheck() { + switch (packet_read()) { + case SG_NFC_CMD_RESET: + sg_nfc_cmd_reset(); + break; + case SG_NFC_CMD_GET_FW_VERSION: + sg_nfc_cmd_get_fw_version(); + break; + case SG_NFC_CMD_GET_HW_VERSION: + sg_nfc_cmd_get_hw_version(); + break; + case SG_NFC_CMD_POLL: + sg_nfc_cmd_poll(); + break; + case SG_NFC_CMD_MIFARE_READ_BLOCK: + sg_nfc_cmd_mifare_read_block(); + break; + case SG_NFC_CMD_FELICA_ENCAP: + sg_nfc_cmd_felica_encap(); + break; + case SG_NFC_CMD_MIFARE_AUTHENTICATE: + sg_res_init(); + break; + case SG_NFC_CMD_MIFARE_SELECT_TAG: + sg_nfc_cmd_mifare_select_tag(); + break; + case SG_NFC_CMD_MIFARE_SET_KEY_AIME: + sg_nfc_cmd_mifare_set_key(); + break; + case SG_NFC_CMD_MIFARE_SET_KEY_BANA: + sg_nfc_cmd_mifare_set_key(); + break; + case SG_NFC_CMD_RADIO_ON: + sg_nfc_cmd_radio_on(); + break; + case SG_NFC_CMD_RADIO_OFF: + sg_nfc_cmd_radio_off(); + break; + case SG_RGB_CMD_RESET: + sg_led_cmd_reset(); + break; + case SG_RGB_CMD_GET_INFO: + sg_led_cmd_get_info(); + break; + case SG_RGB_CMD_SET_COLOR: + sg_led_cmd_set_color(); + break; + case 0: + break; + default: + sg_res_init(); + } +} diff --git a/README.md b/README.md index ba20ab1..6201264 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Arduino-Aime-Reader -使用 Arduino + PN532 + WS2812B 制作的 Aime 读卡器。支持 Felica,Bana,Aime(Mifare 卡模拟 Felica 是可选功能)。 +使用 Arduino + PN532 + WS2812B 制作的 Aime 读卡器。支持 Felica,banapassport,Aime(Mifare 卡模拟 Felica 是可选功能)。 通信数据格式可参考 [card.txt](https://github.com/Sucareto/Arduino-Aime-Reader/blob/main/doc/card.txt) 和 [nfc.txt](https://github.com/Sucareto/Arduino-Aime-Reader/blob/main/doc/nfc.txt)。 替换 chunihook.dll 可在控制台输出通信数据,源码在 [sg-cmd.c](https://github.com/Sucareto/Arduino-Chunithm-Reader/blob/main/tools/sg-cmd.c)。 @@ -11,7 +11,7 @@ Arduino 和 PN532 接好 VCC,GND,SDA,SCL; 打开设备管理器,设置 Arduino 的 COM 号,一些参考如下: - Chunithm:COM12,支持读取 Felica 和 Aime -- Ongeki/Sinmai:COM1,仅支持读取 Aime +- Ongeki/Sinmai:COM1,支持读取 Felica 和 Aime - MaiMai Finale:COM2,仅支持读取 Aime 某些 Arduino 可能需要在打开主程序前给串口发送 DTR/RTS,需要先打开一次 Arduino 串口监视器再启动主程序。 @@ -23,6 +23,11 @@ Arduino 和 PN532 接好 VCC,GND,SDA,SCL; - SparkFun SAMD21 Dev Breakout(ATSAMD21G18) - NodeMCU 1.0(ESP-12E + CP2102 & CH340),SDA=D2,SCL=D1 +#### 待办事项: +- [ ] 确认 Ongeki 读取 Felica 情况 +- [ ] 收集 banapassport 卡结构和读取数据 +- [ ] 确认 NDA_06 和 NDA_08 数据结构 + #### 引用库: - [驱动WS2812B FastLED.h](https://github.com/FastLED/FastLED) - [驱动PN532 PN532.h](https://github.com/elechouse/PN532) diff --git a/cmd.h b/cmd.h index 20704d1..d1f9439 100644 --- a/cmd.h +++ b/cmd.h @@ -1,6 +1,6 @@ #include "FastLED.h" #define NUM_LEDS 6 -#define DATA_PIN 14 +#define DATA_PIN D5//14 CRGB leds[NUM_LEDS]; #include @@ -13,43 +13,47 @@ PN532 nfc(pn532i2c); uint8_t cardtype, uid[4], uL; uint16_t systemCode = 0xFFFF; uint8_t requestCode = 0x01; -uint16_t systemCodeResponse; typedef union { - uint8_t block[16]; + uint8_t block[18]; struct { uint8_t IDm[8]; uint8_t PMm[8]; + uint16_t SystemCode; }; } Felica; Felica felica; uint8_t AimeKey[6], BanaKey[6]; -#define M2F //取消注释此行,将默认密钥的mifare模拟为felica - #ifdef M2F #define M2F_B 1 //指定从mifare读取第几block当作felica的IDm和PMm uint8_t MifareKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; #endif enum { - SG_NFC_CMD_GET_FW_VERSION = 0x30,//获取FW版本 - SG_NFC_CMD_GET_HW_VERSION = 0x32,//获取HW版本 - 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, - SG_RGB_CMD_SET_COLOR = 0x81,//LED颜色设置 - SG_RGB_CMD_RESET = 0xF5,//LED重置 - SG_RGB_CMD_GET_INFO = 0xF0,//LED信息获取 - FELICA_CMD_POLL = 0x00,//ENCAP用 - FELICA_CMD_GET_SYSTEM_CODE = 0x0C, - FELICA_CMD_NDA_A4 = 0xA4, + SG_NFC_CMD_GET_FW_VERSION = 0x30,//获取 FW 版本 + SG_NFC_CMD_GET_HW_VERSION = 0x32,//获取 HW 版本 + SG_RGB_CMD_GET_INFO = 0xF0,//获取 LED 信息 + + SG_NFC_CMD_RESET = 0x62,//重置读卡器 + SG_RGB_CMD_SET_COLOR = 0x81,//LED 颜色设置 + SG_RGB_CMD_RESET = 0xF5,//LED 重置 + 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_SET_KEY_AIME = 0x54, + SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52, + SG_NFC_CMD_MIFARE_AUTHENTICATE = 0x55, + SG_NFC_CMD_FELICA_ENCAP = 0x71, + + //FELICA_ENCAP + FELICA_CMD_POLL = 0x00, + FELICA_CMD_GET_SYSTEM_CODE = 0x0C, + FELICA_CMD_NDA_A4 = 0xA4, + FELICA_CMD_NDA_06 = 0x06,//测试中,作用未知 + FELICA_CMD_NDA_08 = 0x08,//测试中,作用未知 }; typedef union packet_req { @@ -104,10 +108,15 @@ typedef union packet_res { uint8_t code; uint8_t encap_IDm[8]; union { - struct { + struct {//FELICA_CMD_POLL uint8_t encap_PMm[8]; uint8_t system_code[2]; }; + struct {//NDA06 + uint8_t NDA06_code[3]; + uint8_t NDA06_IDm[8]; + uint8_t NDA06_Data[8]; + }; uint8_t felica_payload[241]; }; }; @@ -143,13 +152,13 @@ static void sg_nfc_cmd_reset() {//重置读卡器 static void sg_nfc_cmd_get_fw_version() { sg_res_init(23); - // memcpy(res.version, "TN32MSEC003S F/W Ver1.2E", 23); + // memcpy(res.version, "TN32MSEC003S F/W Ver1.2", 23); memcpy(res.version, "Sucareto Aime Reader FW", 23); } static void sg_nfc_cmd_get_hw_version() { sg_res_init(23); - // memcpy(res.version, "TN32MSEC003S H/W Ver3.0J", 23); + // memcpy(res.version, "TN32MSEC003S H/W Ver3.0", 23); memcpy(res.version, "Sucareto Aime Reader HW", 23); } @@ -163,9 +172,8 @@ static void sg_nfc_cmd_mifare_set_key() { } static void sg_led_cmd_reset() { - sg_res_init(1); - res.reset_payload = 0; - fill_solid(leds, NUM_LEDS, 0x000000); + sg_res_init(); + FastLED.clear(); FastLED.show(); } @@ -198,7 +206,7 @@ static void sg_nfc_cmd_radio_on() { cardtype = 0x10; return; } - if (nfc.felica_Polling(systemCode, requestCode, felica.IDm, felica.PMm, &systemCodeResponse, 200)) { + if (nfc.felica_Polling(systemCode, requestCode, felica.IDm, felica.PMm, &felica.SystemCode, 200)) { cardtype = 0x20; return; } @@ -224,7 +232,7 @@ static void sg_nfc_cmd_poll() { //卡号发送 return; } if (cardtype == 0x20) { - sg_res_init(19);//count,type,id_len,IDm,PMm + sg_res_init(19); memcpy(res.IDm, felica.IDm, 8); memcpy(res.PMm, felica.PMm, 8); res.count = 1; @@ -234,10 +242,12 @@ static void sg_nfc_cmd_poll() { //卡号发送 } #ifdef M2F if (cardtype == 0x30) { - sg_res_init(19);//count,type,id_len,IDm,PMm + sg_res_init(19); nfc.mifareclassic_ReadDataBlock(M2F_B, felica.block); memcpy(res.IDm, felica.IDm, 8); memcpy(res.PMm, felica.PMm, 8); + felica.block[16] = 0x00; + felica.block[17] = 0x03;//suica res.count = 1; res.type = 0x20; res.id_len = 0x10; @@ -275,22 +285,37 @@ static void sg_nfc_cmd_felica_encap() { sg_res_init(0x14); memcpy(res.encap_IDm, felica.IDm, 8); memcpy(res.encap_PMm, felica.PMm, 8); - res.system_code[0] = 0x00; - res.system_code[1] = 0x00; + memcpy(res.system_code, &felica.SystemCode, 2); break; case FELICA_CMD_GET_SYSTEM_CODE: sg_res_init(0x0D); memcpy(res.IDm, felica.IDm, 8); - res.felica_payload[0] = 0x01; + res.felica_payload[0] = 0x01;//未知 + res.felica_payload[1] = felica.block[16];//SystemCode + res.felica_payload[2] = felica.block[17]; + break; + case FELICA_CMD_NDA_A4: + sg_res_init(0x0B); + res.felica_payload[0] = 0x00; + break; + case FELICA_CMD_NDA_06: + sg_res_init(0x1D); + memcpy(res.encap_IDm, felica.IDm, 8); + res.NDA06_code[0] = 0x00; + res.NDA06_code[1] = 0x00; + res.NDA06_code[2] = 0x01;//未知 + memcpy(res.NDA06_IDm, felica.IDm, 8); + memcpy(res.NDA06_Data, felica.PMm, 8);//填补数据用 + break; + case FELICA_CMD_NDA_08: + sg_res_init(0x0C); + memcpy(res.encap_IDm, felica.IDm, 8); + res.felica_payload[0] = 0x00; res.felica_payload[1] = 0x00; - res.felica_payload[2] = 0x00;//0x03 break; - case FELICA_CMD_NDA_A4://pass - // sg_res_init(0x0B); - // res.felica_payload[0] = 0x00; + default: sg_res_init(); res.status = 1; - break; } res.encap_len = res.payload_len; }