Yet Another Check-Out System
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

#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;
}