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.
This commit is contained in:
Farewell_ 2024-02-28 17:31:49 +01:00
parent cabf766316
commit cf4c289253
5 changed files with 89 additions and 24 deletions

View File

@ -14,6 +14,8 @@ All the logic for reading cards from a file has been taken from [CrazyRedMachine
# Usage # 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`: To use it with a game, copy `aimeio.dll` to your `segatools` folder and add the following to your `segatools.ini`:
```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. ;Everything below this line is optional.
;readerOptional=1 ;Make reader optional, so that you can still use the keyboard ;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) ;readerName="ACS ACR122 0" ;Manually select which reader to use
;aimePath="" ;Manually specify an aime.txt file ;disableBuzzer=0 ;Disable the buzzer
;felicaPath="" ;Manually specify a felica.txt file ;aimePath="" ;Manually specify an aime.txt file
;debug=0 ;Display function calls ;felicaPath="" ;Manually specify a felica.txt file
;debug=0 ;Display function calls
``` ```
## Scanning cards ## Scanning cards

View File

@ -50,6 +50,12 @@ static void aime_io_config_read(struct aime_io_config *cfg, const wchar_t *filen
0, 0,
filename); filename);
cfg->disable_buzzer = GetPrivateProfileIntW(
L"aimeio",
L"disableBuzzer",
0,
filename);
cfg->vk_scan = GetPrivateProfileIntW( cfg->vk_scan = GetPrivateProfileIntW(
L"aimeio", L"aimeio",
L"scan", 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) if (card_data.card_type == Mifare)
{ {
memcpy(luid, card_data.card_id, luid_size); 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 memset(&card_data, 0, sizeof(card_data)); // Reset card_data structure
return S_OK; 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]; val = (val << 8) | card_data.card_id[i];
*IDm = val; *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 memset(&card_data, 0, sizeof(card_data)); // Reset card_data structure
return S_OK; return S_OK;

View File

@ -12,6 +12,7 @@ struct aime_io_config
wchar_t aime_path[MAX_PATH]; wchar_t aime_path[MAX_PATH];
wchar_t felica_path[MAX_PATH]; wchar_t felica_path[MAX_PATH];
wchar_t reader_name[MAX_PATH]; wchar_t reader_name[MAX_PATH];
bool disable_buzzer;
bool reader_optional; bool reader_optional;
uint8_t vk_scan; uint8_t vk_scan;
}; };

View File

@ -6,9 +6,16 @@ int readCooldown = 500;
// based off acr122u reader, see page 26 in api document. // based off acr122u reader, see page 26 in api document.
// https://www.acs.com.hk/en/download-manual/419/API-ACR122U-2.04.pdf // 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_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_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 // return bytes from device
#define PICC_SUCCESS 0x90u #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); 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; DWORD cbRecv = MAX_APDU_SIZE;
BYTE pbRecv[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); lRet = SCardControl(hCard, SCARD_CTL_CODE(3500), PARAM_SET_PICC, sizeof(PARAM_SET_PICC), pbRecv, cbRecv, &cbRecv);
Sleep(100);
if (lRet != SCARD_S_SUCCESS) if (lRet != SCARD_S_SUCCESS)
{ {
printf("scard_init: Error setting PICC params : 0x%08X\n", lRet); 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]; 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: 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; card_data->card_type = Mifare;
return;
} }
else if (cardProtocol == SCARD_ATR_PROTOCOL_FELICA_212K) // Handling FeliCa else if (cardProtocol == SCARD_ATR_PROTOCOL_FELICA_212K) // Handling FeliCa
{ {
printf("scard_update: Card protocol: FELICA_212K\n"); printf("scard_update: Card protocol: FELICA_212K\n");
card_data->card_type = FeliCa;
// Read mID // Read mID
cbRecv = MAX_APDU_SIZE; 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); printf("scard_update: taking first 8 bytes of %d received\n", cbRecv);
memcpy(card_data->card_id, pbRecv, 8); memcpy(card_data->card_id, pbRecv, 8);
card_data->card_type = FeliCa;
return;
} }
else 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); printf("scard_update: Unknown NFC Protocol: 0x%02X\n", cardProtocol);
return; 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];
} }

View File

@ -34,15 +34,32 @@ enum AIME_CARDTYPE
FeliCa = 0x02 FeliCa = 0x02
}; };
// Structure containing card_type, card_id and card_id_len // Structure containing card_type and card_id
struct card_data struct card_data
{ {
uint8_t card_type; uint8_t card_type;
uint8_t card_id[32]; uint8_t card_id[32];
}; };
/*
Initialize the smartcard reader
- config: struct loaded from segatools.ini
*/
bool scard_init(struct aime_io_config config); 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); 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); void scard_update(struct card_data *card_data, SCARDCONTEXT _hContext, LPCTSTR _readerName);