Linux bluetooth development
 help / color / mirror / Atom feed
* RE: [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Bing Zhao @ 2013-09-23 19:18 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: linux-bluetooth@vger.kernel.org, Gustavo Padovan, Johan Hedberg,
	linux-wireless@vger.kernel.org, Mike Frysinger, Hyuckjoo Lee,
	Amitkumar Karwar
In-Reply-To: <18678858-E711-43E5-AFE6-E637D1CECFFB@holtmann.org>

Hi Marcel,

> > -	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
> > +	hdev->setup =3D btmrvl_setup;
>=20
> just to make sure you guys understand how ->setup() works. It is only cal=
led once. Bringing the
> adapter down and up again does not call ->setup() a second time. So do yo=
u guys need this setup_done
> variable and if so, then you need to be a bit more verbose and help me un=
derstand why.

It's observed that sometimes the setup handler is called twice when Bluetoo=
th daemon is running in background. We will rebase to latest commit on blue=
tooth-next tree and test again. If the issue is gone with the latest code i=
n -next tree we will remove the setup_done flag.

Thanks,
Bing

^ permalink raw reply

* [PATCH 08/12] bluetooth: Remove extern from function prototypes
From: Joe Perches @ 2013-09-23 18:37 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, linux-kernel, Marcel Holtmann, Gustavo Padovan,
	Johan Hedberg, linux-bluetooth
In-Reply-To: <445209f8885ccd8234fa787c30d63e63fc7917d7.1379961014.git.joe@perches.com>

There are a mix of function prototypes with and without extern
in the kernel sources.  Standardize on not using extern for
function prototypes.

Function prototypes don't need to be written with extern.
extern is assumed by the compiler.  Its use is as unnecessary as
using auto to declare automatic/local variables in a block.

Signed-off-by: Joe Perches <joe@perches.com>
---
 include/net/bluetooth/bluetooth.h | 16 ++++++++--------
 include/net/bluetooth/hci_core.h  | 23 +++++++++++------------
 include/net/bluetooth/rfcomm.h    |  4 ++--
 3 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 10d43d8..13d6c39 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -331,16 +331,16 @@ out:
 
 int bt_to_errno(__u16 code);
 
-extern int hci_sock_init(void);
-extern void hci_sock_cleanup(void);
+int hci_sock_init(void);
+void hci_sock_cleanup(void);
 
-extern int bt_sysfs_init(void);
-extern void bt_sysfs_cleanup(void);
+int bt_sysfs_init(void);
+void bt_sysfs_cleanup(void);
 
-extern int  bt_procfs_init(struct net *net, const char *name,
-			   struct bt_sock_list* sk_list,
-			   int (* seq_show)(struct seq_file *, void *));
-extern void bt_procfs_cleanup(struct net *net, const char *name);
+int bt_procfs_init(struct net *net, const char *name,
+		   struct bt_sock_list *sk_list,
+		   int (*seq_show)(struct seq_file *, void *));
+void bt_procfs_cleanup(struct net *net, const char *name);
 
 extern struct dentry *bt_debugfs;
 
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3ede820..5769061 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -367,18 +367,17 @@ extern rwlock_t hci_dev_list_lock;
 extern rwlock_t hci_cb_list_lock;
 
 /* ----- HCI interface to upper protocols ----- */
-extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
-extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
-extern int l2cap_disconn_ind(struct hci_conn *hcon);
-extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
-extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
-extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
-			      u16 flags);
-
-extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
-extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
-extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
-extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
+int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
+int l2cap_disconn_ind(struct hci_conn *hcon);
+void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
+int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
+int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
+
+int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
+void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
+void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
+int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
 
 /* ----- Inquiry cache ----- */
 #define INQUIRY_CACHE_AGE_MAX   (HZ*30)   /* 30 seconds */
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 7afd419..b7f43e7 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -256,8 +256,8 @@ static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
 		rfcomm_dlc_free(d);
 }
 
-extern void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
-extern void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
+void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
+void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
 
 static inline void rfcomm_dlc_throttle(struct rfcomm_dlc *d)
 {
-- 
1.8.1.2.459.gbcd45b4.dirty

^ permalink raw reply related

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Frederic Danis @ 2013-09-23  9:51 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <226042C8-264A-469E-8D6A-F41141DC0552@holtmann.org>

Hello Marcel,

On 21/09/2013 19:14, Marcel Holtmann wrote:
> Hi Fred,
>
>> Define local mapping to glib path, otherwise this has to be inside central
>> place in the build repository.
>>
>> Retrieve Bluetooth version from configure.ac.
>> ---
>> .gitignore         |    2 +
>> Android.mk         |    9 ++++
>> Makefile.am        |    1 +
>> Makefile.android   |    7 ++++
>> android/Android.mk |   24 +++++++++++
>> android/main.c     |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> configure.ac       |    5 +++
>> 7 files changed, 167 insertions(+)
>> create mode 100644 Android.mk
>> create mode 100644 Makefile.android
>> create mode 100644 android/Android.mk
>> create mode 100644 android/main.c
>
> lets split this out a little bit. Code additions should not be intermixed with additions to the build system and especially configure options.
>
> I rather not have a top-level Android.mk. It should be enough to provide an android/Android.mk.
>
>> diff --git a/.gitignore b/.gitignore
>> index 8a25a3e..331a18b 100644
>> --- a/.gitignore
>> +++ b/.gitignore
>> @@ -98,3 +98,5 @@ unit/test-gobex-packet
>> unit/test-gobex-transfer
>> unit/test-*.log
>> unit/test-*.trs
>> +
>> +android/bluezd
>
> If we keep using prefix btd_ for certain set of functions, then it might be better if the daemon is build as android/bluetoothd or android/btd.

OK, I will rename it android/bluetoothd

>
> <snip>
>
>> +
>> +#ifdef HAVE_CONFIG_H
>> +#include <config.h>
>> +#endif
>> +
>> +#include <signal.h>
>> +#include <stdint.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +
>> +#include <glib.h>
>> +
>> +#include "hcid.h"
>
> I do not think we need to include hcid.h here. If we for some reason still do, then please try to cleanup that first.

OK, I will remove it

>
>> +
>> +#define SHUTDOWN_GRACE_SECONDS 10
>> +
>> +static GMainLoop *event_loop;
>> +
>> +void btd_exit(void)
>> +{
>> +	g_main_loop_quit(event_loop);
>> +}
>> +
>> +static gboolean quit_eventloop(gpointer user_data)
>> +{
>> +	btd_exit();
>> +	return FALSE;
>> +}
>> +
>> +static void signal_handler(int sig)
>> +{
>> +	static unsigned int __terminated = 0;
>
> Make this static volatile bool __terminated = false instead. Remember that you are actually using signals here and not signalfd.

OK, I will do this.

>
>> +
>> +	switch (sig) {
>> +	case SIGINT:
>> +	case SIGTERM:
>> +		if (__terminated == 0) {
>> +			g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
>> +							quit_eventloop, NULL);
>> +		}
>> +
>> +		__terminated = 1;
>> +		break;
>> +	}
>> +}
>> +
>> +static gboolean option_detach = TRUE;
>> +static gboolean option_version = FALSE;
>> +
>> +static GOptionEntry options[] = {
>> +	{ "nodetach", 'n', G_OPTION_FLAG_REVERSE,
>> +				G_OPTION_ARG_NONE, &option_detach,
>> +				"Run with logging in foreground", NULL },
>
> Do we need this option at all. I think we should always run in foreground and the system manager need to make sure we are spawned.

I think this is useful when debugging in conjonction with debug option 
and logging to console.

>
>> +	{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
>> +				"Show version information and exit", NULL },
>> +	{ NULL }
>> +};
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +	GOptionContext *context;
>> +	GError *err = NULL;
>> +	struct sigaction sa;
>> +
>> +	context = g_option_context_new(NULL);
>> +	g_option_context_add_main_entries(context, options, NULL);
>> +
>> +	if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
>> +		if (err != NULL) {
>> +			g_printerr("%s\n", err->message);
>> +			g_error_free(err);
>> +		} else
>> +			g_printerr("An unknown error occurred\n");
>> +		exit(1);
>> +	}
>> +
>> +	g_option_context_free(context);
>> +
>> +	if (option_version == TRUE) {
>> +		printf("%s\n", VERSION);
>> +		exit(0);
>
> I prefer if we start using return EXIT_SUCCESS and in error case EXIT_FAILURE.

OK, I will do this.

>
>> +	}
>> +
>> +	event_loop = g_main_loop_new(NULL, FALSE);
>> +
>> +	memset(&sa, 0, sizeof(sa));
>> +	sa.sa_handler = signal_handler;
>> +	sigaction(SIGINT, &sa, NULL);
>> +	sigaction(SIGTERM, &sa, NULL);
>> +
>> +	g_main_loop_run(event_loop);
>> +
>> +	g_main_loop_unref(event_loop);
>> +
>> +	return 0;
>> +}
>> diff --git a/configure.ac b/configure.ac
>> index 41c2935..3b7a5d9 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -242,4 +242,9 @@ AC_DEFINE_UNQUOTED(CONFIGDIR, "${configdir}",
>> 			[Directory for the configuration files])
>> AC_SUBST(CONFIGDIR, "${configdir}")
>>
>> +AC_ARG_ENABLE(android-daemon, AC_HELP_STRING([--enable-android-daemon],
>> +			[enable BlueZ Android daemon]),
>> +					[android_daemon=${enableval}])
>> +AM_CONDITIONAL(ANDROID_DAEMON, test "${android_daemon}" = "yes")
>> +
>
> This needs to be a separate patch. And it should just say --enable-android.
>
> In addition it needs to be added to bootstrap-configure and distcheck handling.

OK

Regards

Fred

-- 
Frederic Danis                            Open Source Technology Center
frederic.danis@intel.com                              Intel Corporation

^ permalink raw reply

* [PATCH v2 4/4] obexd: Clarify the folder property of PushMessage
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

The folder property of PushMessages does not accept path information,
it allows only to request the messages to be added to a subfolder of the
current folder.
---
 doc/obex-api.txt | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/doc/obex-api.txt b/doc/obex-api.txt
index 28343f6..eda7cb9 100644
--- a/doc/obex-api.txt
+++ b/doc/obex-api.txt
@@ -638,8 +638,9 @@ Methods		void SetFolder(string name)
 			Transfer a message (in bMessage format) to the
 			remote device.
 
-			The message is transferred either to the given folder,
-			or to the current folder if folder is omitted.
+			The message is transferred either to the given
+			subfolder of the current folder, or to the current
+			folder if folder is empty.
 
 			Possible args: Transparent, Retry, Charset
 
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 3/4] obexd: Clarify the folder property of ListMessages
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

The folder property of ListMessages does not accept path information,
it allows only to request the messages of a subfolder of the current
folder.
---
 doc/obex-api.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/obex-api.txt b/doc/obex-api.txt
index 0a8e632..28343f6 100644
--- a/doc/obex-api.txt
+++ b/doc/obex-api.txt
@@ -538,7 +538,8 @@ Methods		void SetFolder(string name)
 		array{object, dict} ListMessages(string folder, dict filter)
 
 			Returns an array containing the messages found in the
-			given folder.
+			given subfolder of the current folder, or in the
+			current folder if folder is empty.
 
 			Possible Filters: Offset, MaxCount, SubjectLength, Fields,
 			Type, PeriodStart, PeriodEnd, Status, Recipient, Sender,
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 2/4] obexd: Fix setting message folder for relative folder in ListMessages
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

The method ListMessages allows to specify a relative subfolder.
This subfolder needs to be added to the current path when registering
a new message interface.
---
 obexd/client/map.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 131b140..45b4ef1 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -103,6 +103,7 @@ struct map_data {
 struct pending_request {
 	struct map_data *map;
 	DBusMessage *msg;
+	char *folder;
 };
 
 #define MAP_MSG_FLAG_PRIORITY	0x01
@@ -154,6 +155,7 @@ static void pending_request_free(struct pending_request *p)
 {
 	dbus_message_unref(p->msg);
 
+	g_free(p->folder);
 	g_free(p);
 }
 
@@ -1098,8 +1100,7 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 
 	msg = g_hash_table_lookup(data->messages, values[i]);
 	if (msg == NULL) {
-		msg = map_msg_create(data, values[i],
-					obc_session_get_folder(data->session));
+		msg = map_msg_create(data, values[i], parser->request->folder);
 		if (msg == NULL)
 			return;
 	}
@@ -1195,6 +1196,17 @@ done:
 	pending_request_free(request);
 }
 
