#include "scanner.h" #include 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; }