Skip to content

Commit

Permalink
Merge branch 'jb51099' into 'master'
Browse files Browse the repository at this point in the history
Expose UID for Tag Type 2 through D-Bus

See merge request mer-core/nfcd!45
  • Loading branch information
monich committed Oct 22, 2020
2 parents 5a9e8dd + ae1ea87 commit b3d1954
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 38 deletions.
3 changes: 2 additions & 1 deletion core/include/nfc_tag_t2.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2018-2019 Jolla Ltd.
* Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of BSD license as follows:
*
Expand Down Expand Up @@ -54,7 +55,7 @@ struct nfc_tag_t2 {
NFC_TAG_T2_FLAGS t2flags;
guint block_size; /* Valid only when initialized */
guint data_size; /* Valid only when initialized */
GUtilData serial; /* Valid only when initialized */
GUtilData serial; /* Same as UID (nfcid1) */
};

GType nfc_tag_t2_get_type();
Expand Down
17 changes: 7 additions & 10 deletions core/src/nfc_tag_t2.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of BSD license as follows:
*
Expand Down Expand Up @@ -114,7 +115,6 @@ struct nfc_tag_t2_priv {
GHashTable* reads;
GHashTable* writes;
GByteArray* cached_blocks;
guint8 serial[4];
guint sector_count;
NfcTagType2Sector* sectors;
guint init_id;
Expand Down Expand Up @@ -902,22 +902,17 @@ nfc_tag_t2_control_area_read_resp(
priv->init_id = 0;
if (status == NFC_TRANSMIT_STATUS_OK && len == 16) {
const guint8* bytes = data;
const guint8* serial = bytes + 4;
const guint8* cc = bytes + 12;

/*
* Layout of the first 4 blocks accorting to NFCForum-TS-Type-2-Tag:
*
* Bytes 0..3 - UID / Internal
* Bytes 4..7 - Serial Number
* Bytes 8..11 - Internal / Lock
* Bytes 0..9 - UID / Internal
* Bytes 10..11 - Lock
* Bytes 12..15 - Capability Container (CC)
*/
memcpy(priv->serial, serial, 4);
self->serial.bytes = priv->serial;
self->serial.size = 4;
GDEBUG("Serial: %02x %02x %02x %02x", priv->serial[0],
priv->serial[1], priv->serial[2], priv->serial[3]);
GDEBUG("Internal data:");
nfc_hexdump(bytes, 10);

if (cc[0] == NFC_TAG_T2_CC_NFC_FORUM_MAGIC &&
cc[1] >= NFC_TAG_T2_CC_MIN_VERSION) {
Expand Down Expand Up @@ -970,6 +965,8 @@ nfc_tag_t2_init2(
nfc_tag_init_base(tag, target, &poll);
/* nfc_tag_init_base has copied nfcid1 to the internal storage */
self->nfcid1 = nfc_tag_param(tag)->a.nfcid1;
/* serial is same as nfcid1 */
self->serial = nfc_tag_param(tag)->a.nfcid1;
self->sel_res = poll_a->sel_res;
} else {
nfc_tag_init_base(tag, target, NULL);
Expand Down
22 changes: 19 additions & 3 deletions plugins/dbus_service/dbus_service_tag.c
Expand Up @@ -786,17 +786,33 @@ dbus_service_tag_get_poll_parameters(

if (G_LIKELY(tag) && G_UNLIKELY(poll)) {
const NfcTarget* target = tag->target;
const NfcParamPollA* poll_a = NULL;
const NfcParamPollB* poll_b = NULL;

if (G_LIKELY(target)) {
switch(tag->target->technology) {
case NFC_TECHNOLOGY_B:
poll_b = &poll->b;
dbus_service_dict_add_byte_array(&builder, "APPDATA",
poll->b.app_data, sizeof(poll->b.app_data));
if (poll->b.prot_info.bytes) {
poll_b->app_data, sizeof(poll_b->app_data));
if (poll_b->prot_info.bytes) {
dbus_service_dict_add_byte_array_data(&builder, "PROTINFO",
&poll->b.prot_info);
&poll_b->prot_info);
}
if (poll_b->nfcid0.bytes) {
dbus_service_dict_add_byte_array_data(&builder, "NFCID0",
&poll_b->nfcid0);
}
break;
case NFC_TECHNOLOGY_A:
poll_a = &poll->a;
dbus_service_dict_add_byte(&builder, "SEL_RES",
poll_a->sel_res);
if (poll_a->nfcid1.bytes) {
dbus_service_dict_add_byte_array_data(&builder, "NFCID1",
&poll_a->nfcid1);
}
break;
case NFC_TECHNOLOGY_F:
case NFC_TECHNOLOGY_UNKNOWN:
break;
Expand Down
29 changes: 7 additions & 22 deletions unit/core_tag_t2/test_core_tag_t2.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2018-2020 Jolla Ltd.
* Copyright (C) 2018-2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of BSD license as follows:
*
Expand Down Expand Up @@ -233,7 +234,7 @@ static const guint8 test_data_jolla[] = { /* "https://www.jolla.com" */
};

/*
* Serial: 9a 85 5c 80
* UID: 04 ea 3d 9a 85 5c 80
* Data size: 872 bytes
*/
static const guint8 test_data_ntag216[] = { /* "https://www.merproject.org" */
Expand Down Expand Up @@ -684,11 +685,8 @@ test_basic_exit(
void* user_data)
{
NfcTagType2* t2 = NFC_TAG_T2(tag);
GUtilData serial;

serial.bytes = test_data_empty + 4;
serial.size = 4;
g_assert(gutil_data_equal(&t2->serial, &serial));
g_assert(gutil_data_equal(&t2->serial, &t2->nfcid1));
g_main_loop_quit((GMainLoop*)user_data);
}

Expand Down Expand Up @@ -747,15 +745,10 @@ test_unsup_done(
void* user_data)
{
NfcTagType2* t2 = NFC_TAG_T2(tag);
TestTarget* test = TEST_TARGET(tag->target);
GUtilData serial;

g_assert(tag->flags & NFC_TAG_FLAG_INITIALIZED);

/* Serial should be there */
serial.bytes = test->storage + 4;
serial.size = 4;
g_assert(gutil_data_equal(&t2->serial, &serial));
g_assert(gutil_data_equal(&t2->serial, &t2->nfcid1));

/* But no NDEF and no size */
g_assert(!tag->ndef);
Expand Down Expand Up @@ -796,7 +789,7 @@ test_init_err1_done(
NfcTagType2* t2 = NFC_TAG_T2(tag);

g_assert(tag->flags & NFC_TAG_FLAG_INITIALIZED);
g_assert(!t2->serial.size);
g_assert(gutil_data_equal(&t2->serial, &t2->nfcid1));
g_assert(!t2->data_size);
g_assert(!tag->ndef);
g_main_loop_quit((GMainLoop*)user_data);
Expand Down Expand Up @@ -838,16 +831,11 @@ test_init_err2_done(
void* user_data)
{
NfcTagType2* t2 = NFC_TAG_T2(tag);
TestTarget* test = TEST_TARGET(tag->target);
GUtilData serial;

g_assert(tag->flags & NFC_TAG_FLAG_INITIALIZED);
g_assert(t2->data_size);

/* Serial should be there */
serial.bytes = test->storage + 4;
serial.size = 4;
g_assert(gutil_data_equal(&t2->serial, &serial));
g_assert(gutil_data_equal(&t2->serial, &t2->nfcid1));

/* But no NDEF */
g_assert(!tag->ndef);
Expand Down Expand Up @@ -909,12 +897,9 @@ test_read_data_start(
TestTarget* test = TEST_TARGET(tag->target);
NfcTagType2* t2 = NFC_TAG_T2(tag);
NfcNdefRec* rec = tag->ndef;
GUtilData serial;
guint8* buf;

serial.bytes = test_data_google + 4;
serial.size = 4;
g_assert(gutil_data_equal(&t2->serial, &serial));
g_assert(gutil_data_equal(&t2->serial, &t2->nfcid1));
g_assert(t2->data_size == test->data.size - TEST_DATA_OFFSET);

g_assert(rec);
Expand Down
137 changes: 135 additions & 2 deletions unit/plugins_dbus_service_tag/test_plugins_dbus_service_tag.c
Expand Up @@ -1887,14 +1887,22 @@ test_get_all3_tag_b_done(
g_assert(ifaces);
g_assert(records);
g_assert(prot_params);
g_assert(2 == g_variant_iter_init (&iter, prot_params));
g_assert_cmpuint(g_variant_iter_init(&iter, prot_params), ==, 3);
GDEBUG("version=%d, present=%d, tech=%u, protocol=%u, type=%u, "
"%u interface(s), %u record(s)", version, present, tech, protocol,
type, g_strv_length(ifaces), g_strv_length(records));
while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) {
GDEBUG("Item '%s' has type '%s'\n", key,
g_variant_get_type_string (value));
g_assert(!g_strcmp0(key, "PROTINFO") || !g_strcmp0(key, "APPDATA"));
g_assert(!g_strcmp0(key, "PROTINFO") || !g_strcmp0(key, "APPDATA") ||
!g_strcmp0(key, "NFCID0"));

if (!g_strcmp0(key, "NFCID0")) {
value_ptr = (guint8*)g_variant_get_data(value);
g_assert(value_ptr);
g_assert(sizeof(nfcid0) == g_variant_get_size(value));
g_assert(!memcmp(value_ptr, nfcid0, sizeof(nfcid0)));
}

if (!g_strcmp0(key, "PROTINFO")) {
value_ptr = (guint8*)g_variant_get_data(value);
Expand Down Expand Up @@ -1951,6 +1959,130 @@ test_get_all3_tag_b(
test_dbus_free(dbus);
}

/*==========================================================================*
* get_all3_tag_a
*==========================================================================*/

static const guint8 nfcid1[] = {0x01, 0x01, 0x02, 0x04};
static const GUtilData nfcid1_data = { TEST_ARRAY_AND_SIZE(nfcid1) };

static
void
test_data_init_tag_a(
TestData* test)
{
NfcPluginsInfo pi;
NfcTarget* target;
NfcParamPoll poll;

g_assert(!test_name_watches);
memset(test, 0, sizeof(*test));
memset(&pi, 0, sizeof(pi));
g_assert((test->manager = nfc_manager_new(&pi)) != NULL);
g_assert((test->adapter = test_adapter_new()) != NULL);

target = test_target_new_tech(NFC_TECHNOLOGY_A);
memset(&poll, 0, sizeof(poll));
poll.a.sel_res = 1;
poll.a.nfcid1 = nfcid1_data;
g_assert(nfc_adapter_add_other_tag2(test->adapter, target, &poll));
nfc_target_unref(target);

g_assert(nfc_manager_add_adapter(test->manager, test->adapter));
test->loop = g_main_loop_new(NULL, TRUE);
test->pool = gutil_idle_pool_new();
}

static
void
test_get_all3_tag_a_done(
GObject* object,
GAsyncResult* result,
gpointer user_data)
{
TestData* test = user_data;
gint version = 0;
gboolean present = FALSE;
guint tech, protocol, type;
gchar** ifaces = NULL;
gchar** records = NULL;
GVariant* prot_params = NULL;
GVariantIter iter;
GVariant* value = NULL;
gchar* key = NULL;
const guint8* value_ptr = NULL;
GVariant* var = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object),
result, NULL);

g_assert(var);
g_variant_get(var, "(ibuuu^as^ao@a{sv})", &version, &present, &tech,
&protocol, &type, &ifaces, &records, &prot_params);
g_assert(ifaces);
g_assert(records);
g_assert(prot_params);
g_assert_cmpuint(g_variant_iter_init(&iter, prot_params), ==, 2);
GDEBUG("version=%d, present=%d, tech=%u, protocol=%u, type=%u, "
"%u interface(s), %u record(s)", version, present, tech, protocol,
type, g_strv_length(ifaces), g_strv_length(records));
while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) {
GDEBUG("Item '%s' has type '%s'\n", key,
g_variant_get_type_string (value));
g_assert(!g_strcmp0(key, "SEL_RES") || !g_strcmp0(key, "NFCID1"));

if (!g_strcmp0(key, "SEL_RES")) {
guint8 sel_res_value = g_variant_get_byte(value);
g_assert(sel_res_value);
g_assert(sel_res_value == 1);
}

if (!g_strcmp0(key, "NFCID1")) {
value_ptr = (guint8*)g_variant_get_data(value);
g_assert(value_ptr);
g_assert(sizeof(nfcid1) == g_variant_get_size(value));
g_assert(!memcmp(value_ptr, nfcid1, sizeof(nfcid1)));
}
}
g_assert(version >= MIN_INTERFACE_VERSION);
g_assert(present);
g_assert(tech == NFC_TECHNOLOGY_A);
g_assert(protocol == NFC_PROTOCOL_UNKNOWN);
g_assert(g_strv_length(records) == 0);
g_strfreev(ifaces);
g_strfreev(records);
g_variant_unref(prot_params);
g_variant_unref(var);
test_quit_later(test->loop);
}

static
void
test_get_all3_tag_a_start(
GDBusConnection* client,
GDBusConnection* server,
void* user_data)
{
TestData* test = user_data;

nfc_tag_set_initialized(test->adapter->tags[0]);
test_start_and_get(test, client, server, "GetAll3",
test_get_all3_tag_a_done);
}

static
void
test_get_all3_tag_a(
void)
{
TestData test;
TestDBus* dbus;

test_data_init_tag_a(&test);
dbus = test_dbus_new(test_get_all3_tag_a_start, &test);
test_run(&test_opt, test.loop);
test_data_cleanup(&test);
test_dbus_free(dbus);
}

/*==========================================================================*
* transceive_ok
*==========================================================================*/
Expand Down Expand Up @@ -2131,6 +2263,7 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("get_all3"), test_get_all3);
g_test_add_func(TEST_("get_poll_parameters"), test_get_poll_parameters);
g_test_add_func(TEST_("get_all3_tag_b"), test_get_all3_tag_b);
g_test_add_func(TEST_("get_all3_tag_a"), test_get_all3_tag_a);
g_test_add_func(TEST_("transceive/ok"), test_transceive_ok);
g_test_add_func(TEST_("transceive/error1"), test_transceive_error1);
g_test_add_func(TEST_("transceive/error2"), test_transceive_error2);
Expand Down

0 comments on commit b3d1954

Please sign in to comment.