Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'jb51200' into 'master'
Add Reset function to ISO-DEP interface

See merge request mer-core/nfcd!43
  • Loading branch information
monich committed Oct 12, 2020
2 parents 16fc688 + 1d30324 commit de3dea8
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 9 deletions.
15 changes: 15 additions & 0 deletions core/include/nfc_tag_t4.h
Expand Up @@ -126,6 +126,13 @@ void
guint len,
void* user_data);

typedef
void
(*NfcTagType4ResetRespFunc)(
NfcTagType4* tag,
gboolean ok,
void* user_data);

guint
nfc_isodep_transmit(
NfcTagType4* tag,
Expand All @@ -140,6 +147,14 @@ nfc_isodep_transmit(
GDestroyNotify destroy,
void* user_data);

gboolean
nfc_isodep_reset(
NfcTagType4* tag,
NfcTargetSequence* seq,
NfcTagType4ResetRespFunc resp,
GDestroyNotify destroy,
void* user_data); /* Since 1.0.44 */

G_END_DECLS

#endif /* NFC_TAG_T4_H */
Expand Down
84 changes: 83 additions & 1 deletion core/src/nfc_tag_t4.c
Expand Up @@ -66,6 +66,13 @@ struct nfc_tag_t4_priv {
NfcParamIsoDep* iso_dep; /* Since 1.0.39 */
};

typedef struct nfc_isodep_reset_data {
NfcTagType4* t4;
NfcTagType4ResetRespFunc resp;
GDestroyNotify destroy;
void* user_data;
} NfcIsoDepResetData;

G_DEFINE_ABSTRACT_TYPE(NfcTagType4, nfc_tag_t4, NFC_TYPE_TAG)

/*
Expand Down Expand Up @@ -419,7 +426,7 @@ nfc_tag_t4_ndef_read_done(
*/
GDEBUG("Reactivating Type 4 tag");
if (!nfc_target_reactivate(self->tag.target, priv->init_seq,
nfc_tag_t4_init_done, self)) {
nfc_tag_t4_init_done, NULL, self)) {
GDEBUG("Oops. Failed to reactivate, leaving the tag as is");
nfc_tag_t4_initialized(self);
}
Expand Down Expand Up @@ -680,6 +687,44 @@ nfc_tag_t4_init_select_ndef_app_resp(
nfc_tag_t4_initialized(self);
}

static
void
nfc_tag_t4_reset_data_free(
NfcIsoDepResetData* rst)
{
GDestroyNotify destroy = rst->destroy;

if (destroy) {
rst->destroy = NULL;
destroy(rst->user_data);
}
g_slice_free1(sizeof(*rst), rst);
}

static
void
nfc_tag_t4_reset_data_free1(
void* data)
{
nfc_tag_t4_reset_data_free((NfcIsoDepResetData*)data);
}

static
void
nfc_tag_t4_reset_data_resp(
NfcTarget* target,
NFC_REACTIVATE_STATUS status,
void* user_data)
{
NfcIsoDepResetData* rst = user_data;

if (rst->resp) {
/* Result is FALSE in case of tag was gone or reactivation timed out */
rst->resp(rst->t4, status == NFC_REACTIVATE_STATUS_SUCCESS,
rst->user_data);
}
}

/*==========================================================================*
* Internal interface
*==========================================================================*/
Expand Down Expand Up @@ -793,6 +838,43 @@ nfc_isodep_transmit(
data, le, seq, resp, destroy, user_data) : 0;
}

gboolean
nfc_isodep_reset(
NfcTagType4* self,
NfcTargetSequence* seq,
NfcTagType4ResetRespFunc resp,
GDestroyNotify destroy,
void* user_data) /* Since 1.0.44 */
{
if (G_LIKELY(self)) {
NfcTag* tag = &self->tag;

if (G_LIKELY(tag) && nfc_target_can_reactivate(tag->target)) {
NfcIsoDepResetData* rst = g_slice_new0(NfcIsoDepResetData);

rst->t4 = self;
rst->resp = resp;
rst->destroy = destroy;
rst->user_data = user_data;

if (nfc_target_reactivate(tag->target, seq, resp ?
nfc_tag_t4_reset_data_resp : NULL, nfc_tag_t4_reset_data_free1,
rst)) {
return TRUE;
} else {
/*
* Should never get here, 'cause nfc_target_reactivate() will
* always return TRUE in case if nfc_target_can_reactivate()
* succeeds.
*/
rst->destroy = NULL;
nfc_tag_t4_reset_data_free(rst);
}
}
}
return FALSE;
}