+static char *get_absolute_folder(const char *root, const char *subfolder)
+{
+	if (!subfolder || strlen(subfolder) == 0)
+		return g_strdup(root);
+	else
+		if (g_str_has_suffix(root, "/"))
+			return g_strconcat(root, subfolder, NULL);
+		else
+			return g_strconcat(root, "/", subfolder, NULL);
+}
+
 static DBusMessage *get_message_listing(struct map_data *map,
 							DBusMessage *message,
 							const char *folder,
@@ -1214,6 +1226,8 @@ static DBusMessage *get_message_listing(struct map_data *map,
 	obc_transfer_set_apparam(transfer, apparam);
 
 	request = pending_request_new(map, message);
+	request->folder = get_absolute_folder(obc_session_get_folder(
+							map->session), folder);
 
 	if (!obc_session_queue(map->session, transfer, message_listing_cb,
 							request, &err)) {
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 1/4] obexd: Add folder property to map_msg_create
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

Message interfaces are not necessarily created for the current folder,
therefore the folder needs to be specified in a parameter.

For example, messages can be created for sub folders when using the folder
parameter in ListMessages.
---
 obexd/client/map.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 9fe872d..131b140 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -809,7 +809,8 @@ static const GDBusPropertyTable map_msg_properties[] = {
 	{ }
 };
 
-static struct map_msg *map_msg_create(struct map_data *data, const char *handle)
+static struct map_msg *map_msg_create(struct map_data *data, const char *handle,
+							const char *folder)
 {
 	struct map_msg *msg;
 
@@ -818,7 +819,7 @@ static struct map_msg *map_msg_create(struct map_data *data, const char *handle)
 	msg->path = g_strdup_printf("%s/message%s",
 					obc_session_get_path(data->session),
 					handle);
-	msg->folder = g_strdup(obc_session_get_folder(data->session));
+	msg->folder = g_strdup(folder);
 
 	if (!g_dbus_register_interface(conn, msg->path, MAP_MSG_INTERFACE,
 						map_msg_methods, NULL,
@@ -1097,7 +1098,8 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 
 	msg = g_hash_table_lookup(data->messages, values[i]);
 	if (msg == NULL) {
-		msg = map_msg_create(data, values[i]);
+		msg = map_msg_create(data, values[i],
+					obc_session_get_folder(data->session));
 		if (msg == NULL)
 			return;
 	}
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 0/4] obexd: Fix setting message folder
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

This fixes an issue that the folder property for messages was set incorrectly
when ListMessages got called with a subfolder parameter.

Calling ListMessages within /telecom/msg for the subfolder inbox would set the
folder property to /telecom/msg instead of /telecom/msg/inbox.

The patchset therefore changes map_msg_create to not set the folder property
to the current folder, but to a folder given as parameter. This change will be
needed as well for new message notifications (that can indicate new messages
for any folder).

In addition I've updated the documentation to clarify that the folder property
for ListMessages and PushMessage can be used only for a subfolder of the
current folder. It's not possible to specify an absolute or relative path.

--
v2: Store folder in MAP pending request

Christian Fetzer (4):
  obexd: Add folder property to map_msg_create
  obexd: Fix setting message folder for relative folder in ListMessages
  obexd: Clarify the folder property of ListMessages
  obexd: Clarify the folder property of PushMessage

 doc/obex-api.txt   |  8 +++++---
 obexd/client/map.c | 22 +++++++++++++++++++---
 2 files changed, 24 insertions(+), 6 deletions(-)

-- 
1.8.3.4


^ permalink raw reply

* Problems with too many connections
From: Markus Roppelt @ 2013-09-23  9:04 UTC (permalink / raw)
  To: linux-bluetooth

[-- Attachment #1: Type: text/plain, Size: 684 bytes --]

Hi,

I want to write an application which repeats the following procedure
for several (100+) bluetooth (low energy) devices:

1. connect
2. read register values
3. disconnect

Therefore I modified the source code from /attrib/interactive.c.  For
testing purposes I am only looping  over one device. See attached
source code.

The code works fine. It connects, reads the values and disconnects.
However, after 1020 repetitions, the following error occurs:
(process:10205): GLib-WARNING **: poll(2) failed due to: Invalid argument.

I think the problem has to do with some sockets / file descriptors not
being closed properly.

Can someone help me to get this fixed?

Thank you
 Markus

[-- Attachment #2: loop.c --]
[-- Type: text/x-csrc, Size: 22672 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2011  Nokia Corporation
 *
 *
 *  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 <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <glib.h>

#include <readline/readline.h>
#include <readline/history.h>

#include "lib/uuid.h"
#include <btio/btio.h>
#include "att.h"
#include "gattrib.h"
#include "gatt.h"
#include "gatttool.h"
#include "client/display.h"

static GIOChannel *iochannel = NULL;
static GAttrib *attrib = NULL;
static GMainLoop *event_loop;
static GString *prompt;

static char *opt_src = NULL;
static char *opt_dst = NULL;
static char *opt_dst_type = NULL;
static char *opt_sec_level = NULL;
static int opt_psm = 0;
static int opt_mtu = 0;
static int start;
static int end;

static gboolean requested_read;
static gboolean done_read;

static void cmd_help(int argcp, char **argvp);

static enum state {
	STATE_DISCONNECTED,
	STATE_CONNECTING,
	STATE_CONNECTED
} conn_state;

static int loop_counter;

#define error(fmt, arg...) \
	rl_printf(COLOR_RED "Error: " COLOR_OFF fmt, ## arg)

#define failed(fmt, arg...) \
	rl_printf(COLOR_RED "Command Failed: " COLOR_OFF fmt, ## arg)

static char *get_prompt(void)
{
	if (conn_state == STATE_CONNECTED)
		g_string_assign(prompt, COLOR_BLUE);
	else
		g_string_assign(prompt, "");

	if (opt_dst)
		g_string_append_printf(prompt, "[%17s]", opt_dst);
	else
		g_string_append_printf(prompt, "[%17s]", "");

	if (conn_state == STATE_CONNECTED)
		g_string_append(prompt, COLOR_OFF);

	if (opt_psm)
		g_string_append(prompt, "[BR]");
	else
		g_string_append(prompt, "[LE]");

	g_string_append(prompt, "> ");

	return prompt->str;
}


static void set_state(enum state st)
{
	conn_state = st;
	rl_set_prompt(get_prompt());
}

static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
{
	uint8_t *opdu;
	uint16_t handle, i, olen;
	size_t plen;
	GString *s;

	handle = att_get_u16(&pdu[1]);

	switch (pdu[0]) {
	case ATT_OP_HANDLE_NOTIFY:
		s = g_string_new(NULL);
		g_string_printf(s, "Notification handle = 0x%04x value: ",
									handle);
		break;
	case ATT_OP_HANDLE_IND:
		s = g_string_new(NULL);
		g_string_printf(s, "Indication   handle = 0x%04x value: ",
									handle);
		break;
	default:
		error("Invalid opcode\n");
		return;
	}

	for (i = 3; i < len; i++)
		g_string_append_printf(s, "%02x ", pdu[i]);

	rl_printf("%s\n", s->str);
	g_string_free(s, TRUE);

	if (pdu[0] == ATT_OP_HANDLE_NOTIFY)
		return;

	opdu = g_attrib_get_buffer(attrib, &plen);
	olen = enc_confirmation(opdu, plen);

	if (olen > 0)
		g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}

static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
	if (err) {
		set_state(STATE_DISCONNECTED);
		error("%s\n", err->message);
		return;
	}

	attrib = g_attrib_new(iochannel);
	g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
						events_handler, attrib, NULL);
	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
						events_handler, attrib, NULL);
	set_state(STATE_CONNECTED);
	rl_printf("Connection successful\n");
}

static void disconnect_io()
{
	if (conn_state == STATE_DISCONNECTED)
		return;

	g_attrib_unref(attrib);
	attrib = NULL;
	opt_mtu = 0;

	g_io_channel_shutdown(iochannel, FALSE, NULL);
	g_io_channel_unref(iochannel);
	iochannel = NULL;

	set_state(STATE_DISCONNECTED);
}

static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Discover all primary services failed: %s\n",
						att_ecode2str(status));
		return;
	}

	if (services == NULL) {
		error("No primary service found\n");
		return;
	}

	for (l = services; l; l = l->next) {
		struct gatt_primary *prim = l->data;
		rl_printf("attr handle: 0x%04x, end grp handle: 0x%04x uuid: %s\n",
				prim->range.start, prim->range.end, prim->uuid);
	}
}

static void primary_by_uuid_cb(GSList *ranges, guint8 status,
							gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Discover primary services by UUID failed: %s\n",
							att_ecode2str(status));
		return;
	}

	if (ranges == NULL) {
		error("No service UUID found\n");
		return;
	}

	for (l = ranges; l; l = l->next) {
		struct att_range *range = l->data;
		rl_printf("Starting handle: 0x%04x Ending handle: 0x%04x\n",
						range->start, range->end);
	}
}

static void included_cb(GSList *includes, guint8 status, gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Find included services failed: %s\n",
							att_ecode2str(status));
		return;
	}

	if (includes == NULL) {
		rl_printf("No included services found for this range\n");
		return;
	}

	for (l = includes; l; l = l->next) {
		struct gatt_included *incl = l->data;
		rl_printf("handle: 0x%04x, start handle: 0x%04x, "
					"end handle: 0x%04x uuid: %s\n",
					incl->handle, incl->range.start,
					incl->range.end, incl->uuid);
	}
}

static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Discover all characteristics failed: %s\n",
							att_ecode2str(status));
		return;
	}

	for (l = characteristics; l; l = l->next) {
		struct gatt_char *chars = l->data;

		rl_printf("handle: 0x%04x, char properties: 0x%02x, char value "
				"handle: 0x%04x, uuid: %s\n", chars->handle,
				chars->properties, chars->value_handle,
				chars->uuid);
	}
}

static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	struct att_data_list *list;
	guint8 format;
	uint16_t handle = 0xffff;
	int i;

	if (status != 0) {
		rl_printf("Discover descriptors finished: %s\n",
						att_ecode2str(status));
		return;
	}

	list = dec_find_info_resp(pdu, plen, &format);
	if (list == NULL)
		return;

	for (i = 0; i < list->num; i++) {
		char uuidstr[MAX_LEN_UUID_STR];
		uint8_t *value;
		bt_uuid_t uuid;

		value = list->data[i];
		handle = att_get_u16(value);

		if (format == 0x01)
			uuid = att_get_uuid16(&value[2]);
		else
			uuid = att_get_uuid128(&value[2]);

		bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
		rl_printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
	}

	att_data_list_free(list);

	if (handle != 0xffff && handle < end)
		gatt_discover_char_desc(attrib, handle + 1, end, char_desc_cb,
									NULL);
}

static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	uint8_t value[plen];
	ssize_t vlen;
	int i;
	GString *s;

	if (status != 0) {
		error("Characteristic value/descriptor read failed: %s\n",
							att_ecode2str(status));
		return;
	}

	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
	if (vlen < 0) {
		error("Protocol error\n");
		return;
	}

	s = g_string_new("Characteristic value/descriptor: ");
	for (i = 0; i < vlen; i++)
		g_string_append_printf(s, "%02x ", value[i]);

	rl_printf("%s\n", s->str);
	g_string_free(s, TRUE);
}

static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
					guint16 plen, gpointer user_data)
{
	struct att_data_list *list;
	int i;
	GString *s;

	if (status != 0) {
		error("Read characteristics by UUID failed: %s\n",
							att_ecode2str(status));
		return;
	}

	list = dec_read_by_type_resp(pdu, plen);
	if (list == NULL)
		return;

	s = g_string_new(NULL);
	for (i = 0; i < list->num; i++) {
		uint8_t *value = list->data[i];
		int j;

		g_string_printf(s, "handle: 0x%04x \t value: ",
							att_get_u16(value));
		value += 2;
		for (j = 0; j < list->len - 2; j++, value++)
			g_string_append_printf(s, "%02x ", *value);

		rl_printf("%s\n", s->str);
	}

	att_data_list_free(list);
	g_string_free(s, TRUE);
	
	done_read = 1;
}

static void cmd_exit(int argcp, char **argvp)
{
	rl_callback_handler_remove();
	g_main_loop_quit(event_loop);
}

static gboolean channel_watcher(GIOChannel *chan, GIOCondition cond,
				gpointer user_data)
{
	disconnect_io();

	return FALSE;
}

static void cmd_connect(int argcp, char **argvp)
{
	GError *gerr = NULL;

	if (conn_state != STATE_DISCONNECTED)
		return;

	if (argcp > 1) {
		g_free(opt_dst);
		opt_dst = g_strdup(argvp[1]);

		g_free(opt_dst_type);
		if (argcp > 2)
			opt_dst_type = g_strdup(argvp[2]);
		else
			opt_dst_type = g_strdup("public");
	}

	if (opt_dst == NULL) {
		error("Remote Bluetooth address required\n");
		return;
	}

	rl_printf("Attempting to connect to %s\n", opt_dst);
	set_state(STATE_CONNECTING);
	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
					opt_psm, opt_mtu, connect_cb, &gerr);
	if (iochannel == NULL) {
		set_state(STATE_DISCONNECTED);
		error("%s\n", gerr->message);
		g_error_free(gerr);
	} else
		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
}

static void cmd_disconnect(int argcp, char **argvp)
{
	disconnect_io();
}

static void cmd_primary(int argcp, char **argvp)
{
	bt_uuid_t uuid;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp == 1) {
		gatt_discover_primary(attrib, NULL, primary_all_cb, NULL);
		return;
	}

	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
		error("Invalid UUID\n");
		return;
	}

	gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL);
}

static int strtohandle(const char *src)
{
	char *e;
	int dst;

	errno = 0;
	dst = strtoll(src, &e, 16);
	if (errno != 0 || *e != '\0')
		return -EINVAL;

	return dst;
}

static void cmd_included(int argcp, char **argvp)
{
	int start = 0x0001;
	int end = 0xffff;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp > 1) {
		start = strtohandle(argvp[1]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
		end = start;
	}

	if (argcp > 2) {
		end = strtohandle(argvp[2]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	}

	gatt_find_included(attrib, start, end, included_cb, NULL);
}

static void cmd_char(int argcp, char **argvp)
{
	int start = 0x0001;
	int end = 0xffff;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp > 1) {
		start = strtohandle(argvp[1]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
	}

	if (argcp > 2) {
		end = strtohandle(argvp[2]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	}

	if (argcp > 3) {
		bt_uuid_t uuid;

		if (bt_string_to_uuid(&uuid, argvp[3]) < 0) {
			error("Invalid UUID\n");
			return;
		}

		gatt_discover_char(attrib, start, end, &uuid, char_cb, NULL);
		return;
	}

	gatt_discover_char(attrib, start, end, NULL, char_cb, NULL);
}

static void cmd_char_desc(int argcp, char **argvp)
{
	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp > 1) {
		start = strtohandle(argvp[1]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
	} else
		start = 0x0001;

	if (argcp > 2) {
		end = strtohandle(argvp[2]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	} else
		end = 0xffff;

	gatt_discover_char_desc(attrib, start, end, char_desc_cb, NULL);
}

static void cmd_read_hnd(int argcp, char **argvp)
{
	int handle;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 2) {
		error("Missing argument: handle\n");
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle < 0) {
		error("Invalid handle: %s\n", argvp[1]);
		return;
	}

	gatt_read_char(attrib, handle, char_read_cb, attrib);
}

static void cmd_read_uuid(int argcp, char **argvp)
{
	int start = 0x0001;
	int end = 0xffff;
	bt_uuid_t uuid;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 2) {
		error("Missing argument: UUID\n");
		return;
	}

	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
		error("Invalid UUID\n");
		return;
	}

	if (argcp > 2) {
		start = strtohandle(argvp[2]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
	}

	if (argcp > 3) {
		end = strtohandle(argvp[3]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	}

	gatt_read_char_by_uuid(attrib, start, end, &uuid, char_read_by_uuid_cb,
									NULL);
	
	requested_read = 1;
}

static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	if (status != 0) {
		error("Characteristic Write Request failed: "
						"%s\n", att_ecode2str(status));
		return;
	}

	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
		error("Protocol error\n");
		return;
	}

	rl_printf("Characteristic value was written successfully\n");
}

static void cmd_char_write(int argcp, char **argvp)
{
	uint8_t *value;
	size_t plen;
	int handle;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 3) {
		rl_printf("Usage: %s <handle> <new value>\n", argvp[0]);
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle <= 0) {
		error("A valid handle is required\n");
		return;
	}

	plen = gatt_attr_data_from_string(argvp[2], &value);
	if (plen == 0) {
		error("Invalid value\n");
		return;
	}

	if (g_strcmp0("char-write-req", argvp[0]) == 0)
		gatt_write_char(attrib, handle, value, plen,
					char_write_req_cb, NULL);
	else
		gatt_write_cmd(attrib, handle, value, plen, NULL, NULL);

	g_free(value);
}

static void cmd_sec_level(int argcp, char **argvp)
{
	GError *gerr = NULL;
	BtIOSecLevel sec_level;

	if (argcp < 2) {
		rl_printf("sec-level: %s\n", opt_sec_level);
		return;
	}

	if (strcasecmp(argvp[1], "medium") == 0)
		sec_level = BT_IO_SEC_MEDIUM;
	else if (strcasecmp(argvp[1], "high") == 0)
		sec_level = BT_IO_SEC_HIGH;
	else if (strcasecmp(argvp[1], "low") == 0)
		sec_level = BT_IO_SEC_LOW;
	else {
		rl_printf("Allowed values: low | medium | high\n");
		return;
	}

	g_free(opt_sec_level);
	opt_sec_level = g_strdup(argvp[1]);

	if (conn_state != STATE_CONNECTED)
		return;

	if (opt_psm) {
		rl_printf("Change will take effect on reconnection\n");
		return;
	}

	bt_io_set(iochannel, &gerr,
			BT_IO_OPT_SEC_LEVEL, sec_level,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s\n", gerr->message);
		g_error_free(gerr);
	}
}

static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	uint16_t mtu;

	if (status != 0) {
		error("Exchange MTU Request failed: %s\n",
						att_ecode2str(status));
		return;
	}

	if (!dec_mtu_resp(pdu, plen, &mtu)) {
		error("Protocol error\n");
		return;
	}

	mtu = MIN(mtu, opt_mtu);
	/* Set new value for MTU in client */
	if (g_attrib_set_mtu(attrib, mtu))
		rl_printf("MTU was exchanged successfully: %d\n", mtu);
	else
		error("Error exchanging MTU\n");
}

static void cmd_mtu(int argcp, char **argvp)
{
	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (opt_psm) {
		failed("Operation is only available for LE transport.\n");
		return;
	}

	if (argcp < 2) {
		rl_printf("Usage: mtu <value>\n");
		return;
	}

	if (opt_mtu) {
		failed("MTU exchange can only occur once per connection.\n");
		return;
	}

	errno = 0;
	opt_mtu = strtoll(argvp[1], NULL, 0);
	if (errno != 0 || opt_mtu < ATT_DEFAULT_LE_MTU) {
		error("Invalid value. Minimum MTU size is %d\n",
							ATT_DEFAULT_LE_MTU);
		return;
	}

	gatt_exchange_mtu(attrib, opt_mtu, exchange_mtu_cb, NULL);
}

