2010-02-19 14:50:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2010, Romain Tartiere, Romuald Conty.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
|
|
|
* under the terms of the GNU Lesser General Public License as published by the
|
|
|
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
|
* option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
|
* more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
|
*
|
|
|
|
|
* $Id$
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
#include <freefare.h>
|
|
|
|
|
|
|
|
|
|
#include "freefare_internal.h"
|
|
|
|
|
|
|
|
|
|
struct supported_tag supported_tags[] = {
|
2010-03-01 14:04:47 +00:00
|
|
|
|
{ { 0x00, 0x44 }, 0x00, ULTRALIGHT, "Mifare UltraLight" },
|
|
|
|
|
{ { 0x00, 0x04 }, 0x08, CLASSIC_1K, "Mifare Classic 1k" },
|
|
|
|
|
{ { 0x00, 0x02 }, 0x18, CLASSIC_4K, "Mifare Classic 4k" },
|
|
|
|
|
{ { 0x00, 0x02 }, 0x38, CLASSIC_4K, "Mifare Classic 4k (Emulated)" },
|
2010-02-19 14:50:18 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* MIFARE card common functions
|
|
|
|
|
*
|
|
|
|
|
* The following functions send NFC commands to the initiator to prepare
|
|
|
|
|
* communication with a MIFARE card, and perform required cleannups after using
|
|
|
|
|
* the targets.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get a list of the MIFARE targets near to the provided NFC initiator.
|
|
|
|
|
*
|
|
|
|
|
* The list has to be freed using the freefare_free_tags() function.
|
|
|
|
|
*/
|
|
|
|
|
MifareTag *
|
|
|
|
|
freefare_get_tags (nfc_device_t *device)
|
|
|
|
|
{
|
|
|
|
|
MifareTag *tags = NULL;
|
|
|
|
|
int tag_count = 0;
|
|
|
|
|
|
|
|
|
|
nfc_initiator_init(device);
|
|
|
|
|
|
|
|
|
|
// Drop the field for a while
|
|
|
|
|
nfc_configure(device,NDO_ACTIVATE_FIELD,false);
|
|
|
|
|
|
|
|
|
|
// Let the reader only try once to find a tag
|
|
|
|
|
nfc_configure(device,NDO_INFINITE_SELECT,false);
|
|
|
|
|
|
|
|
|
|
// Configure the CRC and Parity settings
|
|
|
|
|
nfc_configure(device,NDO_HANDLE_CRC,true);
|
|
|
|
|
nfc_configure(device,NDO_HANDLE_PARITY,true);
|
|
|
|
|
|
|
|
|
|
// Enable field so more power consuming cards can power themselves up
|
|
|
|
|
nfc_configure(device,NDO_ACTIVATE_FIELD,true);
|
|
|
|
|
|
|
|
|
|
// Poll for a ISO14443A (MIFARE) tag
|
|
|
|
|
nfc_target_info_t target_info;
|
|
|
|
|
|
|
|
|
|
tags = malloc(sizeof (void *));
|
|
|
|
|
if(!tags) return NULL;
|
|
|
|
|
tags[0] = NULL;
|
|
|
|
|
|
|
|
|
|
while (nfc_initiator_select_tag(device,NM_ISO14443A_106,NULL,0,&target_info)) {
|
|
|
|
|
|
|
|
|
|
bool found = false;
|
2010-03-01 14:19:48 +00:00
|
|
|
|
struct supported_tag *tag_info;
|
2010-02-19 14:50:18 +00:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < sizeof (supported_tags) / sizeof (struct supported_tag); i++) {
|
|
|
|
|
if ((target_info.nai.abtAtqa[0] == supported_tags[i].ATQA[0]) &&
|
|
|
|
|
(target_info.nai.abtAtqa[1] == supported_tags[i].ATQA[1]) &&
|
|
|
|
|
(target_info.nai.btSak == supported_tags[i].SAK)) {
|
|
|
|
|
|
2010-03-01 14:19:48 +00:00
|
|
|
|
tag_info = &(supported_tags[i]);
|
2010-02-19 14:50:18 +00:00
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
tag_count++;
|
|
|
|
|
|
|
|
|
|
/* (Re)Allocate memory for the found MIFARE targets array */
|
|
|
|
|
MifareTag *p = realloc (tags, (tag_count + 1) * sizeof (MifareTag));
|
|
|
|
|
if (p)
|
|
|
|
|
tags = p;
|
|
|
|
|
else
|
|
|
|
|
return tags; // FAIL! Return what has been found so far.
|
|
|
|
|
|
|
|
|
|
/* Allocate memory for the found MIFARE target */
|
2010-03-01 14:19:48 +00:00
|
|
|
|
switch (tag_info->type) {
|
2010-02-19 14:50:18 +00:00
|
|
|
|
case CLASSIC_1K:
|
|
|
|
|
case CLASSIC_4K:
|
2010-02-22 12:25:23 +00:00
|
|
|
|
tags[tag_count-1] = mifare_classic_tag_new ();
|
2010-02-19 14:50:18 +00:00
|
|
|
|
break;
|
|
|
|
|
case ULTRALIGHT:
|
2010-02-22 12:25:23 +00:00
|
|
|
|
tags[tag_count-1] = mifare_ultralight_tag_new ();
|
2010-02-19 14:50:18 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!tags[tag_count-1])
|
|
|
|
|
return tags; // FAIL! Return what has been found before.
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Initialize common fields
|
2010-02-22 12:25:23 +00:00
|
|
|
|
* (Target specific fields are initialized in mifare_*_tag_new())
|
2010-02-19 14:50:18 +00:00
|
|
|
|
*/
|
|
|
|
|
(tags[tag_count-1])->device = device;
|
|
|
|
|
(tags[tag_count-1])->info = target_info.nai;
|
|
|
|
|
(tags[tag_count-1])->active = 0;
|
2010-03-01 14:19:48 +00:00
|
|
|
|
(tags[tag_count-1])->tag_info = tag_info;
|
2010-02-19 14:50:18 +00:00
|
|
|
|
tags[tag_count] = NULL;
|
|
|
|
|
|
|
|
|
|
nfc_initiator_deselect_tag (device);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns the type of the provided tag.
|
|
|
|
|
*/
|
|
|
|
|
enum mifare_tag_type
|
|
|
|
|
freefare_get_tag_type (MifareTag tag)
|
|
|
|
|
{
|
2010-03-01 14:19:48 +00:00
|
|
|
|
return tag->tag_info->type;
|
2010-02-19 14:50:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-01 14:04:47 +00:00
|
|
|
|
/*
|
|
|
|
|
* Returns the friendly name of the provided tag.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
freefare_get_tag_friendly_name (MifareTag tag)
|
|
|
|
|
{
|
2010-03-01 14:19:48 +00:00
|
|
|
|
return tag->tag_info->friendly_name;
|
2010-03-01 14:04:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-30 16:18:58 +00:00
|
|
|
|
/*
|
|
|
|
|
* Returns the UID of the provided tag.
|
|
|
|
|
*/
|
|
|
|
|
char *
|
|
|
|
|
freefare_get_tag_uid (MifareTag tag)
|
|
|
|
|
{
|
|
|
|
|
char *res = malloc (2 * tag->info.szUidLen + 1);
|
|
|
|
|
for (int i =0; i < tag->info.szUidLen; i++)
|
|
|
|
|
snprintf (res + 2*i, 3, "%02x", tag->info.abtUid[i]);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-20 15:17:17 +00:00
|
|
|
|
/*
|
|
|
|
|
* Free the provided tag.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
freefare_free_tag (MifareTag tag)
|
|
|
|
|
{
|
|
|
|
|
if (tag) {
|
|
|
|
|
switch (tag->tag_info->type) {
|
|
|
|
|
case CLASSIC_1K:
|
|
|
|
|
case CLASSIC_4K:
|
|
|
|
|
mifare_classic_tag_free (tag);
|
|
|
|
|
break;
|
|
|
|
|
case ULTRALIGHT:
|
|
|
|
|
mifare_ultralight_tag_free (tag);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-19 14:50:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* Free the provided tag list.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
freefare_free_tags (MifareTag *tags)
|
|
|
|
|
{
|
|
|
|
|
if (tags) {
|
|
|
|
|
for (int i=0; tags[i]; i++) {
|
2010-04-20 15:17:17 +00:00
|
|
|
|
freefare_free_tag(tags[i]);
|
2010-02-19 14:50:18 +00:00
|
|
|
|
}
|
|
|
|
|
free (tags);
|
|
|
|
|
}
|
|
|
|
|
}
|