/*==========================================================================*
* Internals
*==========================================================================*/
Expand Down
4 changes: 3 additions & 1 deletion core/src/nfc_target.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 @@ -954,6 +955,7 @@ nfc_target_reactivate(
NfcTarget* self,
NfcTargetSequence* seq,
NfcTargetReactivateFunc func,
GDestroyNotify destroy,
void* user_data)
{
if (G_LIKELY(self)) {
Expand All @@ -962,7 +964,7 @@ nfc_target_reactivate(

if (!priv->reactivating && klass->reactivate) {
NfcTargetRequest* req = nfc_target_reactivate_request_new(self,
seq, func, NULL, user_data);
seq, func, destroy, user_data);

nfc_target_transmit_queue_req(&priv->req_queue, req);
nfc_target_submit_next_request(self);
Expand Down
2 changes: 2 additions & 0 deletions core/src/nfc_target_p.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 @@ -65,6 +66,7 @@ nfc_target_reactivate(
NfcTarget* target,
NfcTargetSequence* seq,
NfcTargetReactivateFunc func,
GDestroyNotify destroy,
void* user_data)
NFCD_INTERNAL;

Expand Down
52 changes: 51 additions & 1 deletion plugins/dbus_service/dbus_service_isodep.c
Expand Up @@ -46,6 +46,7 @@ enum {
CALL_TRANSMIT,
CALL_GET_ALL2,
CALL_GET_ACTIVATION_PARAMETERS,
CALL_RESET,
CALL_COUNT
};

Expand All @@ -56,7 +57,7 @@ struct dbus_service_isodep {
gulong call_id[CALL_COUNT];
};

#define NFC_DBUS_ISODEP_INTERFACE_VERSION (2)
#define NFC_DBUS_ISODEP_INTERFACE_VERSION (3)

typedef struct dbus_service_isodep_async_call {
OrgSailfishosNfcIsoDep* iface;
Expand Down Expand Up @@ -273,6 +274,52 @@ dbus_service_isodep_handle_get_act_parameters(
return TRUE;
}

/* Interface version 3 */

/* Reset*/

static
void
dbus_service_isodep_handle_reset_done(
NfcTagType4* tag,
gboolean ok,
void* user_data)
{
DBusServiceIsoDepAsyncCall* async = user_data;

GDEBUG("ISO-DEP reset %s", ok ? "succeeded" : "failed");

if (ok) {
org_sailfishos_nfc_iso_dep_complete_reset(async->iface, async->call);
} else {
GDEBUG("oops");
g_dbus_method_invocation_return_error_literal(async->call,
DBUS_SERVICE_ERROR, DBUS_SERVICE_ERROR_FAILED,
"ISO-DEP reset failed");
}
}

static
gboolean
dbus_service_isodep_handle_reset(
OrgSailfishosNfcIsoDep* iface,
GDBusMethodInvocation* call,
DBusServiceIsoDep* self)
{
DBusServiceIsoDepAsyncCall* async =
dbus_service_isodep_async_call_new(iface, call);

if (!nfc_isodep_reset(self->t4, dbus_service_isodep_sequence(self, call),
dbus_service_isodep_handle_reset_done,
dbus_service_isodep_async_call_free1, async)) {
dbus_service_isodep_async_call_free(async);
g_dbus_method_invocation_return_error_literal(call,
DBUS_SERVICE_ERROR, DBUS_SERVICE_ERROR_FAILED,
"Failed to submit Reset");
}
return TRUE;
}

/*==========================================================================*
* Interface
*==========================================================================*/
Expand Down Expand Up @@ -319,6 +366,9 @@ dbus_service_isodep_new(
self->call_id[CALL_GET_ACTIVATION_PARAMETERS] =
g_signal_connect(self->iface, "handle-get-activation-parameters",
G_CALLBACK(dbus_service_isodep_handle_get_act_parameters), self);
self->call_id[CALL_RESET] =
g_signal_connect(self->iface, "handle-reset",
G_CALLBACK(dbus_service_isodep_handle_reset), self);

if (g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON
(self->iface), connection, path, &error)) {
Expand Down
2 changes: 2 additions & 0 deletions plugins/dbus_service/org.sailfishos.nfc.IsoDep.xml
Expand Up @@ -46,5 +46,7 @@
<method name="GetActivationParameters">
<arg name="parameters" type="a{sv}" direction="out"/>
</method>
<!-- Interface version 3 -->
<method name="Reset"/>
</interface>
</node>
82 changes: 82 additions & 0 deletions unit/core_tag_t4/test_core_tag_t4.c
Expand Up @@ -175,6 +175,8 @@ static const guint8 test_resp_read_ndef_2[] = {
0x73, 0x74, 0x20, 0x74, 0x65, 0x73, 0x74, /* Data */
0x90, 0x00 /* SW1|SW2 */
};
static gint reset_count = 0;
static gint reset_free_count = 0;

static
void
Expand All @@ -185,6 +187,28 @@ test_tag_quit_loop_cb(
g_main_loop_quit((GMainLoop*)user_data);
}

static
void
test_tag_reset_cb(
NfcTagType4* t4,
gboolean ok,
void* user_data)
{
g_assert(ok);
g_assert(user_data);
++reset_count;
test_tag_quit_loop_cb(&t4->tag, user_data);
}

static
void
test_tag_reset_free1(
void* user_data)
{
g_assert(user_data);
++reset_free_count;
}

/*==========================================================================*
* Test target with reactivate
*==========================================================================*/
Expand Down Expand Up @@ -280,6 +304,7 @@ test_null(
g_assert(!nfc_tag_t4b_new(target, NULL, NULL));
g_assert(!nfc_isodep_transmit(NULL, 0, 0, 0, 0, NULL, 0,
NULL, NULL, NULL, NULL));
g_assert(!nfc_isodep_reset(NULL, NULL, NULL, NULL, NULL));
nfc_target_unref(target);
}

Expand Down Expand Up @@ -398,6 +423,62 @@ test_basic_b(
g_main_loop_unref(loop);
}

static
void
test_basic_reset(
void)
{
GMainLoop* loop = g_main_loop_new(NULL, TRUE);

TestTarget2* test = g_object_new(TEST_TYPE_TARGET2, NULL);
NfcTarget* target = NFC_TARGET(test);

NfcParamIsoDepPollA iso_dep_poll_a;
NfcTagType4* t4a;
NfcTag* tag;

memset(&iso_dep_poll_a, 0, sizeof(iso_dep_poll_a));
iso_dep_poll_a.fsc = 256;
target->technology = NFC_TECHNOLOGY_A;
t4a = NFC_TAG_T4(nfc_tag_t4a_new(target, NULL, &iso_dep_poll_a));
g_assert(NFC_IS_TAG_T4A(t4a));
tag = &t4a->tag;

/* If the target supports reactivation, tag doesn't get initialized
* right away (and obviously there won't be any NDEF) */
g_assert(!(tag->flags & NFC_TAG_FLAG_INITIALIZED));
g_assert(!tag->ndef);

const gulong id = nfc_tag_add_initialized_handler(tag,
test_tag_quit_loop_cb, loop);

test_run(&test_opt, loop);
nfc_tag_remove_handler(tag, id);


/* Now it must be initialized */
g_assert(tag->flags & NFC_TAG_FLAG_INITIALIZED);

/* Now try to reset */
reset_count = 0;
reset_free_count = 0;
g_assert(nfc_isodep_reset(t4a, NULL, test_tag_reset_cb,
test_tag_reset_free1, loop));
/* Can't be scheduled second time */
g_assert(!nfc_isodep_reset(t4a, NULL, test_tag_reset_cb,
test_tag_reset_free1, loop));

test_run(&test_opt, loop);
g_assert(reset_count == 1);
g_assert(reset_free_count == 1);

/* Now must be still initialized */
g_assert(tag->flags & NFC_TAG_FLAG_INITIALIZED);

nfc_tag_unref(tag);
nfc_target_unref(target);
g_main_loop_unref(loop);
}

/*==========================================================================*
* init_seq
Expand Down Expand Up @@ -1383,6 +1464,7 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("basic"), test_basic);
g_test_add_func(TEST_("basic_a"), test_basic_a);
g_test_add_func(TEST_("basic_b"), test_basic_b);
g_test_add_func(TEST_("basic_reset"), test_basic_reset);
for (i = 0; i < G_N_ELEMENTS(init_tests); i++) {
const TestInitData* test = init_tests + i;
char* path = g_strconcat(TEST_("init_seq/"), test->name, NULL);
Expand Down

0 comments on commit de3dea8

Please sign in to comment.