static struct {
	const char *cmd;
	void (*func)(int argcp, char **argvp);
	const char *params;
	const char *desc;
} commands[] = {
	{ "help",		cmd_help,	"",
		"Show this help"},
	{ "exit",		cmd_exit,	"",
		"Exit interactive mode" },
	{ "quit",		cmd_exit,	"",
		"Exit interactive mode" },
	{ "connect",		cmd_connect,	"[address [address type]]",
		"Connect to a remote device" },
	{ "disconnect",		cmd_disconnect,	"",
		"Disconnect from a remote device" },
	{ "primary",		cmd_primary,	"[UUID]",
		"Primary Service Discovery" },
	{ "included",		cmd_included,	"[start hnd [end hnd]]",
		"Find Included Services" },
	{ "characteristics",	cmd_char,	"[start hnd [end hnd [UUID]]]",
		"Characteristics Discovery" },
	{ "char-desc",		cmd_char_desc,	"[start hnd] [end hnd]",
		"Characteristics Descriptor Discovery" },
	{ "char-read-hnd",	cmd_read_hnd,	"<handle>",
		"Characteristics Value/Descriptor Read by handle" },
	{ "char-read-uuid",	cmd_read_uuid,	"<UUID> [start hnd] [end hnd]",
		"Characteristics Value/Descriptor Read by UUID" },
	{ "char-write-req",	cmd_char_write,	"<handle> <new value>",
		"Characteristic Value Write (Write Request)" },
	{ "char-write-cmd",	cmd_char_write,	"<handle> <new value>",
		"Characteristic Value Write (No response)" },
	{ "sec-level",		cmd_sec_level,	"[low | medium | high]",
		"Set security level. Default: low" },
	{ "mtu",		cmd_mtu,	"<value>",
		"Exchange MTU for GATT/ATT" },
	{ NULL, NULL, NULL}
};

static void cmd_help(int argcp, char **argvp)
{
	int i;

	for (i = 0; commands[i].cmd; i++)
		rl_printf("%-15s %-30s %s\n", commands[i].cmd,
				commands[i].params, commands[i].desc);
}

static void parse_line(char *line_read)
{
	char **argvp;
	int argcp;
	int i;

	if (line_read == NULL) {
		rl_printf("\n");
		//cmd_exit(0, NULL);
		return;
	}

	line_read = g_strstrip(line_read);

	if (*line_read == '\0')
		goto done;

	add_history(line_read);

	if (g_shell_parse_argv(line_read, &argcp, &argvp, NULL) == FALSE)
		goto done;

	for (i = 0; commands[i].cmd; i++)
		if (strcasecmp(commands[i].cmd, argvp[0]) == 0)
			break;

	if (commands[i].cmd)
		commands[i].func(argcp, argvp);
	else
		error("%s: command not found\n", argvp[0]);

	g_strfreev(argvp);

done:
	;
	//free(line_read);
}

static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
							gpointer user_data)
{
	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
		g_io_channel_unref(chan);
		return FALSE;
	}

	rl_callback_read_char();

	return TRUE;
}

static char *completion_generator(const char *text, int state)
{
	static int index = 0, len = 0;
	const char *cmd = NULL;

	if (state == 0) {
		index = 0;
		len = strlen(text);
	}

	while ((cmd = commands[index].cmd) != NULL) {
		index++;
		if (strncmp(cmd, text, len) == 0)
			return strdup(cmd);
	}

	return NULL;
}

static char **commands_completion(const char *text, int start, int end)
{
	if (start == 0)
		return rl_completion_matches(text, &completion_generator);
	else
		return NULL;
}

static guint setup_standard_input(void)
{
	GIOChannel *channel;
	guint source;

	channel = g_io_channel_unix_new(fileno(stdin));

	source = g_io_add_watch(channel,
				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
				prompt_read, NULL);

	g_io_channel_unref(channel);

	return source;
}

static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
							gpointer user_data)
{
	static unsigned int __terminated = 0;
	struct signalfd_siginfo si;
	ssize_t result;
	int fd;

	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
		g_main_loop_quit(event_loop);
		return FALSE;
	}

	fd = g_io_channel_unix_get_fd(channel);

	result = read(fd, &si, sizeof(si));
	if (result != sizeof(si))
		return FALSE;

	switch (si.ssi_signo) {
	case SIGINT:
		rl_replace_line("", 0);
		rl_crlf();
		rl_on_new_line();
		rl_redisplay();
		break;
	case SIGTERM:
		if (__terminated == 0) {
			rl_replace_line("", 0);
			rl_crlf();
			g_main_loop_quit(event_loop);
		}

		__terminated = 1;
		break;
	}

	return TRUE;
}

static guint setup_signalfd(void)
{
	GIOChannel *channel;
	guint source;
	sigset_t mask;
	int fd;

	sigemptyset(&mask);
	sigaddset(&mask, SIGINT);
	sigaddset(&mask, SIGTERM);

	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
		perror("Failed to set signal mask");
		return 0;
	}

	fd = signalfd(-1, &mask, 0);
	if (fd < 0) {
		perror("Failed to create signal descriptor");
		return 0;
	}

	channel = g_io_channel_unix_new(fd);

	g_io_channel_set_close_on_unref(channel, TRUE);
	g_io_channel_set_encoding(channel, NULL, NULL);
	g_io_channel_set_buffered(channel, FALSE);

	source = g_io_add_watch(channel,
				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
				signal_handler, NULL);

	g_io_channel_unref(channel);

	return source;
}

gboolean callback_fastloop(GIOChannel *source, GIOCondition condition,gpointer data)
{
	if (conn_state == STATE_DISCONNECTED)
	{	
		if (conn_state != STATE_CONNECTING)
		{
		//request
		rl_printf("Requesting Connection \r\n");
		char cmdstring[] = "connect D1:83:15:3C:26:F0 random";
		parse_line((char *) &cmdstring);
		}	
		else
		{
		//wait for connection to be established
		usleep(1000);
		}
	}
	if (conn_state == STATE_CONNECTED)
	{
	// We are connected
		//if not connected 
		if (!requested_read)
		{
		rl_printf("Requesting Reading\r\n");
		//request read
		char cmdstring[] = "char-read-uuid 2a5b";
		parse_line((char *) &cmdstring);	
		requested_read = 1;		
		}	
		else
		{
		//wait until values are read
		usleep(1000);
		}
	}
	if (done_read)
	{
	rl_printf("Done Reading. Disconnecting\r\n");
	
	char cmdstring[] = "disconnect";
	parse_line((char *) &cmdstring);	
		
	//Reset values
	requested_read = 0;
	done_read = 0;
	
	rl_printf("Loop is %d\r\n",loop_counter);
	loop_counter += 1;
	}
    
	return 1;
}

int main(int argc, char *argv[]) {
    guint input;
    guint signal;

    opt_sec_level = g_strdup("low");

//	opt_src = g_strdup(src);
//	opt_dst = g_strdup(dst);
//	opt_dst_type = g_strdup(dst_type);
//	opt_psm = psm;

	conn_state = STATE_DISCONNECTED;
    prompt = g_string_new(NULL);

    event_loop = g_main_loop_new(NULL, FALSE);
	
	
	input = setup_standard_input();
    signal = setup_signalfd();
	
	requested_read = 0;
	done_read = 0;
	

	loop_counter = 0;
	
    g_timeout_add(1, (GSourceFunc) callback_fastloop, NULL);	
    g_main_loop_run(event_loop);
	

	rl_callback_handler_remove();
    cmd_disconnect(0, NULL);
    g_source_remove(input);
    g_source_remove(signal);
    g_main_loop_unref(event_loop);


    g_string_free(prompt, TRUE);

    g_free(opt_src);
    g_free(opt_dst);
    g_free(opt_sec_level);

    return 0;
}

^ permalink raw reply

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Andrei Emeltchenko @ 2013-09-23  7:59 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Frederic Danis, linux-bluetooth
In-Reply-To: <226042C8-264A-469E-8D6A-F41141DC0552@holtmann.org>

On Sat, Sep 21, 2013 at 12:14:55PM -0500, Marcel Holtmann wrote:
> Hi Fred,
> 
> > Define local mapping to glib path, otherwise this has to be inside central
> > place in the build repository.
> > 
> > Retrieve Bluetooth version from configure.ac.
> > ---
> > .gitignore         |    2 +
> > Android.mk         |    9 ++++
> > Makefile.am        |    1 +
> > Makefile.android   |    7 ++++
> > android/Android.mk |   24 +++++++++++
> > android/main.c     |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> > configure.ac       |    5 +++
> > 7 files changed, 167 insertions(+)
> > create mode 100644 Android.mk
> > create mode 100644 Makefile.android
> > create mode 100644 android/Android.mk
> > create mode 100644 android/main.c
> 
> lets split this out a little bit. Code additions should not be intermixed with additions to the build system and especially configure options.
> 
> I rather not have a top-level Android.mk. It should be enough to provide an android/Android.mk.
> 

I believe this way we cannot build our project.

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* Re: [PATCH 2/2] android: Android version of log.c
From: Andrei Emeltchenko @ 2013-09-23  7:48 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Frederic Danis, linux-bluetooth
In-Reply-To: <708DB870-5A40-4056-86C8-79092784757C@holtmann.org>

Hi all,

On Sat, Sep 21, 2013 at 12:20:52PM -0500, Marcel Holtmann wrote:
> Hi Fred,
> > +
> > +static void android_log(int pri, const char *fmt, va_list ap)
> > +{
> > +	char *msg;
> > +	struct iovec vec[3];
> > +
> > +	msg = g_strdup_vprintf(fmt, ap);
> > +
> > +	if (!detached) {
> > +		vec[0].iov_base = (void *) msg;
> > +		vec[0].iov_len = strlen(msg) + 1;
> > +		vec[1].iov_base = "\n";
> > +		vec[1].iov_len = 1;
> > +		writev(STDERR_FILENO, vec, 2);
> > +	}
> 
> Lets not worry about logging to stderr at all.

Then I believe this might be simplified a lot. We might use
__android_log_print - like functions in this case.

Best regards 
Andrei Emeltchenko 


^ permalink raw reply

* Re: [PATCH v2 0/8] decoupling adapter code from sdp
From: Johan Hedberg @ 2013-09-23  7:47 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1379599248-7923-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Thu, Sep 19, 2013, Szymon Janc wrote:
> This includes code removal from sdptool that is no longer fully usable
> with this serie.
> 
> Since Marcel had some objections about Device ID plugin patch it is moved
> to end to not interfere with rest of patches. This plugin now also handles
> setting proper DID values to adapter. Yet, main_opts are still accessed
> directly and that should be worked out later.
> 
> With those patches sdp server is fully controlled by adapters and there
> is no mutual adapter<->sdp code invocations.
> 
> BR
> Szymon
> 
> Szymon Janc (8):
>   adapter: Insert DeviceID record if setting DeviceID data to controller
>   adapter: Handle adding new SDP records
>   adapter: Handle removing of SDP records
>   Remove not needed sdp_init_services_list function
>   unit: Remove not needed functions from test-sdp
>   sdpd: Remove 'register' and 'remove' requests
>   sdptool: Remove support for adding and removing service records
>   sdp: Decouple Device ID profile implementation
> 
>  Makefile.plugins             |    3 +
>  plugins/gatt-example.c       |    2 +-
>  profiles/audio/a2dp.c        |   14 +-
>  profiles/audio/avrcp.c       |    8 +-
>  profiles/deviceid/deviceid.c |  187 +++
>  profiles/health/hdp.c        |    2 +-
>  profiles/health/hdp_util.c   |    6 +-
>  profiles/network/server.c    |    6 +-
>  profiles/sap/server.c        |    4 +-
>  src/adapter.c                |   59 +-
>  src/adapter.h                |    8 +-
>  src/attrib-server.c          |   12 +-
>  src/attrib-server.h          |    2 +-
>  src/profile.c                |    9 +-
>  src/sdpd-database.c          |   41 -
>  src/sdpd-request.c           |   14 -
>  src/sdpd-server.c            |    4 -
>  src/sdpd-service.c           |  158 ---
>  src/sdpd.h                   |    6 -
>  tools/sdptool.1              |   16 -
>  tools/sdptool.c              | 2595 +-----------------------------------------
>  unit/test-sdp.c              |   29 -
>  22 files changed, 321 insertions(+), 2864 deletions(-)
>  create mode 100644 profiles/deviceid/deviceid.c

Patches 1-5 have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH 2/5] Bluetooth: Fix assignment of 0/1 to bool variables
From: Gustavo Padovan @ 2013-09-22 22:21 UTC (permalink / raw)
  To: Peter Senna Tschudin
  Cc: marcel, johan.hedberg, davem, linux-bluetooth, netdev,
	linux-kernel, kernel-janitors
In-Reply-To: <1379875453-20083-2-git-send-email-peter.senna@gmail.com>

Hi Peter,

2013-09-22 Peter Senna Tschudin <peter.senna@gmail.com>:

> Convert 0 to false and 1 to true when assigning values to bool
> variables. Inspired by commit 3db1cd5c05f35fb43eb134df6f321de4e63141f2.
> 
> The simplified semantic patch that find this problem is as
> follows (http://coccinelle.lip6.fr/):
> 
> @@
> bool b;
> @@
> (
> -b = 0
> +b = false
> |
> -b = 1
> +b = true
> )
> 
> Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
> 
> ---
>  net/bluetooth/l2cap_core.c |   16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)

Patch has been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply

* Re: [PATCH 2/5] Bluetooth: Fix assignment of 0/1 to bool variables
From: Marcel Holtmann @ 2013-09-22 18:58 UTC (permalink / raw)
  To: Peter Senna Tschudin
  Cc: gustavo, johan.hedberg, davem, linux-bluetooth, netdev,
	linux-kernel, kernel-janitors
In-Reply-To: <1379875453-20083-2-git-send-email-peter.senna@gmail.com>

Hi Peter,

