From cf4c28925332b9eb9c9d06f89becda7db6d81ec8 Mon Sep 17 00:00:00 2001 From: KIT! Date: Wed, 28 Feb 2024 17:31:49 +0100 Subject: [PATCH] Added support for Mifare 1K, Added option for disabling buzzer Haven't been able to test m1k support with an aime card since i don't have any, but i have validated that the code does read block 2 of m1k tags. --- readme.md | 13 +++++---- src/aimeio.c | 10 +++++-- src/aimeio.h | 1 + src/scard/scard.c | 70 ++++++++++++++++++++++++++++++++++++----------- src/scard/scard.h | 19 ++++++++++++- 5 files changed, 89 insertions(+), 24 deletions(-) diff --git a/readme.md b/readme.md index 299a86e..ec03a10 100644 --- a/readme.md +++ b/readme.md @@ -14,6 +14,8 @@ All the logic for reading cards from a file has been taken from [CrazyRedMachine # Usage +Make sure to install the ACR122U's [driver](https://www.acs.com.hk/en/driver/3/acr122u-usb-nfc-reader/) before using this. + To use it with a game, copy `aimeio.dll` to your `segatools` folder and add the following to your `segatools.ini`: ```ini @@ -24,11 +26,12 @@ scan=0x0D ;Sets the key which will be used to insert a card in game. Th ;Everything below this line is optional. -;readerOptional=1 ;Make reader optional, so that you can still use the keyboard -;readerName="" ;Force using a reader by setting it's name (in case multiple readers are detected) -;aimePath="" ;Manually specify an aime.txt file -;felicaPath="" ;Manually specify a felica.txt file -;debug=0 ;Display function calls +;readerOptional=1 ;Make reader optional, so that you can still use the keyboard +;readerName="ACS ACR122 0" ;Manually select which reader to use +;disableBuzzer=0 ;Disable the buzzer +;aimePath="" ;Manually specify an aime.txt file +;felicaPath="" ;Manually specify a felica.txt file +;debug=0 ;Display function calls ``` ## Scanning cards diff --git a/src/aimeio.c b/src/aimeio.c index 137d47a..3cad94e 100644 --- a/src/aimeio.c +++ b/src/aimeio.c @@ -50,6 +50,12 @@ static void aime_io_config_read(struct aime_io_config *cfg, const wchar_t *filen 0, filename); + cfg->disable_buzzer = GetPrivateProfileIntW( + L"aimeio", + L"disableBuzzer", + 0, + filename); + cfg->vk_scan = GetPrivateProfileIntW( L"aimeio", L"scan", @@ -253,7 +259,7 @@ HRESULT aime_io_nfc_get_aime_id(uint8_t unit_no, uint8_t *luid, size_t luid_size if (card_data.card_type == Mifare) { memcpy(luid, card_data.card_id, luid_size); - printf("aime_io_nfc_get_aime_id: Sending Aime card with luID %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X\r\n", card_data.card_id[0], card_data.card_id[1], card_data.card_id[2], card_data.card_id[3], card_data.card_id[4], card_data.card_id[5], card_data.card_id[6], card_data.card_id[7], card_data.card_id[8], card_data.card_id[9]); + printf("aime_io_nfc_get_aime_id: Sending Aime card with luID %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X\r\n\n", card_data.card_id[0], card_data.card_id[1], card_data.card_id[2], card_data.card_id[3], card_data.card_id[4], card_data.card_id[5], card_data.card_id[6], card_data.card_id[7], card_data.card_id[8], card_data.card_id[9]); memset(&card_data, 0, sizeof(card_data)); // Reset card_data structure return S_OK; @@ -278,7 +284,7 @@ HRESULT aime_io_nfc_get_felica_id(uint8_t unit_no, uint64_t *IDm) val = (val << 8) | card_data.card_id[i]; *IDm = val; - printf("aime_io_nfc_get_felica_id: Sending FeliCa card with serial %02X%02X %02X%02X %02X%02X %02X%02X\r\n", card_data.card_id[0], card_data.card_id[1], card_data.card_id[2], card_data.card_id[3], card_data.card_id[4], card_data.card_id[5], card_data.card_id[6], card_data.card_id[7]); + printf("aime_io_nfc_get_felica_id: Sending FeliCa card with serial %02X%02X %02X%02X %02X%02X %02X%02X\r\n\n", card_data.card_id[0], card_data.card_id[1], card_data.card_id[2], card_data.card_id[3], card_data.card_id[4], card_data.card_id[5], card_data.card_id[6], card_data.card_id[7]); memset(&card_data, 0, sizeof(card_data)); // Reset card_data structure return S_OK; diff --git a/src/aimeio.h b/src/aimeio.h index 121a7b9..7046258 100644 --- a/src/aimeio.h +++ b/src/aimeio.h @@ -12,6 +12,7 @@ struct aime_io_config wchar_t aime_path[MAX_PATH]; wchar_t felica_path[MAX_PATH]; wchar_t reader_name[MAX_PATH]; + bool disable_buzzer; bool reader_optional; uint8_t vk_scan; }; diff --git a/src/scard/scard.c b/src/scard/scard.c index f276cdb..d1a9df3 100644 --- a/src/scard/scard.c +++ b/src/scard/scard.c @@ -6,9 +6,16 @@ int readCooldown = 500; // based off acr122u reader, see page 26 in api document. // https://www.acs.com.hk/en/download-manual/419/API-ACR122U-2.04.pdf -#define PARAM_POLLRATE 0xDFu +// #define PARAM_POLLRATE 0xDFu +#define PARAM_POLLRATE 0x9Bu static const BYTE PARAM_SET_PICC[5] = {0xFFu, 0x00u, 0x51u, PARAM_POLLRATE, 0x00u}; +static const BYTE PARAM_LOAD_KEY[11] = {0xFFu, 0x82u, 0x00u, 0x00u, 0x06u, 0x57u, 0x43u, 0x43u, 0x46u, 0x76u, 0x32u}; +static const BYTE PARAM_ENABLE_BUZZER[5] = {0xFFu, 0x00u, 0x52u, 0xFFu, 0x00u}; +static const BYTE PARAM_DISABLE_BUZZER[5] = {0xFFu, 0x00u, 0x52u, 0x00u, 0x00u}; + static const BYTE COMMAND_GET_UID[5] = {0xFFu, 0xCAu, 0x00u, 0x00u, 0x00u}; +static const BYTE COMMAND_AUTH_BLOCK2[10] = {0xFFu, 0x86u, 0x00u, 0x00u, 0x05u, 0x01u, 0x00u, 0x02u, 0x61u, 0x00u}; +static const BYTE COMMAND_READ_BLOCK2[5] = {0xFFu, 0xB0u, 0x00u, 0x02u, 0x10u}; // return bytes from device #define PICC_SUCCESS 0x90u @@ -86,11 +93,17 @@ bool scard_init(struct aime_io_config config) } printf("scard_init: Connected to reader: %s, sending PICC params\n", reader_list); - // set the reader params + // Enable/Disable the buzzer output DWORD cbRecv = MAX_APDU_SIZE; BYTE pbRecv[MAX_APDU_SIZE]; + lRet = SCardControl(hCard, SCARD_CTL_CODE(3500), config.disable_buzzer ? PARAM_DISABLE_BUZZER : PARAM_ENABLE_BUZZER, sizeof(config.disable_buzzer ? PARAM_DISABLE_BUZZER : PARAM_ENABLE_BUZZER), pbRecv, cbRecv, &cbRecv); + if (lRet != SCARD_S_SUCCESS) + printf("scard_init: Couldn't %s buzzer : 0x%08X\n", config.disable_buzzer ? "disable" : "enable", lRet); + else + printf("scard_init: %s buzzer\n", config.disable_buzzer ? "Disabled" : "Enabled"); + + // set the reader params to allow reading FeliCa cards. lRet = SCardControl(hCard, SCARD_CTL_CODE(3500), PARAM_SET_PICC, sizeof(PARAM_SET_PICC), pbRecv, cbRecv, &cbRecv); - Sleep(100); if (lRet != SCARD_S_SUCCESS) { printf("scard_init: Error setting PICC params : 0x%08X\n", lRet); @@ -203,16 +216,50 @@ void scard_update(struct card_data *card_data, SCARDCONTEXT _hContext, LPCTSTR _ } BYTE cardProtocol = atr[12]; - if (cardProtocol == SCARD_ATR_PROTOCOL_ISO14443_PART3) + if (cardProtocol == SCARD_ATR_PROTOCOL_ISO14443_PART3) // Handling Aime { printf("scard_update: Card protocol: ISO14443_PART3\n"); + + printf("scard_update: Loading key for block auth onto reader...\n"); + cbRecv = MAX_APDU_SIZE; + if ((lRet = SCardTransmit(hCard, pci, PARAM_LOAD_KEY, sizeof(PARAM_LOAD_KEY), NULL, pbRecv, &cbRecv)) != SCARD_S_SUCCESS) + { + printf("scard_update: Error loading key to reader : 0x%08X\n", lRet); + return; + } + + if (cbRecv > 1 && pbRecv[0] == PICC_ERROR) + { + printf("scard_update: loading key failed\n"); + return; + } + + printf("scard_update: key has been loaded, authenticating block 2...\n"); + + cbRecv = MAX_APDU_SIZE; + if ((lRet = SCardTransmit(hCard, pci, COMMAND_AUTH_BLOCK2, sizeof(COMMAND_AUTH_BLOCK2), NULL, pbRecv, &cbRecv)) != SCARD_S_SUCCESS) + { + printf("scard_update: Couldn't authenticate for block 2 : 0x%08X\n", lRet); + return; + } + + printf("scard_update: authentication successful, reading block 2...\n"); + + cbRecv = MAX_APDU_SIZE; + if ((lRet = SCardTransmit(hCard, pci, COMMAND_READ_BLOCK2, sizeof(COMMAND_READ_BLOCK2), NULL, pbRecv, &cbRecv)) != SCARD_S_SUCCESS) + { + printf("scard_update: Couldn't read block 2 : 0x%08X\n", lRet); + return; + } + + memcpy(card_data->card_id, pbRecv + 6, 10); card_data->card_type = Mifare; + return; } else if (cardProtocol == SCARD_ATR_PROTOCOL_FELICA_212K) // Handling FeliCa { printf("scard_update: Card protocol: FELICA_212K\n"); - card_data->card_type = FeliCa; // Read mID cbRecv = MAX_APDU_SIZE; @@ -240,6 +287,8 @@ void scard_update(struct card_data *card_data, SCARDCONTEXT _hContext, LPCTSTR _ printf("scard_update: taking first 8 bytes of %d received\n", cbRecv); memcpy(card_data->card_id, pbRecv, 8); + card_data->card_type = FeliCa; + return; } else @@ -247,15 +296,4 @@ void scard_update(struct card_data *card_data, SCARDCONTEXT _hContext, LPCTSTR _ printf("scard_update: Unknown NFC Protocol: 0x%02X\n", cardProtocol); return; } - - // Copy UID to struct, reversing if necessary - // card_info_t card_info; - // if (shouldReverseUid) - // for (DWORD i = 0; i < 8; i++) - // card_info.uid[i] = pbRecv[7 - i]; - // else - // memcpy(card_info.uid, pbRecv, 8); - - // for (int i = 0; i < 8; ++i) - // buf[i] = card_info.uid[i]; } \ No newline at end of file diff --git a/src/scard/scard.h b/src/scard/scard.h index ff14255..fa20d22 100644 --- a/src/scard/scard.h +++ b/src/scard/scard.h @@ -34,15 +34,32 @@ enum AIME_CARDTYPE FeliCa = 0x02 }; -// Structure containing card_type, card_id and card_id_len +// Structure containing card_type and card_id struct card_data { uint8_t card_type; uint8_t card_id[32]; }; +/* + Initialize the smartcard reader + + - config: struct loaded from segatools.ini +*/ bool scard_init(struct aime_io_config config); +/* + Checks if a new card has been detected + + - card_data: struct containing the card data +*/ void scard_poll(struct card_data *card_data); +/* + Read the card's data + + - card_data: struct containing the card data + - _hContext: context for the card reader + - _readerName: name of the card reader to use +*/ void scard_update(struct card_data *card_data, SCARDCONTEXT _hContext, LPCTSTR _readerName);