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:
parent
cabf766316
commit
cf4c289253
@ -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
|
||||||
@ -25,7 +27,8 @@ 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
|
||||||
|
;disableBuzzer=0 ;Disable the buzzer
|
||||||
;aimePath="" ;Manually specify an aime.txt file
|
;aimePath="" ;Manually specify an aime.txt file
|
||||||
;felicaPath="" ;Manually specify a felica.txt file
|
;felicaPath="" ;Manually specify a felica.txt file
|
||||||
;debug=0 ;Display function calls
|
;debug=0 ;Display function calls
|
||||||
|
10
src/aimeio.c
10
src/aimeio.c
@ -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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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];
|
|
||||||
}
|
}
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user