> Convert 0 to false and 1 to true when assigning values to bool
> variables. Inspired by commit 3db1cd5c05f35fb43eb134df6f321de4e63141f2.
> 
> The simplified semantic patch that find this problem is as
> follows (http://coccinelle.lip6.fr/):
> 
> @@
> bool b;
> @@
> (
> -b = 0
> +b = false
> |
> -b = 1
> +b = true
> )
> 
> Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>
> 
> ---
> net/bluetooth/l2cap_core.c |   16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel


^ permalink raw reply

* [PATCH 2/5] Bluetooth: Fix assignment of 0/1 to bool variables
From: Peter Senna Tschudin @ 2013-09-22 18:44 UTC (permalink / raw)
  To: marcel
  Cc: gustavo, johan.hedberg, davem, linux-bluetooth, netdev,
	linux-kernel, kernel-janitors, Peter Senna Tschudin
In-Reply-To: <1379875453-20083-1-git-send-email-peter.senna@gmail.com>

Convert 0 to false and 1 to true when assigning values to bool
variables. Inspired by commit 3db1cd5c05f35fb43eb134df6f321de4e63141f2.

The simplified semantic patch that find this problem is as
follows (http://coccinelle.lip6.fr/):

@@
bool b;
@@
(
-b = 0
+b = false
|
-b = 1
+b = true
)

Signed-off-by: Peter Senna Tschudin <peter.senna@gmail.com>

---
 net/bluetooth/l2cap_core.c |   16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff -u -p a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -5797,7 +5797,7 @@ static int l2cap_rx_state_recv(struct l2
 			       struct sk_buff *skb, u8 event)
 {
 	int err = 0;
-	bool skb_in_use = 0;
+	bool skb_in_use = false;
 
 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
 	       event);
@@ -5818,7 +5818,7 @@ static int l2cap_rx_state_recv(struct l2
 							   control->txseq);
 
 			chan->buffer_seq = chan->expected_tx_seq;
-			skb_in_use = 1;
+			skb_in_use = true;
 
 			err = l2cap_reassemble_sdu(chan, skb, control);
 			if (err)
@@ -5854,7 +5854,7 @@ static int l2cap_rx_state_recv(struct l2
 			 * current frame is stored for later use.
 			 */
 			skb_queue_tail(&chan->srej_q, skb);
-			skb_in_use = 1;
+			skb_in_use = true;
 			BT_DBG("Queued %p (queue len %d)", skb,
 			       skb_queue_len(&chan->srej_q));
 
@@ -5932,7 +5932,7 @@ static int l2cap_rx_state_srej_sent(stru
 {
 	int err = 0;
 	u16 txseq = control->txseq;
-	bool skb_in_use = 0;
+	bool skb_in_use = false;
 
 	BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
 	       event);
@@ -5944,7 +5944,7 @@ static int l2cap_rx_state_srej_sent(stru
 			/* Keep frame for reassembly later */
 			l2cap_pass_to_tx(chan, control);
 			skb_queue_tail(&chan->srej_q, skb);
-			skb_in_use = 1;
+			skb_in_use = true;
 			BT_DBG("Queued %p (queue len %d)", skb,
 			       skb_queue_len(&chan->srej_q));
 
@@ -5955,7 +5955,7 @@ static int l2cap_rx_state_srej_sent(stru
 
 			l2cap_pass_to_tx(chan, control);
 			skb_queue_tail(&chan->srej_q, skb);
-			skb_in_use = 1;
+			skb_in_use = true;
 			BT_DBG("Queued %p (queue len %d)", skb,
 			       skb_queue_len(&chan->srej_q));
 
@@ -5970,7 +5970,7 @@ static int l2cap_rx_state_srej_sent(stru
 			 * the missing frames.
 			 */
 			skb_queue_tail(&chan->srej_q, skb);
-			skb_in_use = 1;
+			skb_in_use = true;
 			BT_DBG("Queued %p (queue len %d)", skb,
 			       skb_queue_len(&chan->srej_q));
 
@@ -5984,7 +5984,7 @@ static int l2cap_rx_state_srej_sent(stru
 			 * SREJ'd frames.
 			 */
 			skb_queue_tail(&chan->srej_q, skb);
-			skb_in_use = 1;
+			skb_in_use = true;
 			BT_DBG("Queued %p (queue len %d)", skb,
 			       skb_queue_len(&chan->srej_q));
 

^ permalink raw reply

* [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Ken O'Brien @ 2013-09-21 18:14 UTC (permalink / raw)
  To: marcel, gustavo, johan.hedberg
  Cc: linux-bluetooth, linux-kernel, Ken O'Brien

Adding generic rule on encountering Belkin bluetooth usb device F8065bf.

Relevant section from /sys/kernel/debug/usb/devices:

T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
D:  Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=050d ProdID=065a Rev= 1.12
S:  Manufacturer=Broadcom Corp
S:  Product=BCM20702A0
S:  SerialNumber=0002723E2D29
C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E:  Ad=81(I) Atr=03(Int.) MxPS=  16 Ivl=1ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
I:  If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
I:  If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
I:  If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
I:  If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
I:  If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms
E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E:  Ad=84(I) Atr=02(Bulk) MxPS=  32 Ivl=0ms
E:  Ad=04(O) Atr=02(Bulk) MxPS=  32 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)

Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
---
 drivers/bluetooth/btusb.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8e16f0a..dbfbc12 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -111,7 +111,10 @@ static struct usb_device_id btusb_table[] = {
 
 	/*Broadcom devices with vendor specific id */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
-
+
+	/* Belkin F8065bf - Broadcom based */
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
+
 	{ }	/* Terminating entry */
 };
 
-- 
1.8.1.4

^ permalink raw reply related

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Johan Hedberg @ 2013-09-21 18:09 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Frederic Danis, linux-bluetooth
In-Reply-To: <226042C8-264A-469E-8D6A-F41141DC0552@holtmann.org>

Hi Marcel,

On Sat, Sep 21, 2013, Marcel Holtmann wrote:
> > Define local mapping to glib path, otherwise this has to be inside central
> > place in the build repository.
> > 
> > Retrieve Bluetooth version from configure.ac.
> > ---
> > .gitignore         |    2 +
> > Android.mk         |    9 ++++
> > Makefile.am        |    1 +
> > Makefile.android   |    7 ++++
> > android/Android.mk |   24 +++++++++++
> > android/main.c     |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> > configure.ac       |    5 +++
> > 7 files changed, 167 insertions(+)
> > create mode 100644 Android.mk
> > create mode 100644 Makefile.android
> > create mode 100644 android/Android.mk
> > create mode 100644 android/main.c
> 
> lets split this out a little bit. Code additions should not be
> intermixed with additions to the build system and especially configure
> options.

I agree about keeping separate build system changes such as adding
completely new makefiles or adding configure options. However, what I
think doesn't hurt (and the guidance I've given) is to at least include
the matching build system change to the same commit that adds new c/h
files. This way you don't end up having "dead code" in the tree in
between commits that just lies around there but can't be compiled and
wont be included in any release tarballs.

Johan

^ permalink raw reply

* Re: [PATCH v2 7/8] sdptool: Remove support for adding and removing service records
From: Marcel Holtmann @ 2013-09-21 17:27 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1379599248-7923-8-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

> SDP database should now be controlled only by adapters. SDP code
> is no longer able to notify controllers about external changes to
> database. This results in services added/removed by sdptool being
> not updated properly in adapter structure.
> ---
> tools/sdptool.1 |   16 -
> tools/sdptool.c | 2595 ++-----------------------------------------------------
> 2 files changed, 54 insertions(+), 2557 deletions(-)

this is a bit dangerous. We still need sdptool for qualification purposes. So I rather keep it around.

Regards

Marcel

> 
> diff --git a/tools/sdptool.1 b/tools/sdptool.1
> index 88ad818..ee95e67 100644
> --- a/tools/sdptool.1
> +++ b/tools/sdptool.1
> @@ -82,18 +82,6 @@ Browse all available services on the device
> specified by a Bluetooth address as a parameter.
> .IP "\fBrecords [--tree] [--raw] [--xml] bdaddr\fP" 10
> Retrieve all possible service records.
> -.IP "\fBadd [ --handle=N --channel=N ]\fP" 10
> -Add a service to the local
> -SDP database.
> -.IP "" 10
> -You can specify a handle for this record using
> -the \fB--handle\fP option.
> -.IP "" 10
> -You can specify a channel to add the service on
> -using the \fB--channel\fP option.
> -.IP "\fBdel record_handle\fP" 10
> -Remove a service from the local
> -SDP database.
> .IP "\fBget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\fP" 10
> Retrieve a service from the local
> SDP database.
> @@ -112,10 +100,6 @@ Displays help on using sdptool.
> sdptool browse 00:80:98:24:15:6D
> .PP
> sdptool browse local
> -.PP
> -sdptool add DUN
> -.PP
> -sdptool del 0x10000
> .SH "BUGS"
> .PP
> Documentation needs improving.
> diff --git a/tools/sdptool.c b/tools/sdptool.c
> index c241655..7d1121d 100644
> --- a/tools/sdptool.c
> +++ b/tools/sdptool.c
> @@ -1145,2148 +1145,30 @@ static void print_service_attr(sdp_record_t *rec)
> 	}
> }
> 
> -/*
> - * Support for Service (de)registration
> - */
> -typedef struct {
> -	uint32_t handle;
> -	char *name;
> -	char *provider;
> -	char *desc;
> -	unsigned int class;
> -	unsigned int profile;
> -	uint16_t psm;
> -	uint8_t channel;
> -	uint8_t network;
> -} svc_info_t;
> -
> -static int add_sp(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
> -	uuid_t root_uuid, sp_uuid, l2cap, rfcomm;
> -	sdp_profile_desc_t profile;
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel : 1;
> -	sdp_data_t *channel;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -	sdp_list_free(root, 0);
> -
> -	sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &sp_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -	sdp_list_free(svclass_id, 0);
> -
> -	sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
> -	profile.version = 0x0100;
> -	profiles = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, profiles);
> -	sdp_list_free(profiles, 0);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_add_lang_attr(&record);
> -
> -	sdp_set_info_attr(&record, "Serial Port", "BlueZ", "COM Port");
> -
> -	sdp_set_url_attr(&record, "http://www.bluez.org/",
> -			"http://www.bluez.org/", "http://www.bluez.org/");
> -
> -	sdp_set_service_id(&record, sp_uuid);
> -	sdp_set_service_ttl(&record, 0xffff);
> -	sdp_set_service_avail(&record, 0xff);
> -	sdp_set_record_state(&record, 0x00001234);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("Serial Port service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_dun(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto;
> -	uuid_t rootu, dun, gn, l2cap, rfcomm;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel : 2;
> -	sdp_data_t *channel;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &rootu);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &dun);
> -	sdp_uuid16_create(&gn,  GENERIC_NETWORKING_SVCLASS_ID);
> -	svclass_id = sdp_list_append(svclass_id, &gn);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID);
> -	profile.version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("Dial-Up Networking service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_fax(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel? si->channel : 3;
> -	sdp_data_t *channel;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &fax_uuid);
> -	sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
> -	svclass_id = sdp_list_append(svclass_id, &tel_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID);
> -	profile.version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq  = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Fax", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -	printf("Fax service registered\n");
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -	return ret;
> -}
> -
> -static int add_lan(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel : 4;
> -	sdp_data_t *channel;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&svclass_uuid, LAN_ACCESS_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, LAN_ACCESS_PROFILE_ID);
> -	profile.version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("LAN Access service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_headset(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel : 5;
> -	sdp_data_t *channel;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &svclass_uuid);
> -	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
> -	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
> -	profile.version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Headset", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("Headset service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_headset_ag(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel : 7;
> -	sdp_data_t *channel;
> -	uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
> -	sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &svclass_uuid);
> -	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
> -	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
> -	profile.version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
> -
> -	sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
> -
> -	if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("Headset AG service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_handsfree(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel : 6;
> -	uint16_t u16 = 0x31;
> -	sdp_data_t *channel, *features;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &svclass_uuid);
> -	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
> -	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
> -	profile.version = 0x0101;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	features = sdp_data_alloc(SDP_UINT16, &u16);
> -	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Handsfree", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("Handsfree service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel : 7;
> -	uint16_t u16 = 0x17;
> -	sdp_data_t *channel, *features;
> -	uint8_t netid = si->network ? si->network : 0x01; // ???? profile document
> -	sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &svclass_uuid);
> -	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
> -	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
> -	profile.version = 0x0105;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	features = sdp_data_alloc(SDP_UINT16, &u16);
> -	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
> -
> -	sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
> -
> -	if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("Handsfree AG service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_simaccess(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel? si->channel : 8;
> -	uint16_t u16 = 0x31;
> -	sdp_data_t *channel, *features;
> -	int ret = 0;
> -
> -	memset((void *)&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&svclass_uuid, SAP_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &svclass_uuid);
> -	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
> -	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID);
> -	profile.version = 0x0101;
> -	pfseq = sdp_list_append(0, &profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	features = sdp_data_alloc(SDP_UINT16, &u16);
> -	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "SIM Access", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("SIM Access service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_opush(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[3];
> -	sdp_record_t record;
> -	uint8_t chan = si->channel ? si->channel : 9;
> -	sdp_data_t *channel;
> -	uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xff };
> -	void *dtds[sizeof(formats)], *values[sizeof(formats)];
> -	unsigned int i;
> -	uint8_t dtd = SDP_UINT8;
> -	sdp_data_t *sflist;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &opush_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &chan);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	sdp_uuid16_create(&obex_uuid, OBEX_UUID);
> -	proto[2] = sdp_list_append(0, &obex_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	for (i = 0; i < sizeof(formats); i++) {
> -		dtds[i] = &dtd;
> -		values[i] = &formats[i];
> -	}
> -	sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
> -	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
> -
> -	sdp_set_info_attr(&record, "OBEX Object Push", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("OBEX Object Push service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(proto[2], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_pbap(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, pbap_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[3];
> -	sdp_record_t record;
> -	uint8_t chan = si->channel ? si->channel : 19;
> -	sdp_data_t *channel;
> -	uint8_t formats[] = {0x01};
> -	uint8_t dtd = SDP_UINT8;
> -	sdp_data_t *sflist;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&pbap_uuid, PBAP_PSE_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &pbap_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, PBAP_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &chan);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	sdp_uuid16_create(&obex_uuid, OBEX_UUID);
> -	proto[2] = sdp_list_append(0, &obex_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sflist = sdp_data_alloc(dtd,formats);
> -	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_REPOSITORIES, sflist);
> -
> -	sdp_set_info_attr(&record, "OBEX Phonebook Access Server", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record,
> -			SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("PBAP service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(proto[2], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_ftp(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[3];
> -	sdp_record_t record;
> -	uint8_t u8 = si->channel ? si->channel: 10;
> -	sdp_data_t *channel;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&ftrn_uuid, OBEX_FILETRANS_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &ftrn_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, OBEX_FILETRANS_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &u8);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	sdp_uuid16_create(&obex_uuid, OBEX_UUID);
> -	proto[2] = sdp_list_append(0, &obex_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("OBEX File Transfer service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(proto[2], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_directprint(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[3];
> -	sdp_record_t record;
> -	uint8_t chan = si->channel ? si->channel : 12;
> -	sdp_data_t *channel;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&opush_uuid, DIRECT_PRINTING_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &opush_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, BASIC_PRINTING_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> -	channel = sdp_data_alloc(SDP_UINT8, &chan);
> -	proto[1] = sdp_list_append(proto[1], channel);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	sdp_uuid16_create(&obex_uuid, OBEX_UUID);
> -	proto[2] = sdp_list_append(0, &obex_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Direct Printing", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("Direct Printing service registered\n");
> -
> -end:
> -	sdp_data_free(channel);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(proto[2], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_nap(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint16_t lp = 0x000f, ver = 0x0100;
> -	sdp_data_t *psm, *version;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&ftrn_uuid, NAP_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &ftrn_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	psm = sdp_data_alloc(SDP_UINT16, &lp);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
> -	proto[1] = sdp_list_append(0, &bnep_uuid);
> -	version  = sdp_data_alloc(SDP_UINT16, &ver);
> -	proto[1] = sdp_list_append(proto[1], version);
> -
> -	{
> -		uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 };
> -		sdp_data_t *head, *pseq;
> -		int p;
> -
> -		for (p = 0, head = NULL; p < 4; p++) {
> -			sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]);
> -			head = sdp_seq_append(head, data);
> -		}
> -		pseq = sdp_data_alloc(SDP_SEQ16, head);
> -		proto[1] = sdp_list_append(proto[1], pseq);
> -	}
> -
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Network Access Point Service", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("NAP service registered\n");
> -
> -end:
> -	sdp_data_free(version);
> -	sdp_data_free(psm);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_gn(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint16_t lp = 0x000f, ver = 0x0100;
> -	sdp_data_t *psm, *version;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&ftrn_uuid, GN_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &ftrn_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap_uuid);
> -	psm = sdp_data_alloc(SDP_UINT16, &lp);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
> -	proto[1] = sdp_list_append(0, &bnep_uuid);
> -	version = sdp_data_alloc(SDP_UINT16, &ver);
> -	proto[1] = sdp_list_append(proto[1], version);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Group Network Service", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("GN service registered\n");
> -
> -end:
> -	sdp_data_free(version);
> -	sdp_data_free(psm);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_panu(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint16_t lp = 0x000f, ver = 0x0100;
> -	sdp_data_t *psm, *version;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -	sdp_list_free(root, NULL);
> -
> -	sdp_uuid16_create(&ftrn_uuid, PANU_SVCLASS_ID);
> -	svclass_id = sdp_list_append(NULL, &ftrn_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -	sdp_list_free(svclass_id, NULL);
> -
> -	sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(NULL, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -	sdp_list_free(pfseq, NULL);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[0] = sdp_list_append(NULL, &l2cap_uuid);
> -	psm = sdp_data_alloc(SDP_UINT16, &lp);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(NULL, proto[0]);
> -
> -	sdp_uuid16_create(&bnep_uuid, BNEP_UUID);
> -	proto[1] = sdp_list_append(NULL, &bnep_uuid);
> -	version = sdp_data_alloc(SDP_UINT16, &ver);
> -	proto[1] = sdp_list_append(proto[1], version);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(NULL, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "PAN User", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("PANU service registered\n");
> -
> -end:
> -	sdp_data_free(version);
> -	sdp_data_free(psm);
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_hid_keyb(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[3];
> -	sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
> -	unsigned int i;
> -	uint8_t dtd = SDP_UINT16;
> -	uint8_t dtd2 = SDP_UINT8;
> -	uint8_t dtd_data = SDP_TEXT_STR8;
> -	void *dtds[2];
> -	void *values[2];
> -	void *dtds2[2];
> -	void *values2[2];
> -	int leng[2];
> -	uint8_t hid_spec_type = 0x22;
> -	uint16_t hid_attr_lang[] = { 0x409, 0x100 };
> -	static const uint16_t ctrl = 0x11;
> -	static const uint16_t intr = 0x13;
> -	static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 };
> -	static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 };
> -	const uint8_t hid_spec[] = {
> -		0x05, 0x01, // usage page
> -		0x09, 0x06, // keyboard
> -		0xa1, 0x01, // key codes
> -		0x85, 0x01, // minimum
> -		0x05, 0x07, // max
> -		0x19, 0xe0, // logical min
> -		0x29, 0xe7, // logical max
> -		0x15, 0x00, // report size
> -		0x25, 0x01, // report count
> -		0x75, 0x01, // input data variable absolute
> -		0x95, 0x08, // report count
> -		0x81, 0x02, // report size
> -		0x75, 0x08,
> -		0x95, 0x01,
> -		0x81, 0x01,
> -		0x75, 0x01,
> -		0x95, 0x05,
> -		0x05, 0x08,
> -		0x19, 0x01,
> -		0x29, 0x05,
> -		0x91, 0x02,
> -		0x75, 0x03,
> -		0x95, 0x01,
> -		0x91, 0x01,
> -		0x75, 0x08,
> -		0x95, 0x06,
> -		0x15, 0x00,
> -		0x26, 0xff,
> -		0x00, 0x05,
> -		0x07, 0x19,
> -		0x00, 0x2a,
> -		0xff, 0x00,
> -		0x81, 0x00,
> -		0x75, 0x01,
> -		0x95, 0x01,
> -		0x15, 0x00,
> -		0x25, 0x01,
> -		0x05, 0x0c,
> -		0x09, 0xb8,
> -		0x81, 0x06,
> -		0x09, 0xe2,
> -		0x81, 0x06,
> -		0x09, 0xe9,
> -		0x81, 0x02,
> -		0x09, 0xea,
> -		0x81, 0x02,
> -		0x75, 0x01,
> -		0x95, 0x04,
> -		0x81, 0x01,
> -		0xc0         // end tag
> -	};
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_add_lang_attr(&record);
> -
> -	sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &hidkb_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	/* protocols */
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[1] = sdp_list_append(0, &l2cap_uuid);
> -	psm = sdp_data_alloc(SDP_UINT16, &ctrl);
> -	proto[1] = sdp_list_append(proto[1], psm);
> -	apseq = sdp_list_append(0, proto[1]);
> -
> -	sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
> -	proto[2] = sdp_list_append(0, &hidp_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	/* additional protocols */
> -	proto[1] = sdp_list_append(0, &l2cap_uuid);
> -	psm = sdp_data_alloc(SDP_UINT16, &intr);
> -	proto[1] = sdp_list_append(proto[1], psm);
> -	apseq = sdp_list_append(0, proto[1]);
> -
> -	sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
> -	proto[2] = sdp_list_append(0, &hidp_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_add_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL);
> -
> -	for (i = 0; i < sizeof(hid_attr) / 2; i++)
> -		sdp_attr_add_new(&record,
> -					SDP_ATTR_HID_DEVICE_RELEASE_NUMBER + i,
> -					SDP_UINT16, &hid_attr[i]);
> -
> -	dtds[0] = &dtd2;
> -	values[0] = &hid_spec_type;
> -	dtds[1] = &dtd_data;
> -	values[1] = (uint8_t *) hid_spec;
> -	leng[0] = 0;
> -	leng[1] = sizeof(hid_spec);
> -	hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
> -	hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
> -	sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
> -
> -	for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
> -		dtds2[i] = &dtd;
> -		values2[i] = &hid_attr_lang[i];
> -	}
> -
> -	lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
> -	lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
> -	sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]);
> -
> -	for (i = 0; i < sizeof(hid_attr2) / 2 - 1; i++)
> -		sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP + i,
> -						SDP_UINT16, &hid_attr2[i + 1]);
> -
> -	if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("HID keyboard service registered\n");
> -
> -	return 0;
> -}
> -
> -static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[3];
> -	sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
> -	unsigned int i;
> -	uint8_t dtd = SDP_UINT16;
> -	uint8_t dtd2 = SDP_UINT8;
> -	uint8_t dtd_data = SDP_TEXT_STR8;
> -	void *dtds[2];
> -	void *values[2];
> -	void *dtds2[2];
> -	void *values2[2];
> -	int leng[2];
> -	uint8_t hid_spec_type = 0x22;
> -	uint16_t hid_attr_lang[] = { 0x409, 0x100 };
> -	uint16_t ctrl = 0x11, intr = 0x13;
> -	uint16_t hid_release = 0x0100, parser_version = 0x0111;
> -	uint8_t subclass = 0x04, country = 0x33;
> -	uint8_t virtual_cable = 0, reconnect = 1, sdp_disable = 0;
> -	uint8_t battery = 1, remote_wakeup = 1;
> -	uint16_t profile_version = 0x0100, superv_timeout = 0x0c80;
> -	uint8_t norm_connect = 0, boot_device = 0;
> -	const uint8_t hid_spec[] = {
> -		0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10,
> -		0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
> -		0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00,
> -		0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00,
> -		0xc0, 0x00
> -	};
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID);
> -	svclass_id = sdp_list_append(NULL, &hid_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(NULL, profile);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto[1] = sdp_list_append(0, &l2cap_uuid);
> -	psm = sdp_data_alloc(SDP_UINT16, &ctrl);
> -	proto[1] = sdp_list_append(proto[1], psm);
> -	apseq = sdp_list_append(0, proto[1]);
> -
> -	sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
> -	proto[2] = sdp_list_append(0, &hidp_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	proto[1] = sdp_list_append(0, &l2cap_uuid);
> -	psm = sdp_data_alloc(SDP_UINT16, &intr);
> -	proto[1] = sdp_list_append(proto[1], psm);
> -	apseq = sdp_list_append(0, proto[1]);
> -
> -	sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
> -	proto[2] = sdp_list_append(0, &hidp_uuid);
> -	apseq = sdp_list_append(apseq, proto[2]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_add_access_protos(&record, aproto);
> -
> -	sdp_add_lang_attr(&record);
> -
> -	sdp_set_info_attr(&record, "Nintendo RVL-CNT-01",
> -					"Nintendo", "Nintendo RVL-CNT-01");
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
> -						SDP_UINT16, &hid_release);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION,
> -						SDP_UINT16, &parser_version);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS,
> -						SDP_UINT8, &subclass);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE,
> -						SDP_UINT8, &country);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE,
> -						SDP_BOOL, &virtual_cable);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE,
> -						SDP_BOOL, &reconnect);
> -
> -	dtds[0] = &dtd2;
> -	values[0] = &hid_spec_type;
> -	dtds[1] = &dtd_data;
> -	values[1] = (uint8_t *) hid_spec;
> -	leng[0] = 0;
> -	leng[1] = sizeof(hid_spec);
> -	hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
> -	hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
> -	sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
> -
> -	for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
> -		dtds2[i] = &dtd;
> -		values2[i] = &hid_attr_lang[i];
> -	}
> -
> -	lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
> -	lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
> -	sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE,
> -						SDP_BOOL, &sdp_disable);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER,
> -						SDP_BOOL, &battery);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP,
> -						SDP_BOOL, &remote_wakeup);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION,
> -						SDP_UINT16, &profile_version);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT,
> -						SDP_UINT16, &superv_timeout);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE,
> -						SDP_BOOL, &norm_connect);
> -
> -	sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE,
> -						SDP_BOOL, &boot_device);
> -
> -	if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("Wii-Mote service registered\n");
> -
> -	return 0;
> -}
> -
> -static int add_cip(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, l2cap, cmtp, cip;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint16_t psm = si->psm ? si->psm : 0x1001;
> -	uint8_t netid = si->network ? si->network : 0x02; // 0x02 = ISDN, 0x03 = GSM
> -	sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&cip, CIP_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &cip);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, CIP_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	apseq = sdp_list_append(0, proto[0]);
> -	proto[0] = sdp_list_append(proto[0], sdp_data_alloc(SDP_UINT16, &psm));
> -	apseq = sdp_list_append(apseq, proto[0]);
> -
> -	sdp_uuid16_create(&cmtp, CMTP_UUID);
> -	proto[1] = sdp_list_append(0, &cmtp);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
> -
> -	sdp_set_info_attr(&record, "Common ISDN Access", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("CIP service registered\n");
> -
> -end:
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -	sdp_data_free(network);
> -
> -	return ret;
> -}
> -
> -static int add_ctp(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, l2cap, tcsbin, ctp;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	uint8_t netid = si->network ? si->network : 0x02; // 0x01-0x07 cf. p120 profile document
> -	sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&ctp, CORDLESS_TELEPHONY_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &ctp);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, CORDLESS_TELEPHONY_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&tcsbin, TCS_BIN_UUID);
> -	proto[1] = sdp_list_append(0, &tcsbin);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network);
> -
> -	sdp_set_info_attr(&record, "Cordless Telephony", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto end;
> -	}
> -
> -	printf("CTP service registered\n");
> -
> -end:
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -	sdp_data_free(network);
> -
> -	return ret;
> -}
> -
> -static int add_a2source(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, l2cap, avdtp, a2src;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	sdp_data_t *psm, *version;
> -	uint16_t lp = 0x0019, ver = 0x0100;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &a2src);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	psm = sdp_data_alloc(SDP_UINT16, &lp);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&avdtp, AVDTP_UUID);
> -	proto[1] = sdp_list_append(0, &avdtp);
> -	version = sdp_data_alloc(SDP_UINT16, &ver);
> -	proto[1] = sdp_list_append(proto[1], version);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Audio Source", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto done;
> -	}
> -
> -	printf("Audio source service registered\n");
> -
> -done:
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_a2sink(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, l2cap, avdtp, a2snk;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	sdp_data_t *psm, *version;
> -	uint16_t lp = 0x0019, ver = 0x0100;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&a2snk, AUDIO_SINK_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &a2snk);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	psm = sdp_data_alloc(SDP_UINT16, &lp);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&avdtp, AVDTP_UUID);
> -	proto[1] = sdp_list_append(0, &avdtp);
> -	version = sdp_data_alloc(SDP_UINT16, &ver);
> -	proto[1] = sdp_list_append(proto[1], version);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Audio Sink", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto done;
> -	}
> -
> -	printf("Audio sink service registered\n");
> -
> -done:
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_avrct(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, l2cap, avctp, avrct;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	sdp_data_t *psm, *version, *features;
> -	uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &avrct);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	psm = sdp_data_alloc(SDP_UINT16, &lp);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&avctp, AVCTP_UUID);
> -	proto[1] = sdp_list_append(0, &avctp);
> -	version = sdp_data_alloc(SDP_UINT16, &ver);
> -	proto[1] = sdp_list_append(proto[1], version);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	features = sdp_data_alloc(SDP_UINT16, &feat);
> -	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
> -
> -	sdp_set_info_attr(&record, "AVRCP CT", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto done;
> -	}
> -
> -	printf("Remote control service registered\n");
> -
> -done:
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_avrtg(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> -	uuid_t root_uuid, l2cap, avctp, avrtg;
> -	sdp_profile_desc_t profile[1];
> -	sdp_list_t *aproto, *proto[2];
> -	sdp_record_t record;
> -	sdp_data_t *psm, *version, *features;
> -	uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f;
> -	int ret = 0;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(0, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
> -	svclass_id = sdp_list_append(0, &avrtg);
> -	sdp_set_service_classes(&record, svclass_id);
> -
> -	sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
> -	profile[0].version = 0x0100;
> -	pfseq = sdp_list_append(0, &profile[0]);
> -	sdp_set_profile_descs(&record, pfseq);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(0, &l2cap);
> -	psm = sdp_data_alloc(SDP_UINT16, &lp);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(0, proto[0]);
> -
> -	sdp_uuid16_create(&avctp, AVCTP_UUID);
> -	proto[1] = sdp_list_append(0, &avctp);
> -	version = sdp_data_alloc(SDP_UINT16, &ver);
> -	proto[1] = sdp_list_append(proto[1], version);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(0, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	features = sdp_data_alloc(SDP_UINT16, &feat);
> -	sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features);
> -
> -	sdp_set_info_attr(&record, "AVRCP TG", 0, 0);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		ret = -1;
> -		goto done;
> -	}
> -
> -	printf("Remote target service registered\n");
> -
> -done:
> -	sdp_list_free(proto[0], 0);
> -	sdp_list_free(proto[1], 0);
> -	sdp_list_free(apseq, 0);
> -	sdp_list_free(aproto, 0);
> -
> -	return ret;
> -}
> -
> -static int add_udi_ue(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass, *proto;
> -	uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	uint8_t channel = si->channel ? si->channel: 18;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -	sdp_list_free(root, NULL);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(
> -		sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_uuid16_create(&svclass_uuid, UDI_MT_SVCLASS_ID);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -	sdp_list_free(svclass, NULL);
> -
> -	sdp_set_info_attr(&record, "UDI UE", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("UDI UE service registered\n");
> -
> -	return 0;
> -}
> -
> -static int add_udi_te(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass, *proto;
> -	uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	uint8_t channel = si->channel ? si->channel: 19;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -	sdp_list_free(root, NULL);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(
> -		sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_uuid16_create(&svclass_uuid, UDI_TA_SVCLASS_ID);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -	sdp_list_free(svclass, NULL);
> -
> -	sdp_set_info_attr(&record, "UDI TE", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("UDI TE service registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char sr1_uuid[] = {	0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0,
> 					0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 };
> 
> -static int add_sr1(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass;
> -	uuid_t root_uuid, svclass_uuid;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("Toshiba Speech Recognition SR-1 service record registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char syncmls_uuid[] = {	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00,
> 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
> 
> static unsigned char syncmlc_uuid[] = {	0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
> 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 };
> 
> -static int add_syncml(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass, *proto;
> -	uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
> -	uint8_t channel = si->channel ? si->channel: 15;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(
> -		sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
> -
> -	sdp_uuid16_create(&obex_uuid, OBEX_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_set_info_attr(&record, "SyncML Client", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("SyncML Client service record registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char async_uuid[] = {	0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62,
> 					0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C };
> 
> -static int add_activesync(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass, *proto;
> -	uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	uint8_t channel = si->channel ? si->channel: 21;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(
> -	sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_uuid128_create(&svclass_uuid, (void *) async_uuid);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("ActiveSync service record registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char hotsync_uuid[] = {	0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
> 					0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
> 
> -static int add_hotsync(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass, *proto;
> -	uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	uint8_t channel = si->channel ? si->channel: 22;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(
> -	sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("HotSync service record registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char palmos_uuid[] = {	0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51,
> 					0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 };
> 
> -static int add_palmos(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass;
> -	uuid_t root_uuid, svclass_uuid;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("PalmOS service record registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char nokid_uuid[] = {	0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00,
> 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
> 
> -static int add_nokiaid(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass;
> -	uuid_t root_uuid, svclass_uuid;
> -	uint16_t verid = 0x005f;
> -	sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid);
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		sdp_data_free(version);
> -		return -1;
> -	}
> -
> -	printf("Nokia ID service record registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char pcsuite_uuid[] = {	0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00,
> 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
> 
> -static int add_pcsuite(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass, *proto;
> -	uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
> -	uint8_t channel = si->channel ? si->channel: 14;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(
> -		sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid);
> -	svclass = sdp_list_append(NULL, &svclass_uuid);
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("Nokia PC Suite service registered\n");
> -
> -	return 0;
> -}
> -
> static unsigned char nftp_uuid[] = {	0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00,
> 					0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 };
> 
> @@ -3302,436 +1184,69 @@ static unsigned char apple_uuid[] = {	0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e,
> static unsigned char iap_uuid[] = {	0x00, 0x00, 0x00, 0x00, 0xde, 0xca, 0xfa, 0xde,
> 					0xde, 0xca, 0xde, 0xaf, 0xde, 0xca, 0xca, 0xfe };
> 
> -static int add_apple(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root;
> -	uuid_t root_uuid;
> -	uint32_t attr783 = 0x00000000;
> -	uint32_t attr785 = 0x00000002;
> -	uint16_t attr786 = 0x1234;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_attr_add_new(&record, 0x0780, SDP_UUID128, (void *) apple_uuid);
> -	sdp_attr_add_new(&record, 0x0781, SDP_TEXT_STR8, (void *) "Macmini");
> -	sdp_attr_add_new(&record, 0x0782, SDP_TEXT_STR8, (void *) "PowerMac10,1");
> -	sdp_attr_add_new(&record, 0x0783, SDP_UINT32, (void *) &attr783);
> -	sdp_attr_add_new(&record, 0x0784, SDP_TEXT_STR8, (void *) "1.6.6f22");
> -	sdp_attr_add_new(&record, 0x0785, SDP_UINT32, (void *) &attr785);
> -	sdp_attr_add_new(&record, 0x0786, SDP_UUID16, (void *) &attr786);
> -
> -	sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("Apple attribute service registered\n");
> -
> -	return 0;
> -}
> -
> -static int add_isync(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_list_t *root, *svclass, *proto;
> -	uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid;
> -	uint8_t channel = si->channel ? si->channel : 16;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
> -
> -	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> -	proto = sdp_list_append(proto, sdp_list_append(
> -		sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID);
> -	svclass = sdp_list_append(NULL, &serial_uuid);
> -
> -	sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID);
> -	svclass = sdp_list_append(svclass, &svclass_uuid);
> -
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd.");
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	printf("Apple iSync service registered\n");
> -
> -	return 0;
> -}
> -
> -static int add_semchla(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_record_t record;
> -	sdp_profile_desc_t profile;
> -	sdp_list_t *root, *svclass, *proto, *profiles;
> -	uuid_t root_uuid, service_uuid, l2cap_uuid, semchla_uuid;
> -	uint16_t psm = 0xf0f9;
> -
> -	memset(&record, 0, sizeof(record));
> -	record.handle = si->handle;
> -
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -
> -	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> -	proto = sdp_list_append(NULL, sdp_list_append(
> -		sdp_list_append(NULL, &l2cap_uuid), sdp_data_alloc(SDP_UINT16, &psm)));
> -
> -	sdp_uuid32_create(&semchla_uuid, 0x8e770300);
> -	proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid));
> -
> -	sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
> -
> -	sdp_uuid32_create(&service_uuid, 0x8e771301);
> -	svclass = sdp_list_append(NULL, &service_uuid);
> -
> -	sdp_set_service_classes(&record, svclass);
> -
> -	sdp_uuid32_create(&profile.uuid, 0x8e771302);	// Headset
> -	//sdp_uuid32_create(&profile.uuid, 0x8e771303);	// Phone
> -	profile.version = 0x0100;
> -	profiles = sdp_list_append(NULL, &profile);
> -	sdp_set_profile_descs(&record, profiles);
> -
> -	sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL);
> -
> -	if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) {
> -		printf("Service Record registration failed\n");
> -		return -1;
> -	}
> -
> -	/* SEMC High Level Authentication */
> -	printf("SEMC HLA service registered\n");
> -
> -	return 0;
> -}
> -
> -static int add_gatt(sdp_session_t *session, svc_info_t *si)
> -{
> -	sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
> -	uuid_t root_uuid, proto_uuid, gatt_uuid, l2cap;
> -	sdp_profile_desc_t profile;
> -	sdp_record_t record;
> -	sdp_data_t *psm, *sh, *eh;
> -	uint16_t att_psm = 27, start = 0x0001, end = 0x000f;
> -	int ret;
> -
> -	memset(&record, 0, sizeof(sdp_record_t));
> -	record.handle = si->handle;
> -	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> -	root = sdp_list_append(NULL, &root_uuid);
> -	sdp_set_browse_groups(&record, root);
> -	sdp_list_free(root, NULL);
> -
> -	sdp_uuid16_create(&gatt_uuid, GENERIC_ATTRIB_SVCLASS_ID);
> -	svclass_id = sdp_list_append(NULL, &gatt_uuid);
> -	sdp_set_service_classes(&record, svclass_id);
> -	sdp_list_free(svclass_id, NULL);
> -
> -	sdp_uuid16_create(&profile.uuid, GENERIC_ATTRIB_PROFILE_ID);
> -	profile.version = 0x0100;
> -	profiles = sdp_list_append(NULL, &profile);
> -	sdp_set_profile_descs(&record, profiles);
> -	sdp_list_free(profiles, NULL);
> -
> -	sdp_uuid16_create(&l2cap, L2CAP_UUID);
> -	proto[0] = sdp_list_append(NULL, &l2cap);
> -	psm = sdp_data_alloc(SDP_UINT16, &att_psm);
> -	proto[0] = sdp_list_append(proto[0], psm);
> -	apseq = sdp_list_append(NULL, proto[0]);
> -
> -	sdp_uuid16_create(&proto_uuid, ATT_UUID);
> -	proto[1] = sdp_list_append(NULL, &proto_uuid);
> -	sh = sdp_data_alloc(SDP_UINT16, &start);
> -	proto[1] = sdp_list_append(proto[1], sh);
> -	eh = sdp_data_alloc(SDP_UINT16, &end);
> -	proto[1] = sdp_list_append(proto[1], eh);
> -	apseq = sdp_list_append(apseq, proto[1]);
> -
> -	aproto = sdp_list_append(NULL, apseq);
> -	sdp_set_access_protos(&record, aproto);
> -
> -	sdp_set_info_attr(&record, "Generic Attribute Profile", "BlueZ", NULL);
> -
> -	sdp_set_url_attr(&record, "http://www.bluez.org/",
> -			"http://www.bluez.org/", "http://www.bluez.org/");
> -
> -	sdp_set_service_id(&record, gatt_uuid);
> -
> -	ret = sdp_device_record_register(session, &interface, &record,
> -							SDP_RECORD_PERSIST);
> -	if (ret < 0)
> -		printf("Service Record registration failed\n");
> -	else
> -		printf("Generic Attribute Profile Service registered\n");
> -
> -	sdp_data_free(psm);
> -	sdp_data_free(sh);
> -	sdp_data_free(eh);
> -	sdp_list_free(proto[0], NULL);
> -	sdp_list_free(proto[1], NULL);
> -	sdp_list_free(apseq, NULL);
> -	sdp_list_free(aproto, NULL);
> -
> -	return ret;
> -}
> -
> struct {
> 	char		*name;
> 	uint32_t	class;
> -	int		(*add)(sdp_session_t *sess, svc_info_t *si);
> 	unsigned char *uuid;
> } service[] = {
> -	{ "DID",	PNP_INFO_SVCLASS_ID,		NULL,		},
> -
> -	{ "SP",		SERIAL_PORT_SVCLASS_ID,		add_sp		},
> -	{ "DUN",	DIALUP_NET_SVCLASS_ID,		add_dun		},
> -	{ "LAN",	LAN_ACCESS_SVCLASS_ID,		add_lan		},
> -	{ "FAX",	FAX_SVCLASS_ID,			add_fax		},
> -	{ "OPUSH",	OBEX_OBJPUSH_SVCLASS_ID,	add_opush	},
> -	{ "FTP",	OBEX_FILETRANS_SVCLASS_ID,	add_ftp		},
> -	{ "PRINT",	DIRECT_PRINTING_SVCLASS_ID,	add_directprint	},
> -
> -	{ "HS",		HEADSET_SVCLASS_ID,		add_headset	},
> -	{ "HSAG",	HEADSET_AGW_SVCLASS_ID,		add_headset_ag	},
> -	{ "HF",		HANDSFREE_SVCLASS_ID,		add_handsfree	},
> -	{ "HFAG",	HANDSFREE_AGW_SVCLASS_ID,	add_handsfree_ag},
> -	{ "SAP",	SAP_SVCLASS_ID,			add_simaccess	},
> -	{ "PBAP",	PBAP_SVCLASS_ID,		add_pbap,	},
> -
> -	{ "NAP",	NAP_SVCLASS_ID,			add_nap		},
> -	{ "GN",		GN_SVCLASS_ID,			add_gn		},
> -	{ "PANU",	PANU_SVCLASS_ID,		add_panu	},
> -
> -	{ "HCRP",	HCR_SVCLASS_ID,			NULL		},
> -	{ "HID",	HID_SVCLASS_ID,			NULL		},
> -	{ "KEYB",	HID_SVCLASS_ID,			add_hid_keyb	},
> -	{ "WIIMOTE",	HID_SVCLASS_ID,			add_hid_wiimote	},
> -	{ "CIP",	CIP_SVCLASS_ID,			add_cip		},
> -	{ "CTP",	CORDLESS_TELEPHONY_SVCLASS_ID,	add_ctp		},
> -
> -	{ "A2SRC",	AUDIO_SOURCE_SVCLASS_ID,	add_a2source	},
> -	{ "A2SNK",	AUDIO_SINK_SVCLASS_ID,		add_a2sink	},
> -	{ "AVRCT",	AV_REMOTE_SVCLASS_ID,		add_avrct	},
> -	{ "AVRTG",	AV_REMOTE_TARGET_SVCLASS_ID,	add_avrtg	},
> -
> -	{ "UDIUE",	UDI_MT_SVCLASS_ID,		add_udi_ue	},
> -	{ "UDITE",	UDI_TA_SVCLASS_ID,		add_udi_te	},
> -
> -	{ "SEMCHLA",	0x8e771301,			add_semchla	},
> -
> -	{ "SR1",	0,				add_sr1,	sr1_uuid	},
> -	{ "SYNCML",	0,				add_syncml,	syncmlc_uuid	},
> -	{ "SYNCMLSERV",	0,				NULL,		syncmls_uuid	},
> -	{ "ACTIVESYNC",	0,				add_activesync,	async_uuid	},
> -	{ "HOTSYNC",	0,				add_hotsync,	hotsync_uuid	},
> -	{ "PALMOS",	0,				add_palmos,	palmos_uuid	},
> -	{ "NOKID",	0,				add_nokiaid,	nokid_uuid	},
> -	{ "PCSUITE",	0,				add_pcsuite,	pcsuite_uuid	},
> -	{ "NFTP",	0,				NULL,		nftp_uuid	},
> -	{ "NSYNCML",	0,				NULL,		nsyncml_uuid	},
> -	{ "NGAGE",	0,				NULL,		ngage_uuid	},
> -	{ "APPLE",	0,				add_apple,	apple_uuid	},
> -	{ "IAP",	0,				NULL,		iap_uuid	},
> -
> -	{ "ISYNC",	APPLE_AGENT_SVCLASS_ID,		add_isync,	},
> -	{ "GATT",	GENERIC_ATTRIB_SVCLASS_ID,	add_gatt,	},
> +	{ "DID",	PNP_INFO_SVCLASS_ID		},
> +
> +	{ "SP",		SERIAL_PORT_SVCLASS_ID		},
> +	{ "DUN",	DIALUP_NET_SVCLASS_ID		},
> +	{ "LAN",	LAN_ACCESS_SVCLASS_ID		},
> +	{ "FAX",	FAX_SVCLASS_ID			},
> +	{ "OPUSH",	OBEX_OBJPUSH_SVCLASS_ID		},
> +	{ "FTP",	OBEX_FILETRANS_SVCLASS_ID	},
> +	{ "PRINT",	DIRECT_PRINTING_SVCLASS_ID	},
> +
> +	{ "HS",		HEADSET_SVCLASS_ID		},
> +	{ "HSAG",	HEADSET_AGW_SVCLASS_ID		},
> +	{ "HF",		HANDSFREE_SVCLASS_ID		},
> +	{ "HFAG",	HANDSFREE_AGW_SVCLASS_ID	},
> +	{ "SAP",	SAP_SVCLASS_ID			},
> +	{ "PBAP",	PBAP_SVCLASS_ID			},
> +
> +	{ "NAP",	NAP_SVCLASS_ID			},
> +	{ "GN",		GN_SVCLASS_ID			},
> +	{ "PANU",	PANU_SVCLASS_ID			},
> +
> +	{ "HCRP",	HCR_SVCLASS_ID			},
> +	{ "HID",	HID_SVCLASS_ID			},
> +	{ "KEYB",	HID_SVCLASS_ID			},
> +	{ "WIIMOTE",	HID_SVCLASS_ID			},
> +	{ "CIP",	CIP_SVCLASS_ID			},
> +	{ "CTP",	CORDLESS_TELEPHONY_SVCLASS_ID	},
> +
> +	{ "A2SRC",	AUDIO_SOURCE_SVCLASS_ID		},
> +	{ "A2SNK",	AUDIO_SINK_SVCLASS_ID		},
> +	{ "AVRCT",	AV_REMOTE_SVCLASS_ID		},
> +	{ "AVRTG",	AV_REMOTE_TARGET_SVCLASS_ID	},
> +
> +	{ "UDIUE",	UDI_MT_SVCLASS_ID		},
> +	{ "UDITE",	UDI_TA_SVCLASS_ID		},
> +
> +	{ "SEMCHLA",	0x8e771301			},
> +
> +	{ "SR1",	0,				sr1_uuid	},
> +	{ "SYNCML",	0,				syncmlc_uuid	},
> +	{ "SYNCMLSERV",	0,				syncmls_uuid	},
> +	{ "ACTIVESYNC",	0,				async_uuid	},
> +	{ "HOTSYNC",	0,				hotsync_uuid	},
> +	{ "PALMOS",	0,				palmos_uuid	},
> +	{ "NOKID",	0,				nokid_uuid	},
> +	{ "PCSUITE",	0,				pcsuite_uuid	},
> +	{ "NFTP",	0,				nftp_uuid	},
> +	{ "NSYNCML",	0,				nsyncml_uuid	},
> +	{ "NGAGE",	0,				ngage_uuid	},
> +	{ "APPLE",	0,				apple_uuid	},
> +	{ "IAP",	0,				iap_uuid	},
> +
> +	{ "ISYNC",	APPLE_AGENT_SVCLASS_ID		},
> +	{ "GATT",	GENERIC_ATTRIB_SVCLASS_ID	},
> 
> 	{ 0 }
> };
> 
> -/* Add local service */
> -static int add_service(bdaddr_t *bdaddr, svc_info_t *si)
> -{
> -	sdp_session_t *sess;
> -	int i, ret = -1;
> -
> -	if (!si->name)
> -		return -1;
> -
> -	sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
> -	if (!sess)
> -		return -1;
> -
> -	for (i = 0; service[i].name; i++)
> -		if (!strcasecmp(service[i].name, si->name)) {
> -			if (service[i].add)
> -				ret = service[i].add(sess, si);
> -			goto done;
> -		}
> -
> -	printf("Unknown service name: %s\n", si->name);
> -
> -done:
> -	free(si->name);
> -	sdp_close(sess);
> -
> -	return ret;
> -}
> -
> -static struct option add_options[] = {
> -	{ "help",	0, 0, 'h' },
> -	{ "handle",	1, 0, 'r' },
> -	{ "psm",	1, 0, 'p' },
> -	{ "channel",	1, 0, 'c' },
> -	{ "network",	1, 0, 'n' },
> -	{ 0, 0, 0, 0 }
> -};
> -
> -static const char *add_help =
> -	"Usage:\n"
> -	"\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n";
> -
> -static int cmd_add(int argc, char **argv)
> -{
> -	svc_info_t si;
> -	int opt;
> -
> -	memset(&si, 0, sizeof(si));
> -	si.handle = 0xffffffff;
> -
> -	for_each_opt(opt, add_options, 0) {
> -		switch (opt) {
> -		case 'r':
> -			if (strncasecmp(optarg, "0x", 2))
> -				si.handle = atoi(optarg);
> -			else
> -				si.handle = strtol(optarg + 2, NULL, 16);
> -			break;
> -		case 'p':
> -			if (strncasecmp(optarg, "0x", 2))
> -				si.psm = atoi(optarg);
> -			else
> -				si.psm = strtol(optarg + 2, NULL, 16);
> -			break;
> -		case 'c':
> -			if (strncasecmp(optarg, "0x", 2))
> -				si.channel = atoi(optarg);
> -			else
> -				si.channel = strtol(optarg + 2, NULL, 16);
> -			break;
> -		case 'n':
> -			if (strncasecmp(optarg, "0x", 2))
> -				si.network = atoi(optarg);
> -			else
> -				si.network = strtol(optarg + 2, NULL, 16);
> -			break;
> -		default:
> -			printf("%s", add_help);
> -			return -1;
> -		}
> -	}
> -
> -	argc -= optind;
> -	argv += optind;
> -
> -	if (argc < 1) {
> -		printf("%s", add_help);
> -		return -1;
> -	}
> -
> -	si.name = strdup(argv[0]);
> -
> -	return add_service(0, &si);
> -}
> -
> -/* Delete local service */
> -static int del_service(bdaddr_t *bdaddr, void *arg)
> -{
> -	uint32_t handle, range = 0x0000ffff;
> -	sdp_list_t *attr;
> -	sdp_session_t *sess;
> -	sdp_record_t *rec;
> -
> -	if (!arg) {
> -		printf("Record handle was not specified.\n");
> -		return -1;
> -	}
> -
> -	sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
> -	if (!sess) {
> -		printf("No local SDP server!\n");
> -		return -1;
> -	}
> -
> -	handle = strtoul((char *)arg, 0, 16);
> -	attr = sdp_list_append(0, &range);
> -	rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
> -	sdp_list_free(attr, 0);
> -
> -	if (!rec) {
> -		printf("Service Record not found.\n");
> -		sdp_close(sess);
> -		return -1;
> -	}
> -
> -	if (sdp_device_record_unregister(sess, &interface, rec)) {
> -		printf("Failed to unregister service record: %s\n", strerror(errno));
> -		sdp_close(sess);
> -		return -1;
> -	}
> -
> -	printf("Service Record deleted.\n");
> -	sdp_close(sess);
> -
> -	return 0;
> -}
> -
> -static struct option del_options[] = {
> -	{ "help",	0, 0, 'h' },
> -	{ 0, 0, 0, 0 }
> -};
> -
> -static const char *del_help =
> -	"Usage:\n"
> -	"\tdel record_handle\n";
> -
> -static int cmd_del(int argc, char **argv)
> -{
> -	int opt;
> -
> -	for_each_opt(opt, del_options, 0) {
> -		switch (opt) {
> -		default:
> -			printf("%s", del_help);
> -			return -1;
> -		}
> -	}
> -
> -	argc -= optind;
> -	argv += optind;
> -
> -	if (argc < 1) {
> -		printf("%s", del_help);
> -		return -1;
> -	}
> -
> -	return del_service(NULL, argv[0]);
> -}
> -
> /*
>  * Perform an inquiry and search/browse all peer found.
>  */
> @@ -4203,8 +1718,6 @@ static struct {
> 	{ "search",  cmd_search,      "Search for a service"          },
> 	{ "browse",  cmd_browse,      "Browse all available services" },
> 	{ "records", cmd_records,     "Request all records"           },
> -	{ "add",     cmd_add,         "Add local service"             },
> -	{ "del",     cmd_del,         "Delete local service"          },
> 	{ "get",     cmd_get,         "Get local service"             },
> 	{ "setattr", cmd_setattr,     "Set/Add attribute to a SDP record"          },
> 	{ "setseq",  cmd_setseq,      "Set/Add attribute sequence to a SDP record" },
> -- 
> 1.8.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply

* Re: [PATCH v2 6/8] sdpd: Remove 'register' and 'remove' requests
From: Marcel Holtmann @ 2013-09-21 17:25 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1379599248-7923-7-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

> sdpd is now controlled by adapters and should not be modified with
> other means.
> ---
> src/sdpd-request.c |  14 --------
> src/sdpd-service.c | 100 -----------------------------------------------------
> src/sdpd.h         |   2 --
> 3 files changed, 116 deletions(-)
> 
> diff --git a/src/sdpd-request.c b/src/sdpd-request.c
> index fbeb488..5b88a10 100644
> --- a/src/sdpd-request.c
> +++ b/src/sdpd-request.c
> @@ -997,13 +997,6 @@ static void process_request(sdp_req_t *req)
> 		rsphdr->pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
> 		break;
> 	/* Following requests are allowed only for local connections */
> -	case SDP_SVC_REGISTER_REQ:
> -		SDPDBG("Service register request");
> -		if (req->local) {
> -			status = service_register_req(req, &rsp);
> -			rsphdr->pdu_id = SDP_SVC_REGISTER_RSP;
> -		}
> -		break;
> 	case SDP_SVC_UPDATE_REQ:
> 		SDPDBG("Service update request");
> 		if (req->local) {
> @@ -1011,13 +1004,6 @@ static void process_request(sdp_req_t *req)
> 			rsphdr->pdu_id = SDP_SVC_UPDATE_RSP;
> 		}
> 		break;
> -	case SDP_SVC_REMOVE_REQ:
> -		SDPDBG("Service removal request");
> -		if (req->local) {
> -			status = service_remove_req(req, &rsp);
> -			rsphdr->pdu_id = SDP_SVC_REMOVE_RSP;
> -		}
> -		break;

we can not take these out. We need a way to pass qualification.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH v3 8/8] sdp: Decouple Device ID profile implementation
From: Marcel Holtmann @ 2013-09-21 17:23 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1379599910-8666-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

> Make DeviceID profile similar to other profiles implementations. Use
> btd_profile for handling DeviceID profile while adding/removing
> adapters. The nice drawback is that SDP code no longer depends on
> main_opts.
> ---
> 
> Fixed missing g_slist_remove.
> 
> Makefile.plugins             |   3 +
> profiles/deviceid/deviceid.c | 189 +++++++++++++++++++++++++++++++++++++++++++
> src/adapter.c                |  26 +++---
> src/adapter.h                |   3 +
> src/sdpd-server.c            |   4 -
> src/sdpd-service.c           |  58 -------------
> src/sdpd.h                   |   2 -
> 7 files changed, 206 insertions(+), 79 deletions(-)
> create mode 100644 profiles/deviceid/deviceid.c

please do not intermix profiles/ code with src/ code in the same commit.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 2/2] android: Android version of log.c
From: Marcel Holtmann @ 2013-09-21 17:20 UTC (permalink / raw)
  To: Frederic Danis; +Cc: linux-bluetooth
In-Reply-To: <1379679871-29623-2-git-send-email-frederic.danis@linux.intel.com>

Hi Fred,

> Add logging system to BlueZ Android daemon.
> Android build will use android/log.c file while autotools build will use
> src/log.c instead.
> ---
> Makefile.android   |    2 +-
> android/Android.mk |    1 +
> android/log.c      |  184 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> android/main.c     |   39 +++++++++++
> 4 files changed, 225 insertions(+), 1 deletion(-)
> create mode 100644 android/log.c
> 
> diff --git a/Makefile.android b/Makefile.android
> index 7b901ff..8f65dbf 100644
> --- a/Makefile.android
> +++ b/Makefile.android
> @@ -2,6 +2,6 @@
> if ANDROID_DAEMON
> noinst_PROGRAMS += android/bluezd
> 
> -android_bluezd_SOURCES = android/main.c
> +android_bluezd_SOURCES = android/main.c src/log.c
> android_bluezd_LDADD = @GLIB_LIBS@
> endif
> diff --git a/android/Android.mk b/android/Android.mk
> index 50f3c36..25099b3 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -8,6 +8,7 @@ include $(CLEAR_VARS)
> 
> LOCAL_SRC_FILES := \
> 	main.c \
> +	log.c \
> 
> LOCAL_C_INCLUDES := \
> 	$(call include-path-for, glib) \
> diff --git a/android/log.c b/android/log.c
> new file mode 100644
> index 0000000..1f98196
> --- /dev/null
> +++ b/android/log.c
> @@ -0,0 +1,184 @@
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2013  Intel Corporation. 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 <fcntl.h>
> +#include <stdio.h>
> +#include <stdarg.h>
> +#include <unistd.h>
> +#include <sys/uio.h>
> +
> +#include <glib.h>
> +
> +#include "log.h"
> +
> +#define LOG_DEBUG	3
> +#define LOG_INFO	4
> +#define LOG_WARN	5
> +#define LOG_ERR		6
> +
> +const char tag[] = "BlueZ";
> +int system_fd;
> +int detached;

Local variables should be static.

> +
> +static void android_log(int pri, const char *fmt, va_list ap)
> +{
> +	char *msg;
> +	struct iovec vec[3];
> +
> +	msg = g_strdup_vprintf(fmt, ap);
> +
> +	if (!detached) {
> +		vec[0].iov_base = (void *) msg;
> +		vec[0].iov_len = strlen(msg) + 1;
> +		vec[1].iov_base = "\n";
> +		vec[1].iov_len = 1;
> +		writev(STDERR_FILENO, vec, 2);
> +	}

Lets not worry about logging to stderr at all.

> +
> +	if (system_fd == -1)
> +		goto done;
> +
> +	vec[0].iov_base = (unsigned char *) &pri;
> +	vec[0].iov_len = 1;
> +	vec[1].iov_base = (void *) tag;
> +	vec[1].iov_len = strlen(tag) + 1;
> +	vec[2].iov_base = (void *) msg;
> +	vec[2].iov_len = strlen(msg) + 1;
> +
> +	writev(system_fd, vec, 3);
> +
> +done:
> +	g_free(msg);
> +}
> +
> +void info(const char *format, ...)
> +{
> +	va_list ap;
> +
> +	va_start(ap, format);
> +
> +	android_log(LOG_INFO, format, ap);
> +
> +	va_end(ap);
> +}
> +
> +void warn(const char *format, ...)
> +{
> +	va_list ap;
> +
> +	va_start(ap, format);
> +
> +	android_log(LOG_WARN, format, ap);
> +
> +	va_end(ap);
> +}
> +
> +void error(const char *format, ...)
> +{
> +	va_list ap;
> +
> +	va_start(ap, format);
> +
> +	android_log(LOG_ERR, format, ap);
> +
> +	va_end(ap);
> +}
> +
> +void btd_debug(const char *format, ...)
> +{
> +	va_list ap;
> +
> +	va_start(ap, format);
> +
> +	android_log(LOG_DEBUG, format, ap);
> +
> +	va_end(ap);
> +}
> +
> +extern struct btd_debug_desc __start___debug[];
> +extern struct btd_debug_desc __stop___debug[];
> +
> +static char **enabled = NULL;
> +
> +static gboolean is_enabled(struct btd_debug_desc *desc)
> +{
> +	int i;
> +
> +	if (enabled == NULL)
> +		return 0;
> +
> +	for (i = 0; enabled[i] != NULL; i++)
> +		if (desc->file != NULL && g_pattern_match_simple(enabled[i],
> +							desc->file) == TRUE)
> +			return 1;
> +
> +	return 0;
> +}
> +
> +void __btd_enable_debug(struct btd_debug_desc *start,
> +					struct btd_debug_desc *stop)
> +{
> +	struct btd_debug_desc *desc;
> +
> +	if (start == NULL || stop == NULL)
> +		return;
> +
> +	for (desc = start; desc < stop; desc++) {
> +		if (is_enabled(desc))
> +			desc->flags |= BTD_DEBUG_FLAG_PRINT;
> +	}
> +}
> +
> +void __btd_toggle_debug(void)
> +{
> +	struct btd_debug_desc *desc;
> +
> +	for (desc = __start___debug; desc < __stop___debug; desc++)
> +		desc->flags |= BTD_DEBUG_FLAG_PRINT;
> +}
> +
> +void __btd_log_init(const char *debug, int detach)
> +{
> +	if (debug != NULL)
> +		enabled = g_strsplit_set(debug, ":, ", 0);
> +
> +	__btd_enable_debug(__start___debug, __stop___debug);
> +
> +	detached = detach;
> +
> +	system_fd = open("/dev/log/system", O_WRONLY);
> +
> +	info("Bluetooth daemon %s", VERSION);
> +}
> +
> +void __btd_log_cleanup(void)
> +{
> +	close(system_fd);
> +	system_fd = -1;
> +
> +	g_strfreev(enabled);
> +}
> diff --git a/android/main.c b/android/main.c
> index 37a64c1..ef62b3d 100644
> --- a/android/main.c
> +++ b/android/main.c
> @@ -33,6 +33,7 @@
> 
> #include <glib.h>
> 
> +#include "log.h"
> #include "hcid.h"
> 
> #define SHUTDOWN_GRACE_SECONDS 10
> @@ -58,19 +59,45 @@ static void signal_handler(int sig)
> 	case SIGINT:
> 	case SIGTERM:
> 		if (__terminated == 0) {
> +			info("Terminating");

Since you are in a signal handler and not using signalfd, this is racy.

> 			g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
> 							quit_eventloop, NULL);
> 		}
> 
> 		__terminated = 1;
> 		break;
> +
> +	case SIGUSR2:
> +		__btd_toggle_debug();
> +		break;
> 	}

Lets leave this handling out right now. I know that bluetoothd historically supported it, but that is historic baggage. Neither oFono nor ConnMan does it that way. So just do no bother with this. If it becomes useful, we will add it.

> }
> 
> +static char *option_debug = NULL;
> static gboolean option_detach = TRUE;
> static gboolean option_version = FALSE;
> 
> +static void free_options(void)
> +{
> +	g_free(option_debug);
> +	option_debug = NULL;
> +}
> +
> +static gboolean parse_debug(const char *key, const char *value,
> +				gpointer user_data, GError **error)
> +{
> +	if (value)
> +		option_debug = g_strdup(value);
> +	else
> +		option_debug = g_strdup("*");
> +
> +	return TRUE;
> +}
> +
> static GOptionEntry options[] = {
> +	{ "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
> +				G_OPTION_ARG_CALLBACK, parse_debug,
> +				"Specify debug options to enable", "DEBUG" },
> 	{ "nodetach", 'n', G_OPTION_FLAG_REVERSE,
> 				G_OPTION_ARG_NONE, &option_detach,
> 				"Run with logging in foreground", NULL },
> @@ -110,10 +137,22 @@ int main(int argc, char *argv[])
> 	sa.sa_handler = signal_handler;
> 	sigaction(SIGINT, &sa, NULL);
> 	sigaction(SIGTERM, &sa, NULL);
> +	sigaction(SIGUSR2, &sa, NULL);
> +
> +	__btd_log_init(option_debug, option_detach);
> +
> +	/* no need to keep parsed option in memory */
> +	free_options();
> +
> +	DBG("Entering main loop");

Don't do this debug. It is not helpful. The main() is so short, no point in logging that.

> 
> 	g_main_loop_run(event_loop);
> 
> 	g_main_loop_unref(event_loop);
> 
> +	info("Exit");
> +
> +	__btd_log_cleanup();
> +
> 	return 0;
> }

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Marcel Holtmann @ 2013-09-21 17:14 UTC (permalink / raw)
  To: Frederic Danis; +Cc: linux-bluetooth
In-Reply-To: <1379679871-29623-1-git-send-email-frederic.danis@linux.intel.com>

Hi Fred,

> Define local mapping to glib path, otherwise this has to be inside central
> place in the build repository.
> 
> Retrieve Bluetooth version from configure.ac.
> ---
> .gitignore         |    2 +
> Android.mk         |    9 ++++
> Makefile.am        |    1 +
> Makefile.android   |    7 ++++
> android/Android.mk |   24 +++++++++++
> android/main.c     |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> configure.ac       |    5 +++
> 7 files changed, 167 insertions(+)
> create mode 100644 Android.mk
> create mode 100644 Makefile.android
> create mode 100644 android/Android.mk
> create mode 100644 android/main.c

lets split this out a little bit. Code additions should not be intermixed with additions to the build system and especially configure options.

I rather not have a top-level Android.mk. It should be enough to provide an android/Android.mk.

> diff --git a/.gitignore b/.gitignore
> index 8a25a3e..331a18b 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -98,3 +98,5 @@ unit/test-gobex-packet
> unit/test-gobex-transfer
> unit/test-*.log
> unit/test-*.trs
> +
> +android/bluezd

If we keep using prefix btd_ for certain set of functions, then it might be better if the daemon is build as android/bluetoothd or android/btd.

<snip>

> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include <signal.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <glib.h>
> +
> +#include "hcid.h"

I do not think we need to include hcid.h here. If we for some reason still do, then please try to cleanup that first.

> +
> +#define SHUTDOWN_GRACE_SECONDS 10
> +
> +static GMainLoop *event_loop;
> +
> +void btd_exit(void)
> +{
> +	g_main_loop_quit(event_loop);
> +}
> +
> +static gboolean quit_eventloop(gpointer user_data)
> +{
> +	btd_exit();
> +	return FALSE;
> +}
> +
> +static void signal_handler(int sig)
> +{
> +	static unsigned int __terminated = 0;

Make this static volatile bool __terminated = false instead. Remember that you are actually using signals here and not signalfd.

> +
> +	switch (sig) {
> +	case SIGINT:
> +	case SIGTERM:
> +		if (__terminated == 0) {
> +			g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
> +							quit_eventloop, NULL);
> +		}
> +
> +		__terminated = 1;
> +		break;
> +	}
> +}
> +
> +static gboolean option_detach = TRUE;
> +static gboolean option_version = FALSE;
> +
> +static GOptionEntry options[] = {
> +	{ "nodetach", 'n', G_OPTION_FLAG_REVERSE,
> +				G_OPTION_ARG_NONE, &option_detach,
> +				"Run with logging in foreground", NULL },

Do we need this option at all. I think we should always run in foreground and the system manager need to make sure we are spawned.

> +	{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
> +				"Show version information and exit", NULL },
> +	{ NULL }
> +};
> +
> +int main(int argc, char *argv[])
> +{
> +	GOptionContext *context;
> +	GError *err = NULL;
> +	struct sigaction sa;
> +
> +	context = g_option_context_new(NULL);
> +	g_option_context_add_main_entries(context, options, NULL);
> +
> +	if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
> +		if (err != NULL) {
> +			g_printerr("%s\n", err->message);
> +			g_error_free(err);
> +		} else
> +			g_printerr("An unknown error occurred\n");
> +		exit(1);
> +	}
> +
> +	g_option_context_free(context);
> +
> +	if (option_version == TRUE) {
> +		printf("%s\n", VERSION);
> +		exit(0);

I prefer if we start using return EXIT_SUCCESS and in error case EXIT_FAILURE.

> +	}
> +
> +	event_loop = g_main_loop_new(NULL, FALSE);
> +
> +	memset(&sa, 0, sizeof(sa));
> +	sa.sa_handler = signal_handler;
> +	sigaction(SIGINT, &sa, NULL);
> +	sigaction(SIGTERM, &sa, NULL);
> +
> +	g_main_loop_run(event_loop);
> +
> +	g_main_loop_unref(event_loop);
> +
> +	return 0;
> +}
> diff --git a/configure.ac b/configure.ac
> index 41c2935..3b7a5d9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -242,4 +242,9 @@ AC_DEFINE_UNQUOTED(CONFIGDIR, "${configdir}",
> 			[Directory for the configuration files])
> AC_SUBST(CONFIGDIR, "${configdir}")
> 
> +AC_ARG_ENABLE(android-daemon, AC_HELP_STRING([--enable-android-daemon],
> +			[enable BlueZ Android daemon]),
> +					[android_daemon=${enableval}])
> +AM_CONDITIONAL(ANDROID_DAEMON, test "${android_daemon}" = "yes")
> +

This needs to be a separate patch. And it should just say --enable-android.

In addition it needs to be added to bootstrap-configure and distcheck handling.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH v5 2/2] Bluetooth: btmrvl: add calibration data download support
From: Marcel Holtmann @ 2013-09-21 17:03 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-bluetooth, Gustavo Padovan, Johan Hedberg, linux-wireless,
	Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar
In-Reply-To: <1379715667-22424-2-git-send-email-bzhao@marvell.com>

Hi Bing,

> A text file containing calibration data in hex format can
> be provided at following path:
> 
> /lib/firmware/mrvl/sd8797_caldata.conf
> 
> The data will be downloaded to firmware during initialization.
> 
> Reviewed-by: Mike Frysinger <vapier@chromium.org>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>
> Signed-off-by: Hyuckjoo Lee <hyuckjoo.lee@samsung.com>
> ---
> v2: Remove module parameter. The calibration data will be downloaded
>    only when the device speicific data file is provided.
>    (Marcel Holtmann)
> v3: Fix crash (misaligned memory access) on ARM
> v4: Simplify white space parsing and save some CPU cycles (Mike Frysinger)
> v5: Improvements in cal data parsing logic. Add explanatory comments.
>    Replace GFP_ATOMIC flag with GFP_KERNEL (Mike Frysinger)
> 
> drivers/bluetooth/btmrvl_drv.h  |   10 +++-
> drivers/bluetooth/btmrvl_main.c |  144 ++++++++++++++++++++++++++++++++++++++-
> drivers/bluetooth/btmrvl_sdio.c |    9 ++-
> drivers/bluetooth/btmrvl_sdio.h |    2 +
> 4 files changed, 161 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
> index e776b8b..dcd3468 100644
> --- a/drivers/bluetooth/btmrvl_drv.h
> +++ b/drivers/bluetooth/btmrvl_drv.h
> @@ -23,6 +23,8 @@
> #include <linux/bitops.h>
> #include <linux/slab.h>
> #include <net/bluetooth/bluetooth.h>
> +#include <linux/ctype.h>
> +#include <linux/firmware.h>
> 
> #define BTM_HEADER_LEN			4
> #define BTM_UPLD_SIZE			2312
> @@ -41,6 +43,8 @@ struct btmrvl_thread {
> struct btmrvl_device {
> 	void *card;
> 	struct hci_dev *hcidev;
> +	struct device *dev;
> +	const char *cal_data;
> 
> 	u8 dev_type;
> 
> @@ -92,6 +96,7 @@ struct btmrvl_private {
> #define BT_CMD_HOST_SLEEP_CONFIG	0x59
> #define BT_CMD_HOST_SLEEP_ENABLE	0x5A
> #define BT_CMD_MODULE_CFG_REQ		0x5B
> +#define BT_CMD_LOAD_CONFIG_DATA		0x61
> 
> /* Sub-commands: Module Bringup/Shutdown Request/Response */
> #define MODULE_BRINGUP_REQ		0xF1
> @@ -117,10 +122,13 @@ struct btmrvl_private {
> #define PS_SLEEP			0x01
> #define PS_AWAKE			0x00
> 
> +#define BT_CMD_DATA_SIZE		32
> +#define BT_CAL_DATA_SIZE		28
> +
> struct btmrvl_cmd {
> 	__le16 ocf_ogf;
> 	u8 length;
> -	u8 data[4];
> +	u8 data[BT_CMD_DATA_SIZE];
> } __packed;
> 
> struct btmrvl_event {
> diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
> index e352f8e..6eea188 100644
> --- a/drivers/bluetooth/btmrvl_main.c
> +++ b/drivers/bluetooth/btmrvl_main.c
> @@ -57,8 +57,9 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
> 		ocf = hci_opcode_ocf(opcode);
> 		ogf = hci_opcode_ogf(opcode);
> 
> -		if (ocf == BT_CMD_MODULE_CFG_REQ &&
> -					priv->btmrvl_dev.sendcmdflag) {
> +		if ((ocf == BT_CMD_MODULE_CFG_REQ ||
> +		     ocf == BT_CMD_LOAD_CONFIG_DATA) &&
> +		    priv->btmrvl_dev.sendcmdflag) {
> 			priv->btmrvl_dev.sendcmdflag = false;
> 			priv->adapter->cmd_complete = true;
> 			wake_up_interruptible(&priv->adapter->cmd_wait_q);
> @@ -479,6 +480,142 @@ static int btmrvl_open(struct hci_dev *hdev)
> 	return 0;
> }
> 
> +/*
> + * This function parses provided calibration data input. It should contain
> + * hex bytes separated by space or new line character. Here is an example.
> + * 00 1C 01 37 FF FF FF FF 02 04 7F 01
> + * CE BA 00 00 00 2D C6 C0 00 00 00 00
> + * 00 F0 00 00
> + */
> +static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
> +{
> +	const u8 *s = src;
> +	u8 *d = dst;
> +	int ret;
> +	u8 tmp[3];
> +
> +	tmp[2] = '\0';
> +	while ((s - src) <= len - 2) {
> +		if (isspace(*s) || *s == '\n') {
> +			s++;
> +			continue;
> +		}
> +
> +		if (isxdigit(*s)) {
> +			if ((d - dst) >= dst_size) {
> +				BT_ERR("calibration data file too big!!!");
> +				return -EINVAL;
> +			}
> +
> +			memcpy(tmp, s, 2);
> +
> +			ret = kstrtou8(tmp, 16, d++);
> +			if (ret < 0)
> +				return ret;
> +
> +			s += 2;
> +		} else {
> +			return -EINVAL;
> +		}
> +	}
> +	if (d == dst)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int btmrvl_load_cal_data(struct btmrvl_private *priv,
> +				u8 *config_data)
> +{
> +	struct sk_buff *skb;
> +	struct btmrvl_cmd *cmd;
> +	int i;
> +
> +	skb = bt_skb_alloc(sizeof(*cmd), GFP_KERNEL);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct btmrvl_cmd *)skb->data;
> +	cmd->ocf_ogf =
> +		cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_LOAD_CONFIG_DATA));
> +	cmd->length = BT_CMD_DATA_SIZE;
> +	cmd->data[0] = 0x00;
> +	cmd->data[1] = 0x00;
> +	cmd->data[2] = 0x00;
> +	cmd->data[3] = BT_CMD_DATA_SIZE - 4;

why not use __hci_cmd_sync() here. It is designed to be used from ->setup() where it is guaranteed that the HCI request lock is held. And it is guaranteed that ->setup() is executed in a workqueue.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Marcel Holtmann @ 2013-09-21 17:00 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-bluetooth, Gustavo Padovan, Johan Hedberg, linux-wireless,
	Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar
In-Reply-To: <1379715667-22424-1-git-send-email-bzhao@marvell.com>

Hi Bing,

> Move initialization code to hdev's setup handler. New flag
> setup_done is added to make sure that initialization is done only
> during driver load time. Our firmware doesn't expect
> re-initialization later when interface is re-enabled.
> 
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>
> ---
> v5: make use of hdev's setup handler (Marcel Holtmann)
> 
> drivers/bluetooth/btmrvl_drv.h  |    1 +
> drivers/bluetooth/btmrvl_main.c |   23 +++++++++++++++++++++--
> drivers/bluetooth/btmrvl_sdio.c |    6 ------
> 3 files changed, 22 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
> index 27068d1..e776b8b 100644
> --- a/drivers/bluetooth/btmrvl_drv.h
> +++ b/drivers/bluetooth/btmrvl_drv.h
> @@ -68,6 +68,7 @@ struct btmrvl_adapter {
> 	wait_queue_head_t cmd_wait_q;
> 	u8 cmd_complete;
> 	bool is_suspended;
> +	bool setup_done;
> };
> 
> struct btmrvl_private {
> diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
> index 9a9f518..e352f8e 100644
> --- a/drivers/bluetooth/btmrvl_main.c
> +++ b/drivers/bluetooth/btmrvl_main.c
> @@ -479,6 +479,27 @@ static int btmrvl_open(struct hci_dev *hdev)
> 	return 0;
> }
> 
> +static int btmrvl_setup(struct hci_dev *hdev)
> +{
> +	struct btmrvl_private *priv = hci_get_drvdata(hdev);
> +	struct btmrvl_adapter *adapter = priv->adapter;
> +
> +	if (adapter->setup_done)
> +		return 0;
> +
> +	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
> +
> +	priv->btmrvl_dev.psmode = 1;
> +	btmrvl_enable_ps(priv);
> +
> +	priv->btmrvl_dev.gpio_gap = 0xffff;
> +	btmrvl_send_hscfg_cmd(priv);
> +
> +	adapter->setup_done = true;
> +
> +	return 0;
> +}
> +
> /*
>  * This function handles the event generated by firmware, rx data
>  * received from firmware, and tx data sent from kernel.
> @@ -572,8 +592,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
> 	hdev->flush = btmrvl_flush;
> 	hdev->send = btmrvl_send_frame;
> 	hdev->ioctl = btmrvl_ioctl;
> -
> -	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
> +	hdev->setup = btmrvl_setup;

just to make sure you guys understand how ->setup() works. It is only called once. Bringing the adapter down and up again does not call ->setup() a second time. So do you guys need this setup_done variable and if so, then you need to be a bit more verbose and help me understand why.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Marcel Holtmann @ 2013-09-21 16:19 UTC (permalink / raw)
  To: Ken O'Brien; +Cc: gustavo, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <1379718623-1845-1-git-send-email-kernel@kenobrien.org>

Hi Ken,

> Adding generic rule for broadcom devices to generic usb bluetooth driver on encountering another instance of Broadcom's BCM20702A0.
> 
> Relevant section from /sys/kernel/debug/usb/devices:
> 
> T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
> D:  Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=050d ProdID=065a Rev= 1.12
> S:  Manufacturer=Broadcom Corp
> S:  Product=BCM20702A0
> S:  SerialNumber=0002723E2D29
> C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=81(I) Atr=03(Int.) MxPS=  16 Ivl=1ms
> E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> I:  If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> I:  If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> I:  If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> I:  If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> I:  If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
> E:  Ad=84(I) Atr=02(Bulk) MxPS=  32 Ivl=0ms
> E:  Ad=04(O) Atr=02(Bulk) MxPS=  32 Ivl=0ms
> I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
> 
> Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
> ---
> drivers/bluetooth/btusb.c | 1 +
> 1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index 8e16f0a..6d33dca 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -111,6 +111,7 @@ static struct usb_device_id btusb_table[] = {
> 
> 	/*Broadcom devices with vendor specific id */
> 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
> +	{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },

this is not correct. These devices are Broadcom based, but they are actually from Belkin. Same as the controllers from Apple. So it needs its own line and a comment that mentions Belkin.

Regards

Marcel


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox