You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
4.5 KiB
185 lines
4.5 KiB
#include "scanner.h" |
|
#include <glib/glist.h> |
|
|
|
struct _YacosScanner { |
|
GObject parent_instance; |
|
|
|
nfc_context *nfc_ctx; |
|
nfc_device *nfc_pnd; |
|
|
|
GList *detected_tags; |
|
}; |
|
|
|
G_DEFINE_TYPE(YacosScanner, yacos_scanner, G_TYPE_OBJECT) |
|
|
|
enum { |
|
SIGNAL_NEWTAG = 0, |
|
SIGNAL_COUNT |
|
}; |
|
guint yacos_scanner_signals[SIGNAL_COUNT]; |
|
|
|
static int yacos_scanner_list(YacosScanner *self) |
|
{ |
|
int targets_found; |
|
int i, j; |
|
int mod_id; |
|
#define N_SIMUL_TARGETS 5 /* TODO: Make dynamic */ |
|
nfc_target targets[N_SIMUL_TARGETS]; |
|
union _tag_id { |
|
uint8_t bytes[4]; |
|
uint32_t word; |
|
} tag_id; |
|
struct yacos_scanner_tag *scanner_tag = NULL; |
|
GList *l = NULL; |
|
GList *detected_tags_new = NULL; |
|
int new_tags = 0; |
|
int found = 0; |
|
|
|
const nfc_modulation nmModulations[] = { |
|
{ .nmt = NMT_ISO14443A, .nbr = NBR_106 }, |
|
//{ .nmt = NMT_ISO14443B, .nbr = NBR_106 }, |
|
//{ .nmt = NMT_FELICA, .nbr = NBR_212 }, |
|
//{ .nmt = NMT_FELICA, .nbr = NBR_424 }, |
|
{ .nmt = NMT_JEWEL, .nbr = NBR_106 }, |
|
}; |
|
#define NMODULATIONS ((int)(sizeof(nmModulations) / sizeof(nfc_modulation))) |
|
|
|
for (mod_id = 0; mod_id < NMODULATIONS; ++mod_id) { |
|
targets_found = nfc_initiator_list_passive_targets(self->nfc_pnd, |
|
nmModulations[mod_id], |
|
targets, |
|
N_SIMUL_TARGETS |
|
); |
|
for (i = 0; i < targets_found; ++i) { |
|
if (!scanner_tag) |
|
scanner_tag = malloc(sizeof(scanner_tag)); |
|
|
|
scanner_tag->tag_id = 0; |
|
scanner_tag->tag_type = TAG_TYPE_NONE; |
|
|
|
switch (targets[i].nm.nmt) { |
|
case NMT_ISO14443A: |
|
if (targets[i].nti.nai.szUidLen < 4) { |
|
g_warning("Unsupported ISO14443A tag. (UID less than 4 bytes)"); |
|
break; |
|
} |
|
memcpy((char*) &scanner_tag->tag_id, targets[i].nti.nai.abtUid, 4); // Dirty but should work |
|
scanner_tag->tag_type = TAG_TYPE_ID; |
|
break; |
|
case NMT_JEWEL: |
|
memcpy((char*) &scanner_tag->tag_id, targets[i].nti.nji.btId, 4); // Dirty but should work |
|
scanner_tag->tag_type = TAG_TYPE_ITEM; |
|
break; |
|
default: |
|
g_warning("Unsupported tag type: %x", targets[i].nm.nmt); |
|
} |
|
|
|
if (scanner_tag->tag_type != TAG_TYPE_NONE) { |
|
for (l = self->detected_tags; l != NULL; l = l->next) { |
|
found = 0; |
|
if (((struct yacos_scanner_tag*)l->data)->tag_id == scanner_tag->tag_id) { |
|
found = 1; |
|
break; |
|
} |
|
} |
|
if (!found) { |
|
new_tags = 1; |
|
} |
|
detected_tags_new = g_list_append(detected_tags_new, scanner_tag); |
|
scanner_tag = NULL; |
|
} |
|
} |
|
|
|
if (scanner_tag) |
|
free(scanner_tag); |
|
} |
|
|
|
if (self->detected_tags) |
|
g_list_free_full(self->detected_tags, free); |
|
self->detected_tags = detected_tags_new; |
|
|
|
if (new_tags) { |
|
for (l = self->detected_tags; l != NULL; l = l->next) { |
|
g_info("Found %X (%d)", |
|
((struct yacos_scanner_tag*)l->data)->tag_id, |
|
((struct yacos_scanner_tag*)l->data)->tag_type); |
|
} |
|
} |
|
|
|
return new_tags; |
|
} |
|
|
|
static gboolean yacos_scanner_read(gpointer user_data) |
|
{ |
|
YacosScanner *self = YACOS_SCANNER(user_data); |
|
|
|
// TODO: Scan for tags |
|
if (yacos_scanner_list(self)) // TODO: Make this a GTask |
|
g_signal_emit(self, yacos_scanner_signals[SIGNAL_NEWTAG], 0); |
|
|
|
return G_SOURCE_CONTINUE; |
|
} |
|
|
|
static void yacos_scanner_finalize(GObject *gobject) |
|
{ |
|
YacosScanner *self = yacos_scanner_get_instance_private(YACOS_SCANNER(gobject)); |
|
|
|
if (self->nfc_pnd) |
|
nfc_close(self->nfc_pnd); |
|
if (self->nfc_ctx) |
|
nfc_exit(self->nfc_ctx); |
|
|
|
G_OBJECT_CLASS(yacos_scanner_parent_class)->finalize(gobject); |
|
} |
|
|
|
static void yacos_scanner_class_init(YacosScannerClass *klass) |
|
{ |
|
GObjectClass *object_class = G_OBJECT_CLASS(klass); |
|
|
|
yacos_scanner_signals[SIGNAL_NEWTAG] = |
|
g_signal_newv("newtag", |
|
G_TYPE_FROM_CLASS(object_class), |
|
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, |
|
NULL, NULL, NULL, NULL, |
|
G_TYPE_NONE, |
|
0, |
|
NULL); |
|
|
|
object_class->finalize = yacos_scanner_finalize; |
|
} |
|
|
|
static void yacos_scanner_init(YacosScanner *self) |
|
{ |
|
self->detected_tags = NULL; |
|
|
|
g_debug("Using libnfc %s", nfc_version()); |
|
nfc_init(&self->nfc_ctx); |
|
if (!self->nfc_ctx) { |
|
g_error("Error initializing libnfc"); |
|
return; |
|
} |
|
self->nfc_pnd = nfc_open(self->nfc_ctx, NULL); |
|
if (!self->nfc_pnd) { |
|
g_error("Error initializing NFC device"); |
|
return; |
|
} |
|
|
|
g_timeout_add(100, G_SOURCE_FUNC(yacos_scanner_read), self); |
|
} |
|
|
|
YacosScanner *yacos_scanner_new(void) |
|
{ |
|
return g_object_new(YACOS_TYPE_SCANNER, 0); |
|
} |
|
|
|
// Free afterwards using g_free |
|
gchar *yacos_tag_id_to_str(yacos_tag_id tag_id) |
|
{ |
|
return g_strdup_printf("%X", tag_id); |
|
} |
|
|
|
|
|
GList *yacos_scanner_get_present_tags(YacosScanner *scanner) |
|
{ |
|
return scanner->detected_tags; |
|
}
|
|
|