* [PATCH 12/14] neard: Update copyright information
From: Szymon Janc @ 2013-02-07 8:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
---
plugins/neard.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index b3ba2b0..ab51057 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -2,7 +2,7 @@
*
* BlueZ - Bluetooth protocol stack for Linux
*
- * Copyright (C) 2012 Tieto Poland
+ * Copyright (C) 2012-2013 Tieto Poland
*
*
* This program is free software; you can redistribute it and/or modify
--
1.8.1.1
^ permalink raw reply related
* [PATCH 11/14] neard: Use bool instead of gboolean for agent_register_postpone
From: Szymon Janc @ 2013-02-07 8:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
There is no need to use gboolean as this flag is not used with any
glib function.
---
plugins/neard.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 9351ac5..b3ba2b0 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -50,7 +50,7 @@
static guint watcher_id = 0;
static char *neard_path = NULL;
-static gboolean agent_register_postpone = FALSE;
+static bool agent_register_postpone = false;
/* For NFC mimetype limits max OOB EIR size */
#define NFC_OOB_EIR_MAX UINT8_MAX
@@ -242,7 +242,7 @@ static void read_local_complete(struct btd_adapter *adapter,
dbus_message_unref(msg);
if (agent_register_postpone) {
- agent_register_postpone = FALSE;
+ agent_register_postpone = false;
register_agent();
}
@@ -274,7 +274,7 @@ static void bonding_complete(struct btd_adapter *adapter,
dbus_message_unref(msg);
if (agent_register_postpone) {
- agent_register_postpone = FALSE;
+ agent_register_postpone = false;
register_agent();
}
@@ -829,7 +829,7 @@ static void neard_appeared(DBusConnection *conn, void *user_data)
adapter = btd_adapter_get_default();
if (adapter && btd_adapter_check_oob_handler(adapter))
- agent_register_postpone = TRUE;
+ agent_register_postpone = true;
else
register_agent();
}
--
1.8.1.1
^ permalink raw reply related
* [PATCH 10/14] neard: Restrict method calls only to neard process
From: Szymon Janc @ 2013-02-07 8:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
Disallow methods calls from processes other than registered to as
agent.
---
plugins/neard.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/plugins/neard.c b/plugins/neard.c
index 20cfe03..9351ac5 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -637,6 +637,10 @@ static DBusMessage *push_oob(DBusConnection *conn, DBusMessage *msg, void *data)
uint8_t io_cap;
int err;
+ if (neard_path == NULL ||
+ !g_str_equal(neard_path, dbus_message_get_sender(msg)))
+ return error_reply(msg, EPERM);
+
DBG("");
adapter = btd_adapter_get_default();
@@ -714,6 +718,10 @@ static DBusMessage *request_oob(DBusConnection *conn, DBusMessage *msg,
struct btd_device *device;
int err;
+ if (neard_path == NULL ||
+ !g_str_equal(neard_path, dbus_message_get_sender(msg)))
+ return error_reply(msg, EPERM);
+
DBG("");
adapter = btd_adapter_get_default();
@@ -776,6 +784,10 @@ read_local:
static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
+ if (neard_path == NULL ||
+ !g_str_equal(neard_path, dbus_message_get_sender(msg)))
+ return error_reply(msg, EPERM);
+
DBG("");
g_free(neard_path);
--
1.8.1.1
^ permalink raw reply related
* [PATCH 09/14] neard: Use path instead of boolean to track if registered to neard
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
---
plugins/neard.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 0bd376b..20cfe03 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -49,7 +49,7 @@
#define ERROR_INTERFACE "org.neard.HandoverAgent.Error"
static guint watcher_id = 0;
-static gboolean agent_registered = FALSE;
+static char *neard_path = NULL;
static gboolean agent_register_postpone = FALSE;
/* For NFC mimetype limits max OOB EIR size */
@@ -115,7 +115,7 @@ static void register_agent_cb(DBusPendingCall *call, void *user_data)
}
dbus_message_unref(reply);
- agent_registered = TRUE;
+ neard_path = g_strdup(dbus_message_get_sender(reply));
}
static void register_agent(void)
@@ -152,7 +152,8 @@ static void unregister_agent(void)
DBusMessage *message;
const char *path = AGENT_PATH;
- agent_registered = FALSE;
+ g_free(neard_path);
+ neard_path = NULL;
message = dbus_message_new_method_call(NEARD_NAME, NEARD_PATH,
NEARD_MANAGER_INTERFACE, "UnregisterHandoverAgent");
@@ -237,7 +238,7 @@ static void read_local_complete(struct btd_adapter *adapter,
DBG("");
- if (!agent_registered) {
+ if (neard_path == NULL) {
dbus_message_unref(msg);
if (agent_register_postpone) {
@@ -269,7 +270,7 @@ static void bonding_complete(struct btd_adapter *adapter,
DBG("");
- if (!agent_registered) {
+ if (neard_path == NULL) {
dbus_message_unref(msg);
if (agent_register_postpone) {
@@ -777,7 +778,9 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
{
DBG("");
- agent_registered = FALSE;
+ g_free(neard_path);
+ neard_path = NULL;
+
g_dbus_unregister_interface(conn, AGENT_PATH, AGENT_INTERFACE);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
@@ -824,8 +827,10 @@ static void neard_vanished(DBusConnection *conn, void *user_data)
DBG("");
/* neard existed without unregistering agent */
- if (agent_registered) {
- agent_registered = FALSE;
+ if (neard_path != NULL) {
+ g_free(neard_path);
+ neard_path = NULL;
+
g_dbus_unregister_interface(conn, AGENT_PATH, AGENT_INTERFACE);
}
}
@@ -850,7 +855,7 @@ static void neard_exit(void)
g_dbus_remove_watch(btd_get_dbus_connection(), watcher_id);
watcher_id = 0;
- if (agent_registered)
+ if (neard_path != NULL)
unregister_agent();
}
--
1.8.1.1
^ permalink raw reply related
* [PATCH 08/14] neard: Add support for setting power state in RequestOOB reply
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
This allows neard to properly set Bluetooth carrier power state in
handover message.
---
plugins/neard.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/plugins/neard.c b/plugins/neard.c
index 0418430..0bd376b 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -173,6 +173,19 @@ unregister:
AGENT_INTERFACE);
}
+static void add_power_state(DBusMessageIter *dict, struct btd_adapter *adapter)
+{
+ const char *state;
+
+ if (btd_adapter_get_powered(adapter) &&
+ btd_adapter_get_connectable(adapter))
+ state = "active";
+ else
+ state = "inactive";
+
+ dict_append_entry(dict, "State", DBUS_TYPE_STRING, &state);
+}
+
static DBusMessage *create_request_oob_reply(struct btd_adapter *adapter,
const uint8_t *hash,
const uint8_t *randomizer,
@@ -208,6 +221,8 @@ static DBusMessage *create_request_oob_reply(struct btd_adapter *adapter,
dict_append_array(&dict, "EIR", DBUS_TYPE_BYTE, &peir, len);
+ add_power_state(&dict, adapter);
+
dbus_message_iter_close_container(&iter, &dict);
return reply;
--
1.8.1.1
^ permalink raw reply related
* [PATCH 07/14] adapter: Add btd_adapter_get_connectable function
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
---
src/adapter.c | 8 ++++++++
src/adapter.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/src/adapter.c b/src/adapter.c
index cd104a1..2338e60 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2772,6 +2772,14 @@ bool btd_adapter_get_powered(struct btd_adapter *adapter)
return false;
}
+bool btd_adapter_get_connectable(struct btd_adapter *adapter)
+{
+ if (adapter->current_settings & MGMT_SETTING_CONNECTABLE)
+ return true;
+
+ return false;
+}
+
uint32_t btd_adapter_get_class(struct btd_adapter *adapter)
{
return adapter->dev_class;
diff --git a/src/adapter.h b/src/adapter.h
index 2610479..8d23a64 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -87,6 +87,7 @@ void adapter_foreach(adapter_cb func, gpointer user_data);
bool btd_adapter_get_pairable(struct btd_adapter *adapter);
bool btd_adapter_get_powered(struct btd_adapter *adapter);
+bool btd_adapter_get_connectable(struct btd_adapter *adapter);
uint32_t btd_adapter_get_class(struct btd_adapter *adapter);
const char *btd_adapter_get_name(struct btd_adapter *adapter);
--
1.8.1.1
^ permalink raw reply related
* [PATCH 06/14] neard: Check if adapter is powered in PushOOB
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
For PushOOB adapter needs to be powered as bluetoothd daemon is
expected to perform action on success.
---
plugins/neard.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/plugins/neard.c b/plugins/neard.c
index 131e8bd..0418430 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -629,6 +629,9 @@ static DBusMessage *push_oob(DBusConnection *conn, DBusMessage *msg, void *data)
if (err < 0)
return error_reply(msg, -err);
+ if (!btd_adapter_get_powered(adapter))
+ return error_reply(msg, ENONET);
+
agent = adapter_get_agent(adapter);
if (!agent)
return error_reply(msg, ENONET);
--
1.8.1.1
^ permalink raw reply related
* [PATCH 05/14] adapter: Add btd_adapter_get_powered function
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
---
src/adapter.c | 8 ++++++++
src/adapter.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/src/adapter.c b/src/adapter.c
index 9ddd2fc..cd104a1 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2764,6 +2764,14 @@ bool btd_adapter_get_pairable(struct btd_adapter *adapter)
return false;
}
+bool btd_adapter_get_powered(struct btd_adapter *adapter)
+{
+ if (adapter->current_settings & MGMT_SETTING_POWERED)
+ return true;
+
+ return false;
+}
+
uint32_t btd_adapter_get_class(struct btd_adapter *adapter)
{
return adapter->dev_class;
diff --git a/src/adapter.h b/src/adapter.h
index 2787631..2610479 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -86,6 +86,7 @@ struct btd_adapter *adapter_get_default(void);
void adapter_foreach(adapter_cb func, gpointer user_data);
bool btd_adapter_get_pairable(struct btd_adapter *adapter);
+bool btd_adapter_get_powered(struct btd_adapter *adapter);
uint32_t btd_adapter_get_class(struct btd_adapter *adapter);
const char *btd_adapter_get_name(struct btd_adapter *adapter);
--
1.8.1.1
^ permalink raw reply related
* [PATCH 04/14] neard: Move pairable check from check_adapter
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
If device is already paired there is no need to fail with handover
if adapter is not pairable.
---
plugins/neard.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 668c46f..131e8bd 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -579,9 +579,6 @@ static int check_adapter(struct btd_adapter *adapter)
if (btd_adapter_check_oob_handler(adapter))
return -EINPROGRESS;
- if (!btd_adapter_get_pairable(adapter))
- return -ENONET;
-
if (!btd_adapter_ssp_enabled(adapter))
return -ENOTSUP;
@@ -664,6 +661,12 @@ static DBusMessage *push_oob(DBusConnection *conn, DBusMessage *msg, void *data)
return error_reply(msg, -err);
}
+ if (!btd_adapter_get_pairable(adapter)) {
+ free_oob_params(&remote);
+
+ return error_reply(msg, ENONET);
+ }
+
store_params(adapter, device, &remote);
free_oob_params(&remote);
@@ -722,6 +725,12 @@ static DBusMessage *request_oob(DBusConnection *conn, DBusMessage *msg,
return error_reply(msg, -err);
}
+ if (!btd_adapter_get_pairable(adapter)) {
+ free_oob_params(&remote);
+
+ return error_reply(msg, ENONET);
+ }
+
store_params(adapter, device, &remote);
if (!remote.hash) {
--
1.8.1.1
^ permalink raw reply related
* [PATCH 03/14] neard: Add ability to parse 'State' field
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
This contains hint for power state of remote device Bluetooth adapter.
---
plugins/neard.c | 125 +++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 92 insertions(+), 33 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 7df4544..668c46f 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -55,6 +55,13 @@ static gboolean agent_register_postpone = FALSE;
/* For NFC mimetype limits max OOB EIR size */
#define NFC_OOB_EIR_MAX UINT8_MAX
+enum cps {
+ CPS_ACTIVE,
+ CPS_INACTIVE,
+ CPS_ACTIVATING,
+ CPS_UNKNOWN,
+};
+
struct oob_params {
bdaddr_t address;
uint32_t class;
@@ -64,6 +71,7 @@ struct oob_params {
uint8_t *randomizer;
uint8_t *pin;
int pin_len;
+ enum cps power_state;
};
static void free_oob_params(struct oob_params *params)
@@ -451,14 +459,24 @@ static int process_nokia_com_bt(uint8_t *data, size_t size,
}
}
+static enum cps process_state(const char *state)
+{
+ if (strcasecmp(state, "active") == 0)
+ return CPS_ACTIVE;
+
+ if (strcasecmp(state, "activating") == 0)
+ return CPS_ACTIVATING;
+
+ if (strcasecmp(state, "inactive") == 0)
+ return CPS_INACTIVE;
+
+ return CPS_UNKNOWN;
+}
+
static int process_message(DBusMessage *msg, struct oob_params *remote)
{
DBusMessageIter iter;
DBusMessageIter dict;
- DBusMessageIter value;
- DBusMessageIter entry;
- const char *key;
- int type;
dbus_message_iter_init(msg, &iter);
@@ -467,46 +485,87 @@ static int process_message(DBusMessage *msg, struct oob_params *remote)
dbus_message_iter_recurse(&iter, &dict);
- type = dbus_message_iter_get_arg_type(&dict);
- if (type != DBUS_TYPE_DICT_ENTRY) {
- if (type == DBUS_TYPE_INVALID)
- return -ENOENT;
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter value;
+ DBusMessageIter entry;
+ const char *key;
- return -EINVAL;
- }
+ dbus_message_iter_recurse(&dict, &entry);
- dbus_message_iter_recurse(&dict, &entry);
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ goto error;
- if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
- return -EINVAL;
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
- dbus_message_iter_get_basic(&entry, &key);
- dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
- dbus_message_iter_recurse(&entry, &value);
+ if (strcasecmp(key, "EIR") == 0) {
+ DBusMessageIter array;
+ uint8_t *eir;
+ int size;
- /* All keys have byte array type values */
- if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
- return -EINVAL;
+ /* nokia.com:bt and EIR should not be passed together */
+ if (bacmp(&remote->address, BDADDR_ANY) != 0)
+ goto error;
+
+ if (dbus_message_iter_get_arg_type(&value) !=
+ DBUS_TYPE_ARRAY)
+ goto error;
- if (strcasecmp(key, "EIR") == 0) {
- DBusMessageIter array;
- uint8_t *eir;
- int size;
+ dbus_message_iter_recurse(&value, &array);
+ dbus_message_iter_get_fixed_array(&array, &eir, &size);
- dbus_message_iter_recurse(&value, &array);
- dbus_message_iter_get_fixed_array(&array, &eir, &size);
+ if (process_eir(eir, size, remote) < 0)
+ goto error;
+ } else if (strcasecmp(key, "nokia.com:bt") == 0) {
+ DBusMessageIter array;
+ uint8_t *data;
+ int size;
- return process_eir(eir, size, remote);
- } else if (strcasecmp(key, "nokia.com:bt") == 0) {
- DBusMessageIter array;
- uint8_t *data;
- int size;
+ /* nokia.com:bt and EIR should not be passed together */
+ if (bacmp(&remote->address, BDADDR_ANY) != 0)
+ goto error;
- dbus_message_iter_recurse(&value, &array);
- dbus_message_iter_get_fixed_array(&array, &data, &size);
+ if (dbus_message_iter_get_arg_type(&value) !=
+ DBUS_TYPE_ARRAY)
+ goto error;
+
+ dbus_message_iter_recurse(&value, &array);
+ dbus_message_iter_get_fixed_array(&array, &data, &size);
+
+ if (process_nokia_com_bt(data, size, remote))
+ goto error;
+ } else if (strcasecmp(key, "State") == 0) {
+ DBusMessageIter array;
+ const char *state;
+
+ if (dbus_message_iter_get_arg_type(&value) !=
+ DBUS_TYPE_STRING)
+ goto error;
+
+ dbus_message_iter_recurse(&value, &array);
+ dbus_message_iter_get_basic(&value, &state);
+
+ remote->power_state = process_state(state);
+ if (remote->power_state == CPS_UNKNOWN)
+ goto error;
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ /* Check if 'State' was passed along with one of other fields */
+ if (remote->power_state != CPS_UNKNOWN
+ && bacmp(&remote->address, BDADDR_ANY) == 0)
+ return -EINVAL;
+
+ return 0;
- return process_nokia_com_bt(data, size, remote);
+error:
+ if (bacmp(&remote->address, BDADDR_ANY) != 0) {
+ free_oob_params(remote);
+ memset(remote, 0, sizeof(*remote));
}
return -EINVAL;
--
1.8.1.1
^ permalink raw reply related
* [PATCH 02/14] neard: Refactor message processing
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
This refactor code for message processing for future feature addition.
nokia.com:bt and EIR processing is now separated from performing
actions based on received data.
---
plugins/neard.c | 308 +++++++++++++++++++++++++++++---------------------------
1 file changed, 157 insertions(+), 151 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 6272144..7df4544 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -55,6 +55,26 @@ static gboolean agent_register_postpone = FALSE;
/* For NFC mimetype limits max OOB EIR size */
#define NFC_OOB_EIR_MAX UINT8_MAX
+struct oob_params {
+ bdaddr_t address;
+ uint32_t class;
+ char *name;
+ GSList *services;
+ uint8_t *hash;
+ uint8_t *randomizer;
+ uint8_t *pin;
+ int pin_len;
+};
+
+static void free_oob_params(struct oob_params *params)
+{
+ g_slist_free_full(params->services, g_free);
+ g_free(params->name);
+ g_free(params->hash);
+ g_free(params->randomizer);
+ g_free(params->pin);
+}
+
static DBusMessage *error_reply(DBusMessage *msg, int error)
{
const char *name;
@@ -268,14 +288,9 @@ static int check_device(struct btd_device *device)
return 0;
}
-/* returns 1 if action (pairing or reading local data) is not needed */
-static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
- bdaddr_t *remote)
+static int process_eir(uint8_t *eir, size_t size, struct oob_params *remote)
{
struct eir_data eir_data;
- char remote_address[18];
- struct btd_device *device;
- int err;
DBG("size %zu", size);
@@ -284,48 +299,25 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
if (eir_parse_oob(&eir_data, eir, size) < 0)
return -EINVAL;
- ba2str(&eir_data.addr, remote_address);
-
- DBG("hci%u remote:%s", btd_adapter_get_index(adapter), remote_address);
-
- device = adapter_get_device(adapter, &eir_data.addr, BDADDR_BREDR);
-
- err = check_device(device);
- if (err < 0) {
- eir_data_free(&eir_data);
- return err;
- }
+ bacpy(&remote->address, &eir_data.addr);
- /* store OOB data */
- if (eir_data.class != 0)
- device_set_class(device, eir_data.class);
+ remote->class = eir_data.class;
- /* TODO handle incomplete name? */
- if (eir_data.name) {
- adapter_store_cached_name(adapter_get_address(adapter),
- &eir_data.addr, eir_data.name);
- device_set_name(device, eir_data.name);
- }
+ remote->name = eir_data.name;
+ eir_data.name = NULL;
- if (eir_data.hash)
- btd_adapter_add_remote_oob_data(adapter, &eir_data.addr,
- eir_data.hash, eir_data.randomizer);
+ remote->services = eir_data.services;
+ eir_data.services = NULL;
- /* TODO handle UUIDs? */
+ remote->hash = eir_data.hash;
+ eir_data.hash = NULL;
- if (remote)
- bacpy(remote, &eir_data.addr);
-
- /*
- * In RequestOOB reply append local hash and randomizer only if
- * received EIR also contained it.
- */
- if (!remote && !eir_data.hash)
- err = -EALREADY;
+ remote->randomizer = eir_data.randomizer;
+ eir_data.randomizer = NULL;
eir_data_free(&eir_data);
- return err;
+ return 0;
}
/*
@@ -350,16 +342,8 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
* N bytes - name
*/
-struct nokia_com_bt {
- bdaddr_t address;
- uint32_t cod;
- uint8_t pin[16];
- int pin_len;
- char *name;
-};
-
static int process_nokia_long (void *data, size_t size, uint8_t marker,
- struct nokia_com_bt *nokia)
+ struct oob_params *remote)
{
struct {
bdaddr_t address;
@@ -373,26 +357,26 @@ static int process_nokia_long (void *data, size_t size, uint8_t marker,
return -EINVAL;
/* address is not reverted */
- baswap(&nokia->address, &n->address);
+ baswap(&remote->address, &n->address);
- nokia->cod = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
+ remote->class = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
if (n->name_len > 0)
- nokia->name = g_strndup((char *)n->name, n->name_len);
+ remote->name = g_strndup((char *)n->name, n->name_len);
if (marker == 0x01) {
- memcpy(nokia->pin, n->authentication, 4);
- nokia->pin_len = 4;
+ remote->pin = g_memdup(n->authentication, 4);
+ remote->pin_len = 4;
} else if (marker == 0x02) {
- memcpy(nokia->pin, n->authentication, 16);
- nokia->pin_len = 16;
+ remote->pin = g_memdup(n->authentication, 16);
+ remote->pin_len = 16;
}
return 0;
}
static int process_nokia_short (void *data, size_t size,
- struct nokia_com_bt *nokia)
+ struct oob_params *remote)
{
struct {
bdaddr_t address;
@@ -406,21 +390,21 @@ static int process_nokia_short (void *data, size_t size,
return -EINVAL;
/* address is not reverted */
- baswap(&nokia->address, &n->address);
+ baswap(&remote->address, &n->address);
- nokia->cod = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
+ remote->class = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
if (n->name_len > 0)
- nokia->name = g_strndup((char *)n->name, n->name_len);
+ remote->name = g_strndup((char *)n->name, n->name_len);
- memcpy(nokia->pin, n->authentication, 4);
- nokia->pin_len = 4;
+ remote->pin = g_memdup(n->authentication, 4);
+ remote->pin_len = 4;
return 0;
}
static int process_nokia_extra_short (void *data, size_t size,
- struct nokia_com_bt *nokia)
+ struct oob_params *remote)
{
struct {
bdaddr_t address;
@@ -432,95 +416,42 @@ static int process_nokia_extra_short (void *data, size_t size,
if (size != sizeof(*n) + n->name_len)
return -EINVAL;
- bacpy(&nokia->address, &n->address);
+ bacpy(&remote->address, &n->address);
- nokia->cod = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
+ remote->class = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
if (n->name_len > 0)
- nokia->name = g_strndup((char *)n->name, n->name_len);
+ remote->name = g_strndup((char *)n->name, n->name_len);
return 0;
}
-/* returns 1 if pairing is not needed */
-static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
- size_t size, bdaddr_t *remote)
+static int process_nokia_com_bt(uint8_t *data, size_t size,
+ struct oob_params *remote)
{
- uint8_t *marker;
- struct nokia_com_bt nokia;
- struct btd_device *device;
- int ret;
- char remote_address[18];
-
- /* Support this only for PushOOB */
- if (!remote)
- return -EOPNOTSUPP;
+ uint8_t marker;
- marker = data++;
- size --;
+ marker = *data++;
+ size--;
- DBG("marker: 0x%.2x size: %zu", *marker, size);
+ DBG("marker: 0x%.2x size: %zu", marker, size);
- memset(&nokia, 0, sizeof(nokia));
-
- switch (*marker) {
+ switch (marker) {
case 0x00:
case 0x01:
case 0x02:
- ret = process_nokia_long(data, size, *marker, &nokia);
- break;
+ return process_nokia_long(data, size, marker, remote);
case 0x10:
- ret = process_nokia_extra_short(data, size, &nokia);
- break;
+ return process_nokia_extra_short(data, size, remote);
case 0x24:
- ret = process_nokia_short(data, size, &nokia);
- break;
+ return process_nokia_short(data, size, remote);
default:
- info("Not supported Nokia NFC extension (0x%.2x)", *marker);
- ret = -EPROTONOSUPPORT;
- break;
- }
-
- if (ret < 0)
- return ret;
-
- ba2str(&nokia.address, remote_address);
- DBG("hci%u remote:%s", btd_adapter_get_index(adapter), remote_address);
-
- device = adapter_get_device(adapter, &nokia.address, BDADDR_BREDR);
-
- ret = check_device(device);
- if (ret != 0) {
- g_free(nokia.name);
- return ret;
- }
-
- DBG("hci%u remote:%s", btd_adapter_get_index(adapter), remote_address);
-
- if (nokia.name) {
- adapter_store_cached_name(adapter_get_address(adapter), remote,
- nokia.name);
- device_set_name(device, nokia.name);
- g_free(nokia.name);
+ info("Not supported Nokia NFC extension (0x%.2x)", marker);
+ return -EPROTONOSUPPORT;
}
-
- if (nokia.cod != 0)
- device_set_class(device, nokia.cod);
-
- if (nokia.pin_len > 0) {
- /* TODO
- * Handle PIN, for now only discovery mode and 'common' PINs
- * that might be provided by agent will work correctly.
- */
- }
-
- bacpy(remote, &nokia.address);
-
- return 0;
}
-static int process_params(DBusMessage *msg, struct btd_adapter *adapter,
- bdaddr_t *remote)
+static int process_message(DBusMessage *msg, struct oob_params *remote)
{
DBusMessageIter iter;
DBusMessageIter dict;
@@ -538,8 +469,8 @@ static int process_params(DBusMessage *msg, struct btd_adapter *adapter,
type = dbus_message_iter_get_arg_type(&dict);
if (type != DBUS_TYPE_DICT_ENTRY) {
- if (!remote && type == DBUS_TYPE_INVALID)
- return -EALREADY;
+ if (type == DBUS_TYPE_INVALID)
+ return -ENOENT;
return -EINVAL;
}
@@ -566,7 +497,7 @@ static int process_params(DBusMessage *msg, struct btd_adapter *adapter,
dbus_message_iter_recurse(&value, &array);
dbus_message_iter_get_fixed_array(&array, &eir, &size);
- return process_eir(adapter, eir, size, remote);
+ return process_eir(eir, size, remote);
} else if (strcasecmp(key, "nokia.com:bt") == 0) {
DBusMessageIter array;
uint8_t *data;
@@ -575,7 +506,7 @@ static int process_params(DBusMessage *msg, struct btd_adapter *adapter,
dbus_message_iter_recurse(&value, &array);
dbus_message_iter_get_fixed_array(&array, &data, &size);
- return process_nokia_com_bt(adapter, data, size, remote);
+ return process_nokia_com_bt(data, size, remote);
}
return -EINVAL;
@@ -598,12 +529,39 @@ static int check_adapter(struct btd_adapter *adapter)
return 0;
}
+static void store_params(struct btd_adapter *adapter, struct btd_device *device,
+ struct oob_params *params)
+{
+ if (params->class != 0)
+ device_set_class(device, params->class);
+
+ if (params->name) {
+ adapter_store_cached_name(adapter_get_address(adapter),
+ ¶ms->address, params->name);
+ device_set_name(device, params->name);
+ }
+
+ /* TODO handle UUIDs? */
+
+ if (params->hash) {
+ btd_adapter_add_remote_oob_data(adapter, ¶ms->address,
+ params->hash,
+ params->randomizer);
+ } else if (params->pin_len) {
+ /* TODO
+ * Handle PIN, for now only discovery mode and 'common' PINs
+ * that might be provided by agent will work correctly.
+ */
+ }
+}
+
static DBusMessage *push_oob(DBusConnection *conn, DBusMessage *msg, void *data)
{
struct btd_adapter *adapter;
struct agent *agent;
struct oob_handler *handler;
- bdaddr_t remote;
+ struct oob_params remote;
+ struct btd_device *device;
uint8_t io_cap;
int err;
@@ -615,15 +573,6 @@ static DBusMessage *push_oob(DBusConnection *conn, DBusMessage *msg, void *data)
if (err < 0)
return error_reply(msg, -err);
- err = process_params(msg, adapter, &remote);
-
- /* already paired, reply immediately */
- if (err == -EALREADY)
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
-
- if (err < 0)
- return error_reply(msg, -err);
-
agent = adapter_get_agent(adapter);
if (!agent)
return error_reply(msg, ENONET);
@@ -631,13 +580,43 @@ static DBusMessage *push_oob(DBusConnection *conn, DBusMessage *msg, void *data)
io_cap = agent_get_io_capability(agent);
agent_unref(agent);
- err = adapter_create_bonding(adapter, &remote, BDADDR_BREDR, io_cap);
+ memset(&remote, 0, sizeof(remote));
+
+ err = process_message(msg, &remote);
+ if (err < 0)
+ return error_reply(msg, -err);
+
+ if (bacmp(&remote.address, BDADDR_ANY) == 0) {
+ free_oob_params(&remote);
+
+ return error_reply(msg, EINVAL);
+ }
+
+ device = adapter_get_device(adapter, &remote.address, BDADDR_BREDR);
+
+ err = check_device(device);
+ if (err < 0) {
+ free_oob_params(&remote);
+
+ /* already paired, reply immediately */
+ if (err == -EALREADY)
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ return error_reply(msg, -err);
+ }
+
+ store_params(adapter, device, &remote);
+
+ free_oob_params(&remote);
+
+ err = adapter_create_bonding(adapter, device_get_address(device),
+ BDADDR_BREDR, io_cap);
if (err < 0)
return error_reply(msg, -err);
handler = g_new0(struct oob_handler, 1);
handler->bonding_cb = bonding_complete;
- bacpy(&handler->remote_addr, &remote);
+ bacpy(&handler->remote_addr, device_get_address(device));
handler->user_data = dbus_message_ref(msg);
btd_adapter_set_oob_handler(adapter, handler);
@@ -650,6 +629,8 @@ static DBusMessage *request_oob(DBusConnection *conn, DBusMessage *msg,
{
struct btd_adapter *adapter;
struct oob_handler *handler;
+ struct oob_params remote;
+ struct btd_device *device;
int err;
DBG("");
@@ -660,13 +641,38 @@ static DBusMessage *request_oob(DBusConnection *conn, DBusMessage *msg,
if (err < 0)
return error_reply(msg, -err);
- err = process_params(msg, adapter, NULL);
- if (err == -EALREADY)
- return create_request_oob_reply(adapter, NULL, NULL, msg);
+ memset(&remote, 0, sizeof(remote));
+ err = process_message(msg, &remote);
if (err < 0)
return error_reply(msg, -err);
+ if (bacmp(&remote.address, BDADDR_ANY) == 0)
+ goto read_local;
+
+ device = adapter_get_device(adapter, &remote.address, BDADDR_BREDR);
+
+ err = check_device(device);
+ if (err < 0) {
+ free_oob_params(&remote);
+
+ if (err == -EALREADY)
+ return create_request_oob_reply(adapter, NULL, NULL,
+ msg);
+
+ return error_reply(msg, -err);
+ }
+
+ store_params(adapter, device, &remote);
+
+ if (!remote.hash) {
+ free_oob_params(&remote);
+ return create_request_oob_reply(adapter, NULL, NULL, msg);
+ }
+
+read_local:
+ free_oob_params(&remote);
+
err = btd_adapter_read_local_oob_data(adapter);
if (err < 0)
return error_reply(msg, -err);
--
1.8.1.1
^ permalink raw reply related
* [PATCH 01/14] neard: Adjust errors to latest API changes
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
neard Handover API was stripped of not really usefull error codes.
---
plugins/neard.c | 25 ++++++-------------------
1 file changed, 6 insertions(+), 19 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index b0150e9..6272144 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -57,27 +57,14 @@ static gboolean agent_register_postpone = FALSE;
static DBusMessage *error_reply(DBusMessage *msg, int error)
{
- switch (error) {
- case ENOTSUP:
- return g_dbus_create_error(msg, ERROR_INTERFACE ".NotSupported",
- "Operation is not supported");
+ const char *name;
- case ENOENT:
- return g_dbus_create_error(msg, ERROR_INTERFACE ".NoSuchDevice",
- "No such device");
-
- case EINPROGRESS:
- return g_dbus_create_error(msg, ERROR_INTERFACE ".InProgress",
- "Operation already in progress");
-
- case ENONET:
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Disabled",
- "Device disabled");
+ if (error == EINPROGRESS)
+ name = ERROR_INTERFACE ".InProgress";
+ else
+ name = ERROR_INTERFACE ".Failed";
- default:
- return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
- "%s", strerror(error));
- }
+ return g_dbus_create_error(msg, name , "%s", strerror(error));
}
static void register_agent_cb(DBusPendingCall *call, void *user_data)
--
1.8.1.1
^ permalink raw reply related
* [PATCH 00/14] neard plugin update
From: Szymon Janc @ 2013-02-07 8:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Ravi kumar Veeramally, Szymon Janc
This set adds some new features to neard plugin to match it with
recent changes in neard daemon:
- support for carrier power state hint (already merged)
- update register API [with fallback to legacy support] (pending review)
Power state hint could be use to improve IOP e.g. delay or retry pairing when
remote device in activating or incative state.
Other than that bugfixes, small improvements and some code refactoring to
make it better prepared for future feature addition e.g. to perform more
action on PushOOB than only pairing.
There are still some open points regarding how to properly map adapter
state (powered/pairable/connectable) to carrier power state but those
could be discussed separately later on.
Comments are welcome.
BR
Szymon Janc
Ravi kumar Veeramally (1):
neard: Updated neard handover registration agent api calls.
Szymon Janc (13):
neard: Adjust errors to latest API changes
neard: Refactor message processing
neard: Add ability to parse 'State' field
neard: Move pairable check from check_adapter
adapter: Add btd_adapter_get_powered function
neard: Check if adapter is powered in PushOOB
adapter: Add btd_adapter_get_connectable function
neard: Add support for setting power state in RequestOOB reply
neard: Use path instead of boolean to track if registered to neard
neard: Restrict method calls only to neard process
neard: Use bool instead of gboolean for agent_register_postpone
neard: Update copyright information
neard: Add fallback to legacy register if register failed
plugins/neard.c | 562 ++++++++++++++++++++++++++++++++++----------------------
src/adapter.c | 16 ++
src/adapter.h | 2 +
3 files changed, 361 insertions(+), 219 deletions(-)
--
1.8.1.1
^ permalink raw reply
* [PATCH v2 5/5] hostname: Fallback to static hostname if pretty hostname is not set
From: Szymon Janc @ 2013-02-06 21:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1360186838-16904-1-git-send-email-szymon@janc.net.pl>
If pretty hostname is not set fallback to static hostname (if it is
set). If static or pretty hostname is not set appropriate properties
are empty strings not NULLs. This behaviour is recomended by hostnamed.
---
plugins/hostname.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 44 insertions(+), 10 deletions(-)
diff --git a/plugins/hostname.c b/plugins/hostname.c
index 74c25df..92a71e0 100644
--- a/plugins/hostname.c
+++ b/plugins/hostname.c
@@ -53,22 +53,43 @@ static uint8_t major_class = MAJOR_CLASS_MISCELLANEOUS;
static uint8_t minor_class = MINOR_CLASS_UNCATEGORIZED;
static char *pretty_hostname = NULL;
+static char *static_hostname = NULL;
+
+/*
+ * Fallback to static hostname only if empty pretty hostname was already
+ * received.
+ */
+static const char *get_hostname(void)
+{
+ if (pretty_hostname) {
+ if (g_str_equal(pretty_hostname, "") == FALSE)
+ return pretty_hostname;
+
+ if (static_hostname &&
+ g_str_equal(static_hostname, "") == FALSE)
+ return static_hostname;
+ }
+
+ return NULL;
+}
static void update_name(struct btd_adapter *adapter, gpointer user_data)
{
- if (pretty_hostname == NULL)
+ const char *hostname = get_hostname();
+
+ if (hostname == NULL)
return;
if (btd_adapter_is_default(adapter)) {
- DBG("name: %s", pretty_hostname);
+ DBG("name: %s", hostname);
- adapter_set_name(adapter, pretty_hostname);
+ adapter_set_name(adapter, hostname);
} else {
uint16_t index = btd_adapter_get_index(adapter);
char *str;
/* Avoid "some device #0" names, start at #1 */
- str = g_strdup_printf("%s #%u", pretty_hostname, index + 1);
+ str = g_strdup_printf("%s #%u", hostname, index + 1);
DBG("name: %s", str);
@@ -117,17 +138,29 @@ static void property_changed(GDBusProxy *proxy, const char *name,
DBG("pretty hostname: %s", str);
- if (g_str_equal(str, "") == TRUE) {
- g_free(pretty_hostname);
- pretty_hostname = NULL;
- return;
- }
-
g_free(pretty_hostname);
pretty_hostname = g_strdup(str);
adapter_foreach(update_name, NULL);
}
+ } else if (g_str_equal(name, "StaticHostname") == TRUE) {
+ if (iter == NULL) {
+ g_dbus_proxy_refresh_property(proxy, name);
+ return;
+ }
+
+ if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
+ const char *str;
+
+ dbus_message_iter_get_basic(iter, &str);
+
+ DBG("static hostname: %s", str);
+
+ g_free(static_hostname);
+ static_hostname = g_strdup(str);
+
+ adapter_foreach(update_name, NULL);
+ }
} else if (g_str_equal(name, "Chassis") == TRUE) {
if (iter == NULL) {
g_dbus_proxy_refresh_property(proxy, name);
@@ -283,6 +316,7 @@ static void hostname_exit(void)
}
g_free(pretty_hostname);
+ g_free(static_hostname);
}
BLUETOOTH_PLUGIN_DEFINE(hostname, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
--
1.8.1.2
^ permalink raw reply related
* [PATCH v2 4/5] hostname: Fix setting adapter name to empty string
From: Szymon Janc @ 2013-02-06 21:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1360186838-16904-1-git-send-email-szymon@janc.net.pl>
If pretty hostname is not set empty string is received. Don't update
adapters' names is such case.
---
plugins/hostname.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/plugins/hostname.c b/plugins/hostname.c
index 0b75fac..74c25df 100644
--- a/plugins/hostname.c
+++ b/plugins/hostname.c
@@ -117,6 +117,12 @@ static void property_changed(GDBusProxy *proxy, const char *name,
DBG("pretty hostname: %s", str);
+ if (g_str_equal(str, "") == TRUE) {
+ g_free(pretty_hostname);
+ pretty_hostname = NULL;
+ return;
+ }
+
g_free(pretty_hostname);
pretty_hostname = g_strdup(str);
--
1.8.1.2
^ permalink raw reply related
* [PATCH v2 3/5] adapter: Always set new default adapter if current one is removed
From: Szymon Janc @ 2013-02-06 21:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1360186838-16904-1-git-send-email-szymon@janc.net.pl>
In case hci_get_route() failed mark first adapter on list as default.
This make sure default adapter is always set and that
btd_adapter_get_default will not return NULL if at least one adapter
is registered.
---
src/adapter.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 3f51fd4..7b08425 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -5523,8 +5523,10 @@ static int adapter_unregister(struct btd_adapter *adapter)
struct btd_adapter *new_default;
new_default = adapter_find_by_id(hci_get_route(NULL));
- if (new_default)
- new_default->is_default = true;
+ if (new_default == NULL)
+ new_default = adapters->data;
+
+ new_default->is_default = true;
}
adapter_list = g_list_remove(adapter_list, adapter);
--
1.8.1.2
^ permalink raw reply related
* [PATCH v2 2/5] adapter: Mark adapter as default before probing drivers
From: Szymon Janc @ 2013-02-06 21:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1360186838-16904-1-git-send-email-szymon@janc.net.pl>
Drivers may depends on adapter being default or not. This fix hostname
plugin setting default adapter name to 'foo #1' instead of 'foo' if
pretty hostname was received before probing adapter drivers.
---
src/adapter.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 3774c77..3f51fd4 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -5474,6 +5474,9 @@ static int adapter_register(struct btd_adapter *adapter)
return -EINVAL;
}
+ if (adapters == NULL)
+ adapter->is_default = true;
+
adapters = g_slist_append(adapters, adapter);
agent = agent_get(NULL);
@@ -5501,9 +5504,6 @@ static int adapter_register(struct btd_adapter *adapter)
adapter->initialized = TRUE;
- if (g_slist_length(adapters) == 1)
- adapter->is_default = true;
-
if (main_opts.did_source)
set_did(adapter, main_opts.did_vendor, main_opts.did_product,
main_opts.did_version, main_opts.did_source);
--
1.8.1.2
^ permalink raw reply related
* [PATCH v2 1/5] adapter: Add is_default field to struct btd_adapter
From: Szymon Janc @ 2013-02-06 21:40 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Instead of global default_adapter_id variable use is_default field
to indicate if adapter is default one.
---
src/adapter.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 9ddd2fc..3774c77 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -96,7 +96,6 @@ static unsigned int adapter_remaining = 0;
static bool powering_down = false;
static GSList *adapters = NULL;
-static int default_adapter_id = -1;
static struct mgmt *mgmt_master = NULL;
@@ -184,6 +183,8 @@ struct btd_adapter {
unsigned int pair_device_id;
guint pair_device_timeout;
+
+ bool is_default; /* true if adapter is default one */
};
static struct btd_adapter *btd_adapter_lookup(uint16_t index)
@@ -205,14 +206,11 @@ struct btd_adapter *btd_adapter_get_default(void)
{
GList *list;
- if (default_adapter_id < 0)
- return NULL;
-
for (list = g_list_first(adapter_list); list;
list = g_list_next(list)) {
struct btd_adapter *adapter = list->data;
- if (adapter->dev_id == default_adapter_id)
+ if (adapter->is_default)
return adapter;
}
@@ -224,10 +222,7 @@ bool btd_adapter_is_default(struct btd_adapter *adapter)
if (!adapter)
return false;
- if (adapter->dev_id == default_adapter_id)
- return true;
-
- return false;
+ return adapter->is_default;
}
uint16_t btd_adapter_get_index(struct btd_adapter *adapter)
@@ -5506,8 +5501,8 @@ static int adapter_register(struct btd_adapter *adapter)
adapter->initialized = TRUE;
- if (default_adapter_id < 0)
- default_adapter_id = adapter->dev_id;
+ if (g_slist_length(adapters) == 1)
+ adapter->is_default = true;
if (main_opts.did_source)
set_did(adapter, main_opts.did_vendor, main_opts.did_product,
@@ -5524,8 +5519,13 @@ static int adapter_unregister(struct btd_adapter *adapter)
adapters = g_slist_remove(adapters, adapter);
- if (default_adapter_id == adapter->dev_id || default_adapter_id < 0)
- default_adapter_id = hci_get_route(NULL);
+ if (adapter->is_default && adapters != NULL) {
+ struct btd_adapter *new_default;
+
+ new_default = adapter_find_by_id(hci_get_route(NULL));
+ if (new_default)
+ new_default->is_default = true;
+ }
adapter_list = g_list_remove(adapter_list, adapter);
--
1.8.1.2
^ permalink raw reply related
* Re: [PATCH 1/2] hostname: Fallback to static hostname if pretty hostname is not set
From: Szymon Janc @ 2013-02-06 20:29 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1360136648.15783.3.camel@aeonflux>
On Wednesday 06 February 2013 09:44:08 Marcel Holtmann wrote:
Hi Marcel,
> > If pretty hostname is not set fallback to static hostname (if it is
> > set). If static or pretty hostname is not set appropriate properties
> > are empty strings not NULLs. This behaviour is recomended by hostnamed.
> >
> > Also fix setting adapter name to empty string if pretty hostname was
> > not set.
>
> please do not squeeze to patches into one.
Will split that in v2.
>
> I am also not convinced that we should bother with the static hostname
> at all. I left this out on purpose. My thinking here was that if we do
> not have a pretty hostname, then why bother with trying to make
> something useful out of the hostname, it would be ugly or wrong anyway.
Maybe not that fancy as pretty hostname but at least know to user(e.g for
some reason my Fedora doesn't have pretty hostname set and falling back to
static hostname makes adapter name somewhat reasonable).
Also falling back to static hostname will allow hostname plugin to number
adapters' names. Yet, maybe main.conf parsing should be fixed instead to
properly substitute %h/%d as stated in comment. Currently name is simply set
to string '%h-%d' in such case...
--
Szymon K. Janc
szymon@janc.net.pl
^ permalink raw reply
* Re: [PATCH 2/2] adapter: Set default adapter id sooner
From: Szymon Janc @ 2013-02-06 19:54 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <1360137464.15783.7.camel@aeonflux>
On Wednesday 06 February 2013 09:57:44 Marcel Holtmann wrote:
Hi Marcel,
> > When first adapter is registered set it as default before probing
> > drivers or profiles as those might depend on that e.g. hostname.
> >
> > This fix hostname plugin setting default adapter name to 'foo #1'
> > instead of 'foo' if pretty hostname was received before probing
> > adapter drivers.
>
> you find an issue that I meant to fix, but never got around so far. So I
> do not like the magic default_adapter_id global variable.
>
> I would prefer if we add a is_default or similar variable to btd_adapter
> and make it change if one adapter goes away.
OK, will send v2 which address that.
--
Szymon K. Janc
szymon@janc.net.pl
^ permalink raw reply
* [RFC 8/8] obexd: Notify registered notification handlers
From: Christian Fetzer @ 2013-02-06 14:45 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1360161922-6585-1-git-send-email-christian.fetzer@oss.bmw-carit.de>
From: Christian Fetzer <christian.fetzer@bmw-carit.de>
---
obexd/client/mns.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/obexd/client/mns.c b/obexd/client/mns.c
index 81550ef..f16d235 100644
--- a/obexd/client/mns.c
+++ b/obexd/client/mns.c
@@ -41,7 +41,7 @@
#include "service.h"
#include "mimetype.h"
#include "map_ap.h"
-#include "map-event.h"
+#include "map-dispatcher.h"
struct mns_session {
GString *buffer;
@@ -266,6 +266,8 @@ static int event_report_close(void *obj)
GMarkupParseContext *ctxt;
struct map_event *event;
+ DBG("");
+
event = g_new0(struct map_event, 1);
ctxt = g_markup_parse_context_new(&event_report_parser, 0, event,
NULL);
@@ -273,11 +275,7 @@ static int event_report_close(void *obj)
NULL);
g_markup_parse_context_free(ctxt);
- DBG("Received event report for instance %d", mns->mas_instance_id);
- DBG("type=%x, handle=%s, folder=%s, old_folder=%s, msg_type=%s",
- event->type, event->handle, event->folder,
- event->old_folder, event->msg_type);
-
+ mns_dispatch_notification(mns->mas_instance_id, event);
map_event_free(event);
reset_request(mns);
--
1.8.1.2
^ permalink raw reply related
* [RFC 7/8] obexd: Register MAP notification handler
From: Christian Fetzer @ 2013-02-06 14:45 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1360161922-6585-1-git-send-email-christian.fetzer@oss.bmw-carit.de>
From: Christian Fetzer <christian.fetzer@bmw-carit.de>
---
obexd/client/map.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/obexd/client/map.c b/obexd/client/map.c
index 776f19c..682f97a 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -41,6 +41,7 @@
#include "driver.h"
#include "sdp.h"
#include "sdp_lib.h"
+#include "map-dispatcher.h"
#define OBEX_MAS_UUID \
"\xBB\x58\x2B\x40\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66"
@@ -97,6 +98,7 @@ struct map_data {
GHashTable *messages;
int16_t mas_instance_id;
uint8_t supported_message_types;
+ gboolean mns_acquired;
};
#define MAP_MSG_FLAG_PRIORITY 0x01
@@ -1555,6 +1557,13 @@ fail:
return reply;
}
+static void map_handle_notification(struct map_event *event)
+{
+ DBG("event: type=%x, handle=%s, folder=%s, old_folder=%s, msg_type=%s",
+ event->type, event->handle, event->folder,
+ event->old_folder, event->msg_type);
+}
+
static DBusMessage *map_register_notifications(DBusConnection *connection,
DBusMessage *message, void *user_data)
{
@@ -1573,9 +1582,22 @@ static DBusMessage *map_register_notifications(DBusConnection *connection,
ERROR_INTERFACE ".InvalidArguments",
NULL);
+ if (map->mns_acquired == status)
+ return g_dbus_create_error(message,
+ ERROR_INTERFACE ".InvalidArguments",
+ NULL);
+
apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_NOTIFICATIONSTATUS,
status ? 0x01 : 0x00);
+ if (status) {
+ map->mns_acquired = TRUE;
+ map_acquire_mns(map->mas_instance_id, &map_handle_notification);
+ } else {
+ map->mns_acquired = FALSE;
+ map_release_mns(map->mas_instance_id);
+ }
+
return set_notification_registration(map, message, apparam);
}
@@ -1621,6 +1643,9 @@ static void map_free(void *data)
{
struct map_data *map = data;
+ if (map->mns_acquired)
+ map_release_mns(map->mas_instance_id);
+
obc_session_unref(map->session);
g_hash_table_unref(map->messages);
g_free(map);
--
1.8.1.2
^ permalink raw reply related
* [RFC 6/8] obexd: Add MAP notification dispatcher
From: Christian Fetzer @ 2013-02-06 14:45 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1360161922-6585-1-git-send-email-christian.fetzer@oss.bmw-carit.de>
From: Christian Fetzer <christian.fetzer@bmw-carit.de>
The MAP specification allows to reuse one MNS instance for all local
MAS client instances. This dispatching of event reports to the
correct MAS client instance is done by the instance id.
The dispatcher component allows MAP client instances to
register a notification handler (map_aquire_mns).
Events reports are then forwarded by the notification server
using (mns_dispatch_notification).
---
Makefile.obexd | 1 +
obexd/client/map-dispatcher.c | 86 +++++++++++++++++++++++++++++++++++++++++++
obexd/client/map-dispatcher.h | 45 ++++++++++++++++++++++
3 files changed, 132 insertions(+)
create mode 100644 obexd/client/map-dispatcher.c
create mode 100644 obexd/client/map-dispatcher.h
diff --git a/Makefile.obexd b/Makefile.obexd
index 5824e0a..02901a3 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -73,6 +73,7 @@ obexd_src_obexd_SOURCES = $(gdbus_sources) $(btio_sources) $(gobex_sources) \
obexd/client/ftp.h obexd/client/ftp.c \
obexd/client/opp.h obexd/client/opp.c \
obexd/client/map.h obexd/client/map.c \
+ obexd/client/map-dispatcher.h obexd/client/map-dispatcher.c \
obexd/client/transfer.h obexd/client/transfer.c \
obexd/client/transport.h obexd/client/transport.c \
obexd/client/dbus.h obexd/client/dbus.c \
diff --git a/obexd/client/map-dispatcher.c b/obexd/client/map-dispatcher.c
new file mode 100644
index 0000000..ed6e5bb
--- /dev/null
+++ b/obexd/client/map-dispatcher.c
@@ -0,0 +1,86 @@
+/*
+ *
+ * OBEX
+ *
+ * Copyright (C) 2013 BMW Car IT GmbH. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "log.h"
+#include "map-dispatcher.h"
+
+static GSList *mappings = NULL;
+
+struct mns_mapping {
+ int mas_instance_id;
+ map_handle_notification_func handler;
+};
+
+gboolean map_acquire_mns(int mas_instance_id,
+ map_handle_notification_func handler)
+{
+ struct mns_mapping *mapping;
+
+ mapping = g_try_new0(struct mns_mapping, 1);
+ if (mapping == NULL)
+ return FALSE;
+
+ mapping->mas_instance_id = mas_instance_id;
+ mapping->handler = handler;
+
+ mappings = g_slist_append(mappings, mapping);
+ DBG("Added MAP MNS mapping for instance %d", mas_instance_id);
+
+ return TRUE;
+}
+
+static struct mns_mapping *find_mapping(int mas_instance_id)
+{
+ GSList *list;
+
+ for (list = mappings; list; list = list->next) {
+ struct mns_mapping *mapping = list->data;
+ if (mapping->mas_instance_id == mas_instance_id)
+ return mapping;
+ }
+
+ DBG("Cannot find MAP MNS mapping for instance %d", mas_instance_id);
+ return NULL;
+}
+
+void map_release_mns(int mas_instance_id)
+{
+ struct mns_mapping *mapping = find_mapping(mas_instance_id);
+ if (mapping) {
+ mappings = g_slist_remove(mappings, mapping);
+ DBG("Removed MAP MNS mapping for instance %d", mas_instance_id);
+ }
+}
+
+void mns_dispatch_notification(int mas_instance_id, struct map_event *event)
+{
+ struct mns_mapping *mapping = find_mapping(mas_instance_id);
+ if (mapping)
+ mapping->handler(event);
+}
diff --git a/obexd/client/map-dispatcher.h b/obexd/client/map-dispatcher.h
new file mode 100644
index 0000000..8f65137
--- /dev/null
+++ b/obexd/client/map-dispatcher.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * OBEX
+ *
+ * Copyright (C) 2013 BMW Car IT GmbH. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "map-event.h"
+
+/* Handle notification in map client.
+ *
+ * event: Event report.
+ *
+ * Callback shall be called for every received event.
+ */
+typedef void (*map_handle_notification_func)(struct map_event *event);
+
+/* Registers client notification handler callback for events that are
+ * addressed to the given mas instance id.
+ */
+gboolean map_acquire_mns(int mas_instance_id, map_handle_notification_func);
+
+/* Unregisters client notification handler callback.
+ */
+void map_release_mns(int mas_instance_id);
+
+/* Dispatch notification to a registered notification handler callback.
+ */
+void mns_dispatch_notification(int mas_instance_id, struct map_event *event);
--
1.8.1.2
^ permalink raw reply related
* [RFC 5/8] obexd: Add RegisterNotifications function
From: Christian Fetzer @ 2013-02-06 14:45 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1360161922-6585-1-git-send-email-christian.fetzer@oss.bmw-carit.de>
From: Christian Fetzer <christian.fetzer@bmw-carit.de>
This allows applications to register for all different types
of MAP event reports.
In response to this call, the MSE should connect to the local MNS
instance.
---
doc/obex-api.txt | 7 +++++
obexd/client/map.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 91 insertions(+)
diff --git a/doc/obex-api.txt b/doc/obex-api.txt
index 6246933..ddbb9ab 100644
--- a/doc/obex-api.txt
+++ b/doc/obex-api.txt
@@ -630,6 +630,13 @@ Methods void SetFolder(string name)
Possible errors: org.bluez.obex.Error.Failed
+ void RegisterNotifications(boolean)
+
+ Register / unregister reception of notifications.
+
+ Possible errors: org.bluez.obex.Error.InvalidArguments
+ org.bluez.obex.Error.Failed
+
Filter: uint16 Offset:
Offset of the first item, default is 0
diff --git a/obexd/client/map.c b/obexd/client/map.c
index 463d905..776f19c 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -1499,6 +1499,86 @@ fail:
return reply;
}
+static void notification_registration_cb(struct obc_session *session,
+ struct obc_transfer *transfer,
+ GError *err, void *user_data)
+{
+ struct map_data *map = user_data;
+ DBusMessage *reply;
+
+ if (err != NULL) {
+ reply = g_dbus_create_error(map->msg,
+ ERROR_INTERFACE ".Failed",
+ "%s", err->message);
+ goto done;
+ }
+
+ reply = dbus_message_new_method_return(map->msg);
+
+done:
+ g_dbus_send_message(conn, reply);
+ dbus_message_unref(map->msg);
+}
+
+static DBusMessage *set_notification_registration(struct map_data *map,
+ DBusMessage *message,
+ GObexApparam *apparam)
+{
+ struct obc_transfer *transfer;
+ GError *err = NULL;
+ DBusMessage *reply;
+ char contents[2];
+
+ contents[0] = FILLER_BYTE;
+ contents[1] = '\0';
+
+ transfer = obc_transfer_put("x-bt/MAP-NotificationRegistration", NULL,
+ NULL, contents, sizeof(contents), &err);
+
+ if (transfer == NULL) {
+ g_obex_apparam_free(apparam);
+ goto fail;
+ }
+
+ obc_transfer_set_apparam(transfer, apparam);
+
+ if (obc_session_queue(map->session, transfer,
+ notification_registration_cb, map, &err)) {
+ map->msg = dbus_message_ref(message);
+ return NULL;
+ }
+
+fail:
+ reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
+ err->message);
+ g_error_free(err);
+ return reply;
+}
+
+static DBusMessage *map_register_notifications(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct map_data *map = user_data;
+ GObexApparam *apparam;
+ gboolean status;
+
+ if (map->mas_instance_id < 0)
+ return g_dbus_create_error(message,
+ ERROR_INTERFACE ".Failed",
+ "Unknown MAS instance id");
+
+ if (dbus_message_get_args(message, NULL, DBUS_TYPE_BOOLEAN, &status,
+ DBUS_TYPE_INVALID) == FALSE)
+ return g_dbus_create_error(message,
+ ERROR_INTERFACE ".InvalidArguments",
+ NULL);
+
+ apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_NOTIFICATIONSTATUS,
+ status ? 0x01 : 0x00);
+
+ return set_notification_registration(map, message, apparam);
+}
+
static const GDBusMethodTable map_methods[] = {
{ GDBUS_ASYNC_METHOD("SetFolder",
GDBUS_ARGS({ "name", "s" }), NULL,
@@ -1519,6 +1599,10 @@ static const GDBusMethodTable map_methods[] = {
NULL,
NULL,
map_update_inbox) },
+ { GDBUS_ASYNC_METHOD("RegisterNotifications",
+ GDBUS_ARGS({ "status", "b" }),
+ NULL,
+ map_register_notifications) },
{ }
};
--
1.8.1.2
^ permalink raw reply related
* [RFC 4/8] obexd: Add Message Notification Server (MNS)
From: Christian Fetzer @ 2013-02-06 14:45 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1360161922-6585-1-git-send-email-christian.fetzer@oss.bmw-carit.de>
From: Christian Fetzer <christian.fetzer@bmw-carit.de>
This implements the MAP Message Notification Server (MNS)
which is part of the MCE.
---
Makefile.obexd | 3 +
obexd/client/map-event.h | 42 ++++++
obexd/client/mns.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++
obexd/plugins/bluetooth.c | 2 +
obexd/src/obexd.h | 1 +
src/profile.c | 55 ++++++++
6 files changed, 451 insertions(+)
create mode 100644 obexd/client/map-event.h
create mode 100644 obexd/client/mns.c
diff --git a/Makefile.obexd b/Makefile.obexd
index ae05ae9..5824e0a 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -48,6 +48,9 @@ obexd_builtin_sources += obexd/plugins/mas.c obexd/src/map_ap.h \
obexd/plugins/messages.h \
obexd/plugins/messages-dummy.c
+obexd_builtin_modules += mns
+obexd_builtin_sources += obexd/client/mns.c obexd/src/map_ap.h \
+ obexd/client/map-event.h
libexec_PROGRAMS += obexd/src/obexd
diff --git a/obexd/client/map-event.h b/obexd/client/map-event.h
new file mode 100644
index 0000000..749f1e0
--- /dev/null
+++ b/obexd/client/map-event.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * OBEX
+ *
+ * Copyright (C) 2013 BMW Car IT GmbH. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+enum map_event_type {
+ MAP_ET_NEW_MESSAGE,
+ MAP_ET_DELIVERY_SUCCESS,
+ MAP_ET_SENDING_SUCCESS,
+ MAP_ET_DELIVERY_FAILURE,
+ MAP_ET_SENDING_FAILURE,
+ MAP_ET_MEMORY_FULL,
+ MAP_ET_MEMORY_AVAILABLE,
+ MAP_ET_MESSAGE_DELETED,
+ MAP_ET_MESSAGE_SHIFT
+};
+
+struct map_event {
+ enum map_event_type type;
+ char *handle;
+ char *folder;
+ char *old_folder;
+ char *msg_type;
+};
diff --git a/obexd/client/mns.c b/obexd/client/mns.c
new file mode 100644
index 0000000..81550ef
--- /dev/null
+++ b/obexd/client/mns.c
@@ -0,0 +1,348 @@
+/*
+ *
+ * OBEX Server
+ *
+ * Copyright (C) 2013 BMW Car IT GmbH. All rights reserved.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include <gobex/gobex.h>
+#include <gobex/gobex-apparam.h>
+
+#include "obexd.h"
+#include "plugin.h"
+#include "log.h"
+#include "obex.h"
+#include "service.h"
+#include "mimetype.h"
+#include "map_ap.h"
+#include "map-event.h"
+
+struct mns_session {
+ GString *buffer;
+ GObexApparam *inparams;
+ uint8_t mas_instance_id;
+};
+
+static const uint8_t MNS_TARGET[TARGET_SIZE] = {
+ 0xbb, 0x58, 0x2b, 0x41, 0x42, 0x0c, 0x11, 0xdb,
+ 0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 };
+
+static int get_params(struct obex_session *os, struct mns_session *mns)
+{
+ const uint8_t *buffer;
+ ssize_t size;
+
+ size = obex_get_apparam(os, &buffer);
+ if (size < 0)
+ size = 0;
+
+ mns->inparams = g_obex_apparam_decode(buffer, size);
+ if (mns->inparams == NULL) {
+ DBG("Error when parsing parameters!");
+ return -EBADR;
+ }
+
+ return 0;
+}
+
+static void reset_request(struct mns_session *mns)
+{
+ if (mns->buffer) {
+ g_string_free(mns->buffer, TRUE);
+ mns->buffer = NULL;
+ }
+
+ if (mns->inparams) {
+ g_obex_apparam_free(mns->inparams);
+ mns->inparams = NULL;
+ }
+}
+
+static void mns_session_free(struct mns_session *mns)
+{
+ reset_request(mns);
+ g_free(mns);
+}
+
+static void *mns_connect(struct obex_session *os, int *err)
+{
+ struct mns_session *mns;
+
+ DBG("");
+
+ mns = g_new0(struct mns_session, 1);
+
+ manager_register_session(os);
+
+ return mns;
+}
+
+static void mns_disconnect(struct obex_session *os, void *user_data)
+{
+ struct mns_session *mns = user_data;
+
+ DBG("");
+
+ manager_unregister_session(os);
+
+ mns_session_free(mns);
+}
+
+static int mns_put(struct obex_session *os, void *user_data)
+{
+ struct mns_session *mns = user_data;
+ const char *type = obex_get_type(os);
+ const char *name = obex_get_name(os);
+ int ret;
+
+ DBG("PUT: name %s type %s mns %p", name, type, mns);
+
+ if (type == NULL)
+ return -EBADR;
+
+ ret = get_params(os, mns);
+ if (ret < 0)
+ goto failed;
+
+ ret = obex_put_stream_start(os, name);
+ if (ret < 0)
+ goto failed;
+
+ return 0;
+
+failed:
+ reset_request(mns);
+
+ return ret;
+}
+
+static void parse_event_report_type(struct map_event *event, const char *value)
+{
+ if (!g_ascii_strcasecmp(value, "NewMessage"))
+ event->type = MAP_ET_NEW_MESSAGE;
+ else if (!g_ascii_strcasecmp(value, "DeliverySuccess"))
+ event->type = MAP_ET_DELIVERY_SUCCESS;
+ else if (!g_ascii_strcasecmp(value, "SendingSuccess"))
+ event->type = MAP_ET_SENDING_SUCCESS;
+ else if (!g_ascii_strcasecmp(value, "DeliveryFailure"))
+ event->type = MAP_ET_DELIVERY_FAILURE;
+ else if (!g_ascii_strcasecmp(value, "SendingFailure"))
+ event->type = MAP_ET_SENDING_FAILURE;
+ else if (!g_ascii_strcasecmp(value, "MemoryFull"))
+ event->type = MAP_ET_MEMORY_FULL;
+ else if (!g_ascii_strcasecmp(value, "MemoryAvailable"))
+ event->type = MAP_ET_MEMORY_AVAILABLE;
+ else if (!g_ascii_strcasecmp(value, "MessageDeleted"))
+ event->type = MAP_ET_MESSAGE_DELETED;
+ else if (!g_ascii_strcasecmp(value, "MessageShift"))
+ event->type = MAP_ET_MESSAGE_SHIFT;
+}
+
+static void parse_event_report_handle(struct map_event *event,
+ const char *value)
+{
+ event->handle = g_strdup(value);
+}
+
+static void parse_event_report_folder(struct map_event *event,
+ const char *value)
+{
+ event->folder = g_strdup(value);
+}
+
+static void parse_event_report_old_folder(struct map_event *event,
+ const char *value)
+{
+ event->old_folder = g_strdup(value);
+}
+
+static void parse_event_report_msg_type(struct map_event *event,
+ const char *value)
+{
+ event->msg_type = g_strdup(value);
+}
+
+static struct map_event_report_parser {
+ const char *name;
+ void (*func) (struct map_event *event, const char *value);
+} event_report_parsers[] = {
+ { "type", parse_event_report_type },
+ { "handle", parse_event_report_handle },
+ { "folder", parse_event_report_folder },
+ { "old_folder", parse_event_report_old_folder },
+ { "msg_type", parse_event_report_msg_type },
+ { }
+};
+
+static void event_report_element(GMarkupParseContext *ctxt,
+ const gchar *element, const gchar **names,
+ const gchar **values, gpointer user_data,
+ GError **gerr)
+{
+ struct map_event *event = user_data;
+ const gchar *key;
+ gint i;
+
+ if (strcasecmp("event", element) != 0)
+ return;
+
+ for (i = 0, key = names[i]; key; key = names[++i]) {
+ struct map_event_report_parser *parser;
+
+ for (parser = event_report_parsers; parser && parser->name;
+ parser++) {
+ if (strcasecmp(key, parser->name) == 0) {
+ parser->func(event, values[i]);
+ break;
+ }
+ }
+ }
+}
+
+static const GMarkupParser event_report_parser = {
+ event_report_element,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void map_event_free(struct map_event *event)
+{
+ g_free(event->handle);
+ g_free(event->folder);
+ g_free(event->old_folder);
+ g_free(event->msg_type);
+ g_free(event);
+}
+
+static void *event_report_open(const char *name, int oflag, mode_t mode,
+ void *driver_data, size_t *size, int *err)
+{
+ struct mns_session *mns = driver_data;
+
+ DBG("");
+
+ g_obex_apparam_get_uint8(mns->inparams, MAP_AP_MASINSTANCEID,
+ &mns->mas_instance_id);
+
+ mns->buffer = g_string_new("");
+
+ if (*err < 0)
+ return NULL;
+ else
+ return mns;
+}
+
+static int event_report_close(void *obj)
+{
+ struct mns_session *mns = obj;
+ GMarkupParseContext *ctxt;
+ struct map_event *event;
+
+ event = g_new0(struct map_event, 1);
+ ctxt = g_markup_parse_context_new(&event_report_parser, 0, event,
+ NULL);
+ g_markup_parse_context_parse(ctxt, mns->buffer->str, mns->buffer->len,
+ NULL);
+ g_markup_parse_context_free(ctxt);
+
+ DBG("Received event report for instance %d", mns->mas_instance_id);
+ DBG("type=%x, handle=%s, folder=%s, old_folder=%s, msg_type=%s",
+ event->type, event->handle, event->folder,
+ event->old_folder, event->msg_type);
+
+ map_event_free(event);
+
+ reset_request(mns);
+
+ return 0;
+}
+
+static ssize_t event_report_write(void *obj, const void *buf, size_t count)
+{
+ struct mns_session *mns = obj;
+
+ DBG("");
+
+ g_string_append_len(mns->buffer, buf, count);
+ return count;
+}
+
+static struct obex_service_driver mns = {
+ .name = "Message Notification server",
+ .service = OBEX_MNS,
+ .target = MNS_TARGET,
+ .target_size = TARGET_SIZE,
+ .connect = mns_connect,
+ .put = mns_put,
+ .disconnect = mns_disconnect,
+};
+
+static struct obex_mime_type_driver mime_event_report = {
+ .target = MNS_TARGET,
+ .target_size = TARGET_SIZE,
+ .mimetype = "x-bt/MAP-event-report",
+ .open = event_report_open,
+ .close = event_report_close,
+ .write = event_report_write,
+};
+
+static struct obex_mime_type_driver *mas_drivers[] = {
+ &mime_event_report,
+ NULL
+};
+
+static int mns_init(void)
+{
+ int err;
+
+ err = obex_mime_type_driver_register(&mime_event_report);
+ if (err < 0)
+ goto fail_mime_event;
+
+ err = obex_service_driver_register(&mns);
+ if (err < 0)
+ goto fail_mns_reg;
+
+ return 0;
+
+fail_mns_reg:
+ obex_mime_type_driver_unregister(&mime_event_report);
+fail_mime_event:
+ return err;
+}
+
+static void mns_exit(void)
+{
+ obex_service_driver_unregister(&mns);
+ obex_mime_type_driver_unregister(&mime_event_report);
+}
+
+OBEX_PLUGIN_DEFINE(mns, mns_init, mns_exit)
diff --git a/obexd/plugins/bluetooth.c b/obexd/plugins/bluetooth.c
index f80faa4..b9e9c91 100644
--- a/obexd/plugins/bluetooth.c
+++ b/obexd/plugins/bluetooth.c
@@ -336,6 +336,8 @@ static const char *service2uuid(uint16_t service)
return "00000002-0000-1000-8000-0002ee000002";
case OBEX_MAS:
return OBEX_MAS_UUID;
+ case OBEX_MNS:
+ return OBEX_MNS_UUID;
}
return NULL;
diff --git a/obexd/src/obexd.h b/obexd/src/obexd.h
index 1c9b2b3..42c3c4d 100644
--- a/obexd/src/obexd.h
+++ b/obexd/src/obexd.h
@@ -29,6 +29,7 @@
#define OBEX_PCSUITE (1 << 6)
#define OBEX_SYNCEVOLUTION (1 << 7)
#define OBEX_MAS (1 << 8)
+#define OBEX_MNS (1 << 9)
gboolean plugin_init(const char *pattern, const char *exclude);
void plugin_cleanup(void);
diff --git a/src/profile.c b/src/profile.c
index 631a03f..89eed11 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -435,6 +435,44 @@
</attribute> \
</record>"
+#define MNS_RECORD \
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
+ <record> \
+ <attribute id=\"0x0001\"> \
+ <sequence> \
+ <uuid value=\"0x1133\"/> \
+ </sequence> \
+ </attribute> \
+ <attribute id=\"0x0004\"> \
+ <sequence> \
+ <sequence> \
+ <uuid value=\"0x0100\"/> \
+ </sequence> \
+ <sequence> \
+ <uuid value=\"0x0003\"/> \
+ <uint8 value=\"0x%02x\"/> \
+ </sequence> \
+ <sequence> \
+ <uuid value=\"0x0008\"/> \
+ </sequence> \
+ </sequence> \
+ </attribute> \
+ <attribute id=\"0x0009\"> \
+ <sequence> \
+ <sequence> \
+ <uuid value=\"0x1134\"/> \
+ <uint16 value=\"0x%04x\"/> \
+ </sequence> \
+ </sequence> \
+ </attribute> \
+ <attribute id=\"0x0100\"> \
+ <text value=\"%s\"/> \
+ </attribute> \
+ <attribute id=\"0x0200\"> \
+ <uint16 value=\"%u\" name=\"psm\"/> \
+ </attribute> \
+ </record>"
+
#define SYNC_RECORD \
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
<record> \
@@ -1709,6 +1747,20 @@ static char *get_mas_record(struct ext_profile *ext, struct ext_io *l2cap,
ext->name);
}
+static char *get_mns_record(struct ext_profile *ext, struct ext_io *l2cap,
+ struct ext_io *rfcomm)
+{
+ uint16_t psm = 0;
+ uint8_t chan = 0;
+
+ if (l2cap)
+ psm = l2cap->psm;
+ if (rfcomm)
+ chan = rfcomm->chan;
+
+ return g_strdup_printf(MNS_RECORD, chan, ext->version, ext->name, psm);
+}
+
static char *get_sync_record(struct ext_profile *ext, struct ext_io *l2cap,
struct ext_io *rfcomm)
{
@@ -1899,6 +1951,9 @@ static struct default_settings {
.uuid = OBEX_MNS_UUID,
.name = "Message Notification",
.channel = MNS_DEFAULT_CHANNEL,
+ .psm = BTD_PROFILE_PSM_AUTO,
+ .get_record = get_mns_record,
+ .version = 0x0100
},
};
--
1.8.1.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox