Commit 5b702eba authored by Slava Monich's avatar Slava Monich

[core] Expose LLCP version and the list of P2P services. JB#53077

Plugins will need those in order to build the list of LLCP options
exchanged during the link activation.

Also added the following functions:

  nfc_manager_add_service_registered_handler()
  nfc_manager_add_service_unregistered_handler()

to track changes in the service list.
parent 2f8657c7
......@@ -50,6 +50,9 @@ struct nfc_manager {
int error;
/* Since 1.1.0 */
NFC_MODE mode;
/* Since 1.1.1 */
NFC_LLCP_VERSION llcp_version;
NfcPeerService* const* services;
};
GType nfc_manager_get_type() NFCD_EXPORT;
......@@ -73,6 +76,13 @@ void
NfcAdapter* adapter,
void* user_data);
typedef
void
(*NfcManagerServiceFunc)(
NfcManager* manager,
NfcPeerService* service,
void* user_data);
NfcManager*
nfc_manager_ref(
NfcManager* manager)
......@@ -157,6 +167,13 @@ nfc_manager_add_enabled_changed_handler(
void* user_data)
NFCD_EXPORT;
gulong
nfc_manager_add_stopped_handler(
NfcManager* manager,
NfcManagerFunc func,
void* user_data)
NFCD_EXPORT;
gulong
nfc_manager_add_mode_changed_handler(
NfcManager* manager,
......@@ -165,10 +182,17 @@ nfc_manager_add_mode_changed_handler(
NFCD_EXPORT;
gulong
nfc_manager_add_stopped_handler(
nfc_manager_add_service_registered_handler(
NfcManager* manager,
NfcManagerFunc func,
void* user_data)
NfcManagerServiceFunc func,
void* user_data) /* Since 1.1.1 */
NFCD_EXPORT;
gulong
nfc_manager_add_service_unregistered_handler(
NfcManager* manager,
NfcManagerServiceFunc func,
void* user_data) /* Since 1.1.1 */
NFCD_EXPORT;
void
......
......@@ -123,6 +123,12 @@ typedef enum nfc_peer_connect_result {
NFC_PEER_CONNECT_FAILED /* I/O or protocol error */
} NFC_PEER_CONNECT_RESULT;
typedef enum nfc_llcp_version {
NFC_LLCP_VERSION_1_0 = 0x10,
NFC_LLCP_VERSION_1_1 = 0x11,
NFC_LLCP_VERSION_1_2 = 0x12
} NFC_LLCP_VERSION; /* Since 1.1.1 */
/* RF technology specific parameters */
typedef struct nfc_param_poll_a {
......
/*
* Copyright (C) 2020 Jolla Ltd.
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020-2021 Jolla Ltd.
* Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
......@@ -42,9 +42,6 @@
#define NFC_LLC_RW_DEFAULT (1)
#define NFC_LLC_RW_MAX (0xf)
#define NFC_LLCP_VERSION_1_0 (0x10) /* LLCP 1.0 */
#define NFC_LLCP_VERSION_1_1 (0x11) /* LLCP 1.1 */
typedef enum nfc_llc_param_type {
NFC_LLC_PARAM_VERSION = 1,
NFC_LLC_PARAM_MIUX = 2,
......
......@@ -35,6 +35,7 @@
#include "nfc_manager_p.h"
#include "internal/nfc_manager_i.h"
#include "nfc_adapter_p.h"
#include "nfc_peer_service.h"
#include "nfc_peer_services.h"
#include "nfc_plugins.h"
#include "nfc_log.h"
......@@ -72,17 +73,21 @@ G_DEFINE_TYPE(NfcManager, nfc_manager, G_TYPE_OBJECT)
enum nfc_manager_signal {
SIGNAL_ADAPTER_ADDED,
SIGNAL_ADAPTER_REMOVED,
SIGNAL_SERVICE_REGISTERED,
SIGNAL_SERVICE_UNREGISTERED,
SIGNAL_ENABLED_CHANGED,
SIGNAL_MODE_CHANGED,
SIGNAL_STOPPED,
SIGNAL_COUNT
};
#define SIGNAL_ADAPTER_ADDED_NAME "nfc-manager-adapter-added"
#define SIGNAL_ADAPTER_REMOVED_NAME "nfc-manager-adapter-removed"
#define SIGNAL_ENABLED_CHANGED_NAME "nfc-manager-enabled-changed"
#define SIGNAL_MODE_CHANGED_NAME "nfc-manager-mode-changed"
#define SIGNAL_STOPPED_NAME "nfc-manager-stopped"
#define SIGNAL_ADAPTER_ADDED_NAME "nfc-manager-adapter-added"
#define SIGNAL_ADAPTER_REMOVED_NAME "nfc-manager-adapter-removed"
#define SIGNAL_SERVICE_REGISTERED_NAME "nfc-manager-service-registered"
#define SIGNAL_SERVICE_UNREGISTERED_NAME "nfc-manager-service-unregistered"
#define SIGNAL_ENABLED_CHANGED_NAME "nfc-manager-enabled-changed"
#define SIGNAL_MODE_CHANGED_NAME "nfc-manager-mode-changed"
#define SIGNAL_STOPPED_NAME "nfc-manager-stopped"
static guint nfc_manager_signals[SIGNAL_COUNT] = { 0 };
......@@ -468,10 +473,15 @@ nfc_manager_register_service(
NfcManagerPriv* priv = self->priv;
if (nfc_peer_services_add(priv->services, service)) {
nfc_peer_service_ref(service);
self->services = priv->services->list;
if (!priv->p2p_request) {
priv->p2p_request = nfc_manager_mode_request_new_internal(self,
TRUE, NFC_MODES_P2P, NFC_MODE_NONE);
}
g_signal_emit(self, nfc_manager_signals
[SIGNAL_SERVICE_REGISTERED], 0, service);
nfc_peer_service_unref(service);
return TRUE;
}
}
......@@ -486,10 +496,16 @@ nfc_manager_unregister_service(
if (G_LIKELY(self)) {
NfcManagerPriv* priv = self->priv;
nfc_peer_services_remove(priv->services, service);
if (!priv->services->list[0]) {
nfc_manager_release_p2p_mode_request(self);
nfc_peer_service_ref(service);
if (nfc_peer_services_remove(priv->services, service)) {
self->services = priv->services->list;
if (!priv->services->list[0]) {
nfc_manager_release_p2p_mode_request(self);
}
g_signal_emit(self, nfc_manager_signals
[SIGNAL_SERVICE_UNREGISTERED], 0, service);
}
nfc_peer_service_unref(service);
}
}
......@@ -533,6 +549,26 @@ nfc_manager_add_mode_changed_handler(
SIGNAL_MODE_CHANGED_NAME, G_CALLBACK(func), user_data) : 0;
}
gulong
nfc_manager_add_service_registered_handler(
NfcManager* self,
NfcManagerServiceFunc func,
void* user_data) /* Since 1.1.1 */
{
return (G_LIKELY(self) && G_LIKELY(func)) ? g_signal_connect(self,
SIGNAL_SERVICE_REGISTERED_NAME, G_CALLBACK(func), user_data) : 0;
}
gulong
nfc_manager_add_service_unregistered_handler(
NfcManager* self,
NfcManagerServiceFunc func,
void* user_data) /* Since 1.1.1 */
{
return (G_LIKELY(self) && G_LIKELY(func)) ? g_signal_connect(self,
SIGNAL_SERVICE_UNREGISTERED_NAME, G_CALLBACK(func), user_data) : 0;
}
gulong
nfc_manager_add_stopped_handler(
NfcManager* self,
......@@ -621,13 +657,15 @@ nfc_manager_init(
NfcManagerPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NFC_TYPE_MANAGER,
NfcManagerPriv);
priv->services = nfc_peer_services_new();
priv->adapters = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_object_unref);
self->priv = priv;
self->adapters = g_new0(NfcAdapter*, 1);
self->enabled = TRUE;
self->mode = priv->default_mode = NFC_MODE_READER_WRITER;
priv->services = nfc_peer_services_new();
priv->adapters = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_object_unref);
self->llcp_version = NFC_LLCP_VERSION_1_1;
self->services = priv->services->list;
}
static
......@@ -663,6 +701,12 @@ nfc_manager_class_init(
nfc_manager_signals[SIGNAL_ADAPTER_REMOVED] =
g_signal_new(SIGNAL_ADAPTER_REMOVED_NAME, type, G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT);
nfc_manager_signals[SIGNAL_SERVICE_REGISTERED] =
g_signal_new(SIGNAL_SERVICE_REGISTERED_NAME, type, G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT);
nfc_manager_signals[SIGNAL_SERVICE_UNREGISTERED] =
g_signal_new(SIGNAL_SERVICE_UNREGISTERED_NAME, type, G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_OBJECT);
nfc_manager_signals[SIGNAL_ENABLED_CHANGED] =
g_signal_new(SIGNAL_ENABLED_CHANGED_NAME, type, G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
......
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_service.h"
#include "nfc_peer_service_impl.h"
typedef NfcPeerServiceClass TestServiceClass;
G_DEFINE_TYPE(TestService, test_service, NFC_TYPE_PEER_SERVICE)
static
void
test_service_peer_arrived(
NfcPeerService* service,
NfcPeer* peer)
{
TEST_SERVICE(service)->peer_arrived++;
NFC_PEER_SERVICE_CLASS(test_service_parent_class)->
peer_arrived(service, peer);
}
static
void
test_service_peer_left(
NfcPeerService* service,
NfcPeer* peer)
{
TEST_SERVICE(service)->peer_left++;
NFC_PEER_SERVICE_CLASS(test_service_parent_class)->
peer_left(service, peer);
}
static
void
test_service_init(
TestService* self)
{
}
static
void
test_service_class_init(
TestServiceClass* klass)
{
klass->peer_arrived = test_service_peer_arrived;
klass->peer_left = test_service_peer_left;
}
TestService*
test_service_new(
const char* name)
{
TestService* test = g_object_new(TEST_TYPE_SERVICE, NULL);
nfc_peer_service_init_base(&test->service, name);
return test;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/
/*
* Copyright (C) 2021 Jolla Ltd.
* Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TEST_SERVICE_H
#define TEST_SERVICE_H
#include <nfc_types_p.h>
#include <nfc_peer_service_impl.h>
typedef struct test_service {
NfcPeerService service;
int peer_arrived;
int peer_left;
} TestService;
GType test_service_get_type(void);
#define TEST_TYPE_SERVICE (test_service_get_type())
#define TEST_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, \
TEST_TYPE_SERVICE, TestService))
TestService*
test_service_new(
const char* name);
#endif /* TEST_SERVICE_H */
/*
* Local Variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/
......@@ -2,4 +2,6 @@
EXE = test_core_manager
COMMON_SRC = test_main.c test_service.c
include ../common/Makefile
......@@ -30,12 +30,13 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_service.h"
#include "test_common.h"
#include "nfc_manager_p.h"
#include "internal/nfc_manager_i.h"
#include "nfc_adapter_impl.h"
#include "test_common.h"
#include <gutil_log.h>
static TestOpt test_opt;
......@@ -182,6 +183,8 @@ test_null(
g_assert(!nfc_manager_add_adapter(NULL, NULL));
g_assert(!nfc_manager_add_adapter_added_handler(NULL, NULL, NULL));
g_assert(!nfc_manager_add_adapter_removed_handler(NULL, NULL, NULL));
g_assert(!nfc_manager_add_service_registered_handler(NULL, NULL, NULL));
g_assert(!nfc_manager_add_service_unregistered_handler(NULL, NULL, NULL));
g_assert(!nfc_manager_add_enabled_changed_handler(NULL, NULL, NULL));
g_assert(!nfc_manager_add_mode_changed_handler(NULL, NULL, NULL));
g_assert(!nfc_manager_add_stopped_handler(NULL, NULL, NULL));
......@@ -269,6 +272,8 @@ test_basic(
g_assert(!nfc_manager_add_adapter(manager, NULL));
g_assert(!nfc_manager_add_adapter_added_handler(manager, NULL, NULL));
g_assert(!nfc_manager_add_adapter_removed_handler(manager, NULL, NULL));
g_assert(!nfc_manager_add_service_registered_handler(manager, NULL, NULL));
g_assert(!nfc_manager_add_service_unregistered_handler(manager, NULL,NULL));
g_assert(!nfc_manager_add_enabled_changed_handler(manager, NULL, NULL));
g_assert(!nfc_manager_add_stopped_handler(manager, NULL, NULL));
nfc_manager_remove_handler(manager, 0);
......@@ -438,6 +443,74 @@ test_mode(
nfc_manager_unref(manager);
}
/*==========================================================================*
* service
*==========================================================================*/
static
void
test_service_cb(
NfcManager* manager,
NfcPeerService* service,
void* user_data)
{
(*(int*)user_data)++;
}
static
void
test_service(
void)
{
NfcPluginsInfo pi;
NfcManager* manager;
NfcPeerService* service = NFC_PEER_SERVICE(test_service_new("foo"));
int registered = 0, unregistered = 0;
memset(&pi, 0, sizeof(pi));
manager = nfc_manager_new(&pi);
/* Empty list by default */
g_assert(manager->services);
g_assert(!manager->services[0]);
/* Some (non-zero) LLCP version must be there */
g_assert(manager->llcp_version);
/* Register the handlers */
g_assert(nfc_manager_add_service_registered_handler(manager,
test_service_cb, &registered));
g_assert(nfc_manager_add_service_unregistered_handler(manager,
test_service_cb, &unregistered));
/* Register the service */
g_assert(nfc_manager_register_service(manager, service));
g_assert_cmpint(registered, == ,1);
g_assert_cmpint(unregistered, == ,0);
g_assert(manager->services[0] == service);
g_assert(!manager->services[1]);
/* Service can only be registered once */
g_assert(!nfc_manager_register_service(manager, service));
g_assert_cmpint(registered, == ,1);
g_assert_cmpint(unregistered, == ,0);
/* Then unregister it */
nfc_manager_unregister_service(manager, service);
g_assert_cmpint(registered, == ,1);
g_assert_cmpint(unregistered, == ,1);
g_assert(!manager->services[0]);
/* Then again, it won't have any effect */
nfc_manager_unregister_service(manager, service);
g_assert_cmpint(registered, == ,1);
g_assert_cmpint(unregistered, == ,1);
g_assert(!manager->services[0]);
nfc_peer_service_unref(service);
nfc_manager_unref(manager);
}
/*==========================================================================*
* Common
*==========================================================================*/
......@@ -454,6 +527,7 @@ int main(int argc, char* argv[])
g_test_add_func(TEST_("basic"), test_basic);
g_test_add_func(TEST_("adapter"), test_adapter);
g_test_add_func(TEST_("mode"), test_mode);
g_test_add_func(TEST_("service"), test_service);
test_init(&test_opt, argc, argv);
return g_test_run();
}
......
......@@ -2,4 +2,6 @@
EXE = test_core_peer_service
COMMON_SRC = test_main.c test_service.c
include ../common/Makefile
/*
* Copyright (C) 2020 Jolla Ltd.
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020-2021 Jolla Ltd.
* Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
......@@ -31,10 +31,10 @@
*/
#include "test_common.h"
#include "test_service.h"
#include "nfc_llc.h"
#include "nfc_peer_service_impl.h"
#include "nfc_peer_service_p.h"
#include "nfc_llc.h"
#include <gutil_log.h>
......@@ -42,43 +42,6 @@ static TestOpt test_opt;
#define TEST_(name) "/core/peer_service/" name
/*==========================================================================*
* Test service
*==========================================================================*/
typedef NfcPeerServiceClass TestServiceClass;
typedef NfcPeerService TestService;
G_DEFINE_TYPE(TestService, test_service, NFC_TYPE_PEER_SERVICE)
#define TEST_TYPE_SERVICE (test_service_get_type())
#define TEST_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, \
TEST_TYPE_SERVICE, TestService))
static
void
test_service_init(
TestService* self)
{
}
static
void
test_service_class_init(
TestServiceClass* klass)
{
}
static
TestService*
test_service_new(
const char* name)
{
TestService* service = g_object_new(TEST_TYPE_SERVICE, NULL);
nfc_peer_service_init_base(service, name);
return service;
}
/*==========================================================================*
* null
*==========================================================================*/
......
......@@ -2,4 +2,6 @@
EXE = test_core_peer_services
COMMON_SRC = test_main.c test_service.c
include ../common/Makefile
/*
* Copyright (C) 2020 Jolla Ltd.
* Copyright (C) 2020 Slava Monich <slava.monich@jolla.com>
* Copyright (C) 2020-2021 Jolla Ltd.
* Copyright (C) 2020-2021 Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of BSD license as follows:
*
......@@ -30,6 +30,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_service.h"
#include "test_common.h"
#include "nfc_peer_services.h"
......@@ -56,71 +57,6 @@ test_services_count(
return n;
}
/*==========================================================================*
* Test service
*==========================================================================*/
typedef NfcPeerServiceClass TestServiceClass;
typedef struct test_service {
NfcPeerService service;
int peer_arrived;
int peer_left;
} TestService;
G_DEFINE_TYPE(TestService, test_service, NFC_TYPE_PEER_SERVICE)
#define TEST_TYPE_SERVICE (test_service_get_type())
#define TEST_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, \
TEST_TYPE_SERVICE, TestService))
static
void
test_service_peer_arrived(
NfcPeerService* service,
NfcPeer* peer)
{
TEST_SERVICE(service)->peer_arrived++;
NFC_PEER_SERVICE_CLASS(test_service_parent_class)->
peer_arrived(service, peer);
}
static
void
test_service_peer_left(
NfcPeerService* service,
NfcPeer* peer)
{
TEST_SERVICE(service)->peer_left++;
NFC_PEER_SERVICE_CLASS(test_service_parent_class)->
peer_left(service, peer);
}
static
void
test_service_init(
TestService* self)
{
}
static
void
test_service_class_init(
TestServiceClass* klass)
{
klass->peer_arrived = test_service_peer_arrived;
klass->peer_left = test_service_peer_left;
}
static
TestService*
test_service_new(
const char* name)
{
TestService* service = g_object_new(TEST_TYPE_SERVICE, NULL);
nfc_peer_service_init_base(&service->service, name);
return service;
}
/*==========================================================================*
* null
*==========================================================================*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment