Skip to content

Commit

Permalink
[nfcd] Add access to poll parameters for tags. JB#50041
Browse files Browse the repository at this point in the history
Expose add_data and prot_info to poll parameters and add access to them
throught dbus interface. (org.sailfishos.nfc.Tag)
  • Loading branch information
ikamaletdinov committed Aug 27, 2020
1 parent afa7458 commit 50e6010
Show file tree
Hide file tree
Showing 6 changed files with 505 additions and 7 deletions.
8 changes: 8 additions & 0 deletions core/include/nfc_types.h
@@ -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 @@ -111,6 +112,13 @@ typedef struct nfc_param_poll_a {
typedef struct nfc_param_poll_b {
guint fsc; /* FSC (FSCI converted to bytes) */
GUtilData nfcid0;
/* Since 1.0.40 */
/*
* NFCForum-TS-DigitalProtocol-1.0
* Table 25: SENSB_RES Format
*/
guint8 app_data[4];
GUtilData prot_info;
} NfcParamPollB; /* Since 1.0.20 */

typedef union nfc_param_poll {
Expand Down
24 changes: 19 additions & 5 deletions core/src/nfc_tag.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 @@ -186,6 +187,8 @@ nfc_tag_init_base(
if (poll) {
const gsize aligned_size = G_ALIGN8(sizeof(*poll));
const GUtilData* src;
const NfcParamPollB* poll_b;
guint8* dest;
gsize size;

/*
Expand All @@ -198,21 +201,32 @@ nfc_tag_init_base(
size = src->size ? (aligned_size + src->size) : sizeof(*poll);
*(priv->param = g_malloc0(size)) = *poll;
if (src->bytes) {
guint8* dest = (guint8*)priv->param + aligned_size;
dest = (guint8*)priv->param + aligned_size;

memcpy(dest, src->bytes, src->size);
priv->param->a.nfcid1.bytes = dest;
}
break;
case NFC_TECHNOLOGY_B:
src = &poll->b.nfcid0;
size = src->size ? (aligned_size + src->size) : sizeof(*poll);
poll_b = &poll->b;
if (poll_b->nfcid0.size || poll_b->prot_info.size) {
size = aligned_size + G_ALIGN8(poll_b->nfcid0.size) +
poll_b->prot_info.size;
} else {
size = sizeof(*poll);
}
*(priv->param = g_malloc0(size)) = *poll;
dest = (guint8*)priv->param + aligned_size;
src = &poll_b->nfcid0;
if (src->bytes) {
guint8* dest = (guint8*)priv->param + aligned_size;

memcpy(dest, src->bytes, src->size);
priv->param->b.nfcid0.bytes = dest;
dest += G_ALIGN8(src->size);
}
src = &poll_b->prot_info;
if (src->bytes) {
memcpy(dest, src->bytes, src->size);
priv->param->b.prot_info.bytes = dest;
}
break;
case NFC_TECHNOLOGY_F:
Expand Down
126 changes: 125 additions & 1 deletion plugins/dbus_service/dbus_service_tag.c
@@ -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 @@ -64,6 +65,8 @@ enum {
CALL_DEACTIVATE,
CALL_ACQUIRE,
CALL_RELEASE,
CALL_GET_ALL3,
CALL_GET_POLL_PARAMETERS,
CALL_COUNT
};

Expand Down Expand Up @@ -117,7 +120,7 @@ struct dbus_service_tag {
};

#define NFC_DBUS_TAG_INTERFACE "org.sailfishos.nfc.Tag"
#define NFC_DBUS_TAG_INTERFACE_VERSION (2)
#define NFC_DBUS_TAG_INTERFACE_VERSION (3)

static const char* const dbus_service_tag_default_interfaces[] = {
NFC_DBUS_TAG_INTERFACE, NULL
Expand All @@ -141,6 +144,40 @@ dbus_service_tag_find_waiter(
return NULL;
}

static
GVariant*
dbus_service_tag_dup_data_as_variant(
const void* data,
guint size)
{
return size ?
g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, data, size, 1) :
g_variant_new_from_data(G_VARIANT_TYPE("ay"), NULL, 0, TRUE,
NULL, NULL);
}

static
void
dbus_service_tag_dict_add_value(
GVariantBuilder* builder,
const char* name,
GVariant* value)
{
g_variant_builder_add(builder, "{sv}", name, value);
}

static
void
dbus_service_tag_dict_add_bytes_array(
GVariantBuilder* builder,
const char* name,
const void* data,
guint size)
{
dbus_service_tag_dict_add_value(builder, name,
dbus_service_tag_dup_data_as_variant(data, size));
}

NfcTargetSequence*
dbus_service_tag_sequence(
DBusServiceTag* self,
Expand Down Expand Up @@ -761,6 +798,87 @@ dbus_service_tag_handle_release(
return TRUE;
}

/* Interface Version 3 */

static
GVariant*
dbus_service_tag_get_poll_parameters(
NfcTag* tag,
const NfcParamPoll* poll)
{
GVariantBuilder builder;
g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));

if (G_LIKELY(tag) && G_UNLIKELY(poll)) {
const NfcTarget* target = tag->target;
if (G_LIKELY(target)) {
switch(tag->target->technology) {
case NFC_TECHNOLOGY_B:
dbus_service_tag_dict_add_bytes_array(&builder, "APPDATA",
poll->b.app_data, sizeof(poll->b.app_data));
if (poll->b.prot_info.bytes) {
dbus_service_tag_dict_add_bytes_array(&builder, "PROTINFO",
poll->b.prot_info.bytes, poll->b.prot_info.size);
}
break;
case NFC_TECHNOLOGY_A:
case NFC_TECHNOLOGY_F:
case NFC_TECHNOLOGY_UNKNOWN:
break;
}
}
}
return g_variant_builder_end(&builder);
}

/* GetAll3 */

static
void
dbus_service_tag_complete_get_all3(
GDBusMethodInvocation* call,
DBusServiceTag* self)
{
NfcTag* tag = self->tag;
NfcTarget* target = tag->target;

org_sailfishos_nfc_tag_complete_get_all3(self->iface, call,
NFC_DBUS_TAG_INTERFACE_VERSION, tag->present, target->technology,
target->protocol, tag->type, self->interfaces ? self->interfaces :
dbus_service_tag_default_interfaces,
dbus_service_tag_get_ndef_rec_paths(self),
dbus_service_tag_get_poll_parameters(self->tag,
nfc_tag_param(self->tag)));
}

static
gboolean
dbus_service_tag_handle_get_all3(
OrgSailfishosNfcTag* iface,
GDBusMethodInvocation* call,
DBusServiceTag* self)
{
/* Queue the call if the tag is not initialized yet */
return dbus_service_tag_handle_call(self, call,
dbus_service_tag_complete_get_all3);
}

/* GetPollParameters */

static
gboolean
dbus_service_tag_handle_get_poll_parameters(
OrgSailfishosNfcTag* iface,
GDBusMethodInvocation* call,
DBusServiceTag* self)
{
NfcTag* tag = self->tag;

org_sailfishos_nfc_tag_complete_get_poll_parameters(iface, call,
dbus_service_tag_get_poll_parameters(tag, nfc_tag_param(tag)));
return TRUE;
}

/*==========================================================================*
* Interface
*==========================================================================*/
Expand Down Expand Up @@ -871,6 +989,12 @@ dbus_service_tag_new(
self->call_id[CALL_RELEASE] =
g_signal_connect(self->iface, "handle-release",
G_CALLBACK(dbus_service_tag_handle_release), self);
self->call_id[CALL_GET_ALL3] =
g_signal_connect(self->iface, "handle-get-all3",
G_CALLBACK(dbus_service_tag_handle_get_all3), self);
self->call_id[CALL_GET_POLL_PARAMETERS] =
g_signal_connect(self->iface, "handle-get-poll-parameters",
G_CALLBACK(dbus_service_tag_handle_get_poll_parameters), self);

if (tag->flags & NFC_TAG_FLAG_INITIALIZED) {
dbus_service_tag_export_all(self);
Expand Down
14 changes: 14 additions & 0 deletions plugins/dbus_service/org.sailfishos.nfc.Tag.xml
Expand Up @@ -59,5 +59,19 @@
<arg name="wait" type="b" direction="in"/>
</method>
<method name="Release"/>
<!-- Interface version 3 -->
<method name="GetAll3">
<arg name="version" type="i" direction="out"/>
<arg name="present" type="b" direction="out"/>
<arg name="technology" type="u" direction="out"/>
<arg name="protocol" type="u" direction="out"/>
<arg name="type" type="u" direction="out"/>
<arg name="interfaces" type="as" direction="out"/>
<arg name="ndef_records" type="ao" direction="out"/>
<arg name="parameters" type="a{sv}" direction="out"/>
</method>
<method name="GetPollParameters">
<arg name="parameters" type="a{sv}" direction="out"/>
</method>
</interface>
</node>
65 changes: 65 additions & 0 deletions unit/core_tag/test_core_tag.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 @@ -184,6 +185,10 @@ test_basic_b(
{
static const guint8 nfcid0[] = {0x01, 0x01, 0x02, 0x04};
static const GUtilData nfcid0_data = { TEST_ARRAY_AND_SIZE(nfcid0) };
static const guint8 app_data[] = {0x05, 0x06, 0x07, 0x08};
static const guint8 prot_info[] = {0x09, 0x0A, 0x0B, 0x0C, 0x0D};
static const GUtilData prot_info_data = { TEST_ARRAY_AND_SIZE(prot_info) };
static const guint8 app_data_empty[] = {0x00, 0x00, 0x00, 0x00};

NfcTag* tag = g_object_new(NFC_TYPE_TAG, NULL);
NfcTarget* target = test_target_new_tech(NFC_TECHNOLOGY_B);
Expand All @@ -192,13 +197,20 @@ test_basic_b(

memset(&poll, 0, sizeof(poll));
poll.b.nfcid0 = nfcid0_data;
poll.b.prot_info = prot_info_data;
memcpy(poll.b.app_data, app_data, sizeof(app_data));
nfc_tag_init_base(tag, target, &poll);
g_assert(tag->target == target);
g_assert(tag->present == TRUE);
poll_b = &nfc_tag_param(tag)->b;
g_assert(poll_b);
g_assert(poll_b->nfcid0.bytes != poll.b.nfcid0.bytes);
g_assert(poll_b->prot_info.bytes != poll.b.prot_info.bytes);
g_assert_cmpuint(poll_b->nfcid0.size, == ,sizeof(nfcid0));
g_assert(!memcmp(poll_b->nfcid0.bytes, nfcid0, sizeof(nfcid0)));
g_assert_cmpuint(poll_b->prot_info.size, == ,sizeof(prot_info));
g_assert(!memcmp(poll_b->prot_info.bytes, prot_info, sizeof(prot_info)));
g_assert(!memcmp(poll_b->app_data, app_data, sizeof(app_data)));
nfc_tag_unref(tag);

/* Make sure NULL nfcid0 is handled */
Expand All @@ -211,6 +223,59 @@ test_basic_b(
g_assert(!poll_b->nfcid0.bytes);
nfc_tag_unref(tag);

/* Make sure no prot_info and no app_data is handled */
tag = g_object_new(NFC_TYPE_TAG, NULL);
memset(&poll, 0, sizeof(poll));
poll.b.nfcid0 = nfcid0_data;
nfc_tag_init_base(tag, target, &poll);
g_assert(tag->target == target);
g_assert(tag->present == TRUE);
poll_b = &nfc_tag_param(tag)->b;
g_assert(poll_b);
g_assert_cmpuint(poll_b->nfcid0.size, == ,sizeof(nfcid0));
g_assert(!memcmp(poll_b->nfcid0.bytes, nfcid0, sizeof(nfcid0)));
g_assert_cmpuint(poll_b->prot_info.size, == ,0);
g_assert(!poll_b->prot_info.bytes);
g_assert(!memcmp(poll_b->app_data, app_data_empty, sizeof(app_data_empty)));
nfc_tag_unref(tag);

/* Make sure no app_data is handled properly */
tag = g_object_new(NFC_TYPE_TAG, NULL);
memset(&poll, 0, sizeof(poll));
poll.b.nfcid0 = nfcid0_data;
poll.b.prot_info = prot_info_data;
nfc_tag_init_base(tag, target, &poll);
g_assert(tag->target == target);
g_assert(tag->present == TRUE);
poll_b = &nfc_tag_param(tag)->b;
g_assert(poll_b);
g_assert(poll_b->nfcid0.bytes != poll.b.nfcid0.bytes);
g_assert(poll_b->prot_info.bytes != poll.b.prot_info.bytes);
g_assert_cmpuint(poll_b->nfcid0.size, == ,sizeof(nfcid0));
g_assert(!memcmp(poll_b->nfcid0.bytes, nfcid0, sizeof(nfcid0)));
g_assert_cmpuint(poll_b->prot_info.size, == ,sizeof(prot_info));
g_assert(!memcmp(poll_b->prot_info.bytes, prot_info, sizeof(prot_info)));
g_assert(!memcmp(poll_b->app_data, app_data_empty, sizeof(app_data_empty)));
nfc_tag_unref(tag);

/* Make sure NULL prot_info is handled */
tag = g_object_new(NFC_TYPE_TAG, NULL);
memset(&poll, 0, sizeof(poll));
poll.b.nfcid0 = nfcid0_data;
memcpy(poll.b.app_data, app_data, sizeof(app_data));
nfc_tag_init_base(tag, target, &poll);
g_assert(tag->target == target);
g_assert(tag->present == TRUE);
poll_b = &nfc_tag_param(tag)->b;
g_assert(poll_b);
g_assert(poll_b->nfcid0.bytes != poll.b.nfcid0.bytes);
g_assert_cmpuint(poll_b->nfcid0.size, == ,sizeof(nfcid0));
g_assert(!memcmp(poll_b->nfcid0.bytes, nfcid0, sizeof(nfcid0)));
g_assert_cmpuint(poll_b->prot_info.size, == ,0);
g_assert(!poll_b->prot_info.bytes);
g_assert(!memcmp(poll_b->app_data, app_data, sizeof(app_data)));
nfc_tag_unref(tag);

nfc_target_unref(target);
}

Expand Down

0 comments on commit 50e6010

Please sign in to comment.